diff --git a/config/unplugin/auto-import.ts b/config/unplugin/auto-import.ts index 91f9266..5b72bd4 100644 --- a/config/unplugin/auto-import.ts +++ b/config/unplugin/auto-import.ts @@ -29,7 +29,10 @@ export function configAutoImport() { 'merge', 'debounce', 'isEqual', - 'isString' + 'isString', + 'isArray', + 'findLast', + 'findLastIndex', ], '@/hooks': ['useModal'], }, diff --git a/src/components/xt-chat/chat-view/components/right-view/index.vue b/src/components/xt-chat/chat-view/components/right-view/index.vue index a684099..e56e9d6 100644 --- a/src/components/xt-chat/chat-view/components/right-view/index.vue +++ b/src/components/xt-chat/chat-view/components/right-view/index.vue @@ -2,9 +2,11 @@ import { Button } from '@arco-design/web-vue'; import { Bubble } from '@/components/xt-chat/xt-bubble'; +import Http from '@/api'; import { downloadByUrl } from '@/utils/tools'; import markdownit from 'markdown-it'; import { message } from 'ant-design-vue'; +import { FILE_TYPE } from '@/components/xt-chat/chat-view/constants'; export default { emits: ['close'], @@ -21,8 +23,6 @@ export default { setup(props, { emit, expose }) { const bubbleRef = ref(null); - console.log(props.rightViewInfo) - const md = markdownit({ html: true, breaks: true, @@ -30,15 +30,44 @@ export default { typographer: true, }); + const tasks = computed(() => { + return props.rightViewInfo.payload?.tasks ?? []; + }); + + const isTaskManage = computed(() => { + return props.rightViewInfo.task_type === '任务管理'; + }); + const isMediaCenter = computed(() => { + return props.rightViewInfo.task_type === '素材中心'; + }); + const onDownload = () => { // downloadByUrl(''); message.success('下载成功!'); }; const onAddMediaCenter = () => { - message.success('成功添加至“素材中心”模块。'); + const { + api: { endpoint, method }, + payload, + } = props.rightViewInfo; + Http[method.toLowerCase()]?.(endpoint, payload).then((res) => { + const { code } = res; + if (code === 200) { + message.success('成功添加至“素材中心”模块。'); + } + }); }; const onAddTaskManage = () => { - message.success('成功添加至“任务管理”模块。'); + const { + api: { endpoint, method }, + payload, + } = props.rightViewInfo; + Http[method.toLowerCase()]?.(endpoint, payload).then((res) => { + const { code } = res; + if (code === 200) { + message.success('成功添加至“任务管理”模块。'); + } + }); }; const abortTyping = () => { bubbleRef.value?.abortTyping?.(); @@ -46,25 +75,30 @@ export default { const renderHeader = () => { return (
- - - + )} + + {isTaskManage.value && ( + + )} + {/* + */}
emit('close')} />
); }; + const renderTaskManage = () => { + const { file_type } = props.rightViewInfo; + return tasks.value.map((item) => { + const { params, execution_time, name } = item; + if (file_type === FILE_TYPE.topic_only) { + return ( +
+

{params?.media_account ?? '-'}

+

{`- ${execution_time}:${name}`}

+
+ ); + } else if (file_type === FILE_TYPE.topic_with_content) { + return ( +
+

{`${params.media_account}(${params.platform})`}

+

{`日期:${execution_time}`}

+

{`选题:${params.topic}`}

+

{`标题${name}`}

+

{`正文:${params.content}`}

+
+ ); + } + return null; + }); + }; + const renderMediaCenter = () => { + return tasks.value.map((item) => { + const { params, execution_time, name, content } = item; + const { file_type } = props.rightViewInfo; + if (file_type === FILE_TYPE.content_only) { + return ( +
+

{params?.media_account ?? '-'}

+

📅 {`${execution_time}`}

+

📝 {`${name}`}

+

正文:

+

📝 {`${content}`}

+
+ ); + } else if (file_type === FILE_TYPE.topic_with_content) { + return ( +
+

{`${params.media_account}(${params.platform})`}

+

{`日期:${execution_time}`}

+

{`选题:${params.topic}`}

+

{`标题${name}`}

+

{`正文:${params.content}`}

+
+ ); + } + }); + }; const renderContainer = () => { + const renderMessage = () => { + if (isTaskManage.value) { + return renderTaskManage(); + } + if (isMediaCenter.value) { + return renderMediaCenter(); + } + return null; + }; return (
{ console.log('onTypingComplete'); }} - messageRender={(content) =>
} + messageRender={() => { + return renderMessage(); + }} />
); diff --git a/src/components/xt-chat/chat-view/constants.ts b/src/components/xt-chat/chat-view/constants.ts index c5575e6..0eecc2d 100644 --- a/src/components/xt-chat/chat-view/constants.ts +++ b/src/components/xt-chat/chat-view/constants.ts @@ -41,3 +41,14 @@ export enum EnumTeamRunStatus { RunResponseContent = 'RunResponseContent', // l2执行中 RunCompleted = 'RunCompleted', // l2完成 } + +export const FILE_TYPE = { + topic_only: 'topic_only', // 排期&选题 + topic_with_content: 'topic_with_content', // 选题&内容稿件 + content_only: 'content_only', // 内容稿件 +} +export const FILE_TYPE_MAP = { + [FILE_TYPE.topic_only]: '排期&选题', + [FILE_TYPE.topic_with_content]: '选题&内容稿件', + [FILE_TYPE.content_only]: '内容稿件', +} \ No newline at end of file diff --git a/src/components/xt-chat/chat-view/index.vue b/src/components/xt-chat/chat-view/index.vue index 0eb1db1..c05aa49 100644 --- a/src/components/xt-chat/chat-view/index.vue +++ b/src/components/xt-chat/chat-view/index.vue @@ -27,6 +27,7 @@ export default { const rightViewRef = ref(null); const bubbleListRef = ref(null); const sseController = ref(null); + const searchValue = ref(''); const conversationId = computed(() => { return route.params.conversationId; diff --git a/src/components/xt-chat/chat-view/useChatHandler.tsx b/src/components/xt-chat/chat-view/useChatHandler.tsx index cf493a6..cc3357a 100644 --- a/src/components/xt-chat/chat-view/useChatHandler.tsx +++ b/src/components/xt-chat/chat-view/useChatHandler.tsx @@ -3,7 +3,14 @@ import { ref } from 'vue'; import type { BubbleListProps } from '@/components/xt-chat/xt-bubble/types'; import markdownit from 'markdown-it'; import { message as antdMessage, Timeline } from 'ant-design-vue'; -import { IconFile, IconCaretUp, IconDownload, IconRefresh, IconCopy } from '@arco-design/web-vue/es/icon'; +import { + IconFile, + IconCaretUp, + IconDownload, + IconCaretDown, + IconRefresh, + IconCopy, +} from '@arco-design/web-vue/es/icon'; import { Tooltip } from 'ant-design-vue'; import TextOverTips from '@/components/text-over-tips/index.vue'; @@ -131,13 +138,12 @@ export default function useChatHandler({ initSse }): UseChatHandlerReturn { }; // 最终结果处理 - const handleFileReview = (data: MESSAGE.Answer) => { - const { run_id, output } = data; + const handleFileReview = (extra_data: { type: string; data: any }) => { + console.log('handleFileReview', extra_data); + const { type, data } = extra_data; showRightView.value = true; - - // const _files = output?.files; - // rightViewInfo.value = _files?.[0]?.content || ''; + rightViewInfo.value = data?.[0] ?? {}; // conversationList.value.push({ // run_id, @@ -168,28 +174,45 @@ export default function useChatHandler({ initSse }): UseChatHandlerReturn { initSse({ message: senderRef.value?.searchValue }); }; - // 获取同一个对话下的最后一个run_task - const getLastRunTask = (data: MESSAGE.Answer, teamRunTaskId: string) => { - const allRunTask = conversationList.value.filter( - (item) => item.role === ANSWER_ROLE && item.team_run_id === teamRunTaskId && !item.isTeamRunTask, + const getAllRunTask = (teamRunTaskId: string) => { + return conversationList.value.filter( + (item) => item.role === ANSWER_ROLE && item.teamRunTaskId === teamRunTaskId && !item.isTeamRunTask, ); + }; + const getRunTask = (run_id: string) => { + return conversationList.value.find((item) => item.run_id === run_id && !item.isTeamRunTask); + }; + // 设置当前对话所有过程任务展开收起状态 + const setRunTaskCollapse = (teamRunTaskId: string, isCollapse: boolean) => { + getAllRunTask(teamRunTaskId).forEach((item) => { + item.content.isCollapse = isCollapse; + }); + }; + // 获取同一个对话下的最后一个run_task + const getLastRunTask = (teamRunTaskId: string) => { + const allRunTask = getAllRunTask(teamRunTaskId); return allRunTask[allRunTask.length - 1] ?? {}; }; - const getFirstRunTask = (data: MESSAGE.Answer, teamRunTaskId: string) => { - const allRunTask = conversationList.value.filter( - (item) => item.role === ANSWER_ROLE && item.team_run_id === teamRunTaskId && !item.isTeamRunTask, - ); + const getFirstRunTask = (teamRunTaskId: string) => { + const allRunTask = getAllRunTask(teamRunTaskId); return allRunTask[0] ?? {}; }; + // 判断当前对话是否含有过程任务 + const hasRunTask = (teamRunTaskId: string) => { + return conversationList.value.some((item) => item.teamRunTaskId === teamRunTaskId && !item.isTeamRunTask); + }; + + const getTeamRunTask = (teamRunTaskId: string) => { + return conversationList.value.find((item) => item.teamRunTaskId === teamRunTaskId); + }; const isLastRunTask = (data: MESSAGE.Answer, teamRunTaskId: string): boolean => { const { run_id } = data; - return getLastRunTask(data, teamRunTaskId).run_id === run_id; + return getLastRunTask(teamRunTaskId).run_id === run_id; }; const isFirstRunTask = (data: MESSAGE.Answer, teamRunTaskId: string): boolean => { const { run_id } = data; - return getFirstRunTask(data, teamRunTaskId).run_id === run_id; + return getFirstRunTask(teamRunTaskId).run_id === run_id; }; - const isLastTeamRunTask = (data: MESSAGE.Answer) => { const { run_id } = data; const lastElement = conversationList.value[conversationList.value.length - 1]; @@ -203,28 +226,47 @@ export default function useChatHandler({ initSse }): UseChatHandlerReturn { conversationList.value.push({ run_id, key: run_id, - team_run_id: lastTeamRunTaskId.value, - content: data, + teamRunTaskId: lastTeamRunTaskId.value, + content: { ...data, runStatus: EnumTeamRunStatus.RunStarted }, output: data.output, role: ANSWER_ROLE, messageRender: (data: MESSAGE.Answer) => { + const { node, output, runStatus, isCollapse = true } = data; + const isRulCompleted = runStatus === EnumTeamRunStatus.RunCompleted; + + // console.log('messageRender', isCollapse); let outputEleClass: string = `thought-chain-output border-l-#E6E6E8 border-l-1px pl-12px relative left-6px mb-4px`; !isLastRunTask(data, lastTeamRunTaskId.value) && (outputEleClass += ' hasLine pb-12px pt-4px'); + return ( <> {isFirstRunTask(data, lastTeamRunTaskId.value) && (
智能思考 - + {isCollapse ? ( + setRunTaskCollapse(lastTeamRunTaskId.value, false)} + /> + ) : ( + setRunTaskCollapse(lastTeamRunTaskId.value, true)} + /> + )}
)} -
-
- -
{data.node}
+ {isCollapse && ( +
+
+ +
{node}
+
+
-
-
+ )} ); }, @@ -237,31 +279,32 @@ export default function useChatHandler({ initSse }): UseChatHandlerReturn { const existingItem = conversationList.value.find((item) => item.run_id === run_id); if (existingItem && output) { existingItem.content.output += output; + existingItem.content.runStatus = EnumTeamRunStatus.RunResponseContent; } }; // 过程节点结束 const handleRunTaskEnd = (data: MESSAGE.Answer) => { - const { run_id, output } = data; + const { output } = data; - const existingItem = conversationList.value.find((item) => item.run_id === run_id); + const existingItem = getRunTask(data.run_id); if (existingItem) { existingItem.content.output += output; + existingItem.content.runStatus = EnumTeamRunStatus.RunCompleted; } }; // 任务开始 const handleTeamRunTaskStart = (data: MESSAGE.Answer) => { - // console.log('handleRunTaskStart'); const { run_id } = data; lastTeamRunTaskId.value = run_id; currentTaskId.value = run_id; conversationList.value.push({ run_id, isTeamRunTask: true, - team_run_id: lastTeamRunTaskId.value, + teamRunTaskId: lastTeamRunTaskId.value, key: run_id, - content: data, + content: { ...data, teamRunStatus: EnumTeamRunStatus.TeamRunStarted }, output: data.output, role: ANSWER_ROLE, messageRender: (data: MESSAGE.Answer) => { @@ -275,42 +318,52 @@ export default function useChatHandler({ initSse }): UseChatHandlerReturn { const existingItem = conversationList.value.find((item) => item.run_id === run_id); if (existingItem && output) { existingItem.content.output += output; + existingItem.content.teamRunStatus = EnumTeamRunStatus.TeamRunResponseContent; } }; // 任务结束 const handleTeamRunTaskEnd = (data: MESSAGE.Answer) => { - const { run_id, team_session_state } = data; - - const lastRunTask = getLastRunTask(data, lastTeamRunTaskId.value); - resetGenerateStatus(); - console.log('handleTeamRunTaskEnd', { data }, { lastRunTask }); - if (lastRunTask) { - lastRunTask.footer = () => { - return ( -
- onCopy(lastRunTask.content.output)}> + const { run_id, extra_data } = data; + const _hasRunTask = hasRunTask(lastTeamRunTaskId.value); + const _targetTask = _hasRunTask ? getLastRunTask(run_id) : getTeamRunTask(lastTeamRunTaskId.value); + + if (isEmpty(_targetTask)) { + return; + } + + if (_hasRunTask) { + setRunTaskCollapse(lastTeamRunTaskId.value, false); + } else { + _targetTask.content.teamRunStatus = EnumTeamRunStatus.TeamRunCompleted; + } + + if (extra_data) { + handleFileReview(extra_data); + } + _targetTask.footer = () => { + return ( +
+ {!extra_data + // ? ( + // + // + // + // ) : + && ( + onCopy(_targetTask.content.output)}> - {team_session_state && ( - - - - )} - {isLastTeamRunTask(data) && ( - onRefresh(run_id)}> - - - )} -
- ); - }; - } - - if (team_session_state) { - handleFileReview(data); - } + )} + {isLastTeamRunTask(data) && ( + onRefresh(run_id)}> + + + )} +
+ ); + }; }; // 消息处理主函数 diff --git a/src/types/message.ts b/src/types/message.ts index d8e3c3c..d99dfc2 100644 --- a/src/types/message.ts +++ b/src/types/message.ts @@ -1,25 +1,22 @@ declare global { namespace MESSAGE { - type TASK_STATUS = - | 'RunStarted' - | 'RunResponseContent' - | 'RunCompleted' - | 'TeamRunStarted' - | 'TeamRunResponseContent' - | 'TeamRunCompleted'; + type RUN_TASK_STATUS = 'RunStarted' | 'RunResponseContent' | 'RunCompleted'; + type TEAM_RUN_TASK_STATUS = 'TeamRunStarted' | 'TeamRunResponseContent' | 'TeamRunCompleted'; interface Answer { - message: string; - node: string; - output: string; - run_id: string; - team_run_id: string; - status: TASK_STATUS; - extra_data: { + message?: string; + node?: string; + output?: string; + run_id?: string; + teamRunTaskId?: string; + isCollapse?: boolean; + status?: RUN_TASK_STATUS | TEAM_RUN_TASK_STATUS; + runStatus?: RUN_TASK_STATUS; + teamRunStatus?: TEAM_RUN_TASK_STATUS; + extra_data?: { type: string; data: Record; }; - team_session_state: any; } } }