const GLOBAL_HIDDEN_KEY = "tb_qiaobao_hidden_all"; const PAGE_HIDDEN_KEY = "tb_qiaobao_hidden_pages"; const DOCK_EDGE_KEY = "tb_qiaobao_dock_edge"; const POSITION_KEY = "tb_qiaobao_position"; const FIRST_OPEN_KEY = "tb_qiaobao_ai_first_open_v1"; const FIRST_LOGIN_PREFIX = "tb_qiaobao_ai_first_login_v1_"; const CHAT_SESSION_KEY = "tb_qiaobao_ai_session_v1"; const CHAT_HISTORY_PREFIX = "tb_qiaobao_ai_history_v1_"; // Memory-only flag: closing Qiaobao lasts until the App/WebView process restarts. // It is intentionally not written to storage so users can always recover it by // reopening the App. let sessionClosed = false; function getChatHistoryKey(scope) { const safeScope = String(scope || "guest").replace(/[^a-zA-Z0-9_-]/g, "_"); return `${CHAT_HISTORY_PREFIX}${safeScope}`; } export function getQiaobaoChatSessionId() { let value = uni.getStorageSync(CHAT_SESSION_KEY); if (!value) { value = `qb-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`; uni.setStorageSync(CHAT_SESSION_KEY, value); } return value; } export function getQiaobaoChatHistory(scope = "guest") { const value = uni.getStorageSync(getChatHistoryKey(scope)); return Array.isArray(value) ? value.slice(-30) : []; } export function saveQiaobaoChatHistory(messages, scope = "guest") { const safe = Array.isArray(messages) ? messages.filter((item) => item && ["user", "assistant"].includes(item.role) && item.content).slice(-30) : []; uni.setStorageSync(getChatHistoryKey(scope), safe); } export function consumeQiaobaoAutoIntro(userId) { if (uni.getStorageSync(FIRST_OPEN_KEY) !== true) { uni.setStorageSync(FIRST_OPEN_KEY, true); return "first-open"; } if (userId !== undefined && userId !== null && String(userId)) { const key = `${FIRST_LOGIN_PREFIX}${String(userId)}`; if (uni.getStorageSync(key) !== true) { uni.setStorageSync(key, true); return "first-login"; } } return ""; } export function getQiaobaoDockEdge() { return uni.getStorageSync(DOCK_EDGE_KEY) === "left" ? "left" : "right"; } export function setQiaobaoDockEdge(edge) { uni.setStorageSync(DOCK_EDGE_KEY, edge === "left" ? "left" : "right"); } export function getQiaobaoPosition() { const position = uni.getStorageSync(POSITION_KEY); if (!position || typeof position !== "object") return null; const x = Number(position.x); const y = Number(position.y); return Number.isFinite(x) && Number.isFinite(y) ? { x, y } : null; } export function saveQiaobaoPosition(position) { if (!position) return; const x = Number(position.x); const y = Number(position.y); if (Number.isFinite(x) && Number.isFinite(y)) { uni.setStorageSync(POSITION_KEY, { x, y }); } } export function getCurrentPagePath() { try { const pages = getCurrentPages(); const current = pages[pages.length - 1]; return current?.route || current?.$page?.fullPath?.split("?")[0] || "unknown"; } catch (error) { return "unknown"; } } export function isQiaobaoHidden(pagePath = getCurrentPagePath()) { const hiddenAll = uni.getStorageSync(GLOBAL_HIDDEN_KEY); const hiddenPages = uni.getStorageSync(PAGE_HIDDEN_KEY); return hiddenAll === true || (Array.isArray(hiddenPages) && hiddenPages.includes(pagePath)); } export function isQiaobaoClosedForSession() { return sessionClosed; } export function closeQiaobaoForSession() { sessionClosed = true; uni.$emit("qiaobao-visibility-change", { scope: "close" }); } export function hideQiaobaoForPage(pagePath = getCurrentPagePath(), edge = "right") { const hiddenPages = uni.getStorageSync(PAGE_HIDDEN_KEY); const nextPages = Array.isArray(hiddenPages) ? [...hiddenPages] : []; if (!nextPages.includes(pagePath)) nextPages.push(pagePath); uni.setStorageSync(PAGE_HIDDEN_KEY, nextPages); setQiaobaoDockEdge(edge); uni.$emit("qiaobao-visibility-change", { scope: "page", pagePath, edge }); } export function hideQiaobaoGlobally(edge = "right") { uni.setStorageSync(GLOBAL_HIDDEN_KEY, true); setQiaobaoDockEdge(edge); uni.$emit("qiaobao-visibility-change", { scope: "all", edge }); } export function showQiaobao(pagePath = getCurrentPagePath()) { uni.removeStorageSync(GLOBAL_HIDDEN_KEY); const hiddenPages = uni.getStorageSync(PAGE_HIDDEN_KEY); if (Array.isArray(hiddenPages)) { uni.setStorageSync( PAGE_HIDDEN_KEY, hiddenPages.filter((item) => item !== pagePath), ); } uni.$emit("qiaobao-visibility-change", { scope: "show", pagePath }); } export function resetQiaobaoVisibility() { uni.removeStorageSync(GLOBAL_HIDDEN_KEY); uni.removeStorageSync(PAGE_HIDDEN_KEY); uni.$emit("qiaobao-visibility-change", { scope: "reset" }); }