地区选择开发,AI接口联调

This commit is contained in:
francis_fh
2026-01-22 12:57:01 +08:00
parent 7dcfbd35fe
commit f73d3f7a8c
7 changed files with 813 additions and 134 deletions

View File

@@ -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)