From 8bb0e77ecdf5549bda02543ee789e0df7a92f925 Mon Sep 17 00:00:00 2001 From: li-shengren-123456 Date: Thu, 20 Feb 2025 14:12:28 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E8=B0=83=E8=AF=95=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E5=AD=97=E6=AE=B5=E6=9B=B4=E6=94=B9=EF=BC=8C=E4=BB=A5=E5=8F=8A?= =?UTF-8?q?=E5=B7=A5=E4=BD=9C=E6=B5=81=E7=8A=B6=E6=80=81=E5=8F=98=E6=9B=B4?= =?UTF-8?q?,=E6=B7=BB=E5=8A=A0mitt=E4=BE=9D=E8=B5=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 1 + src/assets/styles/theme.scss | 4 + src/bus/index.ts | 4 + .../dialoguePanel/DialoguePanel.vue | 5 +- src/store/conversation.ts | 103 +++++++++------ src/views/api/style.scss | 2 +- src/views/app/index.vue | 10 +- src/views/app/style.scss | 7 ++ .../components/codeMirror/nodeMirrorText.vue | 54 +++++++- src/views/createapp/components/workFlow.vue | 118 ++++++++++++++---- .../components/workFlowConfig/BranchNode.vue | 49 ++++++-- .../components/workFlowConfig/CustomNode.vue | 14 ++- .../createapp/components/workFlowDebug.vue | 2 +- .../dialogue/components/DialogueAside.vue | 1 - src/views/styles/workFlowArrange.scss | 101 ++++++++++++--- 15 files changed, 375 insertions(+), 100 deletions(-) create mode 100644 src/bus/index.ts diff --git a/package.json b/package.json index cc30675..93ed47a 100644 --- a/package.json +++ b/package.json @@ -63,6 +63,7 @@ "eslint": "9.16.0", "eslint-plugin-vue": "9.32.0", "globals": "15.13.0", + "mitt": "^3.0.1", "prettier": "3.4.2", "typescript-eslint": "8.17.0", "uuid": "^11.0.5", diff --git a/src/assets/styles/theme.scss b/src/assets/styles/theme.scss index 6cce089..6d8b29e 100644 --- a/src/assets/styles/theme.scss +++ b/src/assets/styles/theme.scss @@ -20,6 +20,8 @@ body[theme='dark'] { --flow-node-boder-default-over: #314265; --flow-node-success-over-color: #1F312A; --flow-node-error-over-color: #332127; + --flow-branch-node-error-node-cover-color: #602c27; + --flow-branch-node-success-node-cover-color: #295336; } body[theme='light'] { @@ -44,4 +46,6 @@ body[theme='light'] { --flow-node-boder-default-over: #c7d6f5; --flow-node-success-over-color: #e6f6e9; --flow-node-error-over-color: #f8e7e7; + --flow-branch-node-error-node-cover-color: #edb3b3; + --flow-branch-node-success-node-cover-color: #b3dbb8; } diff --git a/src/bus/index.ts b/src/bus/index.ts new file mode 100644 index 0000000..0020e13 --- /dev/null +++ b/src/bus/index.ts @@ -0,0 +1,4 @@ +// 引入mitt +import mitt from 'mitt' +const bus = mitt(); +export default bus; \ No newline at end of file diff --git a/src/components/dialoguePanel/DialoguePanel.vue b/src/components/dialoguePanel/DialoguePanel.vue index 7288af2..751cf80 100644 --- a/src/components/dialoguePanel/DialoguePanel.vue +++ b/src/components/dialoguePanel/DialoguePanel.vue @@ -1119,10 +1119,13 @@ const handleSendMessage = async (question, user_selected_flow, user_selected_app height: 20px; } } -// 工作流调试抽屉样式-- +// 工作流调试抽屉样式 .workFlowDebugStyle { width: auto; padding-right: 24px; + .loading { + display: none; + } .dialogue-panel__content { gap: 16px; .userArea { diff --git a/src/store/conversation.ts b/src/store/conversation.ts index 8847cae..78b0061 100644 --- a/src/store/conversation.ts +++ b/src/store/conversation.ts @@ -24,8 +24,9 @@ import { ElMessageBox } from 'element-plus'; import { qiankunWindow } from 'vite-plugin-qiankun/dist/helper'; import { storeToRefs } from 'pinia'; import { Application } from 'src/apis/paths/type'; - +import $bus from 'src/bus/index' const STREAM_URL = '/api/chat'; +const newStreamUrl = 'api/mock/chat'; let controller = new AbortController(); export var txt2imgPath = ref(""); export var echartsObj = ref({}); @@ -88,6 +89,7 @@ export const useSessionStore = defineStore('conversation', () => { user_selected_flow?: string; groupId?: string; params?: any; + type?: any; }, ind?: number ): Promise => { @@ -115,26 +117,44 @@ export const useSessionStore = defineStore('conversation', () => { pp = {}; } if (params.user_selected_flow) { - resp = await fetch(STREAM_URL, { - signal: controller.signal, - method: 'POST', - keepalive: true, - headers: headers, - body: JSON.stringify({ - question: params.question, - language, - conversationId: params.conversationId, - groupId: params.groupId, - // record_id: params.qaRecordId, - app:{ + // 之前的对话历史记录 + if (!params.type) { + resp = await fetch(STREAM_URL, { + signal: controller.signal, + method: 'POST', + keepalive: true, + headers: headers, + body: JSON.stringify({ + question: params.question, + language, + conversationId: params.conversationId, + groupId: params.groupId, + // record_id: params.qaRecordId, + app:{ + appId:params.user_selected_app[0], + flowId: params.user_selected_flow, + params: pp, + auth:{}, + }, + features:features, + }), + }); + } else { + // 新的工作流调试记录 + resp = await fetch(newStreamUrl, { + signal: controller.signal, + method: 'POST', + keepalive: true, + headers: headers, + body: JSON.stringify({ + question: params.question, appId:params.user_selected_app[0], + conversationId: params.conversationId, flowId: params.user_selected_flow, - params: pp, - auth:{}, - }, - features:features, - }), - }); + }), + }); + + } } else if (params.user_selected_app) { resp = await fetch(STREAM_URL, { @@ -239,6 +259,9 @@ export const useSessionStore = defineStore('conversation', () => { conversationItem.message[conversationItem.currentInd] += message.content.text; scrollBottom(); // conversationItem.message[conversationItem.currentInd] += message.content.text; + }else if (message["event"] === 'text') { + conversationItem.message[conversationItem.currentInd] += message.content; + scrollBottom(); } else if(message["event"] === "heartbeat") { // conversationItem.files = [...conversationItem.files, message.content]; @@ -258,17 +281,13 @@ export const useSessionStore = defineStore('conversation', () => { conversationItem.groupId = message.groupId; } else if(message["event"] === "flow.start") { - //事件流开始 - // display:boolean, - // progress:string, - // id:number - // title:string, - // data:any, + //事件流开始--后续验证对话无下拉连接后则完全替换 let flow = message.flow; conversationItem.flowdata = { - id: flow?.step_name||"", + id: flow?.stepName||"", title: i18n.global.t('flow.flow_start'), - progress: flow?.step_progresss||"", + // 工作流这里stepName代替step_progresss,为不影响首页对话暂且用|| + progress: flow?.stepProgress || "", status:'running', display:true, flowId:flow?.flowId||"", @@ -281,25 +300,25 @@ export const useSessionStore = defineStore('conversation', () => { // target.data.input = message // } conversationItem.flowdata?.data[0].push({ - id:message.flow?.step_name, - title:message.flow?.step_name, - status:message.flow?.step_status, + id:message.flow?.stepName, + title:message.flow?.stepName, + status:message.flow?.stepStatus, data:{ input:message.content, } }) if(conversationItem.flowdata){ - conversationItem.flowdata.progress = message.flow?.step_progress; - conversationItem.flowdata.status = message.flow?.step_status; + conversationItem.flowdata.progress = message.flow?.stepProgress; + conversationItem.flowdata.status = message.flow?.stepStatus; } } else if(message["event"] === "step.output") { - const target = conversationItem.flowdata?.data[0].find(item => item.id === message.flow.step_name); + const target = conversationItem.flowdata?.data[0].find(item => item.id === message.flow.stepName); if (target) { target.data.output = message.content - target.status = message.flow.step_status; + target.status = message.flow?.stepStatus; if(message.flow.step_status === "error"){ - conversationItem.flowdata.status = message.flow?.step_status; + conversationItem.flowdata.status = message.flow?.stepStatus; } } } @@ -310,15 +329,15 @@ export const useSessionStore = defineStore('conversation', () => { conversationItem.flowdata?.data[0].push({ id:"end", title:"end", - status:message.flow?.step_status, + status:message.flow?.stepStatus, data:{ input:message.content, } }) conversationItem.flowdata = { - id: flow?.step_name, + id: flow?.stepName, title: i18n.global.t('flow.flow_end'), - progress: flow?.step_progress, + progress: flow?.stepProgress, status:"success", display:true, data:conversationItem.flowdata.data, @@ -336,6 +355,10 @@ export const useSessionStore = defineStore('conversation', () => { } } }); + // 将lines传递给workflow-以更新工作流节点的状态 + if(params.user_selected_flow && params.user_selected_app) { + $bus.emit('getNodesStatue', lines); + } } } catch (err: any) { isPaused.value = true; @@ -458,11 +481,12 @@ export const useSessionStore = defineStore('conversation', () => { qaRecordId?: string, user_selected_flow?: string, params?: any, + type?: any, ): Promise => { const { updateSessionTitle, currentSelectedSession } = useHistorySessionStore(); if (conversationList.value.length === 0) { // 如果当前还没有对话记录,将第一个问题的questtion作为对话标题 - updateSessionTitle({ conversationId: currentSelectedSession, title: question.slice(0, 20) }); + const res = await updateSessionTitle({ conversationId: currentSelectedSession, title: question.slice(0, 20) }); } if (regenerateInd) { // 重新生成,指定某个回答,修改默认索引 @@ -506,6 +530,7 @@ export const useSessionStore = defineStore('conversation', () => { user_selected_flow, groupId:groupId, params:params||undefined, + type: type }, regenerateInd ?? undefined ) diff --git a/src/views/api/style.scss b/src/views/api/style.scss index b8fd4b7..7ee635a 100644 --- a/src/views/api/style.scss +++ b/src/views/api/style.scss @@ -58,7 +58,7 @@ .appCenterCardContainer { margin-top: 16px; width: fit-content; - max-width: 1328px; + max-width: 1336px; .appCenterCardBox { width: fit-content; display: flex; diff --git a/src/views/app/index.vue b/src/views/app/index.vue index a0215ee..5d2fece 100644 --- a/src/views/app/index.vue +++ b/src/views/app/index.vue @@ -35,7 +35,7 @@
-
+
+
{ }; const routerToDetail = appItem => { + if (!appItem.published && appType.value === 'createdByMe') { + return; + } //获取appItem.id & appItem.name - router.push(`/copilot?appId=${appItem.appId}&name=${encodeURIComponent(encodeURI(appItem.name))}`); + router.push(`/copilot?appId=${appItem.appId}&name=${appItem.name}`); }; const handleParmasQueryAppList = (params?: any) => { diff --git a/src/views/app/style.scss b/src/views/app/style.scss index 96eb9d7..878576c 100644 --- a/src/views/app/style.scss +++ b/src/views/app/style.scss @@ -31,6 +31,7 @@ .createApp { margin-left: 16px; + border-radius: 4px; } } @@ -155,6 +156,12 @@ ) !important; } } + .appCenterNoData { + width: 480px; + height: 240px; + background-image: var(--no-work-flow); + background-size: contain; + } } ::-webkit-scrollbar { width: 4px; diff --git a/src/views/createapp/components/codeMirror/nodeMirrorText.vue b/src/views/createapp/components/codeMirror/nodeMirrorText.vue index 4d3327d..a9a24d1 100644 --- a/src/views/createapp/components/codeMirror/nodeMirrorText.vue +++ b/src/views/createapp/components/codeMirror/nodeMirrorText.vue @@ -29,19 +29,27 @@ diff --git a/src/views/createapp/components/workFlowConfig/BranchNode.vue b/src/views/createapp/components/workFlowConfig/BranchNode.vue index adfc201..96dcb38 100644 --- a/src/views/createapp/components/workFlowConfig/BranchNode.vue +++ b/src/views/createapp/components/workFlowConfig/BranchNode.vue @@ -23,12 +23,16 @@ const props = defineProps({ }); const emits = defineEmits(['delNode', 'editYamlDrawer']); -const statusList = ref(['running', 'success', 'error']); +const statusList = ref(['pending', 'success', 'error']); const branchIdList = ref([]); +// 当前节点状态-工作流调试结果-成功/失败/运行中 const curStatus = ref(''); +// 当前节点运行耗时 +const costTime = ref(''); + watch( () => props.data, () => { @@ -38,10 +42,12 @@ watch( } else { curStatus.value = props.data?.status; } - if (props.data.parameters?.input_parameters?.input_parameters) { - branchIdList.value = props.data.parameters.input_parameters.input_parameters.choices?.choices?.map(item => item?.branchId); + costTime.value = props.data?.constTime || ''; + if (props.data?.parameters?.input_parameters?.choices) { + branchIdList.value = props.data?.parameters?.input_parameters?.choices.map( + item => item?.branchId, + ); } - console.log(props.data.parameters?.input_parameters?.input_parameters?.choices?.choices, 'props', branchIdList.value) }, { deep: true, immediate: true }, ); @@ -75,10 +81,13 @@ const editYaml = (nodeName, yamlCode) => {
{{ props.data.description }}
-
-
+
+
{{ item.description }} -
@@ -86,7 +95,13 @@ const editYaml = (nodeName, yamlCode) => {
- +
@@ -106,7 +121,7 @@ const editYaml = (nodeName, yamlCode) => { position: relative; margin-bottom: 8px; .vue-flow__handle-right { - right: -18px; + right: -30px; } &:last-child { margin-bottom: 0px; @@ -124,5 +139,21 @@ const editYaml = (nodeName, yamlCode) => { } } } + .customNodeStyle.default { + .branchDesc { + .branchItem { + .vue-flow__handle-right { + right: -18px; + } + } + } + &:hover { + .branchItem { + .vue-flow__handle-right { + right: -30px; + } + } + } + } } diff --git a/src/views/createapp/components/workFlowConfig/CustomNode.vue b/src/views/createapp/components/workFlowConfig/CustomNode.vue index 4cd53c7..0e1198e 100644 --- a/src/views/createapp/components/workFlowConfig/CustomNode.vue +++ b/src/views/createapp/components/workFlowConfig/CustomNode.vue @@ -28,8 +28,12 @@ const emits = defineEmits(['delNode', 'editYamlDrawer']); const statusList = ref(['running', 'success', 'error']); +// 当前节点状态-工作流调试结果-成功/失败/运行中 const curStatus = ref(''); +// 当前节点运行耗时 +const costTime = ref(''); + watch( () => props.data, () => { @@ -39,10 +43,12 @@ watch( } else { curStatus.value = props.data?.status; } + costTime.value = props.data?.constTime || ''; }, { deep: true, immediate: true }, ); +// 删除节点 const delNode = id => { emits('delNode', id); }; @@ -79,6 +85,12 @@ const editYaml = (nodeName, yamlCode) => {
- +
diff --git a/src/views/createapp/components/workFlowDebug.vue b/src/views/createapp/components/workFlowDebug.vue index 354efea..9e94fd9 100644 --- a/src/views/createapp/components/workFlowDebug.vue +++ b/src/views/createapp/components/workFlowDebug.vue @@ -111,7 +111,7 @@ const handleSendMessage = async (groupId: string | undefined, question: string, if (!currentSelectedSession.value) { await generateSessionDebug({ debug: true }); } - await sendQuestion(groupId, question, [props.appId], undefined, undefined, props.flowId, undefined); + await sendQuestion(groupId, question, [props.appId], undefined, undefined, props.flowId, undefined, true); }; const clearSuggestion = (index: number): void => { diff --git a/src/views/dialogue/components/DialogueAside.vue b/src/views/dialogue/components/DialogueAside.vue index 7998f2d..5c50129 100644 --- a/src/views/dialogue/components/DialogueAside.vue +++ b/src/views/dialogue/components/DialogueAside.vue @@ -50,7 +50,6 @@ const isCollapsed = ref(false); const selectedAppId = ref(null); // const apps = ref([ - { appId: "1", name: 'CVE热修复助手' }, ]); const filteredHistorySessions = computed(() => { diff --git a/src/views/styles/workFlowArrange.scss b/src/views/styles/workFlowArrange.scss index 6915c15..909414d 100644 --- a/src/views/styles/workFlowArrange.scss +++ b/src/views/styles/workFlowArrange.scss @@ -80,7 +80,7 @@ width: 312px; min-width: 256px; background-color: var(--o-bg-color-base); - padding: 24px 0px 24px 24px; + padding: 24px 4px 24px 24px; display: flex; flex-direction: column; border-radius: 8px; @@ -88,10 +88,14 @@ } .apiCenterBox { + height: 100%; + display: flex; + flex-direction: column; .apiCenterTitle { color: var(--o-text-color-primary); font-size: 16px; font-weight: 700; + line-height: 24px; } .apiCenterSearch { margin: 8px 0; @@ -108,21 +112,25 @@ } .apiContanter { - .el-collapse-item__header { - padding: 0 !important; - height: 28px; - font-size: 14px; - color: var(--o-text-color-primary); - display: flex; - gap: 8px; - text-align: left; - flex-wrap: nowrap; - .el-icon { - color: var(--o-text-color-tertiary); + flex: 1; + overflow: auto; + .el-collapse { + .el-collapse-item__header { + padding: 0 !important; + height: 28px; + font-size: 14px; + color: var(--o-text-color-primary); + display: flex; + gap: 8px; + text-align: left; + flex-wrap: nowrap; + .el-icon { + color: var(--o-text-color-tertiary); + } + } + .el-collapse-item__content { + margin-left: 0px; } - } - .el-collapse-item__content { - margin-left: 0px; } } } @@ -488,6 +496,9 @@ .outRingRight { box-shadow: 0px 0px 0px 8px rgba(36, 171, 54, 0.1); } + .leftNodeBox { + background-color: var(--flow-branch-node-success-node-cover-color); + } .leftBox { background-color: var(--flow-node-success-over-color); } @@ -542,6 +553,10 @@ } .outRingRight { box-shadow: 0px 0px 0px 8px rgba(227, 32, 32, 0.1); + display: none; + } + .leftNodeBox { + background-color: var(--flow-branch-node-error-node-cover-color); } .leftBox { background-color: var(--flow-node-error-over-color); @@ -551,6 +566,62 @@ } } } + + .customNodeStyle.running { + border: 4px solid rgba(99, 149, 253, 0.3); + box-shadow: 0px 0px 0px 8px rgba(99, 149, 253, 0.1); + .vue-flow__handle-left { + transform: rotate(-45deg); + width: 24px; + height: 24px; + left: -12px; + margin-top: -12px; + border: 4px solid rgba(99, 149, 253, 0.3); + border-right: 4px solid transparent; + border-bottom: 4px solid transparent; + &::after { + border: 4px solid rgba(99, 149, 253, 0.3); + background: rgba(99, 149, 253); + background-clip: content-box; + } + } + .vue-flow__handle-right { + width: 24px; + height: 24px; + right: -12px; + margin-top: -12px; + transform: rotate(45deg); + border: 4px solid rgba(99, 149, 253, 0.3); + border-left: 4px solid transparent; + border-bottom: 4px solid transparent; + &::after { + border: 4px solid rgba(99, 149, 253, 0.3); + background: rgba(99, 149, 253); + background-clip: content-box; + } + } + .leftBox { + background-color: transparent; + } + .rightBox { + background-color: transparent; + } + &:hover { + box-shadow: 0px 0px 0px 8px rgba(99, 149, 253, 0.1); + .outRingLeft { + box-shadow: 0px 0px 0px 8px rgba(99, 149, 253, 0.1); + } + .outRingRight { + box-shadow: 0px 0px 0px 8px rgba(99, 149, 253, 0.1); + } + .leftBox { + background-color: var(--flow-node-default-over-color); + } + .rightBox { + background-color: var(--flow-node-default-over-color); + } + } + } } .vue-flow__node:has(.default) { margin-top: 0px; -- Gitee From 51e38005bc3861ab2651e77a73a0e804383cedb7 Mon Sep 17 00:00:00 2001 From: li-shengren-123456 Date: Thu, 20 Feb 2025 14:16:51 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E5=88=A0=E5=8E=BB=E5=A4=9A=E4=BD=99?= =?UTF-8?q?=E6=94=B9=E5=8A=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/store/conversation.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/store/conversation.ts b/src/store/conversation.ts index 78b0061..a962de8 100644 --- a/src/store/conversation.ts +++ b/src/store/conversation.ts @@ -259,9 +259,6 @@ export const useSessionStore = defineStore('conversation', () => { conversationItem.message[conversationItem.currentInd] += message.content.text; scrollBottom(); // conversationItem.message[conversationItem.currentInd] += message.content.text; - }else if (message["event"] === 'text') { - conversationItem.message[conversationItem.currentInd] += message.content; - scrollBottom(); } else if(message["event"] === "heartbeat") { // conversationItem.files = [...conversationItem.files, message.content]; -- Gitee