diff --git a/backend/apps/chat/models/chat_model.py b/backend/apps/chat/models/chat_model.py index f095a65d..2f771051 100644 --- a/backend/apps/chat/models/chat_model.py +++ b/backend/apps/chat/models/chat_model.py @@ -1,17 +1,18 @@ from datetime import datetime from typing import List, Optional +from fastapi import Body from pydantic import BaseModel from sqlalchemy import Column, Integer, Text, BigInteger, DateTime, Identity, Boolean from sqlmodel import SQLModel, Field +from apps.template.filter.generator import get_permissions_template from apps.template.generate_analysis.generator import get_analysis_template from apps.template.generate_chart.generator import get_chart_template from apps.template.generate_guess_question.generator import get_guess_question_template from apps.template.generate_predict.generator import get_predict_template from apps.template.generate_sql.generator import get_sql_template from apps.template.select_datasource.generator import get_datasource_template -from apps.template.filter.generator import get_permissions_template class Chat(SQLModel, table=True): @@ -24,7 +25,8 @@ class Chat(SQLModel, table=True): chat_type: str = Field(max_length=20, default="chat") # chat, datasource datasource: int = Field(sa_column=Column(BigInteger, nullable=True)) engine_type: str = Field(max_length=64) - origin: Optional[int] = Field(sa_column=Column(Integer, nullable=False, default=0)) # 0: default, 1: mcp, 2: assistant + origin: Optional[int] = Field( + sa_column=Column(Integer, nullable=False, default=0)) # 0: default, 1: mcp, 2: assistant class ChatRecord(SQLModel, table=True): @@ -152,13 +154,14 @@ class AiModelQuestion(BaseModel): class ChatQuestion(AiModelQuestion): - question: str = '' - chat_id: int = 0 + question: str = Body(description='用户提问') + chat_id: int = Body(description='会话ID') + class ChatMcp(ChatQuestion): - token: str = '' + token: str = Body(description='token') class ChatStart(BaseModel): - username: str = '' - password: str = '' + username: str = Body(description='用户名') + password: str = Body(description='密码') diff --git a/backend/apps/system/crud/assistant.py b/backend/apps/system/crud/assistant.py index 76c8c3bf..d56acb97 100644 --- a/backend/apps/system/crud/assistant.py +++ b/backend/apps/system/crud/assistant.py @@ -132,14 +132,24 @@ class AssistantOutDs: def get_db_schema(self, ds_id: int) -> str: ds = self.get_ds(ds_id) schema_str = "" - db_name = ds.db_schema + #db_name = ds.db_schema + db_name = ds.db_schema if ds.db_schema is not None and ds.db_schema != "" else ds.dataBase schema_str += f"【DB_ID】 {db_name}\n【Schema】\n" for table in ds.tables: - schema_str += f"# Table: {db_name}.{table.name}" - schema_str += f", {table.comment}\n[\n" + schema_str += f"# Table: {db_name}.{table.name}" if ds.type != "mysql" else f"# Table: {table.name}" + table_comment = table.comment + if table_comment == '': + schema_str += '\n[\n' + else: + schema_str += f", {table_comment}\n[\n" + field_list = [] for field in table.fields: - field_list.append(f"({field.name}:{field.type}, {field.comment})") + field_comment = field.comment + if field_comment == '': + field_list.append(f"({field.name}:{field.type})") + else: + field_list.append(f"({field.name}:{field.type}, {field_comment})") schema_str += ",\n".join(field_list) schema_str += '\n]\n' return schema_str diff --git a/backend/common/utils/utils.py b/backend/common/utils/utils.py index bbc4c2a0..9d35dd4b 100644 --- a/backend/common/utils/utils.py +++ b/backend/common/utils/utils.py @@ -76,7 +76,9 @@ def extract_nested_json(text): def string_to_numeric_hash(text: str, bits: Optional[int] = 64) -> int: hash_bytes = hashlib.sha256(text.encode()).digest() - return int.from_bytes(hash_bytes[:bits//8], byteorder='big') + hash_num = int.from_bytes(hash_bytes, byteorder='big') + max_bigint = 2**63 - 1 + return hash_num % max_bigint def setup_logging(): diff --git a/frontend/src/views/dashboard/components/sq-view/index.vue b/frontend/src/views/dashboard/components/sq-view/index.vue index f9c089c9..86708611 100644 --- a/frontend/src/views/dashboard/components/sq-view/index.vue +++ b/frontend/src/views/dashboard/components/sq-view/index.vue @@ -2,7 +2,7 @@ import ChartComponent from '@/views/chat/component/ChartComponent.vue' import icon_window_mini_outlined from '@/assets/svg/icon_window-mini_outlined.svg' import SqViewDisplay from '@/views/dashboard/components/sq-view/index.vue' -defineProps({ +const props = defineProps({ viewInfo: { type: Object, required: true, @@ -14,20 +14,80 @@ defineProps({ }, }) -import { ref } from 'vue' +import { computed, nextTick, ref } from 'vue' import { useI18n } from 'vue-i18n' +import ChartPopover from '@/views/chat/chat-block/ChartPopover.vue' +import ICON_TABLE from '@/assets/svg/chart/icon_form_outlined.svg' +import ICON_COLUMN from '@/assets/svg/chart/icon_dashboard_outlined.svg' +import ICON_BAR from '@/assets/svg/chart/icon_bar_outlined.svg' +import ICON_LINE from '@/assets/svg/chart/icon_chart-line.svg' +import ICON_PIE from '@/assets/svg/chart/icon_pie_outlined.svg' +import type { ChartTypes } from '@/views/chat/component/BaseChart.ts' const { t } = useI18n() const chartRef = ref(null) +const currentChartType = ref(undefined) + const renderChart = () => { //@ts-expect-error eslint-disable-next-line @typescript-eslint/no-unused-expressions // eslint-disable-next-line @typescript-eslint/no-unused-expressions chartRef.value?.renderChart } + const enlargeDialogVisible = ref(false) const enlargeView = () => { enlargeDialogVisible.value = true } + +const chartTypeList = computed(() => { + const _list = [] + if (props.viewInfo.chart) { + switch (props.viewInfo.chart.type) { + case 'table': + break + case 'column': + case 'bar': + case 'line': + _list.push({ + value: 'column', + name: t('chat.chart_type.column'), + icon: ICON_COLUMN, + }) + _list.push({ + value: 'bar', + name: t('chat.chart_type.bar'), + icon: ICON_BAR, + }) + _list.push({ + value: 'line', + name: t('chat.chart_type.line'), + icon: ICON_LINE, + }) + break + case 'pie': + _list.push({ + value: 'pie', + name: t('chat.chart_type.pie'), + icon: ICON_PIE, + }) + } + } + + return _list +}) + +function changeTable() { + onTypeChange('table') +} + +function onTypeChange(val: any) { + // eslint-disable-next-line vue/no-mutating-props + props.viewInfo.chart.type = val + nextTick(() => { + //@ts-expect-error eslint-disable-next-line @typescript-eslint/no-unused-expressions + chartRef.value?.renderChart() + }) +} defineExpose({ renderChart, enlargeView, @@ -40,6 +100,32 @@ defineExpose({
{{ viewInfo.chart.title }}
+
+
+ + + + + + + + + + +
+
+
diff --git a/frontend/src/views/dashboard/editor/ChartSelection.vue b/frontend/src/views/dashboard/editor/ChartSelection.vue index 07e152ad..2704c511 100644 --- a/frontend/src/views/dashboard/editor/ChartSelection.vue +++ b/frontend/src/views/dashboard/editor/ChartSelection.vue @@ -39,7 +39,7 @@ const curSelectChange = (value: boolean) => { overflow: hidden; .select-area { position: absolute; - top: 20px; + top: 26px; right: 20px; } }