From 222dafa1888b0adef7fefaee14361bcd7095fac1 Mon Sep 17 00:00:00 2001 From: xueyinfei <1207092115@qq.com> Date: Sun, 7 Dec 2025 00:41:18 +0800 Subject: [PATCH] =?UTF-8?q?aichat=E5=8A=A9=E6=89=8B=E4=BA=A4=E4=BA=92?= =?UTF-8?q?=E5=8D=87=E7=BA=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/aichat_controller.py | 15 + .../module_admin/dao/aichat_dao.py | 18 +- .../module_admin/entity/do/aichat_do.py | 3 + .../module_admin/entity/vo/aichat_vo.py | 3 + .../module_admin/service/aichat_service.py | 30 +- vue-fastapi-frontend/src/api/aichat/aichat.js | 18 +- .../codemirror/SQLCodeMirrorSqlFlow.vue | 7 +- .../src/views/aichat/Interrupt.vue | 88 ++++++ .../src/views/aichat/aichat.vue | 289 +++++++++++++++--- .../src/views/aichat/index.vue | 5 +- .../src/views/meta/metaInfo/bloodRelation.vue | 2 +- .../views/meta/metaInfo/bloodRelationSql.vue | 2 +- .../src/views/sqlFlow/index.vue | 15 +- 13 files changed, 432 insertions(+), 63 deletions(-) create mode 100644 vue-fastapi-frontend/src/views/aichat/Interrupt.vue diff --git a/vue-fastapi-backend/module_admin/controller/aichat_controller.py b/vue-fastapi-backend/module_admin/controller/aichat_controller.py index d958554..03133ad 100644 --- a/vue-fastapi-backend/module_admin/controller/aichat_controller.py +++ b/vue-fastapi-backend/module_admin/controller/aichat_controller.py @@ -44,6 +44,14 @@ async def delete_chat_session(request: Request, sessionId: str, query_db: AsyncS return ResponseUtil.success(msg=delete_chat_session_result.message) +@aichatController.post("/delete/chatList/{chatId}") +async def delete_chat_session(request: Request, chatId: str, query_db: AsyncSession = Depends(get_db), + current_user: CurrentUserModel = Depends(LoginService.get_current_user)): + delete_chat_session_result = await AiChatService.delete_chat_list(query_db, chatId, current_user) + logger.info(delete_chat_session_result.message) + return ResponseUtil.success(msg=delete_chat_session_result.message) + + @aichatController.post("/add") async def add_chat(request: Request, add_chat: AiChatModel, query_db: AsyncSession = Depends(get_db), current_user: CurrentUserModel = Depends(LoginService.get_current_user)): @@ -59,6 +67,13 @@ async def update_chat(request: Request, update_chat: AiChatModel, query_db: Asyn logger.info(operate_result.message) return ResponseUtil.success(msg=operate_result.message) +@aichatController.post("/updateChatProcessData") +async def update_chat(request: Request, update_chat: AiChatModel, query_db: AsyncSession = Depends(get_db), + current_user: CurrentUserModel = Depends(LoginService.get_current_user)): + operate_result = await AiChatService.update_chat_process(query_db, update_chat) + logger.info(operate_result.message) + return ResponseUtil.success(msg=operate_result.message) + @aichatController.post("/upload") async def upload_file(request: Request, sessionId: str = Form(), file: UploadFile = File(...), diff --git a/vue-fastapi-backend/module_admin/dao/aichat_dao.py b/vue-fastapi-backend/module_admin/dao/aichat_dao.py index 57d3a3d..6fc73b3 100644 --- a/vue-fastapi-backend/module_admin/dao/aichat_dao.py +++ b/vue-fastapi-backend/module_admin/dao/aichat_dao.py @@ -31,12 +31,18 @@ class AiChatDao: return result @classmethod - async def get_ai_chat_by_id(cls, sessionId: str, db: AsyncSession, user_id: int): + async def get_chat_session_by_id(cls, sessionId: str, db: AsyncSession, user_id: int): chat_list = (await db.execute(select(AiChatSession) .where(AiChatSession.user == user_id, AiChatSession.sessionId == sessionId))).scalars().first() return chat_list + + @classmethod + async def get_ai_chat_by_id(cls, chatId: str, db: AsyncSession): + chat = (await db.execute(select(AiChatHistory).where(AiChatHistory.chatId == chatId))).scalars().first() + return chat + @classmethod async def add_ai_chat_session(cls, sessionId: str, sessionName: str, time: str, db: AsyncSession, user_id: int): chat_session = AiChatSession() @@ -59,6 +65,16 @@ class AiChatDao: await db.execute(delete(AiChatHistory).where(AiChatHistory.sessionId == sessionId)) await db.execute(delete(AiChatSession).where(AiChatSession.sessionId == sessionId)) + @classmethod + async def delete_chat_with_session_and_time(cls, db: AsyncSession, sessionId: str, time: str): + await db.execute(delete(AiChatHistory).where(AiChatHistory.sessionId == sessionId, AiChatHistory.time >= time)) + @classmethod async def update_ai_chat_history(cls, update_chat: AiChatModel, db: AsyncSession): await db.execute(update(AiChatHistory), [dict(update_chat)]) + + @classmethod + async def update_chat_process(cls, update_chat: AiChatModel, db: AsyncSession): + await db.execute(update(AiChatHistory) + .values(action=update_chat.action, interrupt=update_chat.interrupt) + .where(AiChatHistory.chatId == update_chat.chatId)) diff --git a/vue-fastapi-backend/module_admin/entity/do/aichat_do.py b/vue-fastapi-backend/module_admin/entity/do/aichat_do.py index 0a9e50d..b342744 100644 --- a/vue-fastapi-backend/module_admin/entity/do/aichat_do.py +++ b/vue-fastapi-backend/module_admin/entity/do/aichat_do.py @@ -22,6 +22,9 @@ class AiChatHistory(Base): operate = Column(String(50), default=None, comment='点赞,差评等操作') thumbDownReason = Column(String(255), default=None, comment='差评原因') file = Column(String(255), default=None, comment='文件id集合') + interrupt = Column(LONGTEXT, default=None, comment='中断内容') + checkpointer = Column(LONGTEXT, default=None, comment='结束内容') + action = Column(String(50), default=None, comment='交互审批处理动作') class AiChatSession(Base): diff --git a/vue-fastapi-backend/module_admin/entity/vo/aichat_vo.py b/vue-fastapi-backend/module_admin/entity/vo/aichat_vo.py index b1c10ad..498fb33 100644 --- a/vue-fastapi-backend/module_admin/entity/vo/aichat_vo.py +++ b/vue-fastapi-backend/module_admin/entity/vo/aichat_vo.py @@ -33,6 +33,9 @@ class AiChatModel(BaseModel): operate: Optional[str] = None thumbDownReason: Optional[str] = None file: Optional[str] = None + interrupt: Optional[str] = None + checkpointer: Optional[str] = None + action: Optional[str] = None class ThumbOperateModel(BaseModel): diff --git a/vue-fastapi-backend/module_admin/service/aichat_service.py b/vue-fastapi-backend/module_admin/service/aichat_service.py index 0e124ef..44a6544 100644 --- a/vue-fastapi-backend/module_admin/service/aichat_service.py +++ b/vue-fastapi-backend/module_admin/service/aichat_service.py @@ -17,37 +17,45 @@ class AiChatService: @classmethod async def get_ai_session_list_services(cls, result_db: AsyncSession, sessionId: str, - current_user: Optional[CurrentUserModel] = None): - ai_session_list = await AiChatDao.get_ai_session_list(result_db, sessionId, current_user.user.user_id) # 查询最新的20条 + current_user: Optional[CurrentUserModel] = None): + ai_session_list = await AiChatDao.get_ai_session_list(result_db, sessionId, + current_user.user.user_id) # 查询最新的20条 return ai_session_list @classmethod async def get_ai_chat_list_services(cls, result_db: AsyncSession, query: AiListQuery, - current_user: Optional[CurrentUserModel] = None): + current_user: Optional[CurrentUserModel] = None): ai_session_list = await AiChatDao.get_ai_chat_list(result_db, query, current_user.user.user_id) # 查询最新的20条 return CamelCaseUtil.transform_result(ai_session_list) @classmethod async def delete_chat_session(cls, result_db: AsyncSession, sessionId: str, - current_user: Optional[CurrentUserModel] = None): + current_user: Optional[CurrentUserModel] = None): await AiChatDao.delete_chat_session(result_db, sessionId, current_user.user.user_id) await result_db.commit() return CrudResponseModel(is_success=True, message='删除成功') + @classmethod + async def delete_chat_list(cls, result_db: AsyncSession, chatId: str, + current_user: Optional[CurrentUserModel] = None): + chat = AiChatDao.get_ai_chat_by_id(chatId, result_db) + await AiChatDao.delete_chat_with_session_and_time(result_db, chat.sessionId, chat.time) + await result_db.commit() + return CrudResponseModel(is_success=True, message='删除成功') + @classmethod async def add_chat(cls, result_db: AsyncSession, add_chat: AiChatModel, - current_user: Optional[CurrentUserModel] = None): - chat_session = await AiChatDao.get_ai_chat_by_id(add_chat.sessionId, result_db, current_user.user.user_id) + current_user: Optional[CurrentUserModel] = None): + chat_session = await AiChatDao.get_chat_session_by_id(add_chat.sessionId, result_db, current_user.user.user_id) print(chat_session) add_chat.user = current_user.user.user_id if add_chat.time is None: add_chat.time = datetime.now().strftime("%Y-%m-%d %H:%M:%S") if chat_session is None: await AiChatDao.add_ai_chat_session(add_chat.sessionId, add_chat.sessionName, - add_chat.time, result_db, current_user.user.user_id) + add_chat.time, result_db, current_user.user.user_id) await result_db.commit() chat_history = AiChatHistory(**add_chat.dict()) - chat_history.chatId = uuid.uuid4() await AiChatDao.add_ai_chat_history(chat_history, result_db) await result_db.commit() return CrudResponseModel(is_success=True, message='操作成功') @@ -57,3 +65,9 @@ class AiChatService: await AiChatDao.update_ai_chat_history(update_chat, result_db) await result_db.commit() return CrudResponseModel(is_success=True, message='操作成功') + + @classmethod + async def update_chat_process(cls, result_db: AsyncSession, update_chat: AiChatModel): + await AiChatDao.update_chat_process(update_chat, result_db) + await result_db.commit() + return CrudResponseModel(is_success=True, message='操作成功') diff --git a/vue-fastapi-frontend/src/api/aichat/aichat.js b/vue-fastapi-frontend/src/api/aichat/aichat.js index 8ad351c..f733fa9 100644 --- a/vue-fastapi-frontend/src/api/aichat/aichat.js +++ b/vue-fastapi-frontend/src/api/aichat/aichat.js @@ -32,10 +32,17 @@ export function DeleteChatSession(sessionId) { method: 'post' }) } +//删除chat之后的所有数据 +export function DeleteChatList(chatId) { + return request({ + url: '/default-api/aichat/delete/chatList/'+chatId, + method: 'post' + }) +} -export function updateChat(data) { +export function updateChatProcessData(data) { return request({ - url: '/default-api/aichat/update', + url: '/default-api/aichat/updateChatProcessData', method: 'post', data: data }) @@ -48,6 +55,13 @@ export async function addChat(data) { data: data }) } +export async function updateChat(data) { + return request({ + url: '/default-api/aichat/update', + method: 'post', + data: data + }) +} export async function postDataQuery(data) { return request({ url: '/dataquery-api/datachat', diff --git a/vue-fastapi-frontend/src/components/codemirror/SQLCodeMirrorSqlFlow.vue b/vue-fastapi-frontend/src/components/codemirror/SQLCodeMirrorSqlFlow.vue index 7ddb735..b312632 100644 --- a/vue-fastapi-frontend/src/components/codemirror/SQLCodeMirrorSqlFlow.vue +++ b/vue-fastapi-frontend/src/components/codemirror/SQLCodeMirrorSqlFlow.vue @@ -1,5 +1,5 @@ + \ No newline at end of file diff --git a/vue-fastapi-frontend/src/views/aichat/aichat.vue b/vue-fastapi-frontend/src/views/aichat/aichat.vue index 0e2ca88..d92781a 100644 --- a/vue-fastapi-frontend/src/views/aichat/aichat.vue +++ b/vue-fastapi-frontend/src/views/aichat/aichat.vue @@ -3,40 +3,50 @@
-
- -
+ + +
- - 您好,我是 果知小助手,您可以向我提出关于 果知的相关问题。 - + 您好,我是 果知小助手,您可以向我提出关于 果知的相关问题。
@@ -146,6 +160,41 @@ + + + + +
@@ -184,10 +233,11 @@ import OperationButton from './OperationButton.vue' import MdRenderer from '@/views/aichat/MdRenderer.vue' import fullscreenG6 from '@/views/aichat/fullscreenG6.vue' import {getToken} from "@/utils/auth.js"; -import {postChatMessage} from "@/api/aichat/aichat.js" +import {addChat, DeleteChatList, postChatMessage, updateChatProcessData} from "@/api/aichat/aichat.js" import cache from "@/plugins/cache.js"; import Cookies from "js-cookie"; -import {addChat} from "@/api/aichat/aichat"; +import Interrupt from "@/views/aichat/Interrupt.vue"; +import { v4 as uuidv4 } from 'uuid'; defineOptions({ name: 'AiChat' }) const route = useRoute() @@ -226,11 +276,17 @@ const scrollDiv = ref() const dialogScrollbar = ref() const loading = ref(false) const inputValue = ref('') +const currentQuestion = ref({}) const chartOpenId = ref('') const chatList = ref([]) const answerList = ref([]) const controller = ref(null) - +const autoProcess = ref({ + checkAll: false, + isIndeterminate: false, + autoArray:[], + robots:['数据治理管理专家自动批准','元数据专家自动批准','数据标准专家自动批准','数据安全专家自动批准','数据分析专家自动批准','数据模型专家自动批准','数据质量专家自动批准','智能导航专家自动审批'], +}) const popoverVisible = ref(false) const currentMachine = ref([]) const currentFiles = ref([]) @@ -258,6 +314,39 @@ function setScrollBottom() { scrollDiv.value.setScrollTop(getMaxHeight()) } +function confirmReturn(item,index){ + DeleteChatList(item.chatId).then(res=>{ + chatList.value.splice(index, chatList.value.length - index); + let reqData = { + "user_id": cache.local.get("username"), + "session_id": Cookies.get("chatSessionId"), + "checkpointer": item.checkpointer + } + sendChatMessage(reqData) + }) + +} + +function handleCheckAllRobot(){ + autoProcess.value.checkAll = !autoProcess.value.checkAll + autoProcess.value.autoArray = autoProcess.value.checkAll ? autoProcess.value.robots : [] + autoProcess.value.isIndeterminate = false +} + +function toggleRobot(robot){ + const index = autoProcess.value.autoArray.indexOf(robot) + if (index !== -1) { + // 已选中则取消 + autoProcess.value.autoArray = autoProcess.value.autoArray.filter(item => item !== robot) + } else { + // 未选中则添加 + autoProcess.value.autoArray = [...autoProcess.value.autoArray, robot] + } + const checkedCount = autoProcess.value.autoArray.length + autoProcess.value.checkAll = checkedCount === autoProcess.value.robots.length + autoProcess.value.isIndeterminate = checkedCount > 0 && checkedCount < autoProcess.value.robots.length +} + /** * 滚动条距离最上面的高度 */ @@ -329,6 +418,7 @@ watch(() => props.cookieSessionId, value => upload.data = {sessionId:value}) function regenerationChart(index){ let question = chatList.value[index - 1] let chat = { + "chatId":uuidv4(), "type":"question", "content":question.content, "time": formatDate(new Date()), @@ -340,7 +430,6 @@ function regenerationChart(index){ "robot": currentMachine.value.length>0?currentMachine.value[0]:"", "session_id": Cookies.get("chatSessionId"), "doc": chat.file, - "history": [] } sendChatMessage(data) } @@ -413,6 +502,25 @@ function downloadFile(file,bucket,sessionId){ }, file); } +function processAuth(data){ + let updateData = { + chatId: data.chatId, + action: data.action, + interrupt: JSON.stringify(data.interrupt) + } + updateChatProcessData(updateData).then(res=>{ + let reqData = { + "user_id": cache.local.get("username"), + "session_id": Cookies.get("chatSessionId"), + "checkpointer": data.checkpointer, + "action": data.action, + "resume": true, + "block": data.interrupt.block + } + sendChatMessage(reqData) + }) +} + async function sendChatHandle(event) { if (!event.ctrlKey) { // 如果没有按下组合键ctrl,则会阻止默认事件 @@ -421,6 +529,7 @@ async function sendChatHandle(event) { (chatList.value[chatList.value.length - 1].isStop || chatList.value[chatList.value.length - 1].isEnd))) { chatList.value.push({ + "chatId": uuidv4(), "type": "question", "content": inputValue.value.trim(), "time": formatDate(new Date()), @@ -440,9 +549,14 @@ async function sendChatHandle(event) { "user_id": cache.local.get("username"), "robot": currentMachine.value.length > 0 ? currentMachine.value[0] : "", "session_id": Cookies.get("chatSessionId"), - "doc": currentFiles.value, - "history": [] + "doc": currentFiles.value + } + if (chatList.value.length > 1){ + // 判断为1 因为上方已将问题加入 chatList了 , >1 则视为已存在提问交互 + //取最新的checkpointer值 + data.checkpointer = chatList.value[chatList.value.length - 2].content.checkpointer } + currentQuestion.value = data inputValue.value = '' sendChatMessage(data) } @@ -456,23 +570,73 @@ function sendChatMessage(data){ controller.value = new AbortController() postChatMessage(data,{signal:controller.value.signal}).then(res=>{ if (res.status !== 200){ - chatList.value.push({"type":"answer","content":[{"type":"text","content":"服务异常,错误码:"+res.status}],"isEnd":true,"isStop":false,"sessionId":chatList.value[0].sessionId,"sessionName":chatList.value[0].sessionName,"operate":'',"thumbDownReason":''}) + chatList.value.push({"chatId":uuidv4(),"type":"answer","content":[{"type":"text","content":"服务异常,错误码:"+res.status}],"isEnd":true,"isStop":false,"sessionId":chatList.value[0].sessionId,"sessionName":chatList.value[0].sessionName,"operate":'',"thumbDownReason":''}) }else { currentFiles.value = [] - chatList.value.push({"type":"answer","content":[],"isEnd":false,"isStop":false,"sessionId":chatList.value[0].sessionId,"sessionName":chatList.value[0].sessionName, "operate":'',"thumbDownReason":''}) + chatList.value.push({"chatId":uuidv4(),"type":"answer","content":[],"isEnd":false,"isStop":false,"sessionId":chatList.value[0].sessionId,"sessionName":chatList.value[0].sessionName, "operate":'',"thumbDownReason":''}) const reader = res.body.getReader() const write = getWrite(reader) reader.read().then(write).then(()=> { let answer = JSON.parse(JSON.stringify(chatList.value[chatList.value.length - 1])) answer.content = JSON.stringify(answer.content) + answer.interrupt = JSON.stringify(answer.interrupt)? answer.interrupt: null + answer.checkpointer = JSON.stringify(answer.checkpointer) addChat(answer) + }).then(()=>{ + let answer = JSON.parse(JSON.stringify(chatList.value[chatList.value.length - 1])) + if(answer.interrupt){ + let robot = answer.interrupt.robot + let block = answer.interrupt.block + let action = answer.interrupt.action + let autoRequest = false + if (autoProcess.value.autoArray.length > 0 && autoProcess.value.autoArray.indexOf(robot) !== -1){ + //自动审批信号有效,需判断 block内容的必填项,有无默认值,有的话,可以自动发送,没有需填写 + autoRequest = true + if (block && block.length>0){ + for (let i = 0; i < block.length; i++) { + if (block[i].required){ + if (block[i].ct_type === 'dateRangePicker' || block[i].ct_type === 'checkboxGroup' || block[i].ct_type === 'multiselect'){ + //default_value 是数组 + if (!block[i].default_value || block[i].default_value === []){ + autoRequest = false + } + } + if (block[i].ct_type === 'datePicker' || block[i].ct_type === 'input' || block[i].ct_type === 'radioGroup' ||block[i].ct_type === 'select'){ + //default_value 是文字 + if (!block[i].default_value || block[i].default_value.trim() === ''){ + autoRequest = false + } + } + } + } + } + if (autoRequest){ + let reqData = { + "user_id": cache.local.get("username"), + "session_id": Cookies.get("chatSessionId"), + "checkpointer": answer.checkpointer, + "action":"", + "resume": true, + "block": block + } + for (let i = 0; i < action.length; i++) { + if (action[i].style === 'primary'){ + reqData.action = action[i].action + } + } + sendChatMessage(reqData) + } + } + } }) } }).catch((e) => { - chatList.value.push({"type":"answer","content":[{"type":"text","content":"服务异常"}],"isEnd":true,"isStop":false,"sessionId":chatList.value[0].sessionId,"sessionName":chatList.value[0].sessionName,"operate":"","thumbDownReason":""}) + chatList.value.push({"chatId":uuidv4(),"type":"answer","content":[{"type":"text","content":"服务异常"}],"isEnd":true,"isStop":false,"sessionId":chatList.value[0].sessionId,"sessionName":chatList.value[0].sessionName,"operate":"","thumbDownReason":""}) }) } + + watch( chatList, () => { @@ -504,7 +668,6 @@ const getWrite = (reader) => { for (let i = 0; i < split.length; i++) { const chunkStr = split[i]; tempResult = tempResult.replace(chunkStr, '', 1); // 修复点4:单次替换避免残留 - try { const chunk = JSON.parse(chunkStr.replace('data:', '').trim()); processChunk(chunk); @@ -512,7 +675,6 @@ const getWrite = (reader) => { console.error('解析错误:', e, chunkStr); } } - // 递归处理剩余数据 return reader.read().then(write_stream); } else { @@ -523,7 +685,6 @@ const getWrite = (reader) => { const processChunk = (chunk) => { const lastMsg = chatList.value[chatList.value.length - 1]; - console.log(chunk) // 修复点5:统一处理所有类型的数据块 if (chunk.docs?.length) { lastMsg.content.push({ content: chunk.docs, type: "docs" }); @@ -552,13 +713,15 @@ const getWrite = (reader) => { lastMsg.content.push({ content: text, type: "text" }); } } - + if (chunk.interrupt){ + lastMsg.interrupt = chunk.interrupt + } // 修复点7:统一处理结束标志 - if (chunk.isEnd || chunk.is_end) { + if (chunk.checkpointer) { + lastMsg.checkpointer = chunk.checkpointer lastMsg.isEnd = true; lastMsg.time = formatDate(new Date()); } - nextTick(() => scrollDiv.value.setScrollTop(getMaxHeight())); }; @@ -586,7 +749,7 @@ defineExpose({ diff --git a/vue-fastapi-frontend/src/views/aichat/index.vue b/vue-fastapi-frontend/src/views/aichat/index.vue index b6021ec..8bc1164 100644 --- a/vue-fastapi-frontend/src/views/aichat/index.vue +++ b/vue-fastapi-frontend/src/views/aichat/index.vue @@ -14,7 +14,7 @@

果知小助手

-
+
0)?"("+table.tab_cn_name+")":""), attrs:[], collapsed:true diff --git a/vue-fastapi-frontend/src/views/meta/metaInfo/bloodRelationSql.vue b/vue-fastapi-frontend/src/views/meta/metaInfo/bloodRelationSql.vue index 14c4a5c..0bf5afb 100644 --- a/vue-fastapi-frontend/src/views/meta/metaInfo/bloodRelationSql.vue +++ b/vue-fastapi-frontend/src/views/meta/metaInfo/bloodRelationSql.vue @@ -660,7 +660,7 @@ watch( for (let i = 0; i < props.data.tableList.length; i++) { let table = props.data.tableList[i] let g6Tab = { - id: table.ssys_id+"-"+table.mdl_name+"-"+table.tab_eng_name, + id: table.ssys_id+"-"+table.mdl_name.toLowerCase()+"-"+table.tab_eng_name.toLowerCase(), label: table.tab_eng_name + ((table.tab_cn_name && table.tab_cn_name.length>0)?"("+table.tab_cn_name+")":""), attrs:[], collapsed:true diff --git a/vue-fastapi-frontend/src/views/sqlFlow/index.vue b/vue-fastapi-frontend/src/views/sqlFlow/index.vue index 82e1d9f..aad05de 100644 --- a/vue-fastapi-frontend/src/views/sqlFlow/index.vue +++ b/vue-fastapi-frontend/src/views/sqlFlow/index.vue @@ -4,8 +4,6 @@
- - - + @@ -55,8 +53,9 @@
@@ -83,11 +82,13 @@ import cache from "@/plugins/cache"; const userStore = useUserStore() const dsSysList = userStore.dsSysList + // ========================= 数据定义 ========================= const activeColumnTab = ref('proc') -const procStr = ref('SELECT * FROM users LIMIT 100;') +const procStr = ref('') const dbType = ref('MYSQL') const containerRef = ref(null) +const childRef = ref(null) // 当前选中系统 const selectedSystem = ref(dsSysList?.[0]?.id || null) @@ -153,16 +154,15 @@ const changeBloodOption = () => { * 执行 SQL 并生成血缘分析图 */ const executeSql = async () => { + if (!selectedSystem.value) { ElMessage.warning('请选择系统') return } - if (!procStr.value.trim()) { ElMessage.warning('请输入 SQL 语句') return } - const params = { sqlType: dbType.value, defaultSystem: selectedSystem.value, @@ -171,7 +171,6 @@ const executeSql = async () => { userName: cache.local.get("username"), password: cache.local.get("password") } -console.log(params) try { ElMessage.info('正在执行血缘分析,请稍候...') const res = await runBloodAnalysisBySql(params)