fix bug
This commit is contained in:
@@ -26,31 +26,33 @@ function doPost(e) {
|
|||||||
|
|
||||||
var headers = [];
|
var headers = [];
|
||||||
|
|
||||||
// 2. If sheet is brand new (no rows), create headers first
|
// 2. Determine headers
|
||||||
if (sheet.getLastRow() === 0) {
|
if (sheet.getLastRow() === 0) {
|
||||||
// Extract keys from data, excluding 'sheetName' which is a control parameter
|
// Use provided headers if available
|
||||||
headers = Object.keys(data).filter(function(key) {
|
if (data.headers && Array.isArray(data.headers)) {
|
||||||
return key !== "sheetName";
|
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);
|
sheet.appendRow(headers);
|
||||||
} else {
|
} else {
|
||||||
// 3. If sheet already exists, get existing headers from the first row
|
// Get existing headers from the first row
|
||||||
var lastCol = sheet.getLastColumn();
|
var lastCol = sheet.getLastColumn();
|
||||||
if (lastCol > 0) {
|
if (lastCol > 0) {
|
||||||
headers = sheet.getRange(1, 1, 1, lastCol).getValues()[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) {
|
var row = headers.map(function(header) {
|
||||||
// data[header] might be undefined for some rows if schema changes
|
var val = data[header];
|
||||||
return data[header] !== undefined ? data[header] : "N/A";
|
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);
|
sheet.appendRow(row);
|
||||||
|
|||||||
45
sidepanel.js
45
sidepanel.js
@@ -157,29 +157,56 @@ async function handleExtraction(type, presetObj) {
|
|||||||
resultsArea.textContent = '正在发送至 Gemini...';
|
resultsArea.textContent = '正在发送至 Gemini...';
|
||||||
|
|
||||||
const systemPrompt = `你是一个专业的采购助手。
|
const systemPrompt = `你是一个专业的采购助手。
|
||||||
请从以下文本中提取产品数据。
|
请从以下网页文本中提取产品数据。
|
||||||
将技术术语翻译成中文。
|
|
||||||
仅返回有效的 JSON 格式。
|
仅返回有效的 JSON 格式。
|
||||||
如果可能,将本地货币转换为美元,或者保留原始符号。
|
如果可能,将本地货币转换为美元,或者保留原始符号。
|
||||||
URL: ${pageData.url}
|
URL: ${pageData.url}
|
||||||
Title: ${pageData.title}`;
|
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 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);
|
resultsArea.textContent = JSON.stringify(cleanedJson, null, 2);
|
||||||
|
|
||||||
if (googleScriptUrl) {
|
if (googleScriptUrl) {
|
||||||
updateStatus('保存至表格...', 'bg-purple-500 text-white');
|
updateStatus('保存至表格...', 'bg-purple-500 text-white');
|
||||||
await sendToGoogleScript(googleScriptUrl, {
|
|
||||||
...cleanedJson,
|
// 1. 获取用户预设的业务表头
|
||||||
preset_type: presetObj.name || 'custom',
|
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 || '',
|
sheetName: presetObj.sheetName || '',
|
||||||
source_url: pageData.url,
|
headers: allHeaders
|
||||||
timestamp: new Date().toISOString()
|
};
|
||||||
|
|
||||||
|
// 将提取的数据填入 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');
|
updateStatus('成功', 'bg-green-500 text-white');
|
||||||
} else {
|
} else {
|
||||||
updateStatus('完成 (未配置脚本链接)', 'bg-yellow-500 text-white');
|
updateStatus('完成 (未配置脚本链接)', 'bg-yellow-500 text-white');
|
||||||
|
|||||||
Reference in New Issue
Block a user