diff --git a/src/pages/activity-outline/index.vue b/src/pages/activity-outline/index.vue index 1e55aca..9e1bfc0 100644 --- a/src/pages/activity-outline/index.vue +++ b/src/pages/activity-outline/index.vue @@ -9,6 +9,7 @@ 志愿服务 主题沙龙 校园赛事 + 历史记录 @@ -458,6 +459,18 @@ this.form.event_type = '校园赛事 + 开幕仪式 + 分组淘汰赛' this.form.event_location = '学校室外篮球场' this.form.event_meme = '需要体现赛事组织、赛程安排、安全保障、医疗预案和宣传报道计划。' + }, + /** + * 历史记录统一在助手页查看。 + * + * 助手页是 tabBar 页,`switchTab` 不能带参数,所以先把类型筛选 + * 写进 storage,助手页 onShow 读取后立即清除。 + */ + goHistoryPage() { + uni.setStorageSync('ai_history_type', 'activity_outline') + uni.switchTab({ + url: '/pages/assistant/index' + }) } } } diff --git a/src/pages/assistant/chat-service.js b/src/pages/assistant/chat-service.js index e92bcf6..665883c 100644 --- a/src/pages/assistant/chat-service.js +++ b/src/pages/assistant/chat-service.js @@ -370,6 +370,14 @@ export function apiRequest({ }) } +/** + * 历史记录列表。 + * + * @param {object} [params] + * @param {string} [params.chatType] 可选,按记录类型精确筛选: + * `chat` / `writing` / `image` / `creative` / `activity_outline`; + * 不传则返回该用户全部类型的记录(助手页即拉全量后在前端过滤)。 + */ export function listAiChatList(params) { return apiRequest({ url: `${MODULES_API_URL}/ai/ai-chat-list`, diff --git a/src/pages/assistant/index.vue b/src/pages/assistant/index.vue index fafe8e0..b8d39e3 100644 --- a/src/pages/assistant/index.vue +++ b/src/pages/assistant/index.vue @@ -45,7 +45,7 @@ > 请先登录后使用 AI 助手 - 当前页面已接入真实会话逻辑,发送消息和历史会话依赖登录态。 + 当前页面已接入真实会话逻辑,发送消息和历史记录依赖登录态。 @@ -262,38 +262,91 @@ - 历史会话 - 按最近更新时间展示 + 历史记录 + 仅展示最近 30 条,按更新时间排序 关闭 + + + + {{ option.label }} + + + {{ section.label }} - - - {{ getHistoryTitle(item) }} - - {{ formatHistoryItemTime(item.createTime) }} + + + + + {{ getHistoryTypeLabel(item) }} + {{ getHistoryTitle(item) }} + + + {{ formatHistoryItemTime(item.createTime) }} + + + + {{ deletingChatId === item.id ? '删除中' : '删除' }} - - {{ deletingChatId === item.id ? '删除中' : '删除' }} + + + + + 记录详情 + 收起 + + 正在加载记录… + - 暂无历史对话 + 暂无历史记录 @@ -334,6 +387,36 @@ { label: '写作', value: 'writing' }, { label: '图片', value: 'image' } ] + /* + 历史记录的类型(后端 chat_type)。旧数据没有 chat_type,按 chat 处理。 + 「全部」只用于筛选,不是一种记录类型。 + */ + const HISTORY_TYPE_OPTIONS = [ + { label: '全部', value: 'all' }, + { label: '聊天', value: 'chat' }, + { label: '写作', value: 'writing' }, + { label: '图片', value: 'image' }, + { label: '创意', value: 'creative' }, + { label: '活动策划', value: 'activity_outline' } + ] + const HISTORY_TYPE_META = { + chat: { label: '聊天', replayable: false }, + writing: { label: '写作', replayable: true }, + image: { label: '图片', replayable: true }, + creative: { label: '创意', replayable: false }, + activity_outline: { label: '活动策划', replayable: false } + } + /* 独立页 switchTab 不能带参,类型经 storage 传进来(见接口契约 §6) */ + const HISTORY_TYPE_STORAGE_KEY = 'ai_history_type' + + /** 每个模式各自的工作区:消息、当前记录、草稿互不干扰 */ + const createWorkspace = () => ({ + messageList: [], + activeChatId: null, + activeConversationId: '', + streamingMessageId: '', + draft: '' + }) // 图片比例选择器已撤掉:上游创意助手开始节点没有比例变量(实测只有 user_content / // user_files),前端只能把它拼进 user_content —— 那是替上游写 prompt。 // 要恢复这个功能,先在上游开始节点加变量,再按变量契约接上来。 @@ -362,8 +445,13 @@ participants: '' }, statusBarHeight: 0, - draft: '', activeChatMode: 'chat', + // 三个模式各自独立的工作区:切换模式不丢消息、当前记录与草稿 + workspaces: { + chat: createWorkspace(), + writing: createWorkspace(), + image: createWorkspace() + }, loading: false, wsConnected: false, scrollIntoView: '', @@ -374,11 +462,12 @@ '优化竞赛申报书摘要', '整理五四评优申报材料清单' ], - messageList: [], historyList: [], - activeChatId: null, - activeConversationId: '', - streamingMessageId: '', + // 历史面板的类型筛选,默认「全部」 + historyTypeFilter: 'all', + historyTypeOptions: HISTORY_TYPE_OPTIONS, + // 面板内展开的非聊天记录详情(含写作 / 图片的「再来一次」) + historyPreview: null, showHistoryPanel: false, deletingChatId: null, currentUser: { @@ -394,6 +483,50 @@ } }, computed: { + /** 当前模式的工作区;模板里的 messageList / draft 等都指向它 */ + workspace() { + return this.workspaces[this.activeChatMode] || this.workspaces.chat + }, + messageList: { + get() { + return this.workspace.messageList + }, + set(value) { + this.workspace.messageList = value + } + }, + draft: { + get() { + return this.workspace.draft + }, + set(value) { + this.workspace.draft = value + } + }, + activeChatId: { + get() { + return this.workspace.activeChatId + }, + set(value) { + this.workspace.activeChatId = value + } + }, + activeConversationId: { + get() { + return this.workspace.activeConversationId + }, + set(value) { + this.workspace.activeConversationId = value + } + }, + streamingMessageId: { + get() { + return this.workspace.streamingMessageId + }, + set(value) { + this.workspace.streamingMessageId = value + } + }, navbarTotalHeight() { return this.statusBarHeight + 44 }, @@ -472,6 +605,9 @@ return 'AI 助手待命中' }, activeHistoryKey() { + if (this.historyPreview && this.historyPreview.key) { + return this.historyPreview.key + } if (this.activeChatId) { return `chat-${this.activeChatId}` } @@ -491,9 +627,18 @@ ) return target ? this.getHistoryTitle(target) : '当前会话' }, + /** 类型筛选之后的历史记录(全部类型时不复制数组) */ + historyFilteredList() { + if (this.historyTypeFilter === 'all') { + return this.historyList + } + return this.historyList.filter( + (item) => this.getHistoryType(item) === this.historyTypeFilter + ) + }, historySections() { const groupMap = {} - ;[...this.historyList] + ;[...this.historyFilteredList] .sort((left, right) => this.getTimestamp(right.updateTime || right.createTime) - this.getTimestamp(left.updateTime || left.createTime)) .forEach((item) => { const label = this.getHistoryDateLabel(item.createTime || item.updateTime) @@ -502,10 +647,6 @@ } groupMap[label].push(item) }) - console.log(Object.keys(groupMap).map((label) => ({ - label, - items: groupMap[label] - }))) return Object.keys(groupMap).map((label) => ({ label, items: groupMap[label] @@ -518,13 +659,15 @@ }, onShow() { this.refreshUser() + // 独立页经 storage 传来的类型:预置筛选并直接打开历史面板 + const fromHistoryEntry = this.applyPendingHistoryType() if (!this.initialized) { - this.initAssistant() + this.initAssistant(!fromHistoryEntry) return } if (this.currentUser.userId) { this.loadHistoryList(false).catch((error) => { - this.showError(error, '刷新历史会话失败') + this.showError(error, '刷新历史记录失败') }) } }, @@ -542,19 +685,45 @@ } return this.currentUser }, - async initAssistant() { + async initAssistant(autoSelect = true) { try { this.refreshUser() if (!this.currentUser.userId) { return } - await this.loadHistoryList(true) + await this.loadHistoryList(autoSelect) } catch (error) { this.showError(error, '初始化聊天页失败') } finally { this.initialized = true } }, + /** + * 读取独立页写入的类型筛选。 + * + * 小程序 `switchTab` 不能带参,所以「文稿 / 创意 / 活动策划」页先 + * `setStorageSync('ai_history_type', ...)` 再跳过来;这里读完立即清掉, + * 避免下次从 tabBar 进来又莫名带上筛选。 + * + * @returns {boolean} 是否由独立页的历史入口跳转而来 + */ + applyPendingHistoryType() { + let pendingType = '' + try { + pendingType = uni.getStorageSync(HISTORY_TYPE_STORAGE_KEY) + } catch (error) { + pendingType = '' + } + if (!pendingType) { + return false + } + uni.removeStorageSync(HISTORY_TYPE_STORAGE_KEY) + const matched = Object.keys(HISTORY_TYPE_META).indexOf(pendingType) > -1 + this.historyTypeFilter = matched ? pendingType : 'all' + this.historyPreview = null + this.showHistoryPanel = true + return true + }, showToast(title) { uni.showToast({ title, @@ -649,6 +818,33 @@ } return '未命名对话' }, + /** 记录类型;旧数据没有 chatType,按 chat 处理 */ + getHistoryType(item) { + const value = String((item && item.chatType) || 'chat').trim() + return HISTORY_TYPE_META[value] ? value : 'chat' + }, + getHistoryTypeLabel(item) { + const type = this.getHistoryType(item) + return (HISTORY_TYPE_META[type] && HISTORY_TYPE_META[type].label) || '聊天' + }, + /** 只有写作 / 图片记录能回填原参数「再来一次」 */ + canReplayHistory(item) { + const type = this.getHistoryType(item) + return !!(HISTORY_TYPE_META[type] && HISTORY_TYPE_META[type].replayable) + }, + pickHistoryType(value) { + if (this.historyTypeFilter === value) { + return + } + this.historyTypeFilter = value + this.historyPreview = null + }, + isHistoryPreview(item) { + return !!this.historyPreview && this.historyPreview.key === this.getHistoryKey(item) + }, + closeHistoryPreview() { + this.historyPreview = null + }, parseAssistantContent(value) { if (!value || value === ASSISTANT_PENDING_TEXT) { return { @@ -737,6 +933,8 @@ return } this.activeChatMode = mode + // 切回某个模式时,该模式自己的消息区滚到底部 + this.scrollToBottom() }, scrollToBottom() { this.bottomAnchorId = `chat-bottom-${Date.now()}` @@ -806,10 +1004,19 @@ target.content === ASSISTANT_PENDING_TEXT ? answer : `${target.content}${answer}` this.scrollToBottom() }, - async finishAssistantMessage(conversationId) { + /** + * 聊天收尾:刷新历史并认领后端回传的记录 id。 + * + * @param {string} [conversationId] 上游会话标识 + * @param {number|string} [chatId] `__END__` 帧新增的记录 id(仅成功写入时出现) + */ + async finishAssistantMessage(conversationId, chatId) { if (conversationId) { this.activeConversationId = conversationId } + if (chatId !== undefined && chatId !== null && chatId !== '') { + this.activeChatId = chatId + } const target = this.messageList.find((item) => item.id === this.streamingMessageId) if (target) { target.loading = false @@ -846,7 +1053,8 @@ try { const data = JSON.parse(raw) if (data && data.answer === '__END__') { - await this.finishAssistantMessage(data.conversationId) + // 末帧带后端刚写入的记录 id(失败态没有);带上它才能高亮对应记录 + await this.finishAssistantMessage(data.conversationId, data.chatId) this.disconnectWebSocket() return } @@ -963,40 +1171,186 @@ !this.activeConversationId && this.historyList.length ) { - await this.selectChat(this.historyList[0], true) + // 只自动打开聊天记录:其他类型没有会话,进面板看详情即可 + const firstChat = this.historyList.find( + (item) => this.getHistoryType(item) === 'chat' + ) + if (firstChat) { + await this.selectChat(firstChat, true) + } } }, - async loadChatHistory(item) { + async fetchHistoryMessages(item) { const { userId } = this.refreshUser() const response = await listAiChatHistory({ chatId: item.id, conversationId: item.conversationId, userId }) - this.messageList = this.formatHistoryMessages(Array.isArray(response) ? response : []) + return this.formatHistoryMessages(Array.isArray(response) ? response : []) + }, + async loadChatHistory(item) { + this.messageList = await this.fetchHistoryMessages(item) this.scrollToBottom() }, async selectChat(item, silent = false) { if (this.loading && !silent) { - this.showToast('当前正在生成回复,请稍后再切换会话') + this.showToast('当前正在生成回复,请稍后再切换记录') return } + // 聊天记录打开会话;其余类型在面板内展开详情 + if (this.getHistoryType(item) !== 'chat') { + await this.openHistoryPreview(item) + return + } + this.historyPreview = null + this.activeChatMode = 'chat' this.activeChatId = item.id || null this.activeConversationId = item.conversationId || '' this.showHistoryPanel = false await this.loadChatHistory(item) }, + /** 非聊天记录的面板内详情(写作 / 图片另带「再来一次」) */ + async openHistoryPreview(item) { + const key = this.getHistoryKey(item) + // 再点同一条即收起 + if (this.historyPreview && this.historyPreview.key === key && !this.historyPreview.loading) { + this.historyPreview = null + return + } + this.historyPreview = { + key, + item, + messages: [], + loading: true + } + try { + const messages = await this.fetchHistoryMessages(item) + if (!this.historyPreview || this.historyPreview.key !== key) { + return + } + this.historyPreview.messages = messages + } catch (error) { + if (this.historyPreview && this.historyPreview.key === key) { + this.historyPreview = null + this.showError(error, '加载历史记录失败') + } + } finally { + if (this.historyPreview && this.historyPreview.key === key) { + this.historyPreview.loading = false + } + } + }, + /** 解析后端 `params`(入参快照 JSON,老记录为空) */ + parseHistoryParams(value) { + if (!value) { + return {} + } + if (typeof value === 'object') { + return value + } + try { + const parsed = JSON.parse(String(value)) + return parsed && typeof parsed === 'object' ? parsed : {} + } catch (error) { + return {} + } + }, + /** 老记录没有 params 时,退回详情里的用户原话(再退回标题) */ + historyRecordInput(item) { + const messages = (this.historyPreview && this.historyPreview.messages) || [] + const userMessage = messages.find((message) => this.isUserMessage(message)) + if (userMessage && String(userMessage.content || '').trim()) { + return String(userMessage.content || '').trim() + } + return String((item && item.title) || '').trim() + }, + /** + * 按原参数再来一次:只回填参数与输入框,不自动发送。 + * + * 写作回填文体 / 字数 / 写作参数 / 正文(自由创作回填 userContent), + * 图片回填提示词;创意与活动策划没有可回填的界面参数,只读。 + */ + replayHistoryItem(item) { + const type = this.getHistoryType(item) + if (!this.canReplayHistory(item)) { + this.showToast('该记录仅可查看') + return + } + const params = this.parseHistoryParams(item.params) + if (type === 'writing') { + this.fillWritingFromHistory(item, params) + } else { + this.fillImageFromHistory(item, params) + } + this.activeChatMode = type + this.showHistoryPanel = false + this.historyPreview = null + this.showToast('已按原参数回填,可修改后发送') + }, + fillWritingFromHistory(item, params) { + const docType = String(params.docType || params.doc_type || '').trim() + this.writingDocType = + docType && docType !== WRITING_DOC_TYPE_FREE ? docType : WRITING_DOC_TYPE_FREE + const wordCount = params.number + this.writingWordCount = + wordCount !== undefined && wordCount !== null && String(wordCount).trim() + ? String(wordCount) + : 'auto' + const nextParams = { + eventType: String(params.eventType || params.event_type || '').trim(), + theme: String(params.theme || '').trim(), + time: String(params.time || '').trim(), + location: String(params.location || '').trim(), + participants: String(params.participants || '').trim() + } + this.writingParams = nextParams + // 有参数就展开,方便用户看到回填结果 + this.writingParamsOpen = ['theme', 'time', 'location', 'participants'].some( + (key) => !!nextParams[key] + ) + const input = String( + params.highlights || params.userContent || params.user_content || '' + ).trim() + this.workspaces.writing.draft = input || this.historyRecordInput(item) + }, + fillImageFromHistory(item, params) { + const input = String(params.user_content || params.userContent || '').trim() + this.workspaces.image.draft = input || this.historyRecordInput(item) + }, + /** + * 认领生成记录:取末帧 `chatId` 设为当前模式的高亮项,并刷新历史。 + * 失败态没有 chatId,调用方只在成功分支调用。 + */ + async claimGenerationRecord(payload) { + const chatId = + payload && payload.chatId !== undefined && payload.chatId !== null + ? payload.chatId + : payload && payload.data && payload.data.chatId + if (chatId !== undefined && chatId !== null && chatId !== '') { + this.activeChatId = chatId + } + try { + await this.loadHistoryList(false) + } catch (error) { + // 列表刷新失败不该把已成功的生成提示成「发送失败」 + console.warn('refresh history after generation failed', error) + } + }, startNewChat() { if (this.loading) { this.showToast('当前正在生成回复,请稍后再开启新对话') return } - this.disconnectWebSocket() + if (this.activeChatMode === 'chat') { + this.disconnectWebSocket() + } this.activeChatId = null this.activeConversationId = '' this.streamingMessageId = '' this.messageList = [] this.draft = '' + this.historyPreview = null this.showHistoryPanel = false }, /** @@ -1318,6 +1672,8 @@ }).promise if (finalPayload && Number(finalPayload.code) === 0) { setResult(this.formatWritingResult(finalPayload.data)) + // 末帧带上后端刚写入的记录 id(失败态没有) + await this.claimGenerationRecord(finalPayload) return } if (finalPayload) { @@ -1359,32 +1715,35 @@ return } setResult(this.formatCreativeResult(finalPayload.data)) + await this.claimGenerationRecord(finalPayload) } }, openHistoryPanel() { + this.historyPreview = null this.showHistoryPanel = true if (this.currentUser.userId) { this.loadHistoryList(false).catch((error) => { - this.showError(error, '加载历史会话失败') + this.showError(error, '加载历史记录失败') }) } }, closeHistoryPanel() { this.showHistoryPanel = false + this.historyPreview = null }, async removeChat(item) { if (this.loading) { - this.showToast('当前正在生成回复,请稍后再删除会话') + this.showToast('当前正在生成回复,请稍后再删除记录') return } if (!item.id) { - this.showToast('当前会话缺少标识,无法删除') + this.showToast('当前记录缺少标识,无法删除') return } const result = await new Promise((resolve) => { uni.showModal({ - title: '删除会话', + title: '删除记录', content: `确定删除“${this.getHistoryTitle(item)}”吗?`, success: resolve, fail: () => resolve({ confirm: false }) @@ -1394,15 +1753,36 @@ return } + const itemKey = this.getHistoryKey(item) + const itemType = this.getHistoryType(item) + // 同一条记录可能正开在某个模式的工作区里(三模式各自独立) + const affectedModes = Object.keys(this.workspaces).filter((mode) => { + const workspace = this.workspaces[mode] + return ( + workspace.activeChatId === item.id || + (item.conversationId && workspace.activeConversationId === item.conversationId) + ) + }) + this.deletingChatId = item.id try { - const isActive = - this.activeChatId === item.id || - (item.conversationId && this.activeConversationId === item.conversationId) await removeAiChatList(item.id) + if (this.historyPreview && this.historyPreview.key === itemKey) { + this.historyPreview = null + } await this.loadHistoryList(false) - if (isActive) { - const nextChat = this.historyList[0] + affectedModes.forEach((mode) => { + const workspace = this.workspaces[mode] + workspace.activeChatId = null + workspace.activeConversationId = '' + workspace.streamingMessageId = '' + workspace.messageList = [] + }) + // 聊天记录被删且正开在聊天模式:接上最近的一条聊天记录 + if (itemType === 'chat' && this.activeChatMode === 'chat' && affectedModes.indexOf('chat') > -1) { + const nextChat = this.historyList.find( + (candidate) => this.getHistoryType(candidate) === 'chat' + ) if (nextChat) { this.activeChatId = nextChat.id || null this.activeConversationId = nextChat.conversationId || '' @@ -2087,6 +2467,37 @@ font-size: 24rpx; } + /* 类型筛选:与写作参数一致,单行横向滑动,不换行堆叠 */ + .history-filter { + flex-shrink: 0; + width: 100%; + margin-top: 20rpx; + white-space: nowrap; + } + + .history-filter-track { + display: inline-flex; + align-items: center; + gap: 10rpx; + } + + .history-filter-chip { + flex-shrink: 0; + padding: 10rpx 18rpx; + border-radius: 999rpx; + border: 1rpx solid rgba(20, 150, 242, 0.18); + background: rgba(255, 255, 255, 0.9); + color: #1496f2; + font-size: 22rpx; + line-height: 1.3; + } + + .history-filter-chip--active { + border-color: transparent; + background: linear-gradient(145deg, #0f7dd1 0%, #1496f2 100%); + color: #fff; + } + .history-scroll { flex: 1; min-height: 0; @@ -2104,6 +2515,10 @@ color: #8b817b; } + .history-item-wrap + .history-item-wrap { + margin-top: 14rpx; + } + .history-item { display: flex; align-items: center; @@ -2115,10 +2530,6 @@ box-shadow: 0 10rpx 28rpx rgba(76, 49, 35, 0.06); } - .history-item + .history-item { - margin-top: 14rpx; - } - .history-item--active { border-color: rgba(20, 150, 242, 0.2); background: #fff1ec; @@ -2129,7 +2540,48 @@ min-width: 0; } + .history-item-head { + display: flex; + align-items: flex-start; + gap: 10rpx; + } + + /* 类型徽标:聊天 / 写作 / 图片 / 创意 / 活动策划 */ + .history-type-badge { + flex-shrink: 0; + margin-top: 4rpx; + padding: 2rpx 12rpx; + border-radius: 10rpx; + background: rgba(20, 150, 242, 0.1); + color: #1496f2; + font-size: 20rpx; + font-weight: 600; + line-height: 1.6; + } + + .history-type-badge--writing { + background: rgba(31, 143, 73, 0.1); + color: #1f8f49; + } + + .history-type-badge--image { + background: rgba(240, 122, 61, 0.12); + color: #c1652d; + } + + .history-type-badge--creative { + background: rgba(123, 97, 255, 0.1); + color: #6a53d6; + } + + .history-type-badge--activity_outline { + background: rgba(20, 150, 242, 0.08); + color: #0f7dd1; + } + .history-item-title { + flex: 1; + min-width: 0; font-size: 26rpx; font-weight: 700; color: #2f3136; @@ -2151,6 +2603,84 @@ font-size: 22rpx; } + /* 面板内的记录详情:仅非聊天类型出现 */ + .history-preview { + margin-top: 10rpx; + padding: 18rpx 20rpx; + border-radius: 20rpx; + border: 1rpx dashed rgba(20, 150, 242, 0.24); + background: rgba(255, 255, 255, 0.86); + } + + .history-preview-head { + display: flex; + align-items: center; + justify-content: space-between; + gap: 12rpx; + } + + .history-preview-caption { + font-size: 22rpx; + font-weight: 600; + color: #1496f2; + } + + .history-preview-close { + font-size: 20rpx; + color: #8a7f79; + } + + .history-preview-hint { + padding: 14rpx 0; + font-size: 22rpx; + color: #978b84; + } + + .history-preview-row { + margin-top: 14rpx; + } + + .history-preview-role { + margin-bottom: 6rpx; + font-size: 20rpx; + color: #8e837d; + } + + .history-preview-text { + font-size: 24rpx; + line-height: 1.7; + color: #2f3136; + word-break: break-all; + white-space: pre-wrap; + } + + .history-preview-markdown { + display: block; + white-space: normal; + } + + .history-preview-actions { + display: flex; + align-items: center; + flex-wrap: wrap; + gap: 12rpx; + margin-top: 18rpx; + } + + .history-preview-replay { + padding: 12rpx 22rpx; + border-radius: 999rpx; + background: linear-gradient(145deg, #0f7dd1 0%, #1496f2 100%); + color: #fff; + font-size: 22rpx; + font-weight: 600; + } + + .history-preview-tip { + font-size: 20rpx; + color: #978b84; + } + .history-empty { padding: 40rpx 20rpx; text-align: center; diff --git a/src/pages/creative-assistant/index.vue b/src/pages/creative-assistant/index.vue index 3c1ce2f..c183a56 100644 --- a/src/pages/creative-assistant/index.vue +++ b/src/pages/creative-assistant/index.vue @@ -10,6 +10,7 @@ 短视频创意 脚本创作 海报排版 + 历史记录 @@ -405,6 +406,18 @@ return } this.content = '请根据上传的活动照片、LOGO 和文案素材,生成一套公众号头图与活动海报排版,风格青春、明亮,输出图片文件。' + }, + /** + * 历史记录统一在助手页查看。 + * + * 助手页是 tabBar 页,`switchTab` 不能带参数,所以先把类型筛选 + * 写进 storage,助手页 onShow 读取后立即清除。 + */ + goHistoryPage() { + uni.setStorageSync('ai_history_type', 'creative') + uni.switchTab({ + url: '/pages/assistant/index' + }) } } } diff --git a/src/pages/manuscript/index.vue b/src/pages/manuscript/index.vue index f898c22..a535153 100644 --- a/src/pages/manuscript/index.vue +++ b/src/pages/manuscript/index.vue @@ -10,6 +10,7 @@ 公众号推文 通知公告 自由创作示例 + 历史记录 进入问答助手 @@ -743,6 +744,18 @@ uni.switchTab({ url: '/pages/assistant/index' }) + }, + /** + * 历史记录统一在助手页查看。 + * + * 助手页是 tabBar 页,`switchTab` 不能带参数,所以先把类型筛选 + * 写进 storage,助手页 onShow 读取后立即清除。 + */ + goHistoryPage() { + uni.setStorageSync('ai_history_type', 'writing') + uni.switchTab({ + url: '/pages/assistant/index' + }) } } }