/** * buildChatGPTChartHtml — ChatGPT charts_widget_v2 数据 → 完整渲染 HTML * * 单一事实源:backend-service(本目录)与桌面 APP(xwx-backup/app/src-tauri/pdf-render/) * 共用同一份实现。桌面端通过 make/build-pdf-render-assets.mjs 同步并做指纹校验。 * 提取自 server.js WidgetRenderer.buildChatGPTChatHtml 原实现(函数体逐字节一致, * 仅类方法→独立函数)。修改时保持两端同步流程:先改这里,再跑 make 脚本同步。 */ function buildChatGPTChartHtml(chartType, series, data, xKey, nameKey, valueKey, formattedData, axes, title, description) { // ChatGPT official chart color palette (extracted from live ChatGPT web) // ChatGPT official chart color palette (first 4) + D3 schemeCategory10 extended (10 total) // D3 schemeCategory10: industry-standard categorical palette, colorblind-friendly const COLORS = ['#339CFF', '#40C977', '#FF8549', '#FFD240', '#6366f1', '#ec4899', '#14b8a6', '#f97316', '#8b5cf6', '#06b6d4']; // Serialize data safely for inline script const dataJson = JSON.stringify(data || []) .replace(/<\/script/gi, '<\\/script'); const seriesJson = JSON.stringify(series || []) .replace(/<\/script/gi, '<\\/script'); const chartTypeJson = JSON.stringify(chartType || 'bar') .replace(/<\/script/gi, '<\\/script'); const titleJson = JSON.stringify(title || '') .replace(/<\/script/gi, '<\\/script'); const descJson = JSON.stringify(description || '') .replace(/<\/script/gi, '<\\/script'); const xKeyJson = JSON.stringify(xKey || 'x') .replace(/<\/script/gi, '<\\/script'); const nameKeyJson = JSON.stringify(nameKey || '') .replace(/<\/script/gi, '<\\/script'); const valueKeyJson = JSON.stringify(valueKey || '') .replace(/<\/script/gi, '<\\/script'); const formattedDataJson = JSON.stringify(formattedData || []) .replace(/<\/script/gi, '<\\/script'); const axesJson = JSON.stringify(axes || []) .replace(/<\/script/gi, '<\\/script'); return `