diff --git a/src/api/ai/aiChatList/model/index.ts b/src/api/ai/aiChatList/model/index.ts index 361fa08..653e4b9 100644 --- a/src/api/ai/aiChatList/model/index.ts +++ b/src/api/ai/aiChatList/model/index.ts @@ -28,6 +28,10 @@ export interface AiChatList { updateTime?: string; // title?: string; + // 记录类型:chat / writing / image / creative / activity_outline + chatType?: string; + // 生成记录入参快照(JSON 字符串,可能为 null) + params?: string; } /** @@ -43,5 +47,6 @@ export interface AiChatListParam extends PageParam { status?: number; deleted?: number; title?: string; + chatType?: string; keywords?: string; } diff --git a/src/utils/ai-chat-type.ts b/src/utils/ai-chat-type.ts new file mode 100644 index 0000000..02da8c7 --- /dev/null +++ b/src/utils/ai-chat-type.ts @@ -0,0 +1,42 @@ +/** + * AI 历史记录的类型(对应后端 `ai_chat_list.chat_type`)。 + * + * 契约见 `docs/ai-history-contract.md`:类型由后端在生成成功时判定,前端只负责展示与筛选。 + * 旧数据没有 `chat_type`,按聊天处理。 + */ + +export type AiChatType = + | 'chat' + | 'writing' + | 'image' + | 'creative' + | 'activity_outline'; + +/** 类型的中文名(徽标与后台表格共用) */ +export const AI_CHAT_TYPE_LABELS: Record = { + chat: '聊天', + writing: '写作', + image: '图片', + creative: '创意', + activity_outline: '活动策划' +}; + +/** 筛选下拉的可选项(不含「全部」,由使用方按需补充) */ +export const AI_CHAT_TYPE_OPTIONS: { label: string; value: AiChatType }[] = [ + { label: '聊天', value: 'chat' }, + { label: '写作', value: 'writing' }, + { label: '图片', value: 'image' }, + { label: '创意', value: 'creative' }, + { label: '活动策划', value: 'activity_outline' } +]; + +/** 把后端返回值收敛到已知类型,缺失或未知一律按聊天处理 */ +export function resolveAiChatType(value?: string | null): AiChatType { + const type = String(value || '').trim() as AiChatType; + return type in AI_CHAT_TYPE_LABELS ? type : 'chat'; +} + +/** 直接取中文名,用于模板与表格列 */ +export function getAiChatTypeLabel(value?: string | null): string { + return AI_CHAT_TYPE_LABELS[resolveAiChatType(value)]; +} diff --git a/src/utils/ai-stream.ts b/src/utils/ai-stream.ts index 49e9571..7edc60f 100644 --- a/src/utils/ai-stream.ts +++ b/src/utils/ai-stream.ts @@ -148,6 +148,28 @@ export function streamCreativeAssistant( }); } +/** + * 末帧 `result` 是普通接口的完整响应包(`{code, message, data}`)。 + * 生成成功后后端会在包里带上 `chatId`(见 `docs/ai-history-contract.md`), + * 既可能在包上也可能在 `data` 里;这里统一把它合并进返回的 data, + * 页面只读 `result.chatId` 即可。 + */ +function unwrapFinalData(finalResult: any) { + const data = finalResult?.data ?? null; + const chatId = Number(finalResult?.chatId); + if ( + data && + typeof data === 'object' && + !Array.isArray(data) && + Number.isFinite(chatId) && + chatId > 0 && + data.chatId == null + ) { + data.chatId = chatId; + } + return data; +} + /** * 创意助手(出图/出视频):跑完才有结果,中途一个字节都不推。 * @@ -181,7 +203,7 @@ export async function runCreativeAssistantStream( if (Number(finalResult.code) !== 0) { throw new Error(finalResult.message || '创意助手处理失败'); } - return finalResult.data ?? null; + return unwrapFinalData(finalResult); } /** @@ -224,5 +246,5 @@ export async function runManuscriptGenStream( if (Number(finalResult.code) !== 0) { throw new Error(finalResult.message || '稿件生成失败'); } - return finalResult.data ?? null; + return unwrapFinalData(finalResult); } diff --git a/src/views/ai/aiChatList/components/search.vue b/src/views/ai/aiChatList/components/search.vue index 82fea9d..f8cf842 100644 --- a/src/views/ai/aiChatList/components/search.vue +++ b/src/views/ai/aiChatList/components/search.vue @@ -1,6 +1,14 @@