From f73d3f7a8c100737d10c9394437c4e5b4642c899 Mon Sep 17 00:00:00 2001 From: francis_fh <13935151924@163.com> Date: Thu, 22 Jan 2026 12:57:01 +0800 Subject: [PATCH] =?UTF-8?q?=E5=9C=B0=E5=8C=BA=E9=80=89=E6=8B=A9=E5=BC=80?= =?UTF-8?q?=E5=8F=91=EF=BC=8CAI=E6=8E=A5=E5=8F=A3=E8=81=94=E8=B0=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config.js | 10 +- pages.json | 6 + pages/chat/components/ai-paging.vue | 36 +-- pages/city-select/index.vue | 425 +++++++++++++++++++++++++++ pages/index/components/index-one.vue | 26 +- stores/userChatGroupStore.js | 198 +++++++------ utils/streamRequest.js | 246 +++++++++++++++- 7 files changed, 813 insertions(+), 134 deletions(-) create mode 100644 pages/city-select/index.vue diff --git a/config.js b/config.js index 972541c..c4e0710 100644 --- a/config.js +++ b/config.js @@ -6,9 +6,9 @@ */ export default { // baseUrl: 'http://39.98.44.136:8080', // 测试 - baseUrl: 'https://www.xjksly.cn/api/ks', // 测试 // baseUrl: 'https://www.xjksly.cn/api/ks', // 测试 - // baseUrl: 'http://ks.zhaopinzao8dian.com/api/ks', // 测试 + // baseUrl: 'https://www.xjksly.cn/api/ks', // 测试 + baseUrl: 'http://ks.zhaopinzao8dian.com/api/ks', // 测试 // LCBaseUrl:'http://10.110.145.145:9100',//内网端口 // LCBaseUrlInner:'http://10.110.145.145:10100',//招聘、培训、帮扶 @@ -20,11 +20,11 @@ export default { trainVideoImgUrl:'https://www.xjksly.cn/prod-api/file/file/minio', // sseAI+ // StreamBaseURl: 'http://39.98.44.136:8000', - StreamBaseURl: 'https://qd.zhaopinzao8dian.com/ai', + StreamBaseURl: 'https://www.xjksly.cn/api/ks/app/chat', // StreamBaseURl: 'https://qd.zhaopinzao8dian.com/ai/test', // 语音转文字 - // vioceBaseURl: 'ws://39.98.44.136:8080/speech-recognition', - vioceBaseURl: 'wss://qd.zhaopinzao8dian.com/api/speech-recognition', + vioceBaseURl: 'wss://qd.zhaopinzao8dian.com/api/ks/app/speech/asr', + // vioceBaseURl: 'wss://qd.zhaopinzao8dian.com/api/speech-recognition', // 语音合成 speechSynthesis: 'wss://qd.zhaopinzao8dian.com/api/speech-synthesis', // indexedDB diff --git a/pages.json b/pages.json index 3cc332c..f7fa64d 100644 --- a/pages.json +++ b/pages.json @@ -6,6 +6,12 @@ "navigationBarTitleText": "喀什智慧就业平台" } }, + { + "path": "pages/city-select/index", + "style": { + "navigationBarTitleText": "选择城市" + } + }, { "path": "pages/mine/mine", "style": { diff --git a/pages/chat/components/ai-paging.vue b/pages/chat/components/ai-paging.vue index 2c5309f..81d4b09 100644 --- a/pages/chat/components/ai-paging.vue +++ b/pages/chat/components/ai-paging.vue @@ -551,7 +551,9 @@ const scrollToBottom = throttle(function () { }, 500); function getGuess() { - $api.chatRequest('/guest', { sessionId: chatSessionID.value }, 'POST').then((res) => { + // $api.chatRequest('/guest', { sessionId: chatSessionID.value }, 'POST').then((res) => { + $api.chatRequest('/guest', undefined, 'POST').then((res) => { + console.log('getGuess ---- res:', res); guessList.value = res.data; showGuess.value = true; nextTick(() => { @@ -804,22 +806,22 @@ function refreshMarkdown(index) { } const jobSearchQueries = [ - '青岛有哪些薪资 12K 以上的岗位适合我?', - '青岛 3 年工作经验能找到哪些 12K 以上的工作?', - '青岛哪些公司在招聘,薪资范围在 12K 以上?', - '青岛有哪些企业提供 15K 以上的岗位?', - '青岛哪些公司在招 3-5 年经验的岗位?', - '我有三年的工作经验,能否推荐一些适合我的青岛的国企 岗位?', - '青岛国企目前在招聘哪些岗位?', - '青岛有哪些适合 3 年经验的国企岗位?', - '青岛国企招聘的岗位待遇如何?', - '青岛国企岗位的薪资水平是多少?', - '青岛哪些国企支持双休 & 五险一金完善?', - '青岛有哪些公司支持远程办公?', - '青岛有哪些外企的岗位,薪资 12K 以上的多吗?', - '青岛哪些企业在招聘 Web3.0 相关岗位?', - '青岛哪些岗位支持海外远程?薪资如何?', - '青岛招聘 AI/大数据相关岗位的公司有哪些?', + '喀什地区有哪些薪资 12K 以上的岗位适合我?', + '喀什地区 3 年工作经验能找到哪些 12K 以上的工作?', + '喀什地区哪些公司在招聘,薪资范围在 12K 以上?', + '喀什地区有哪些企业提供 15K 以上的岗位?', + '喀什地区哪些公司在招 3-5 年经验的岗位?', + '我有三年的工作经验,能否推荐一些适合我的喀什地区的国企 岗位?', + '喀什地区国企目前在招聘哪些岗位?', + '喀什地区有哪些适合 3 年经验的国企岗位?', + '喀什地区国企招聘的岗位待遇如何?', + '喀什地区国企岗位的薪资水平是多少?', + '喀什地区哪些国企支持双休 & 五险一金完善?', + '喀什地区有哪些公司支持远程办公?', + '喀什地区有哪些外企的岗位,薪资 12K 以上的多吗?', + '喀什地区哪些企业在招聘 Web3.0 相关岗位?', + '喀什地区哪些岗位支持海外远程?薪资如何?', + '喀什地区招聘 AI/大数据相关岗位的公司有哪些?', ]; function changeQueries(value) { diff --git a/pages/city-select/index.vue b/pages/city-select/index.vue new file mode 100644 index 0000000..c62b2ea --- /dev/null +++ b/pages/city-select/index.vue @@ -0,0 +1,425 @@ + + + + + \ No newline at end of file diff --git a/pages/index/components/index-one.vue b/pages/index/components/index-one.vue index 7c71594..23060b7 100644 --- a/pages/index/components/index-one.vue +++ b/pages/index/components/index-one.vue @@ -250,10 +250,16 @@ + 添加 + + + {{ selectedCity.name || '地区' }} + + @@ -317,7 +323,7 @@ {{ config.appInfo.areaName }} - + @@ -394,7 +400,7 @@ {{ config.appInfo.areaName }} - + @@ -631,6 +637,8 @@ const inputText = ref(''); const showFilter = ref(false); const selectFilterModel = ref(null); const showModel = ref(false); +// 选中的城市 +const selectedCity = ref({ code: '', name: '' }); const rangeOptions = ref([ { value: 0, text: '推荐' }, { value: 1, text: '最热' }, @@ -723,6 +731,7 @@ onMounted(() => { // 在组件挂载时绑定事件监听,确保只绑定一次 // 先移除可能存在的旧监听,避免重复绑定 uni.$off('showLoginModal'); + uni.$off('citySelected'); // 绑定新的监听 uni.$on('showLoginModal', () => { @@ -731,6 +740,15 @@ onMounted(() => { pageNull.value = 0; }); + // 监听城市选择事件 + uni.$on('citySelected', (city) => { + console.log('收到citySelected事件,选择的城市:', city); + selectedCity.value = city; + // 可以在这里添加根据城市筛选职位的逻辑 + conditionSearch.value.jobLocationAreaCode = city.code; + getJobRecommend('refresh'); + }); + // 获取企业信息 getCompanyInfo(); }); @@ -738,6 +756,7 @@ onMounted(() => { onUnmounted(() => { // 组件销毁时移除事件监听 uni.$off('showLoginModal'); + uni.$off('citySelected'); }); onShow(() => { @@ -1728,6 +1747,9 @@ defineExpose({ loadData }); min-width: 80rpx; padding: 8rpx 12rpx; white-space: nowrap; + .right-sx + width: 28rpx; + height: 28rpx; .filter-bottom display: flex justify-content: space-between diff --git a/stores/userChatGroupStore.js b/stores/userChatGroupStore.js index 9eb330f..ae21f54 100644 --- a/stores/userChatGroupStore.js +++ b/stores/userChatGroupStore.js @@ -107,102 +107,108 @@ const useChatGroupDBStore = defineStore("messageGroup", () => { return await baseDB.db.add(massageName.value, payload); } - async function getStearm(text, fileUrls = [], progress, options = {}) { - - return new Promise((resolve, reject) => { - try { - toggleTyping(true); - const customDataID = 'message_' + UUID.generate() - const params = { - data: text, - sessionId: chatSessionID.value, - dataId: customDataID - }; - if (fileUrls && fileUrls.length) { - params['fileUrl'] = fileUrls.map((item) => item.url); - } - // ------> - const MsgData = { - text: text, - self: true, - displayText: text, - files: fileUrls - }; - addMessage(MsgData); // 添加message数据 - // <------ - const newMsg = { - text: '', // 存储原始结构化内容 - self: false, - displayText: '', // 用于流式渲染展示 - dataId: customDataID - }; - const index = messages.value.length; - messages.value.push(newMsg); - - const rawParts = Array.isArray(text) ? text : [text]; // 统一处理 - - // 用于追加每个部分的流式数据 - let partIndex = 0; - - function handleUnload() { - newMsg.parentGroupId = chatSessionID.value; - baseDB.db.add(massageName.value, newMsg).then((id) => { - messages.value[index] = { - ...newMsg, - id - }; - }); - } - // #ifdef H5 - if (typeof window !== 'undefined') { - window.addEventListener("unload", handleUnload); - } - // #endif - - function onDataReceived(data) { - // 支持追加多个部分 - newMsg.text += data; - newMsg.displayText += data; - messages.value[index] = { - ...newMsg - }; - progress && progress(); - - // 调用外部传入的onDataReceived回调 - if (options.onDataReceived) { - options.onDataReceived(data, newMsg, index); - } - } - - function onError(error) { - msg('服务响应异常'); - reject(error); - } - - function onComplete() { - messages.value[index] = { - ...newMsg - }; - toggleTyping(false); - // #ifdef H5 - if (typeof window !== 'undefined') { - window.removeEventListener("unload", handleUnload); - } - // #endif - handleUnload(); - // 调用外部传入的onComplete回调 - if (options.onComplete) { - options.onComplete(); - } - resolve(); - } - - $api.streamRequest('/chat', params, onDataReceived, onError, onComplete); - } catch (err) { - console.log(err); - reject(err); - } - }); + async function getStearm(text, fileUrls = [], progress, options = {}) { + + return new Promise((resolve, reject) => { + try { + toggleTyping(true); + const customDataID = 'message_' + UUID.generate() + + // 对话历史管理:只保留最近的N条消息,防止token超限 + // 计算消息数量,只保留最近的10条消息(可根据实际情况调整) + const MAX_HISTORY_MESSAGES = 10; + const historyMessages = messages.value.slice(-MAX_HISTORY_MESSAGES); + + const params = { + data: text, + sessionId: chatSessionID.value, + dataId: customDataID + }; + if (fileUrls && fileUrls.length) { + params['fileUrl'] = fileUrls.map((item) => item.url); + } + // ------> + const MsgData = { + text: text, + self: true, + displayText: text, + files: fileUrls + }; + addMessage(MsgData); // 添加message数据 + // <------ + const newMsg = { + text: '', // 存储原始结构化内容 + self: false, + displayText: '', // 用于流式渲染展示 + dataId: customDataID + }; + const index = messages.value.length; + messages.value.push(newMsg); + + const rawParts = Array.isArray(text) ? text : [text]; // 统一处理 + + // 用于追加每个部分的流式数据 + let partIndex = 0; + + function handleUnload() { + newMsg.parentGroupId = chatSessionID.value; + baseDB.db.add(massageName.value, newMsg).then((id) => { + messages.value[index] = { + ...newMsg, + id + }; + }); + } + // #ifdef H5 + if (typeof window !== 'undefined') { + window.addEventListener("unload", handleUnload); + } + // #endif + + function onDataReceived(data) { + // 支持追加多个部分 + newMsg.text += data; + newMsg.displayText += data; + messages.value[index] = { + ...newMsg + }; + progress && progress(); + + // 调用外部传入的onDataReceived回调 + if (options.onDataReceived) { + options.onDataReceived(data, newMsg, index); + } + } + + function onError(error) { + msg('服务响应异常'); + reject(error); + } + + function onComplete() { + messages.value[index] = { + ...newMsg + }; + toggleTyping(false); + // #ifdef H5 + if (typeof window !== 'undefined') { + window.removeEventListener("unload", handleUnload); + } + // #endif + handleUnload(); + // 调用外部传入的onComplete回调 + if (options.onComplete) { + options.onComplete(); + } + resolve(); + } + + $api.streamRequest('/chat', params, onDataReceived, onError, onComplete); + } catch (err) { + console.log(err); + reject(err); + } + }); } // 状态控制 diff --git a/utils/streamRequest.js b/utils/streamRequest.js index 9a49cef..7073f97 100644 --- a/utils/streamRequest.js +++ b/utils/streamRequest.js @@ -27,6 +27,7 @@ function StreamRequestMiniProgram(url, data = {}, onDataReceived, onError, onCom return new Promise((resolve, reject) => { let buffer = ''; + let hasReceivedContent = false; const requestTask = uni.request({ url: config.StreamBaseURl + url, @@ -55,15 +56,33 @@ function StreamRequestMiniProgram(url, data = {}, onDataReceived, onError, onCom try { const decoder = new TextDecoder('utf-8'); const chunk = decoder.decode(new Uint8Array(res.data)); + console.log('📦 收到分块数据:', chunk); buffer += chunk; let lines = buffer.split("\n"); buffer = lines.pop() || ''; // 保留不完整的行 + console.log('📝 解析到行:', lines.length, '行,缓冲区剩余:', buffer.length, '字符'); for (let line of lines) { - if (line.startsWith("data: ")) { - const jsonData = line.slice(6).trim(); + console.log('🔍 处理行:', line); + // 处理重复的 data: 前缀 + let processedLine = line; + // 移除所有开头的 data: 前缀(无论是否有空格),直到只剩下一个或没有 + while (processedLine.startsWith("data:")) { + // 检查是否还有另一个 data: 前缀 + const nextPart = processedLine.slice(5).trimStart(); + if (nextPart.startsWith("data:")) { + processedLine = nextPart; + } else { + break; + } + } + + if (processedLine.startsWith("data: ")) { + const jsonData = processedLine.slice(6).trim(); + console.log('📄 提取的JSON数据:', jsonData); if (jsonData === "[DONE]") { + console.log('✅ 收到结束标记 [DONE]'); onComplete && onComplete(); resolve(); return; @@ -72,11 +91,35 @@ function StreamRequestMiniProgram(url, data = {}, onDataReceived, onError, onCom if (jsonData && jsonData.trim()) { try { const parsedData = JSON.parse(jsonData); + console.log('🔧 解析后的JSON:', parsedData); + // 检查是否有错误信息 + const finishReason = parsedData?.choices?.[0]?.finish_reason; + if (finishReason === "error") { + let errorContent = parsedData?.choices?.[0]?.delta?.content || "流式请求失败"; + console.error('❌ 收到错误信息:', errorContent); + + // 优化token超限错误提示 + if (errorContent.includes("maximum input ids length")) { + errorContent = "对话历史过长,请尝试清除部分历史记录或简化问题"; + } + + // 只有当未收到正常内容时才显示错误信息 + if (!hasReceivedContent) { + // 显示错误信息给用户 + uni.showToast({ + title: errorContent, + icon: 'none', + duration: 3000 + }); + } + } // 处理标准的choices格式 - if (parsedData?.choices?.[0]?.delta?.content) { + else if (parsedData?.choices?.[0]?.delta?.content) { const content = parsedData.choices[0].delta.content; if (content) { + hasReceivedContent = true; + console.log('📤 调用onDataReceived(content):', content); onDataReceived && onDataReceived(content); } } @@ -84,6 +127,8 @@ function StreamRequestMiniProgram(url, data = {}, onDataReceived, onError, onCom else if (parsedData?.choices?.[0]?.delta?.reasoning_content) { const content = parsedData.choices[0].delta.reasoning_content; if (content) { + hasReceivedContent = true; + console.log('📤 调用onDataReceived(reasoning_content):', content); onDataReceived && onDataReceived(content); } } @@ -91,14 +136,42 @@ function StreamRequestMiniProgram(url, data = {}, onDataReceived, onError, onCom else if (parsedData?.tool?.response) { const content = parsedData.tool.response; if (content) { + hasReceivedContent = true; + console.log('📤 调用onDataReceived(tool.response):', content); onDataReceived && onDataReceived(content); } } + // 处理其他可能的内容格式 + else if (parsedData?.content) { + // 直接返回content字段的情况 + const content = parsedData.content; + if (content) { + hasReceivedContent = true; + console.log('📤 调用onDataReceived(direct content):', content); + onDataReceived && onDataReceived(content); + } + } + // 处理完整的text字段(非流式) + else if (parsedData?.choices?.[0]?.text) { + const content = parsedData.choices[0].text; + if (content) { + hasReceivedContent = true; + console.log('📤 调用onDataReceived(full text):', content); + onDataReceived && onDataReceived(content); + } + } + else { + console.warn('⚠️ 未匹配到任何内容格式:', parsedData); + } } catch (e) { - console.error("JSON 解析失败:", e.message); + console.error("JSON 解析失败:", e.message, "原始数据:", jsonData); } } } + else if (processedLine.trim()) { + // 处理非data:开头的行 + console.warn('⚠️ 收到非data:开头的行:', processedLine); + } } } catch (error) { console.error('处理分块数据失败:', error); @@ -135,6 +208,7 @@ function StreamRequestH5(url, data = {}, onDataReceived, onError, onComplete) { let buffer = ""; let retryCount = 0; const maxRetries = 3; + let hasReceivedContent = false; while (true) { const { @@ -157,9 +231,25 @@ function StreamRequestH5(url, data = {}, onDataReceived, onError, onComplete) { console.log(`📦 Processing ${lines.length} lines, buffer length: ${buffer.length}`); for (let line of lines) { - if (line.startsWith("data: ")) { - const jsonData = line.slice(6).trim(); + console.log('🔍 处理行:', line); + // 处理重复的 data: 前缀 + let processedLine = line; + // 移除所有开头的 data: 前缀(无论是否有空格),直到只剩下一个或没有 + while (processedLine.startsWith("data:")) { + // 检查是否还有另一个 data: 前缀 + const nextPart = processedLine.slice(5).trimStart(); + if (nextPart.startsWith("data:")) { + processedLine = nextPart; + } else { + break; + } + } + + if (processedLine.startsWith("data: ")) { + const jsonData = processedLine.slice(6).trim(); + console.log('📄 提取的JSON数据:', jsonData); if (jsonData === "[DONE]") { + console.log('✅ 收到结束标记 [DONE]'); onComplete && onComplete(); resolve(); return; @@ -169,11 +259,35 @@ function StreamRequestH5(url, data = {}, onDataReceived, onError, onComplete) { // 检查JSON数据是否完整 if (jsonData && jsonData.trim() && jsonData !== "[DONE]") { const parsedData = JSON.parse(jsonData); + console.log('🔧 解析后的JSON:', parsedData); + // 检查是否有错误信息 + const finishReason = parsedData?.choices?.[0]?.finish_reason; + if (finishReason === "error") { + let errorContent = parsedData?.choices?.[0]?.delta?.content || "流式请求失败"; + console.error('❌ 收到错误信息:', errorContent); + + // 优化token超限错误提示 + if (errorContent.includes("maximum input ids length")) { + errorContent = "对话历史过长,请尝试清除部分历史记录或简化问题"; + } + + // 只有当未收到正常内容时才显示错误信息 + if (!hasReceivedContent) { + // 显示错误信息给用户 + uni.showToast({ + title: errorContent, + icon: 'none', + duration: 3000 + }); + } + } // 处理标准的choices格式 - if (parsedData?.choices?.[0]?.delta?.content) { + else if (parsedData?.choices?.[0]?.delta?.content) { const content = parsedData.choices[0].delta.content; if (content) { + hasReceivedContent = true; + console.log('📤 调用onDataReceived(content):', content); onDataReceived && onDataReceived(content); } } @@ -181,6 +295,8 @@ function StreamRequestH5(url, data = {}, onDataReceived, onError, onComplete) { else if (parsedData?.choices?.[0]?.delta?.reasoning_content) { const content = parsedData.choices[0].delta.reasoning_content; if (content) { + hasReceivedContent = true; + console.log('📤 调用onDataReceived(reasoning_content):', content); onDataReceived && onDataReceived(content); } } @@ -188,6 +304,27 @@ function StreamRequestH5(url, data = {}, onDataReceived, onError, onComplete) { else if (parsedData?.tool?.response) { const content = parsedData.tool.response; if (content) { + hasReceivedContent = true; + console.log('📤 调用onDataReceived(tool.response):', content); + onDataReceived && onDataReceived(content); + } + } + // 处理其他可能的内容格式 + else if (parsedData?.content) { + // 直接返回content字段的情况 + const content = parsedData.content; + if (content) { + hasReceivedContent = true; + console.log('📤 调用onDataReceived(direct content):', content); + onDataReceived && onDataReceived(content); + } + } + // 处理完整的text字段(非流式) + else if (parsedData?.choices?.[0]?.text) { + const content = parsedData.choices[0].text; + if (content) { + hasReceivedContent = true; + console.log('📤 调用onDataReceived(full text):', content); onDataReceived && onDataReceived(content); } } @@ -201,6 +338,10 @@ function StreamRequestH5(url, data = {}, onDataReceived, onError, onComplete) { // 不抛出错误,继续处理下一个数据块 } } + else if (processedLine.trim()) { + // 处理非data:开头的行 + console.warn('⚠️ 收到非data:开头的行:', processedLine); + } } } @@ -209,16 +350,55 @@ function StreamRequestH5(url, data = {}, onDataReceived, onError, onComplete) { console.log("📦 Processing remaining buffer:", buffer.substring(0, 100) + "..."); const lines = buffer.split("\n"); for (let line of lines) { - if (line.startsWith("data: ")) { - const jsonData = line.slice(6).trim(); + console.log('🔍 处理剩余缓冲区行:', line); + // 处理重复的 data: 前缀 + let processedLine = line; + // 移除所有开头的 data: 前缀(无论是否有空格),直到只剩下一个或没有 + while (processedLine.startsWith("data:")) { + // 检查是否还有另一个 data: 前缀 + const nextPart = processedLine.slice(5).trimStart(); + if (nextPart.startsWith("data:")) { + processedLine = nextPart; + } else { + break; + } + } + + if (processedLine.startsWith("data: ")) { + const jsonData = processedLine.slice(6).trim(); + console.log('📄 提取的剩余JSON数据:', jsonData); if (jsonData && jsonData !== "[DONE]") { try { const parsedData = JSON.parse(jsonData); + console.log('🔧 解析后的剩余JSON:', parsedData); + // 检查是否有错误信息 + const finishReason = parsedData?.choices?.[0]?.finish_reason; + if (finishReason === "error") { + let errorContent = parsedData?.choices?.[0]?.delta?.content || "流式请求失败"; + console.error('❌ 收到错误信息:', errorContent); + + // 优化token超限错误提示 + if (errorContent.includes("maximum input ids length")) { + errorContent = "对话历史过长,请尝试清除部分历史记录或简化问题"; + } + + // 只有当未收到正常内容时才显示错误信息 + if (!hasReceivedContent) { + // 显示错误信息给用户 + uni.showToast({ + title: errorContent, + icon: 'none', + duration: 3000 + }); + } + } // 处理标准的choices格式 - if (parsedData?.choices?.[0]?.delta?.content) { + else if (parsedData?.choices?.[0]?.delta?.content) { const content = parsedData.choices[0].delta.content; if (content) { + hasReceivedContent = true; + console.log('📤 调用onDataReceived(content):', content); onDataReceived && onDataReceived(content); } } @@ -226,6 +406,8 @@ function StreamRequestH5(url, data = {}, onDataReceived, onError, onComplete) { else if (parsedData?.choices?.[0]?.delta?.reasoning_content) { const content = parsedData.choices[0].delta.reasoning_content; if (content) { + hasReceivedContent = true; + console.log('📤 调用onDataReceived(reasoning_content):', content); onDataReceived && onDataReceived(content); } } @@ -233,6 +415,27 @@ function StreamRequestH5(url, data = {}, onDataReceived, onError, onComplete) { else if (parsedData?.tool?.response) { const content = parsedData.tool.response; if (content) { + hasReceivedContent = true; + console.log('📤 调用onDataReceived(tool.response):', content); + onDataReceived && onDataReceived(content); + } + } + // 处理其他可能的内容格式 + else if (parsedData?.content) { + // 直接返回content字段的情况 + const content = parsedData.content; + if (content) { + hasReceivedContent = true; + console.log('📤 调用onDataReceived(direct content):', content); + onDataReceived && onDataReceived(content); + } + } + // 处理完整的text字段(非流式) + else if (parsedData?.choices?.[0]?.text) { + const content = parsedData.choices[0].text; + if (content) { + hasReceivedContent = true; + console.log('📤 调用onDataReceived(full text):', content); onDataReceived && onDataReceived(content); } } @@ -241,6 +444,10 @@ function StreamRequestH5(url, data = {}, onDataReceived, onError, onComplete) { } } } + else if (processedLine.trim()) { + // 处理非data:开头的行 + console.warn('⚠️ 收到非data:开头的剩余行:', processedLine); + } } } @@ -295,16 +502,27 @@ export function chatRequest(url, data = {}, method = 'GET', loading = false, hea return } uni.showToast({ - title: msg, + title: msg || '请求失败', icon: 'none' }) + // 拒绝Promise并提供详细错误信息 + const err = new Error(msg || '请求失败,服务器返回错误码: ' + code) + err.error = resData + reject(err) + } else { + // 处理非200状态码 + const errorMsg = `请求失败,HTTP状态码: ${resData.statusCode}` + uni.showToast({ + title: errorMsg, + icon: 'none' + }) + const err = new Error(errorMsg) + err.error = resData + reject(err) } if (resData.data?.code === 401 || resData.data?.code === 402) { useUserStore().logOut() } - const err = new Error('请求出现异常,请联系工作人员') - err.error = resData - reject(err) }, fail: (err) => { reject(err)