'use strict'; const { ensureObjectPayload, toInt } = require('./helpers'); const { sanitizeQueryBlockConfig, buildChartSnapshotPayload, buildTableSnapshotPayload, buildKpiSnapshotPayload, } = require('./chartSnapshot'); const { analyzeBlockSnapshotWithPrompt } = require('./ai'); const normalizeOptionalString = value => { const normalized = String(value || '').trim(); return normalized || null; }; const deepCloneJson = value => { if (value === null || value === undefined) return value; return JSON.parse(JSON.stringify(value)); }; const rewriteAiAnalysisConfig = (config = {}, blockIdMap = null) => { const nextConfig = deepCloneJson(config) || {}; if (!(blockIdMap instanceof Map) || !blockIdMap.size) { return sanitizeQueryBlockConfig(nextConfig); } const sourceTemplateBlockId = toInt( nextConfig.sourceTemplateBlockId || nextConfig.sourceBlockId || nextConfig.linkedBlockId ); if (!sourceTemplateBlockId) return sanitizeQueryBlockConfig(nextConfig); const resolvedBlockId = blockIdMap.get(String(sourceTemplateBlockId)); if (resolvedBlockId) { nextConfig.sourceBlockId = resolvedBlockId; nextConfig.linkedBlockId = resolvedBlockId; } delete nextConfig.sourceTemplateBlockId; return sanitizeQueryBlockConfig(nextConfig); }; const resolveBlockPayload = async (ctx, options = {}) => { const normalizedBlockType = String(options?.blockType || 'text').trim().toLowerCase(); const safeConfig = ensureObjectPayload(options?.config || {}, 'config'); const safeSnapshot = deepCloneJson(options?.contentSnapshot) || null; const dataSourceId = toInt(options?.dataSourceId); const transaction = options?.transaction || null; if (normalizedBlockType === 'chart') { if (!dataSourceId) throw '缺少参数: dataSourceId'; return buildChartSnapshotPayload( ctx, dataSourceId, safeConfig, transaction, safeSnapshot ); } if (normalizedBlockType === 'table') { if (!dataSourceId) throw '缺少参数: dataSourceId'; return buildTableSnapshotPayload(ctx, dataSourceId, safeConfig, transaction); } if (normalizedBlockType === 'kpi') { if (!dataSourceId) throw '缺少参数: dataSourceId'; return buildKpiSnapshotPayload(ctx, dataSourceId, safeConfig, transaction); } return { config: sanitizeQueryBlockConfig(safeConfig), contentSnapshot: safeSnapshot, }; }; const finalizeResolvedBlockPayload = async (ctx, options = {}) => { const normalizedBlockType = String(options?.blockType || 'text').trim().toLowerCase(); const baseConfig = ensureObjectPayload(options?.config || {}, 'config'); const safeSnapshot = deepCloneJson(options?.contentSnapshot) || null; if (normalizedBlockType !== 'ai_analysis') { return { config: sanitizeQueryBlockConfig(baseConfig), contentSnapshot: safeSnapshot, }; } const rewrittenConfig = rewriteAiAnalysisConfig(baseConfig, options?.blockIdMap || null); const sourceBlockId = toInt(rewrittenConfig.sourceBlockId || rewrittenConfig.linkedBlockId); const prompt = normalizeOptionalString(rewrittenConfig.prompt); if (!sourceBlockId || !prompt || typeof options?.getCreatedBlockStateByInstanceId !== 'function') { return { config: rewrittenConfig, contentSnapshot: safeSnapshot, }; } const sourceBlockState = options.getCreatedBlockStateByInstanceId(sourceBlockId); if (!sourceBlockState) { return { config: rewrittenConfig, contentSnapshot: safeSnapshot, }; } let content = ''; try { content = await analyzeBlockSnapshotWithPrompt(ctx, { actionId: `report-block:${sourceBlockState.createdId || sourceBlockId}`, prompt, sourceBlock: { id: sourceBlockState.createdId || sourceBlockId, blockType: sourceBlockState.blockType, config: sourceBlockState.config || {}, contentSnapshot: sourceBlockState.contentSnapshot || null, }, }); } catch (error) { content = normalizeOptionalString(safeSnapshot?.content) || `AI 分析生成失败: ${error?.message || error || '未知错误'}`; } return { config: rewrittenConfig, contentSnapshot: { kind: 'ai_analysis', content, }, }; }; module.exports = { resolveBlockPayload, finalizeResolvedBlockPayload, rewriteAiAnalysisConfig, };