export const allowedChartSpans = [12, 6, 4] export function isChartDefinition(definition) { return definition?.kind === 'chart' } export function buildDefaultChartInstance(definition, id) { const chartType = definition?.chartType || 'line' return { id, blockCode: definition.code, name: definition.name || definition.code, span: allowedChartSpans.includes(definition.defaultSpan) ? definition.defaultSpan : 12, config: {}, dataset: { schema: definition.datasetSchema || 'single-table-aggregate-v1', table: '', dimension: chartType === 'metric' ? null : { field: '', timeUnit: '' }, metrics: [{ field: '', aggregate: chartType === 'metric' ? 'count' : 'sum', alias: 'metric1', label: '指标 1' }], filters: [], dateRange: null, sort: chartType === 'metric' ? null : { by: 'dimension', order: 'asc' }, limit: chartType === 'pie' ? 10 : chartType === 'bar' ? 20 : chartType === 'metric' ? 1 : 100 }, display: { showTitle: true, showLegend: chartType !== 'metric', emptyText: '暂无数据', smooth: chartType === 'line', donut: chartType === 'pie', horizontal: false, stacked: false } } } export function updateChartDataset(block, dataset) { return { ...block, dataset: structuredClone(dataset || {}) } } export function updateChartDisplay(block, display) { return { ...block, display: structuredClone(display || {}) } } export function validateChartInstance(definition, block, tables) { const errors = [] const dataset = block?.dataset || {} const table = tables.find((item) => item.tableName === dataset.table) if (!table) { errors.push({ key: 'table', message: '请选择数据表' }) } if (definition?.chartType !== 'metric' && !dataset.dimension?.field) { errors.push({ key: 'dimension.field', message: '请选择维度字段' }) } if (!Array.isArray(dataset.metrics) || !dataset.metrics.length || dataset.metrics.some((item) => !item.field)) { errors.push({ key: 'metrics', message: '请配置指标字段' }) } return errors }