"use strict"; const common_vendor = require("../../common/vendor.js"); const pages_api_ai = require("../api/ai.js"); const pages_api_config = require("../api/config.js"); const common_assets = require("../../common/assets.js"); const _sfc_main = { data() { return { inputMessage: "", messages: [], isLoading: false, scrollTop: 0, maxLength: 300, userId: "user_123", // 模拟用户ID sessionId: "", eventSource: null, // SSE连接对象 pollingInterval: null, // 轮询定时器 isConnected: false, // SSE连接状态 isDevelopment: true, // 控制测试按钮显示 // 快捷问题 quickQuestions: { "重庆深度5日游": { destination: "重庆", days: 5, budget: 3e3, preferences: ["景点", "美食", "文化"], transportation: "公共交通" }, "推荐几个热门旅游城市": { requestType: "recommendation", preferences: ["热门", "旅游城市"] }, "旅游注意事项有哪些": { requestType: "travelTips", preferences: ["安全", "注意事项"] } } }; }, computed: { // 用于显示除欢迎消息外的其他消息 displayMessages() { if (this.messages.length === 0 || this.messages.length === 1 && this.messages[0].type === "ai") { return []; } if (this.messages.length > 1 && this.messages[0].type === "ai") { return this.messages.slice(1); } return this.messages; } }, onLoad(options) { if (typeof __wxConfig !== "undefined") { this.isDevelopment = __wxConfig.envVersion === "develop" || __wxConfig.envVersion === "trial"; } try { const savedMessages = common_vendor.index.getStorageSync("chat_messages"); if (savedMessages) { this.messages = JSON.parse(savedMessages); } else { this.addMessage("您好,欢迎遇见Gooh旅记旅行规划师!我将为您设计专属行程,解答旅途中的各类问题,让旅行无忧。有任何想法,请随时告诉我~", "ai"); } } catch (e) { common_vendor.index.__f__("error", "at pages/ai-assistant/index.vue:296", "加载消息历史失败:", e); this.addMessage("您好,欢迎遇见Gooh旅记旅行规划师!我将为您设计专属行程,解答旅途中的各类问题,让旅行无忧。有任何想法,请随时告诉我~", "ai"); } this.startSession(); }, onUnload() { try { common_vendor.index.setStorageSync("chat_messages", JSON.stringify(this.messages)); } catch (e) { common_vendor.index.__f__("error", "at pages/ai-assistant/index.vue:309", "保存消息历史失败:", e); } if (this.eventSource) { this.eventSource.close(); } this.stopPolling(); }, methods: { // 返回旅游规划页面 goBack() { common_vendor.index.switchTab({ url: "/pages/planning/index" }); }, // 创建新对话 async createNewChat() { if (this.eventSource) { try { this.eventSource.close(); this.eventSource = null; } catch (e) { common_vendor.index.__f__("error", "at pages/ai-assistant/index.vue:337", "关闭SSE连接失败:", e); } } if (this.pollingInterval) { clearInterval(this.pollingInterval); this.pollingInterval = null; } this.messages = []; this.inputMessage = ""; this.sessionId = ""; await this.startSession(); common_vendor.index.showToast({ title: "已创建新对话", icon: "none" }); }, // 开始新会话 async startSession() { try { const response = await pages_api_ai.startAISession(); if (response && response.code === 200 && response.sessionId) { this.sessionId = response.sessionId; common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:368", "会话创建成功,sessionId:", this.sessionId); if (response.msg && this.messages.length === 0) { this.addMessage(response.msg, "ai"); } if (this.sessionId) { await this.setupWebSocket(); } else { throw new Error("未获取到有效的sessionId"); } } else { throw new Error((response == null ? void 0 : response.msg) || "创建会话失败"); } } catch (error) { common_vendor.index.__f__("error", "at pages/ai-assistant/index.vue:386", "创建会话失败:", error); common_vendor.index.showToast({ title: error.message || "连接失败,请重试", icon: "none" }); } }, // 设置SSE连接 async setupWebSocket() { if (!this.sessionId) { common_vendor.index.__f__("error", "at pages/ai-assistant/index.vue:397", "无法建立SSE连接:sessionId不存在"); return; } const url = pages_api_ai.getSSEUrl(this.sessionId); common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:403", "尝试连接SSE:", url); if (this.eventSource) { try { this.eventSource.close(); common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:409", "已关闭旧的SSE连接"); } catch (e) { common_vendor.index.__f__("error", "at pages/ai-assistant/index.vue:411", "关闭旧SSE连接失败:", e); } this.eventSource = null; } return new Promise((resolve, reject) => { try { common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:418", "开始创建SSE连接..."); common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:465", "在小程序环境下使用替代方法连接SSE"); this.isConnected = true; this.setupPolling(); resolve(); setTimeout(() => { if (!this.isConnected) { common_vendor.index.__f__("error", "at pages/ai-assistant/index.vue:476", "SSE连接超时"); reject(new Error("SSE连接超时")); } }, 1e4); } catch (error) { common_vendor.index.__f__("error", "at pages/ai-assistant/index.vue:488", "创建SSE连接时发生错误:", error); reject(error); } }); }, // 处理WebSocket消息 handleSocketMessage(res) { try { common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:497", "开始处理WebSocket消息:", res.data); let data; try { data = JSON.parse(res.data); } catch (parseError) { common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:505", "WebSocket数据不是JSON格式,尝试作为纯文本处理"); data = { type: "message", content: res.data }; } common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:512", "处理后的WebSocket消息数据:", data); if (!data.type && data.content) { data.type = "message"; } switch (data.type) { case "start": common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:521", "收到start类型消息"); if (this.messages.length > 0 && this.messages[this.messages.length - 1].type === "user") { this.addMessage("AI正在思考...", "ai", true); } this.setupPolling(); break; case "message": common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:532", "收到message类型消息:", data.content); if (this.messages.length > 0 && this.messages[this.messages.length - 1].isThinking) { this.messages.pop(); } if (data.content) { const isPlanContent = this.checkIfTravelPlanContent(data.content); if (isPlanContent) { common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:540", "检测到旅游行程信息,解析为卡片显示"); const planData = this.parseTravelPlanContent(data.content); this.addTravelPlanMessage(planData); } else { let formattedContent = this.formatAIResponse(data.content); this.addMessage(formattedContent, "ai"); } } break; case "done": common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:550", "收到done类型消息"); if (this.messages.length > 0 && this.messages[this.messages.length - 1].isThinking) { this.messages.pop(); } this.isLoading = false; this.stopPolling(); break; case "error": common_vendor.index.__f__("error", "at pages/ai-assistant/index.vue:561", "收到error类型消息:", data.content); if (this.messages.length > 0 && this.messages[this.messages.length - 1].isThinking) { this.messages.pop(); } this.addMessage(`错误: ${data.content}`, "ai"); this.isLoading = false; common_vendor.index.showToast({ title: "发生错误,请重试", icon: "none" }); this.stopPolling(); break; default: common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:577", "收到未知类型消息:", data); if (data.content || typeof data === "string" && data) { const content = data.content || data; if (this.messages.length > 0 && this.messages[this.messages.length - 1].isThinking) { this.messages.pop(); } let formattedContent = this.formatAIResponse(content); this.addMessage(formattedContent, "ai"); } break; } } catch (error) { common_vendor.index.__f__("error", "at pages/ai-assistant/index.vue:590", "处理WebSocket消息失败:", error); this.isLoading = false; try { let content = res.data; if (typeof content === "string" && content.length > 0) { common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:598", "尝试直接显示原始消息内容"); if (this.messages.length > 0 && this.messages[this.messages.length - 1].isThinking) { this.messages.pop(); } let formattedContent = this.formatAIResponse(content); this.addMessage(formattedContent, "ai"); return; } } catch (e) { common_vendor.index.__f__("error", "at pages/ai-assistant/index.vue:607", "尝试直接显示消息内容也失败:", e); } if (this.messages.length > 0 && this.messages[this.messages.length - 1].isThinking) { this.messages.pop(); } this.addMessage("消息处理出错,请重试", "ai"); } }, // 设置轮询 - 仅当需要时才开始轮询,有结果就停止 setupPolling() { common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:619", "设置轮询检查"); this.stopPolling(); this.pollingCount = 0; const maxPollingCount = 20; this.pollingInterval = setInterval(async () => { try { this.pollingCount++; common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:631", `第${this.pollingCount}次轮询检查`); if (!this.isLoading || this.pollingCount > maxPollingCount) { common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:635", "条件不满足,停止轮询:", { isLoading: this.isLoading, pollingCount: this.pollingCount }); this.stopPolling(); return; } const response = await pages_api_ai.getLastAIReply(this.sessionId); common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:645", "轮询结果:", response); if (response && response.code === 200 && response.reply) { common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:649", "轮询发现新消息"); this.handleSocketMessage({ data: JSON.stringify({ type: "message", content: response.reply }) }); setTimeout(() => { this.handleSocketMessage({ data: JSON.stringify({ type: "done" }) }); }, 500); this.stopPolling(); } } catch (err) { common_vendor.index.__f__("error", "at pages/ai-assistant/index.vue:670", "轮询出错:", err); this.pollingErrorCount = (this.pollingErrorCount || 0) + 1; if (this.pollingErrorCount > 3) { common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:675", "轮询错误太多,停止轮询"); this.stopPolling(); } } }, 3e3); }, // 停止轮询 stopPolling() { if (this.pollingInterval) { common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:685", "停止轮询"); clearInterval(this.pollingInterval); this.pollingInterval = null; this.pollingCount = 0; this.pollingErrorCount = 0; } }, // 发送消息 async sendMessage() { if (!this.inputMessage.trim() || this.isLoading) return; common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:697", "准备发送消息:", this.inputMessage); if (!this.sessionId) { common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:701", "sessionId不存在,先创建新会话"); try { const response = await pages_api_ai.startAISession(); if (response && response.code === 200 && response.sessionId) { this.sessionId = response.sessionId; common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:706", "新会话创建成功,sessionId:", this.sessionId); } else { throw new Error("创建会话失败"); } } catch (error) { common_vendor.index.__f__("error", "at pages/ai-assistant/index.vue:711", "创建会话失败:", error); common_vendor.index.showToast({ title: "创建会话失败,请重试", icon: "none" }); return; } } if (this.inputMessage.length > this.maxLength) { common_vendor.index.showToast({ title: `消息不能超过${this.maxLength}字`, icon: "none" }); return; } const messageToSend = this.inputMessage.trim(); this.inputMessage = ""; this.addMessage(messageToSend, "user"); this.isLoading = true; try { if (!this.isConnected) { common_vendor.index.__f__("warn", "at pages/ai-assistant/index.vue:741", "SSE未连接,尝试重新连接"); await this.setupWebSocket(); common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:743", "SSE重连状态:", this.isConnected ? "已连接" : "未连接"); } common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:747", "发送消息到服务器:", { sessionId: this.sessionId, message: messageToSend }); const response = await pages_api_ai.chatWithAI(this.sessionId, messageToSend); common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:754", "服务器响应:", response); if (response.code === 200) { if (response.msg) { common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:759", "服务器返回的消息:", response.msg); let formattedContent = this.formatAIResponse(response.msg); this.addMessage(formattedContent, "ai"); } else { common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:764", "服务器未返回消息,等待WebSocket响应"); } common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:769", "小程序环境中启动轮询检查"); this.setupPolling(); } else if (response.code === 404) { common_vendor.index.__f__("warn", "at pages/ai-assistant/index.vue:773", "会话不存在,尝试重新开始会话"); const newSessionResponse = await pages_api_ai.startAISession(); if (newSessionResponse && newSessionResponse.code === 200 && newSessionResponse.sessionId) { this.sessionId = newSessionResponse.sessionId; const retryResponse = await pages_api_ai.chatWithAI(this.sessionId, messageToSend); common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:779", "重试响应:", retryResponse); if (retryResponse.code === 200) { if (retryResponse.msg) { common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:784", "重试后服务器返回的消息:", retryResponse.msg); let formattedContent = this.formatAIResponse(retryResponse.msg); this.addMessage(formattedContent, "ai"); } } else { throw new Error(retryResponse.msg || "重试发送失败"); } } else { throw new Error("重新创建会话失败"); } } else { throw new Error(response.msg || "发送失败"); } } catch (error) { common_vendor.index.__f__("error", "at pages/ai-assistant/index.vue:798", "发送消息失败:", error); common_vendor.index.showToast({ title: error.message || "发送失败,请重试", icon: "none" }); this.addMessage("抱歉,发送消息失败,请重试。", "ai"); } finally { this.isLoading = false; } }, // 处理快捷问题 async handleQuickQuestion(question) { if (this.isLoading) return; common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:813", "处理快捷问题:", question); this.isLoading = true; try { if (!this.sessionId) { common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:819", "sessionId不存在,先创建新会话"); try { const response2 = await pages_api_ai.startAISession(); if (response2 && response2.code === 200 && response2.sessionId) { this.sessionId = response2.sessionId; common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:824", "新会话创建成功,sessionId:", this.sessionId); } else { throw new Error("创建会话失败"); } } catch (error) { common_vendor.index.__f__("error", "at pages/ai-assistant/index.vue:829", "创建会话失败:", error); common_vendor.index.showToast({ title: "创建会话失败,请重试", icon: "none" }); this.isLoading = false; return; } } this.addMessage(question, "user"); common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:843", "发送快捷问题到服务器:", { sessionId: this.sessionId, message: question }); const response = await pages_api_ai.chatWithAI(this.sessionId, question); common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:849", "快捷问题服务器响应:", response); if (response.code === 200) { if (response.msg) { common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:854", "服务器返回的消息:", response.msg); let formattedContent = this.formatAIResponse(response.msg); this.addMessage(formattedContent, "ai"); } else { common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:859", "服务器未返回消息,等待WebSocket响应"); } common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:864", "小程序环境中启动轮询检查"); this.setupPolling(); } else if (response.code === 404) { common_vendor.index.__f__("warn", "at pages/ai-assistant/index.vue:868", "会话不存在,尝试重新开始会话"); this.addMessage("会话已过期,正在重新创建会话...", "system"); const newSessionResponse = await pages_api_ai.startAISession(); if (newSessionResponse && newSessionResponse.code === 200 && newSessionResponse.sessionId) { this.sessionId = newSessionResponse.sessionId; this.handleQuickQuestion(question); } else { throw new Error("重新创建会话失败"); } } else { throw new Error(response.msg || "发送失败"); } } catch (error) { common_vendor.index.__f__("error", "at pages/ai-assistant/index.vue:883", "处理快捷问题失败:", error); common_vendor.index.showToast({ title: error.message || "发送失败,请重试", icon: "none" }); this.addMessage("抱歉,处理问题失败,请重试。", "ai"); } finally { this.isLoading = false; } }, // 添加消息 addMessage(content, type, isThinking = false) { common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:896", "添加新消息:", { content, type, isThinking }); if (type === "user") { content = content.replace(//g, ">"); } const message = { type, content, isThinking, timestamp: Date.now() }; if (!isThinking && this.messages.length > 0) { const lastMessage = this.messages[this.messages.length - 1]; if (lastMessage.isThinking && lastMessage.type === type) { common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:914", "替换思考状态消息"); this.messages.splice(-1, 1); } } this.messages.push(message); common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:920", "当前消息列表:", this.messages); try { common_vendor.index.setStorageSync("chat_messages", JSON.stringify(this.messages)); common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:925", "消息已保存到本地存储"); } catch (e) { common_vendor.index.__f__("error", "at pages/ai-assistant/index.vue:927", "保存消息到本地存储失败:", e); } this.$nextTick(() => { this.scrollToBottom(); }); }, // 滚动到底部 scrollToBottom() { const query = common_vendor.index.createSelectorQuery().in(this); query.select(".message-list").boundingClientRect((data) => { if (data) { this.scrollTop = data.height; } }).exec(); }, // 格式化时间 formatTime(timestamp) { if (!timestamp) return ""; const date = new Date(timestamp); const hours = date.getHours().toString().padStart(2, "0"); const minutes = date.getMinutes().toString().padStart(2, "0"); return `${hours}:${minutes}`; }, // 加载更多消息 loadMoreMessages() { common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:958", "加载更多消息"); }, // 格式化AI响应的方法增加日志 formatAIResponse(content) { common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:963", "开始格式化AI响应:", content); content = content.replace(/\d+e\d+;margin:[\s\d]+px[\s\d]+px[\s\d]+;"/g, '"'); content = content.replace(/\n/g, "
"); content = content.replace(/最佳旅行时间[::]/g, '
🕒最佳旅行时间:
'); content = content.replace(/景点推荐[::]/g, '
🏞️景点推荐:
'); content = content.replace(/美食推荐[::]/g, '
🍜美食推荐:
'); content = content.replace(/住宿推荐[::]/g, '
🏨住宿推荐:
'); content = content.replace(/交通指南[::]/g, '
🚗交通指南:
'); content = content.replace(/旅游贴士[::]/g, '
💡旅游贴士:
'); content = content.replace(/费用预算[::]/g, '
💰费用预算:
'); content = content.replace(/行程安排[::]/g, '
📅行程安排:
'); content = content.replace(/###\s*(.*?)(\*\*)?(\*\*)?(\|\s|$)/g, '

$1

'); content = content.replace(/##\s*(.*?)(\|\s|$)/g, '

$2

'); content = content.replace(/#\s*(.*?)(\|\s|$)/g, '

$1

'); content = content.replace(/---(\|\s|$)/g, '
'); content = content.replace(/- ([^<]+)(?:|$)/g, '
$1
'); content = content.replace(/([^<::]+)[::](?=\s*亚洲|世界|有"|\w)/g, '$1:'); content = content.replace(/\*\*(.*?)\*\*/g, "$1"); content = content.replace(/【(.*?)】/g, '【$1】'); content = content.replace(/\*(.*?)\*/g, "$1"); if (content.includes("行程") || content.includes("旅游") || content.includes("景点") || content.includes("住宿") || content.includes("Day") || content.includes("预算")) { common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:1007", "检测到旅游相关内容,进行格式化"); content = content.replace(/¥(\d+)/g, '¥$1'); content = content.replace(/(\d+)元/g, '$1元'); content = content.replace(/¥(\d+)/g, '¥$1'); content = content.replace(/¥(\d+[-~]\d+)/g, '¥$1'); content = content.replace(/(Day\d+)[::]/g, '$1:'); content = content.replace(/(第\d+天)[::]/g, '$1:'); content = content.replace(/(上午|下午|晚上|早上|中午|傍晚)[::]/g, '$1:'); content = content.replace(/(著名|必去|推荐|特色|知名)/g, '$1'); common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:1023", "格式化后的内容:", content); } return content; }, async testConnection() { common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:1030", "开始测试连接"); try { common_vendor.index.showLoading({ title: "测试连接中..." }); if (!this.isConnected) { common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:1039", "WebSocket未连接,尝试重新连接"); await this.startSession(); } const testMessage = "测试消息:你好"; common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:1045", "发送测试消息:", testMessage); this.addMessage("开始连接测试...", "system"); await this.testWebSocketConnection(); try { const response = await pages_api_ai.chatWithAI(this.sessionId, testMessage); if (response.code === 200) { common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:1057", "测试消息发送成功"); } else { throw new Error(response.msg || "测试消息发送失败"); } } catch (error) { throw new Error("测试消息发送失败: " + error.message); } common_vendor.index.hideLoading(); common_vendor.index.showToast({ title: "连接测试成功", icon: "success" }); } catch (error) { common_vendor.index.__f__("error", "at pages/ai-assistant/index.vue:1075", "测试连接失败:", error); common_vendor.index.hideLoading(); common_vendor.index.showToast({ title: "测试失败", icon: "error" }); } }, // WebSocket连接测试 async testWebSocketConnection() { return new Promise((resolve, reject) => { try { if (!this.isConnected) { common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:1092", "WebSocket未连接,无法发送测试消息"); reject(new Error("WebSocket未连接")); return; } common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:1097", "尝试通过WebSocket发送测试消息"); common_vendor.index.sendSocketMessage({ data: JSON.stringify({ type: "test", message: "WebSocket测试消息" }), success: () => { common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:1103", "WebSocket测试消息发送成功"); this.addMessage("WebSocket测试消息已发送,等待回应...", "system"); setTimeout(() => { resolve(); }, 1e3); }, fail: (error) => { common_vendor.index.__f__("error", "at pages/ai-assistant/index.vue:1111", "WebSocket测试消息发送失败:", error); this.addMessage("WebSocket测试消息发送失败", "system"); reject(error); } }); } catch (error) { common_vendor.index.__f__("error", "at pages/ai-assistant/index.vue:1117", "WebSocket测试过程出错:", error); reject(error); } }); }, // 轮询获取AI回复 async pollForAIReply(sessionId, maxAttempts = 3, interval = 5e3) { common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:1125", `开始轮询获取AI回复,最多${maxAttempts}次,间隔${interval}ms`); this.addMessage("正在获取AI回复...", "system"); const lastMessage = this.messages[this.messages.length - 1]; if (lastMessage && lastMessage.type === "ai" && !lastMessage.isThinking) { common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:1133", "已通过WebSocket收到回复,停止轮询"); return; } let attempt = 0; const poll = async () => { if (attempt >= maxAttempts) { common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:1141", `已达到最大轮询次数(${maxAttempts}),停止轮询`); this.addMessage("获取AI回复超时,尝试从服务器直接获取回复...", "system"); try { common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:1148", "尝试通过直接聊天请求获取回复"); const response = await pages_api_ai.chatWithAI(sessionId, "获取上一条回复"); if (response && response.data && response.data.reply) { common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:1152", "成功通过chatWithAI获取回复:", response.data.reply); if (this.messages.length > 0 && this.messages[this.messages.length - 1].isThinking) { this.messages.pop(); } const isPlanContent = this.checkIfTravelPlanContent(response.data.reply); if (isPlanContent) { common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:1160", "轮询检测到旅游行程信息,解析为卡片显示"); const planData = this.parseTravelPlanContent(response.data.reply); this.addTravelPlanMessage(planData); } else { let formattedContent = this.formatAIResponse(response.data.reply); this.addMessage(formattedContent, "ai"); } this.isLoading = false; return; } } catch (error) { common_vendor.index.__f__("error", "at pages/ai-assistant/index.vue:1173", "通过直接聊天请求获取回复失败:", error); } if (this.messages.length > 0 && this.messages[this.messages.length - 1].isThinking) { this.messages.pop(); this.addMessage("获取回复失败,请重新发送消息", "ai"); } this.isLoading = false; return; } attempt++; common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:1186", `第${attempt}次轮询获取AI回复`); try { const response = await pages_api_ai.getLastAIReply(sessionId); common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:1190", `第${attempt}次轮询响应:`, response); if (response && response.code === 200 && response.reply) { common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:1193", "轮询成功获取到AI回复:", response.reply); const lastMessage2 = this.messages[this.messages.length - 1]; if (lastMessage2 && lastMessage2.type === "ai" && !lastMessage2.isThinking && lastMessage2.content === response.reply) { common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:1199", "已有此消息,不重复显示"); return; } const isPlanContent = this.checkIfTravelPlanContent(response.reply); if (isPlanContent) { common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:1206", "轮询检测到旅游行程信息,解析为卡片显示"); const planData = this.parseTravelPlanContent(response.reply); this.addTravelPlanMessage(planData); } else { let formattedContent = this.formatAIResponse(response.reply); this.addMessage(formattedContent, "ai"); } this.isLoading = false; return; } setTimeout(poll, interval); } catch (error) { common_vendor.index.__f__("error", "at pages/ai-assistant/index.vue:1222", `第${attempt}次轮询出错:`, error); setTimeout(poll, interval); } }; poll(); }, async fetchServerResponse() { common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:1233", "开始获取服务器响应"); try { common_vendor.index.showLoading({ title: "获取服务器响应中..." }); common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:1241", "发送HTTP请求到服务器:", { sessionId: this.sessionId, message: "获取服务器响应", baseUrl: pages_api_config.baseUrl, url: `${pages_api_config.baseUrl}/api/ai/travel/fetchServerResponse` }); const response = await pages_api_ai.fetchServerResponse(this.sessionId); common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:1249", "服务器响应:", response); if (response.code === 200) { common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:1252", "服务器响应获取成功"); if (this.messages.length > 0 && this.messages[this.messages.length - 1].isThinking) { this.messages.pop(); } let formattedContent = this.formatAIResponse(response.data.reply); this.addMessage(formattedContent, "ai"); } else { throw new Error(response.msg || "获取服务器响应失败"); } } catch (error) { common_vendor.index.__f__("error", "at pages/ai-assistant/index.vue:1263", "获取服务器响应失败:", error); common_vendor.index.showToast({ title: error.message || "获取服务器响应失败,请重试", icon: "none" }); this.addMessage("抱歉,获取服务器响应失败,请重试。", "ai"); } finally { this.isLoading = false; common_vendor.index.hideLoading(); } }, // 检查是否有未接收的消息 async checkForMissedMessages() { if (!this.sessionId) return; common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:1280", "检查是否有未接收的消息"); try { if (this.socketTask && this.isConnected) { common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:1285", "WebSocket已连接,发送请求获取最新消息"); this.socketTask.send({ data: JSON.stringify({ type: "get_last_message", sessionId: this.sessionId }), success() { common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:1292", "请求最新消息发送成功"); }, fail(error) { common_vendor.index.__f__("error", "at pages/ai-assistant/index.vue:1295", "请求最新消息发送失败:", error); } }); } common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:1301", "尝试通过HTTP接口获取最新回复"); const response = await pages_api_ai.getLastAIReply(this.sessionId); if (response && response.code === 200 && response.reply) { common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:1305", "成功获取到最新回复:", response.reply); const lastMessage = this.messages[this.messages.length - 1]; if (lastMessage && lastMessage.type === "ai" && !lastMessage.isThinking && lastMessage.content === response.reply) { common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:1311", "已有此消息,不重复显示"); return; } const isPlanContent = this.checkIfTravelPlanContent(response.reply); if (isPlanContent) { common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:1318", "检测到旅游行程信息,解析为卡片显示"); const planData = this.parseTravelPlanContent(response.reply); this.addTravelPlanMessage(planData); } else { let formattedContent = this.formatAIResponse(response.reply); this.addMessage(formattedContent, "ai"); } } } catch (error) { common_vendor.index.__f__("error", "at pages/ai-assistant/index.vue:1328", "检查未接收消息失败:", error); } }, // 检查是否是旅游行程信息 checkIfTravelPlanContent(content) { const keywords = [ "行程安排", "旅游计划", "旅行计划", "计划名称", "计划简介", "行程特色", "行程总花费", "行程总费用", "旅游地点", "¥", "¥", "预算", "第一天", "第二天", "第三天", "Day1", "Day2", "第.*天" ]; const contentHasKeywords = keywords.some((keyword) => { const regex = new RegExp(keyword, "i"); return regex.test(content); }); const hasColonFormat = (content.match(/[::]/g) || []).length >= 3; const hasDayPattern = /第\s*\d+\s*天|Day\s*\d+/i.test(content); return contentHasKeywords && (hasColonFormat || hasDayPattern); }, // 解析旅游行程信息 parseTravelPlanContent(content) { common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:1358", "开始解析旅游行程内容"); const planData = { name: "", description: "", features: "", price: "", currentDay: "1", city: "", attractions: "", food: "", arrangement: "", note: "", days: "5天4晚", spots: "12个地点" }; const nameMatch = content.match(/计划名称[::]\s*([^\n]+)/); if (nameMatch) planData.name = nameMatch[1].trim(); if (!planData.name) { const altNameMatch = content.match(/(.*)[日游|旅行|旅游计划]/); if (altNameMatch) planData.name = altNameMatch[1].trim(); } if (!planData.name) planData.name = "旅游计划"; const descMatch = content.match(/计划简介[::]\s*([^\n]+)/); if (descMatch) planData.description = descMatch[1].trim(); else { const altDescMatch = content.match(/简介[::]\s*([^\n]+)/); if (altDescMatch) planData.description = altDescMatch[1].trim(); } const featuresMatch = content.match(/行程特色[::]\s*([^\n]+)/); if (featuresMatch) planData.features = featuresMatch[1].trim(); const priceMatch = content.match(/行程总花费[::]\s*([^\n]+)|预算[::]\s*([^\n]+)|总花费[::]\s*([^\n]+)|花费[::]\s*([^\n]+)/); if (priceMatch) { planData.price = (priceMatch[1] || priceMatch[2] || priceMatch[3] || priceMatch[4]).trim(); planData.price = planData.price.replace(/[¥¥]/g, ""); } const dayMatch = content.match(/第\s*(\d+)\s*天|Day\s*(\d+)/i); if (dayMatch) { planData.currentDay = dayMatch[1] || dayMatch[2]; } const cityMatch = content.match(/城市[::]\s*([^\n]+)|地点[::]\s*([^\n]+)|国家[::]\s*([^\n]+)/); if (cityMatch) planData.city = (cityMatch[1] || cityMatch[2] || cityMatch[3]).trim(); const attractionsMatch = content.match(/地点[::]\s*([^\n]+)|景点[::]\s*([^\n]+)|旅游地点[::]\s*([^\n]+)/); if (attractionsMatch) planData.attractions = (attractionsMatch[1] || attractionsMatch[2] || attractionsMatch[3]).trim(); const foodMatch = content.match(/周边美食[::]\s*([^\n]+)|美食[::]\s*([^\n]+)|特色美食[::]\s*([^\n]+)/); if (foodMatch) planData.food = (foodMatch[1] || foodMatch[2] || foodMatch[3]).trim(); const arrangementMatch = content.match(/安排说明[::]\s*([^\n]+)|安排[::]\s*([^\n]+)|行程安排[::]\s*([^\n]+)/); if (arrangementMatch) planData.arrangement = (arrangementMatch[1] || arrangementMatch[2] || arrangementMatch[3]).trim(); const noteMatch = content.match(/备注[::]\s*([^\n]+)/); if (noteMatch) planData.note = noteMatch[1].trim(); const totalDaysMatch = content.match(/(\d+)\s*天\s*(\d+)\s*晚|(\d+)\s*日\s*(\d+)\s*晚/); if (totalDaysMatch) { const days = totalDaysMatch[1] || totalDaysMatch[3]; const nights = totalDaysMatch[2] || totalDaysMatch[4]; planData.days = `${days}天${nights}晚`; } const spotsMatch = content.match(/(\d+)\s*个景点|(\d+)\s*个地点/); if (spotsMatch) { const count = spotsMatch[1] || spotsMatch[2]; planData.spots = `${count}个地点`; } common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:1451", "解析后的旅游行程数据:", planData); return planData; }, // 添加旅游行程消息 addTravelPlanMessage(planData) { common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:1457", "添加旅游行程卡片消息:", planData); const message = { type: "ai-plan", planData, isThinking: false, timestamp: Date.now() }; this.messages.push(message); common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:1467", "当前消息列表:", this.messages); try { common_vendor.index.setStorageSync("chat_messages", JSON.stringify(this.messages)); common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:1472", "消息已保存到本地存储"); } catch (e) { common_vendor.index.__f__("error", "at pages/ai-assistant/index.vue:1474", "保存消息到本地存储失败:", e); } this.$nextTick(() => { this.scrollToBottom(); }); }, async testConsoleLog() { common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:1483", "开始测试控制台输出"); try { common_vendor.index.showLoading({ title: "测试控制台输出中..." }); if (!this.sessionId) { common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:1492", "sessionId不存在,先创建新会话"); const response2 = await pages_api_ai.startAISession(); if (response2 && response2.code === 200 && response2.sessionId) { this.sessionId = response2.sessionId; common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:1496", "新会话创建成功,sessionId:", this.sessionId); } else { throw new Error("创建会话失败"); } } const testMessage = "[CONSOLE_TEST] 这是一条测试控制台输出的消息 " + (/* @__PURE__ */ new Date()).toLocaleString(); common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:1504", "发送测试消息:", testMessage); this.addMessage("开始测试控制台输出...", "system"); const response = await pages_api_ai.chatWithAI(this.sessionId, testMessage); common_vendor.index.__f__("log", "at pages/ai-assistant/index.vue:1511", "测试消息发送结果:", response); if (response.code === 200) { this.addMessage("测试消息已发送到后端,请检查后端控制台输出", "system"); } else { throw new Error(response.msg || "发送测试消息失败"); } common_vendor.index.hideLoading(); common_vendor.index.showToast({ title: "消息已发送", icon: "success" }); } catch (error) { common_vendor.index.__f__("error", "at pages/ai-assistant/index.vue:1530", "控制台输出测试失败:", error); common_vendor.index.hideLoading(); common_vendor.index.showToast({ title: "控制台输出测试失败", icon: "error" }); this.addMessage(`控制台输出测试失败: ${error.message}`, "system"); } } } }; function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) { return common_vendor.e({ a: common_vendor.o((...args) => $options.goBack && $options.goBack(...args)), b: common_vendor.o((...args) => $options.createNewChat && $options.createNewChat(...args)), c: $data.messages.length > 0 && $data.messages[0].type === "ai" }, $data.messages.length > 0 && $data.messages[0].type === "ai" ? { d: common_assets._imports_0$3, e: $data.messages[0].content, f: common_vendor.f($data.quickQuestions, (question, key, i0) => { return { a: common_vendor.t(key), b: key, c: common_vendor.o(($event) => $options.handleQuickQuestion(key), key) }; }) } : {}, { g: common_vendor.f($options.displayMessages, (msg, index, i0) => { return common_vendor.e({ a: common_vendor.t($options.formatTime(msg.timestamp)), b: common_vendor.t(msg.type === "user" ? "我" : "AI助手"), c: msg.type === "user" ? "/static/images/user-avatar.png" : "/static/images/ai-avatar.png", d: !msg.isThinking && msg.type !== "ai-plan" }, !msg.isThinking && msg.type !== "ai-plan" ? { e: msg.content } : msg.type === "ai-plan" ? common_vendor.e({ g: common_vendor.t(msg.planData.name), h: common_vendor.t(msg.planData.description), i: common_vendor.t(msg.planData.features), j: common_vendor.t(msg.planData.price), k: msg.planData.price.includes("-") }, msg.planData.price.includes("-") ? {} : {}, { l: common_vendor.t(msg.planData.currentDay), m: common_vendor.t(msg.planData.city), n: msg.planData.attractions }, msg.planData.attractions ? { o: common_vendor.t(msg.planData.attractions) } : {}, { p: msg.planData.food }, msg.planData.food ? { q: common_vendor.t(msg.planData.food) } : {}, { r: common_vendor.t(msg.planData.arrangement), s: common_vendor.t(msg.planData.days), t: common_vendor.t(msg.planData.price), v: common_vendor.t(msg.planData.spots), w: msg.planData.note }, msg.planData.note ? { x: common_vendor.t(msg.planData.note) } : {}) : {}, { f: msg.type === "ai-plan", y: index, z: common_vendor.n(msg.type) }); }), h: $data.scrollTop, i: common_vendor.o((...args) => $options.loadMoreMessages && $options.loadMoreMessages(...args)), j: $data.isLoading, k: $data.maxLength, l: common_vendor.o((...args) => $options.sendMessage && $options.sendMessage(...args)), m: $data.inputMessage, n: common_vendor.o(($event) => $data.inputMessage = $event.detail.value), o: common_vendor.t($data.isLoading ? "发送中..." : "发送"), p: $data.isLoading || !$data.inputMessage.trim(), q: $data.isLoading ? 1 : "", r: common_vendor.o((...args) => $options.sendMessage && $options.sendMessage(...args)) }); } const MiniProgramPage = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["render", _sfc_render]]); wx.createPage(MiniProgramPage); //# sourceMappingURL=../../../.sourcemap/mp-weixin/pages/ai-assistant/index.js.map