|
|
const cloud = require("wx-server-sdk");
|
|
|
cloud.init({
|
|
|
env: cloud.DYNAMIC_CURRENT_ENV,
|
|
|
});
|
|
|
|
|
|
const db = cloud.database();
|
|
|
// 获取openid
|
|
|
const getOpenId = async () => {
|
|
|
// 获取基础信息
|
|
|
const wxContext = cloud.getWXContext();
|
|
|
return {
|
|
|
openid: wxContext.OPENID,
|
|
|
appid: wxContext.APPID,
|
|
|
unionid: wxContext.UNIONID,
|
|
|
};
|
|
|
};
|
|
|
|
|
|
// 获取小程序二维码
|
|
|
const getMiniProgramCode = async () => {
|
|
|
// 获取小程序二维码的buffer
|
|
|
const resp = await cloud.openapi.wxacode.get({
|
|
|
path: "pages/index/index",
|
|
|
});
|
|
|
const { buffer } = resp;
|
|
|
// 将图片上传云存储空间
|
|
|
const upload = await cloud.uploadFile({
|
|
|
cloudPath: "code.png",
|
|
|
fileContent: buffer,
|
|
|
});
|
|
|
return upload.fileID;
|
|
|
};
|
|
|
|
|
|
// 创建集合
|
|
|
const createCollection = async () => {
|
|
|
try {
|
|
|
// 创建集合
|
|
|
await db.createCollection("sales");
|
|
|
await db.collection("sales").add({
|
|
|
// data 字段表示需新增的 JSON 数据
|
|
|
data: {
|
|
|
region: "华东",
|
|
|
city: "上海",
|
|
|
sales: 11,
|
|
|
},
|
|
|
});
|
|
|
await db.collection("sales").add({
|
|
|
// data 字段表示需新增的 JSON 数据
|
|
|
data: {
|
|
|
region: "华东",
|
|
|
city: "南京",
|
|
|
sales: 11,
|
|
|
},
|
|
|
});
|
|
|
await db.collection("sales").add({
|
|
|
// data 字段表示需新增的 JSON 数据
|
|
|
data: {
|
|
|
region: "华南",
|
|
|
city: "广州",
|
|
|
sales: 22,
|
|
|
},
|
|
|
});
|
|
|
await db.collection("sales").add({
|
|
|
// data 字段表示需新增的 JSON 数据
|
|
|
data: {
|
|
|
region: "华南",
|
|
|
city: "深圳",
|
|
|
sales: 22,
|
|
|
},
|
|
|
});
|
|
|
return {
|
|
|
success: true,
|
|
|
};
|
|
|
} catch (e) {
|
|
|
// 这里catch到的是该collection已经存在,从业务逻辑上来说是运行成功的,所以catch返回success给前端,避免工具在前端抛出异常
|
|
|
return {
|
|
|
success: true,
|
|
|
data: "create collection success",
|
|
|
};
|
|
|
}
|
|
|
};
|
|
|
|
|
|
// 查询数据
|
|
|
const selectRecord = async () => {
|
|
|
// 返回数据库查询结果
|
|
|
return await db.collection("sales").get();
|
|
|
};
|
|
|
|
|
|
// 更新数据
|
|
|
const updateRecord = async (event) => {
|
|
|
try {
|
|
|
// 遍历修改数据库信息
|
|
|
for (let i = 0; i < event.data.length; i++) {
|
|
|
await db
|
|
|
.collection("sales")
|
|
|
.where({
|
|
|
_id: event.data[i]._id,
|
|
|
})
|
|
|
.update({
|
|
|
data: {
|
|
|
sales: event.data[i].sales,
|
|
|
},
|
|
|
});
|
|
|
}
|
|
|
return {
|
|
|
success: true,
|
|
|
data: event.data,
|
|
|
};
|
|
|
} catch (e) {
|
|
|
return {
|
|
|
success: false,
|
|
|
errMsg: e,
|
|
|
};
|
|
|
}
|
|
|
};
|
|
|
|
|
|
// 新增数据
|
|
|
const insertRecord = async (event) => {
|
|
|
try {
|
|
|
const insertRecord = event.data;
|
|
|
// 插入数据
|
|
|
await db.collection("sales").add({
|
|
|
data: {
|
|
|
region: insertRecord.region,
|
|
|
city: insertRecord.city,
|
|
|
sales: Number(insertRecord.sales),
|
|
|
},
|
|
|
});
|
|
|
return {
|
|
|
success: true,
|
|
|
data: event.data,
|
|
|
};
|
|
|
} catch (e) {
|
|
|
return {
|
|
|
success: false,
|
|
|
errMsg: e,
|
|
|
};
|
|
|
}
|
|
|
};
|
|
|
|
|
|
// 删除数据
|
|
|
const deleteRecord = async (event) => {
|
|
|
try {
|
|
|
await db
|
|
|
.collection("sales")
|
|
|
.where({
|
|
|
_id: event.data._id,
|
|
|
})
|
|
|
.remove();
|
|
|
return {
|
|
|
success: true,
|
|
|
};
|
|
|
} catch (e) {
|
|
|
return {
|
|
|
success: false,
|
|
|
errMsg: e,
|
|
|
};
|
|
|
}
|
|
|
};
|
|
|
|
|
|
// const getOpenId = require('./getOpenId/index');
|
|
|
// const getMiniProgramCode = require('./getMiniProgramCode/index');
|
|
|
// const createCollection = require('./createCollection/index');
|
|
|
// const selectRecord = require('./selectRecord/index');
|
|
|
// const updateRecord = require('./updateRecord/index');
|
|
|
// const sumRecord = require('./sumRecord/index');
|
|
|
// const fetchGoodsList = require('./fetchGoodsList/index');
|
|
|
// const genMpQrcode = require('./genMpQrcode/index');
|
|
|
// 查询T_user表数据
|
|
|
const queryTUser = async () => {
|
|
|
try {
|
|
|
const result = await db.collection("T_user").get();
|
|
|
return {
|
|
|
success: true,
|
|
|
data: result.data,
|
|
|
count: result.data.length
|
|
|
};
|
|
|
} catch (e) {
|
|
|
return {
|
|
|
success: false,
|
|
|
error: e.message
|
|
|
};
|
|
|
}
|
|
|
};
|
|
|
|
|
|
// 根据openid查询用户信息(用于表关联)
|
|
|
const getUserByOpenId = async (event) => {
|
|
|
try {
|
|
|
const wxContext = cloud.getWXContext();
|
|
|
const openid = event.openid || wxContext.OPENID;
|
|
|
|
|
|
console.log('查询用户信息,openid:', openid);
|
|
|
|
|
|
if (!openid) {
|
|
|
return {
|
|
|
success: false,
|
|
|
error: 'openid不能为空'
|
|
|
};
|
|
|
}
|
|
|
|
|
|
// 先尝试通过_openid查询(微信云开发自动添加的字段)
|
|
|
let userResult = await db.collection("T_user").where({
|
|
|
_openid: openid
|
|
|
}).get();
|
|
|
|
|
|
// 如果没找到,尝试通过其他方式查询(如果T_user表中有openid字段)
|
|
|
if (userResult.data.length === 0) {
|
|
|
// 这里可以根据实际需求添加其他查询方式
|
|
|
// 例如:如果有存储openid字段,可以查询
|
|
|
// userResult = await db.collection("T_user").where({
|
|
|
// openid: openid
|
|
|
// }).get();
|
|
|
}
|
|
|
|
|
|
if (userResult.data.length > 0) {
|
|
|
const userData = userResult.data[0];
|
|
|
return {
|
|
|
success: true,
|
|
|
data: {
|
|
|
userId: userData._id,
|
|
|
sno: userData.sno || '',
|
|
|
sname: userData.sname || '',
|
|
|
phone: userData.phone || '',
|
|
|
major: userData.major || '',
|
|
|
sushe: userData.sushe || '',
|
|
|
grade: userData.年级 || '',
|
|
|
avatar: userData.avatar || '',
|
|
|
openid: openid
|
|
|
}
|
|
|
};
|
|
|
} else {
|
|
|
return {
|
|
|
success: false,
|
|
|
error: '未找到用户信息',
|
|
|
openid: openid
|
|
|
};
|
|
|
}
|
|
|
} catch (e) {
|
|
|
console.error('查询用户信息失败:', e);
|
|
|
return {
|
|
|
success: false,
|
|
|
error: e.message
|
|
|
};
|
|
|
}
|
|
|
};
|
|
|
|
|
|
// 添加测试用户到T_user表
|
|
|
const addTestUser = async (event) => {
|
|
|
try {
|
|
|
const userData = event.userData || {
|
|
|
sno: "230340151",
|
|
|
sname: "测试用户",
|
|
|
phone: "13800138000",
|
|
|
password: "100997@mkg",
|
|
|
major: "计算机科学",
|
|
|
sushe: "1号楼 101",
|
|
|
年级: "大三",
|
|
|
avatar: "https://via.placeholder.com/100x100/4285F4/ffffff?text=T"
|
|
|
};
|
|
|
|
|
|
const result = await db.collection("T_user").add({
|
|
|
data: userData
|
|
|
});
|
|
|
|
|
|
return {
|
|
|
success: true,
|
|
|
data: result,
|
|
|
message: "测试用户添加成功"
|
|
|
};
|
|
|
} catch (e) {
|
|
|
return {
|
|
|
success: false,
|
|
|
error: e.message
|
|
|
};
|
|
|
}
|
|
|
};
|
|
|
|
|
|
// AI定价功能 - 调用Coze工作流分析商品图片
|
|
|
const analyzeProductPrice = async (event) => {
|
|
|
const axios = require('axios');
|
|
|
const FormData = require('form-data');
|
|
|
|
|
|
const COZE_API_TOKEN = 'pat_EB0pYMqiuAjIEnGK3i1e12RWwBjF5iZzrzMgdLQE8jNgZWVykJo6ZPGZ2YESYamq';
|
|
|
const COZE_UPLOAD_URL = 'https://api.coze.cn/v1/files/upload';
|
|
|
const COZE_WORKFLOW_URL = 'https://api.coze.cn/v1/workflow/run';
|
|
|
const WORKFLOW_ID = '7567021771821105167';
|
|
|
|
|
|
try {
|
|
|
console.log('========== AI定价功能开始 ==========');
|
|
|
console.log('接收到的参数:', JSON.stringify(event, null, 2));
|
|
|
|
|
|
// 获取参数
|
|
|
const { fileID, originalPrice, imageUrl } = event;
|
|
|
|
|
|
// 确保originalPrice是数字类型
|
|
|
const priceNum = originalPrice ? parseFloat(originalPrice) : null;
|
|
|
if (priceNum && isNaN(priceNum)) {
|
|
|
throw new Error('原价必须是有效的数字');
|
|
|
}
|
|
|
|
|
|
console.log('接收到的参数详情:');
|
|
|
console.log(' fileID:', fileID);
|
|
|
console.log(' originalPrice:', originalPrice, '类型:', typeof originalPrice);
|
|
|
console.log(' imageUrl:', imageUrl);
|
|
|
|
|
|
// 第一步:获取图片文件内容
|
|
|
let imageBuffer = null;
|
|
|
let fileName = 'image.jpg';
|
|
|
|
|
|
if (fileID) {
|
|
|
// 从云存储下载文件
|
|
|
console.log('步骤1: 从云存储下载文件, fileID:', fileID);
|
|
|
try {
|
|
|
if (!fileID || typeof fileID !== 'string') {
|
|
|
throw new Error('fileID参数无效');
|
|
|
}
|
|
|
|
|
|
const result = await cloud.downloadFile({
|
|
|
fileID: fileID
|
|
|
});
|
|
|
|
|
|
if (!result || !result.fileContent) {
|
|
|
throw new Error('下载文件结果为空');
|
|
|
}
|
|
|
|
|
|
imageBuffer = result.fileContent;
|
|
|
fileName = fileID.split('/').pop() || 'image.jpg';
|
|
|
|
|
|
// 确保imageBuffer是Buffer类型
|
|
|
if (!Buffer.isBuffer(imageBuffer)) {
|
|
|
imageBuffer = Buffer.from(imageBuffer);
|
|
|
}
|
|
|
|
|
|
console.log('✅ 文件下载成功,文件名:', fileName, '文件大小:', imageBuffer.length, 'bytes');
|
|
|
} catch (downloadError) {
|
|
|
console.error('❌ 下载云存储文件失败:', downloadError);
|
|
|
console.error('下载错误详情:', JSON.stringify(downloadError, Object.getOwnPropertyNames(downloadError)));
|
|
|
throw new Error('下载图片文件失败: ' + (downloadError.message || downloadError));
|
|
|
}
|
|
|
} else if (imageUrl) {
|
|
|
// 从URL下载图片
|
|
|
console.log('步骤1: 从URL下载图片, imageUrl:', imageUrl);
|
|
|
try {
|
|
|
if (!imageUrl || typeof imageUrl !== 'string') {
|
|
|
throw new Error('imageUrl参数无效');
|
|
|
}
|
|
|
|
|
|
const response = await axios.get(imageUrl, {
|
|
|
responseType: 'arraybuffer',
|
|
|
timeout: 30000 // 30秒超时
|
|
|
});
|
|
|
|
|
|
imageBuffer = Buffer.from(response.data);
|
|
|
fileName = imageUrl.split('/').pop().split('?')[0] || 'image.jpg';
|
|
|
console.log('✅ 图片下载成功,文件名:', fileName, '文件大小:', imageBuffer.length, 'bytes');
|
|
|
} catch (downloadError) {
|
|
|
console.error('❌ 下载图片失败:', downloadError);
|
|
|
console.error('下载错误详情:', downloadError.response?.data || downloadError.message);
|
|
|
throw new Error('下载图片失败: ' + (downloadError.message || downloadError));
|
|
|
}
|
|
|
} else {
|
|
|
throw new Error('缺少必要参数:需要提供fileID或imageUrl');
|
|
|
}
|
|
|
|
|
|
// 验证图片缓冲区
|
|
|
if (!imageBuffer || imageBuffer.length === 0) {
|
|
|
throw new Error('图片数据为空');
|
|
|
}
|
|
|
|
|
|
// 第二步:上传图片到Coze
|
|
|
console.log('步骤2: 上传图片到Coze');
|
|
|
let cozeFileId = null;
|
|
|
let uploadResponse = null; // 在外部声明,确保在返回时能访问
|
|
|
|
|
|
try {
|
|
|
if (!imageBuffer || imageBuffer.length === 0) {
|
|
|
throw new Error('图片数据为空,无法上传');
|
|
|
}
|
|
|
|
|
|
const formData = new FormData();
|
|
|
formData.append('file', imageBuffer, {
|
|
|
filename: fileName,
|
|
|
contentType: 'image/jpeg'
|
|
|
});
|
|
|
|
|
|
console.log('准备上传到Coze,文件大小:', imageBuffer.length, 'bytes');
|
|
|
|
|
|
uploadResponse = await axios.post(COZE_UPLOAD_URL, formData, {
|
|
|
headers: {
|
|
|
'Authorization': `Bearer ${COZE_API_TOKEN}`,
|
|
|
...formData.getHeaders()
|
|
|
},
|
|
|
timeout: 60000, // 60秒超时
|
|
|
maxContentLength: Infinity,
|
|
|
maxBodyLength: Infinity
|
|
|
});
|
|
|
|
|
|
console.log('✅ 图片上传到Coze成功');
|
|
|
console.log('上传响应数据:', JSON.stringify(uploadResponse.data, null, 2));
|
|
|
|
|
|
if (uploadResponse.data.code === 0 && uploadResponse.data.data && uploadResponse.data.data.id) {
|
|
|
cozeFileId = uploadResponse.data.data.id;
|
|
|
console.log('✅ 获取到Coze file_id:', cozeFileId);
|
|
|
} else {
|
|
|
throw new Error('上传响应格式错误: ' + JSON.stringify(uploadResponse.data));
|
|
|
}
|
|
|
} catch (uploadError) {
|
|
|
console.error('❌ 上传图片到Coze失败:', uploadError.response?.data || uploadError.message);
|
|
|
throw new Error('上传图片到Coze失败: ' + (uploadError.response?.data?.msg || uploadError.message));
|
|
|
}
|
|
|
|
|
|
// 第三步:调用Coze工作流
|
|
|
console.log('步骤3: 调用Coze工作流');
|
|
|
console.log('workflow_id:', WORKFLOW_ID);
|
|
|
console.log('file_id:', cozeFileId);
|
|
|
|
|
|
try {
|
|
|
// 根据curl示例,input参数应该是数字类型(原价)
|
|
|
// curl示例: "input": 30
|
|
|
// 不再需要inputText,直接使用priceNum
|
|
|
|
|
|
// 验证file_id
|
|
|
if (!cozeFileId || typeof cozeFileId !== 'string') {
|
|
|
throw new Error('Coze file_id无效: ' + cozeFileId);
|
|
|
}
|
|
|
|
|
|
// 根据API文档,image参数应该是字符串,内容是JSON格式的字符串
|
|
|
// 格式: "{\"file_id\":\"...\"}"
|
|
|
// 注意:需要手动构建JSON字符串,确保格式正确
|
|
|
const imageParam = JSON.stringify({ file_id: String(cozeFileId) });
|
|
|
|
|
|
// 验证image参数格式
|
|
|
try {
|
|
|
const imageObj = JSON.parse(imageParam);
|
|
|
if (!imageObj.file_id || typeof imageObj.file_id !== 'string') {
|
|
|
throw new Error('image参数格式错误: file_id无效');
|
|
|
}
|
|
|
console.log('✅ image参数格式验证通过:', imageObj);
|
|
|
} catch (parseError) {
|
|
|
console.error('❌ image参数格式验证失败:', parseError);
|
|
|
throw new Error('image参数格式错误: ' + parseError.message);
|
|
|
}
|
|
|
|
|
|
// 构建请求对象
|
|
|
const workflowRequest = {
|
|
|
workflow_id: String(WORKFLOW_ID),
|
|
|
parameters: {
|
|
|
image: imageParam, // JSON字符串: "{\"file_id\":\"7567222758887850038\"}"
|
|
|
input: Number(priceNum || 0) // 数字类型(原价),根据curl示例
|
|
|
}
|
|
|
};
|
|
|
|
|
|
// 验证最终请求格式
|
|
|
const testSerialize = JSON.stringify(workflowRequest);
|
|
|
console.log('测试序列化结果:', testSerialize);
|
|
|
const testParse = JSON.parse(testSerialize);
|
|
|
console.log('测试解析结果:', JSON.stringify(testParse, null, 2));
|
|
|
|
|
|
// 验证解析后的image参数格式
|
|
|
const parsedImage = JSON.parse(testParse.parameters.image);
|
|
|
console.log('解析后的image对象:', parsedImage);
|
|
|
if (!parsedImage.file_id) {
|
|
|
throw new Error('序列化后image参数格式错误');
|
|
|
}
|
|
|
|
|
|
// 打印最终发送的请求(序列化后的格式)
|
|
|
const requestBody = JSON.stringify(workflowRequest);
|
|
|
console.log('========== 请求参数详情 ==========');
|
|
|
console.log('工作流请求数据(序列化前):', JSON.stringify(workflowRequest, null, 2));
|
|
|
console.log('工作流请求数据(序列化后,将发送给API):', requestBody);
|
|
|
console.log('参数类型检查:');
|
|
|
console.log(' workflow_id类型:', typeof workflowRequest.workflow_id);
|
|
|
console.log(' workflow_id值:', workflowRequest.workflow_id);
|
|
|
console.log(' image类型:', typeof workflowRequest.parameters.image);
|
|
|
console.log(' image值:', workflowRequest.parameters.image);
|
|
|
console.log(' image值长度:', workflowRequest.parameters.image.length);
|
|
|
console.log(' image值解析:', JSON.parse(workflowRequest.parameters.image));
|
|
|
console.log(' input类型:', typeof workflowRequest.parameters.input);
|
|
|
console.log(' input值:', workflowRequest.parameters.input);
|
|
|
console.log('===================================');
|
|
|
|
|
|
// 验证input是数字类型
|
|
|
if (typeof workflowRequest.parameters.input !== 'number') {
|
|
|
throw new Error('input参数必须是数字类型,当前类型: ' + typeof workflowRequest.parameters.input);
|
|
|
}
|
|
|
|
|
|
// 模拟curl命令格式,用于对比
|
|
|
const curlFormat = JSON.stringify({
|
|
|
workflow_id: workflowRequest.workflow_id,
|
|
|
parameters: {
|
|
|
image: workflowRequest.parameters.image,
|
|
|
input: workflowRequest.parameters.input
|
|
|
}
|
|
|
}, null, 2);
|
|
|
console.log('预期格式(类似curl):', curlFormat);
|
|
|
console.log('✅ 参数格式验证通过,符合curl示例格式');
|
|
|
|
|
|
const workflowResponse = await axios.post(COZE_WORKFLOW_URL, workflowRequest, {
|
|
|
headers: {
|
|
|
'Authorization': `Bearer ${COZE_API_TOKEN}`,
|
|
|
'Content-Type': 'application/json'
|
|
|
},
|
|
|
timeout: 120000 // 120秒超时,因为AI分析可能需要较长时间
|
|
|
});
|
|
|
|
|
|
console.log('✅ Coze工作流HTTP请求成功');
|
|
|
console.log('HTTP状态码:', workflowResponse.status);
|
|
|
console.log('工作流响应数据:', JSON.stringify(workflowResponse.data, null, 2));
|
|
|
|
|
|
// 检查响应状态
|
|
|
if (workflowResponse.data.code !== 0) {
|
|
|
const errorData = workflowResponse.data;
|
|
|
console.error('❌ Coze API返回错误');
|
|
|
console.error('错误代码:', errorData.code);
|
|
|
console.error('错误消息:', errorData.msg);
|
|
|
console.error('错误详情:', errorData.detail);
|
|
|
console.error('调试URL:', errorData.debug_url);
|
|
|
|
|
|
// 如果是参数错误,提供更详细的诊断信息
|
|
|
if (errorData.code === 4000) {
|
|
|
console.error('参数错误诊断:');
|
|
|
console.error(' 发送的请求数据:', JSON.stringify(workflowRequest, null, 2));
|
|
|
console.error(' image参数原始值:', imageParam);
|
|
|
console.error(' input参数原始值:', inputText);
|
|
|
}
|
|
|
|
|
|
throw new Error(`Coze API错误 (${errorData.code}): ${errorData.msg || '未知错误'}`);
|
|
|
}
|
|
|
|
|
|
// 解析返回结果
|
|
|
let parsedResult = {};
|
|
|
if (workflowResponse.data.data) {
|
|
|
try {
|
|
|
// data字段是字符串,需要解析
|
|
|
const dataStr = typeof workflowResponse.data.data === 'string'
|
|
|
? workflowResponse.data.data
|
|
|
: JSON.stringify(workflowResponse.data.data);
|
|
|
|
|
|
const parsedData = JSON.parse(dataStr);
|
|
|
|
|
|
// 解析output字段
|
|
|
if (parsedData.output) {
|
|
|
let outputStr = typeof parsedData.output === 'string'
|
|
|
? parsedData.output
|
|
|
: JSON.stringify(parsedData.output);
|
|
|
|
|
|
console.log('步骤3.1: 原始output字符串:', outputStr);
|
|
|
|
|
|
// 尝试解析output中的JSON字符串
|
|
|
try {
|
|
|
// 处理多重转义的情况
|
|
|
// 如果output是被双重转义的JSON字符串,需要先解析一次
|
|
|
if (outputStr.startsWith('"') && outputStr.endsWith('"')) {
|
|
|
try {
|
|
|
outputStr = JSON.parse(outputStr);
|
|
|
console.log('步骤3.2: 解析外层引号后的output:', outputStr);
|
|
|
} catch (e) {
|
|
|
// 如果解析失败,继续使用原始字符串
|
|
|
console.warn('步骤3.2: 解析外层引号失败,继续使用原始字符串');
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 处理转义字符
|
|
|
let cleanedOutput = outputStr;
|
|
|
|
|
|
// 如果仍然是字符串,尝试多次解析转义
|
|
|
if (typeof cleanedOutput === 'string') {
|
|
|
// 尝试解析转义的JSON字符串
|
|
|
try {
|
|
|
// 如果看起来像转义的JSON,尝试解析
|
|
|
if (cleanedOutput.includes('\\"')) {
|
|
|
cleanedOutput = cleanedOutput.replace(/\\"/g, '"').replace(/\\n/g, '\n');
|
|
|
}
|
|
|
} catch (e) {
|
|
|
// 忽略解析错误
|
|
|
}
|
|
|
}
|
|
|
|
|
|
console.log('步骤3.3: 清理后的output:', cleanedOutput);
|
|
|
console.log('步骤3.3: output类型:', typeof cleanedOutput);
|
|
|
|
|
|
// 使用正则表达式提取字段值
|
|
|
// 匹配格式: "name":"值" 或 name:"值" 或 name=值
|
|
|
const outputContent = typeof cleanedOutput === 'string' ? cleanedOutput : JSON.stringify(cleanedOutput);
|
|
|
|
|
|
const nameMatch = outputContent.match(/["']?name["']?\s*[:=]\s*["']([^"']+)["']/);
|
|
|
const priceMatch = outputContent.match(/["']?price["']?\s*[:=]\s*["']([^"']+)["']/);
|
|
|
const chengseMatch = outputContent.match(/["']?chengse["']?\s*[:=]\s*["']([^"']+)["']/);
|
|
|
const gradeMatch = outputContent.match(/["']?grade["']?\s*[:=]\s*["']([^"']+)["']/);
|
|
|
const suggMatch = outputContent.match(/["']?sugg["']?\s*[:=]\s*["']([^"']+)["']/);
|
|
|
|
|
|
console.log('步骤3.4: 正则匹配结果:');
|
|
|
console.log(' name:', nameMatch ? nameMatch[1] : '未匹配');
|
|
|
console.log(' price:', priceMatch ? priceMatch[1] : '未匹配');
|
|
|
console.log(' chengse:', chengseMatch ? chengseMatch[1] : '未匹配');
|
|
|
console.log(' grade:', gradeMatch ? gradeMatch[1] : '未匹配');
|
|
|
console.log(' sugg:', suggMatch ? (suggMatch[1].substring(0, 50) + '...') : '未匹配');
|
|
|
|
|
|
// 如果正则匹配失败,尝试直接解析为JSON对象
|
|
|
let parsedOutput = null;
|
|
|
try {
|
|
|
// 尝试构建一个完整的JSON对象
|
|
|
if (outputContent.includes('name') && outputContent.includes('price')) {
|
|
|
// 尝试提取JSON部分
|
|
|
const jsonMatch = outputContent.match(/\{[\s\S]*\}/);
|
|
|
if (jsonMatch) {
|
|
|
parsedOutput = JSON.parse(jsonMatch[0]);
|
|
|
console.log('步骤3.5: 成功解析为JSON对象:', parsedOutput);
|
|
|
} else {
|
|
|
// 尝试手动构建JSON字符串
|
|
|
const jsonStr = '{' + outputContent.replace(/\n/g, ',') + '}';
|
|
|
try {
|
|
|
parsedOutput = JSON.parse(jsonStr);
|
|
|
console.log('步骤3.5: 成功构建并解析JSON对象:', parsedOutput);
|
|
|
} catch (e) {
|
|
|
// 忽略错误
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
} catch (e) {
|
|
|
console.warn('步骤3.5: 解析JSON对象失败:', e.message);
|
|
|
}
|
|
|
|
|
|
// 优先使用解析后的对象,否则使用正则匹配
|
|
|
parsedResult = {
|
|
|
productName: parsedOutput?.name || nameMatch?.[1] || '--',
|
|
|
suggestedPrice: parsedOutput?.price || priceMatch?.[1] || '0.00',
|
|
|
conditionLevel: parsedOutput?.chengse || chengseMatch?.[1] || '--',
|
|
|
aiScore: parsedOutput?.grade || gradeMatch?.[1] || '--',
|
|
|
analysisReport: parsedOutput?.sugg || suggMatch?.[1] || 'AI分析完成',
|
|
|
rawOutput: outputContent
|
|
|
};
|
|
|
|
|
|
console.log('✅ 步骤3.6: 最终解析结果:', JSON.stringify(parsedResult, null, 2));
|
|
|
} catch (parseError) {
|
|
|
console.warn('⚠️ 解析output失败,使用原始数据:', parseError.message);
|
|
|
console.warn('解析错误堆栈:', parseError.stack);
|
|
|
parsedResult = {
|
|
|
productName: '--',
|
|
|
suggestedPrice: originalPrice ? (originalPrice * 0.8).toFixed(2) : '0.00',
|
|
|
conditionLevel: '--',
|
|
|
aiScore: '--',
|
|
|
analysisReport: outputStr.substring(0, 200),
|
|
|
rawOutput: outputStr
|
|
|
};
|
|
|
}
|
|
|
} else {
|
|
|
parsedResult = {
|
|
|
productName: '--',
|
|
|
suggestedPrice: originalPrice ? (originalPrice * 0.8).toFixed(2) : '0.00',
|
|
|
conditionLevel: '--',
|
|
|
aiScore: '--',
|
|
|
analysisReport: 'AI分析完成,但未获取到详细信息',
|
|
|
rawOutput: dataStr
|
|
|
};
|
|
|
}
|
|
|
} catch (parseError) {
|
|
|
console.error('❌ 解析响应数据失败:', parseError);
|
|
|
parsedResult = {
|
|
|
productName: '--',
|
|
|
suggestedPrice: originalPrice ? (originalPrice * 0.8).toFixed(2) : '0.00',
|
|
|
conditionLevel: '--',
|
|
|
aiScore: '--',
|
|
|
analysisReport: '解析响应数据失败: ' + parseError.message,
|
|
|
rawResponse: workflowResponse.data
|
|
|
};
|
|
|
}
|
|
|
} else {
|
|
|
console.warn('⚠️ 工作流响应中没有data字段');
|
|
|
console.warn('响应内容:', JSON.stringify(workflowResponse.data, null, 2));
|
|
|
|
|
|
// 如果响应中没有data,返回默认结果
|
|
|
parsedResult = {
|
|
|
productName: '--',
|
|
|
suggestedPrice: originalPrice ? (originalPrice * 0.8).toFixed(2) : '0.00',
|
|
|
conditionLevel: '--',
|
|
|
aiScore: '--',
|
|
|
analysisReport: 'AI分析完成,但未获取到详细信息',
|
|
|
rawResponse: workflowResponse.data
|
|
|
};
|
|
|
}
|
|
|
|
|
|
console.log('========== AI定价功能完成 ==========');
|
|
|
|
|
|
return {
|
|
|
success: true,
|
|
|
data: parsedResult,
|
|
|
debug: {
|
|
|
uploadResponse: uploadResponse ? uploadResponse.data : null,
|
|
|
workflowResponse: workflowResponse.data
|
|
|
}
|
|
|
};
|
|
|
|
|
|
} catch (workflowError) {
|
|
|
console.error('❌ 调用Coze工作流失败');
|
|
|
console.error('错误对象:', workflowError);
|
|
|
console.error('错误响应:', workflowError.response?.data);
|
|
|
console.error('错误状态码:', workflowError.response?.status);
|
|
|
console.error('错误消息:', workflowError.message);
|
|
|
|
|
|
// 提取详细的错误信息
|
|
|
let errorMsg = '调用Coze工作流失败';
|
|
|
if (workflowError.response?.data) {
|
|
|
const errorData = workflowError.response.data;
|
|
|
errorMsg = errorData.msg || errorData.message || errorMsg;
|
|
|
if (errorData.detail) {
|
|
|
errorMsg += '\n详情: ' + JSON.stringify(errorData.detail);
|
|
|
}
|
|
|
if (errorData.code) {
|
|
|
errorMsg += '\n错误代码: ' + errorData.code;
|
|
|
}
|
|
|
} else {
|
|
|
errorMsg += ': ' + workflowError.message;
|
|
|
}
|
|
|
|
|
|
throw new Error(errorMsg);
|
|
|
}
|
|
|
|
|
|
} catch (error) {
|
|
|
console.error('========== AI定价功能出错 ==========');
|
|
|
console.error('错误信息:', error.message);
|
|
|
console.error('错误堆栈:', error.stack);
|
|
|
|
|
|
return {
|
|
|
success: false,
|
|
|
error: error.message,
|
|
|
details: error.response?.data || error.stack
|
|
|
};
|
|
|
}
|
|
|
};
|
|
|
|
|
|
// 云函数入口函数
|
|
|
exports.main = async (event, context) => {
|
|
|
try {
|
|
|
console.log('云函数被调用,type:', event.type);
|
|
|
console.log('event参数:', JSON.stringify(event, null, 2));
|
|
|
|
|
|
switch (event.type) {
|
|
|
case "getOpenId":
|
|
|
return await getOpenId();
|
|
|
case "getMiniProgramCode":
|
|
|
return await getMiniProgramCode();
|
|
|
case "createCollection":
|
|
|
return await createCollection();
|
|
|
case "selectRecord":
|
|
|
return await selectRecord();
|
|
|
case "updateRecord":
|
|
|
return await updateRecord(event);
|
|
|
case "insertRecord":
|
|
|
return await insertRecord(event);
|
|
|
case "deleteRecord":
|
|
|
return await deleteRecord(event);
|
|
|
case "queryTUser":
|
|
|
return await queryTUser();
|
|
|
case "addTestUser":
|
|
|
return await addTestUser(event);
|
|
|
case "analyzeProductPrice":
|
|
|
return await analyzeProductPrice(event);
|
|
|
case "getUserByOpenId":
|
|
|
return await getUserByOpenId(event);
|
|
|
default:
|
|
|
return {
|
|
|
success: false,
|
|
|
error: '未知的操作类型: ' + event.type
|
|
|
};
|
|
|
}
|
|
|
} catch (error) {
|
|
|
console.error('========== 云函数入口函数错误 ==========');
|
|
|
console.error('错误信息:', error.message);
|
|
|
console.error('错误堆栈:', error.stack);
|
|
|
console.error('event:', JSON.stringify(event, null, 2));
|
|
|
|
|
|
return {
|
|
|
success: false,
|
|
|
error: error.message || '云函数执行失败',
|
|
|
details: error.stack,
|
|
|
type: event.type
|
|
|
};
|
|
|
}
|
|
|
};
|