From d50a9a1b86d4d7afaa8dd084b80ac8af93516d3a Mon Sep 17 00:00:00 2001 From: Julian Freeman Date: Wed, 11 Mar 2026 13:21:34 -0400 Subject: [PATCH] fix bug --- google-script.js | 32 +++++++++++++++++--------------- sidepanel.js | 45 ++++++++++++++++++++++++++++++++++++--------- 2 files changed, 53 insertions(+), 24 deletions(-) diff --git a/google-script.js b/google-script.js index 7f2ef39..0ea3242 100644 --- a/google-script.js +++ b/google-script.js @@ -26,31 +26,33 @@ function doPost(e) { var headers = []; - // 2. If sheet is brand new (no rows), create headers first + // 2. Determine headers if (sheet.getLastRow() === 0) { - // Extract keys from data, excluding 'sheetName' which is a control parameter - headers = Object.keys(data).filter(function(key) { - return key !== "sheetName"; - }); + // Use provided headers if available + if (data.headers && Array.isArray(data.headers)) { + headers = data.headers; + } else { + // Fallback: Use keys but exclude internal control keys + headers = Object.keys(data).filter(function(key) { + return !["sheetName", "headers"].includes(key); + }); + } sheet.appendRow(headers); } else { - // 3. If sheet already exists, get existing headers from the first row + // Get existing headers from the first row var lastCol = sheet.getLastColumn(); if (lastCol > 0) { headers = sheet.getRange(1, 1, 1, lastCol).getValues()[0]; - } else { - // Fallback for edge cases where lastRow > 0 but lastCol is 0 - headers = Object.keys(data).filter(function(key) { - return key !== "sheetName"; - }); - sheet.appendRow(headers); } } - // 4. Map data to the determined headers + // 3. Map data to headers var row = headers.map(function(header) { - // data[header] might be undefined for some rows if schema changes - return data[header] !== undefined ? data[header] : "N/A"; + var val = data[header]; + if (val === undefined || val === null) return "N/A"; + // If value is an object or array, stringify it to avoid [Ljava.lang.Object] + if (typeof val === 'object') return JSON.stringify(val); + return val; }); sheet.appendRow(row); diff --git a/sidepanel.js b/sidepanel.js index bca6d32..026d2d6 100644 --- a/sidepanel.js +++ b/sidepanel.js @@ -157,29 +157,56 @@ async function handleExtraction(type, presetObj) { resultsArea.textContent = '正在发送至 Gemini...'; const systemPrompt = `你是一个专业的采购助手。 -请从以下文本中提取产品数据。 -将技术术语翻译成中文。 +请从以下网页文本中提取产品数据。 仅返回有效的 JSON 格式。 如果可能,将本地货币转换为美元,或者保留原始符号。 URL: ${pageData.url} Title: ${pageData.title}`; - const userPrompt = `提取以下字段:${presetObj.fields}。仅返回 JSON 格式。`; + const userPrompt = `提取以下字段:${presetObj.fields}。 +【重要约束】: +1. 必须使用我提供的字段名称作为 JSON 的键名(Key),不要翻译成英文。 +2. 将提取到的具体内容翻译成中文。 +3. 仅返回 JSON 格式,不要包含任何多余的解释文字。`; const geminiResult = await callGemini(geminiApiKey, selectedModel, systemPrompt, pageData.text, userPrompt); - const cleanedJson = parseGeminiJson(geminiResult); + let cleanedJson = parseGeminiJson(geminiResult); + + // 核心修复:处理 AI 返回数组的情况 + if (Array.isArray(cleanedJson)) { + cleanedJson = cleanedJson[0] || {}; + } resultsArea.textContent = JSON.stringify(cleanedJson, null, 2); if (googleScriptUrl) { updateStatus('保存至表格...', 'bg-purple-500 text-white'); - await sendToGoogleScript(googleScriptUrl, { - ...cleanedJson, - preset_type: presetObj.name || 'custom', + + // 1. 获取用户预设的业务表头 + const businessHeaders = presetObj.fields.split(',').map(f => f.trim()).filter(f => f !== ""); + + // 2. 定义元数据表头(可选,方便您追踪来源) + const metaHeaders = ["来源链接", "提取时间"]; + + // 3. 合并总表头顺序 + const allHeaders = [...businessHeaders, ...metaHeaders]; + + // 4. 构建发送给后端的最终数据 + const payload = { sheetName: presetObj.sheetName || '', - source_url: pageData.url, - timestamp: new Date().toISOString() + headers: allHeaders + }; + + // 将提取的数据填入 payload + businessHeaders.forEach(h => { + payload[h] = cleanedJson[h] || "N/A"; }); + + // 填入元数据 + payload["来源链接"] = pageData.url; + payload["提取时间"] = new Date().toLocaleString(); + + await sendToGoogleScript(googleScriptUrl, payload); updateStatus('成功', 'bg-green-500 text-white'); } else { updateStatus('完成 (未配置脚本链接)', 'bg-yellow-500 text-white');