From 3135c41b21c9ac1c7fd92dea039dac9b263a1bf1 Mon Sep 17 00:00:00 2001 From: Timi Date: Thu, 17 Sep 2026 01:00:30 +0800 Subject: [PATCH] update aiChatQuestions.ts from api --- src/pages/ai/aiChatQuestions.ts | 149 +++++++++++++++++- src/pages/ai/components/AiChatMessageList.vue | 72 +++++++-- src/pages/ai/components/AiChatPanel.vue | 12 +- .../ai/components/AiConversationList.vue | 18 +-- 4 files changed, 214 insertions(+), 37 deletions(-) diff --git a/src/pages/ai/aiChatQuestions.ts b/src/pages/ai/aiChatQuestions.ts index 48ae653..c210a0d 100644 --- a/src/pages/ai/aiChatQuestions.ts +++ b/src/pages/ai/aiChatQuestions.ts @@ -1,8 +1,141 @@ -/** 门店智能助手快捷问题。 */ -export const aiQuickQuestionList = [ - "今天门店经营怎么样?", - "本月销售额、订单数和应收款是多少?", - "哪些产品库存需要关注?", - "本月有哪些需要重点跟进的客户?", - "本月客户复购情况如何?" -] as const; +import { ref } from "vue"; +import { SettingAPI } from "timi-web-api"; + +const AI_QUICK_QUESTION_CACHE_KEY = "gao-customer-h5:ai-agent-example"; +const AI_QUICK_QUESTION_CACHE_TTL = 24 * 60 * 60 * 1000; +const AI_QUICK_QUESTION_COUNT = 5; + +interface AiQuickQuestionCache { + cachedAt: number; + questionList: string[]; +} + +/** 从快捷问题题库中随机抽取指定数量的问题。 */ +export function getRandomAiQuickQuestions(count = AI_QUICK_QUESTION_COUNT, questionPool: readonly string[] = []): string[] { + const result: string[] = [...questionPool]; + const targetCount = Math.min(Math.max(Math.floor(count), 0), result.length); + + for (let index = 0; index < targetCount; index += 1) { + const randomIndex = index + Math.floor(Math.random() * (result.length - index)); + [result[index], result[randomIndex]] = [result[randomIndex], result[index]]; + } + + return result.slice(0, targetCount); +} + +/** 清理并去重快捷问题。 */ +function normalizeAiQuickQuestionList(value: unknown): string[] { + if (!Array.isArray(value)) { + return []; + } + + return [...new Set(value.filter((item): item is string => typeof item === "string").map(item => item.trim()).filter(Boolean))]; +} + +/** 将 Setting 中的题库值解析为有效的快捷问题列表。 */ +function parseAiQuickQuestionList(value: unknown): string[] { + if (typeof value !== "string") { + return []; + } + + try { + return normalizeAiQuickQuestionList(JSON.parse(value)); + } catch { + return []; + } +} + +/** 读取一天内有效的本地题库缓存。 */ +function readAiQuickQuestionCache(): string[] { + try { + const cacheValue = localStorage.getItem(AI_QUICK_QUESTION_CACHE_KEY); + if (!cacheValue) { + return []; + } + + const cache: unknown = JSON.parse(cacheValue); + if (typeof cache !== "object" || cache === null || !("cachedAt" in cache) || !("questionList" in cache)) { + return []; + } + + const typedCache = cache as AiQuickQuestionCache; + if (typeof typedCache.cachedAt !== "number" || !Number.isFinite(typedCache.cachedAt)) { + return []; + } + + const cacheAge = Date.now() - typedCache.cachedAt; + if (cacheAge < 0 || AI_QUICK_QUESTION_CACHE_TTL < cacheAge || !Array.isArray(typedCache.questionList)) { + return []; + } + + return normalizeAiQuickQuestionList(typedCache.questionList); + } catch { + return []; + } +} + +/** 将动态题库缓存到本地一天。 */ +function writeAiQuickQuestionCache(questionList: string[]): void { + try { + const cache: AiQuickQuestionCache = { + cachedAt: Date.now(), + questionList + }; + localStorage.setItem(AI_QUICK_QUESTION_CACHE_KEY, JSON.stringify(cache)); + } catch { + // 本地存储不可用时跳过缓存。 + } +} + +/** 从系统设置中获取动态快捷问题题库。 */ +async function fetchAiQuickQuestionPool(): Promise { + const settingMap = await SettingAPI.map("GAO_SYSTEM", undefined, ["AI_AGENT_EXAMPLE"]); + return parseAiQuickQuestionList(settingMap.AI_AGENT_EXAMPLE?.value); +} + +let loadingPromise: Promise | undefined; +let currentAiQuickQuestionPool: string[] = []; + +/** 从已加载的题库中重新抽取快捷问题。 */ +export function refreshAiQuickQuestions(): void { + aiQuickQuestionList.value = getRandomAiQuickQuestions(AI_QUICK_QUESTION_COUNT, currentAiQuickQuestionPool); +} + +/** 加载动态题库并刷新当前会话展示的问题。 */ +export async function loadAiQuickQuestions(): Promise { + if (loadingPromise) { + await loadingPromise; + return; + } + + loadingPromise = (async () => { + const cachedQuestionList = readAiQuickQuestionCache(); + if (cachedQuestionList.length > 0) { + currentAiQuickQuestionPool = cachedQuestionList; + refreshAiQuickQuestions(); + return; + } + + currentAiQuickQuestionPool = []; + aiQuickQuestionList.value = []; + try { + const questionList = await fetchAiQuickQuestionPool(); + if (questionList.length > 0) { + currentAiQuickQuestionPool = questionList; + writeAiQuickQuestionCache(questionList); + refreshAiQuickQuestions(); + } + } catch { + // 接口异常时保持为空。 + } + })(); + + try { + await loadingPromise; + } finally { + loadingPromise = undefined; + } +} + +/** 当前会话欢迎页展示的快捷问题。 */ +export const aiQuickQuestionList = ref([]); diff --git a/src/pages/ai/components/AiChatMessageList.vue b/src/pages/ai/components/AiChatMessageList.vue index 7218126..37b4aa6 100644 --- a/src/pages/ai/components/AiChatMessageList.vue +++ b/src/pages/ai/components/AiChatMessageList.vue @@ -16,6 +16,19 @@ + + + 换一批 +