UNPKG

chart-mcp-service

Version:

MCP服务,实现根据输入自动生成对应图表的功能

395 lines 13.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ChartRules = void 0; class ChartRules { constructor() { this.chartPatterns = { line: [ "趋势", "时间", "走势", "变化", "增长", "下降", "发展", "历史", "序列", "时序", "折线", "trend", "time", "series", "growth", "change", "history", "timeline", ], bar: [ "对比", "比较", "排名", "排行", "分类", "统计", "数量", "柱状", "条形", "直方", "compare", "ranking", "category", "count", "statistics", "comparison", ], pie: [ "占比", "比例", "分布", "构成", "份额", "百分比", "饼图", "环形", "圆形", "percentage", "proportion", "composition", "share", "distribution", "pie", ], area: [ "面积", "区域", "填充", "堆叠", "累积", "累计", "叠加", "area", "filled", "stacked", "cumulative", "accumulate", ], scatter: [ "散点", "相关性", "关联", "分散", "聚类", "点图", "关系", "scatter", "correlation", "relationship", "cluster", "point", ], radar: [ "雷达", "多维", "能力", "评估", "评价", "指标", "维度", "蜘蛛", "radar", "multidimensional", "capability", "assessment", "metrics", "spider", ], heatmap: [ "热力", "热图", "密度", "强度", "活跃度", "热度", "频率", "heatmap", "density", "intensity", "activity", "frequency", "heat", ], wordcloud: [ "词云", "文字云", "标签云", "关键词", "词频", "词汇", "wordcloud", "tag cloud", "keywords", "word frequency", "text cloud", ], strip: [ "水平", "条形", "横向", "分布", "范围", "区间", "horizontal", "strip", "range", "distribution", "interval", ], sankey: [ "流向", "流程", "流量", "桑基", "河流", "流向图", "flow", "sankey", "stream", "process flow", "flow diagram", ], treemap: [ "树图", "矩形", "层级", "嵌套", "树状", "分层", "treemap", "hierarchy", "nested", "rectangular", "tree structure", ], }; this.bestPractices = { line: [ "使用合适的时间格式作为X轴", "确保数据点连续性", "使用seriesField区分多条线", "设置合适的point大小", "配置smooth属性增强视觉效果", ], bar: [ "合理设置柱状图宽度比例(columnWidthRatio)", "使用seriesField实现分组或堆叠", "配置isStack属性用于堆叠展示", "支持正负值混合展示", "添加交互增强用户体验", ], pie: [ "使用colorField指定扇形的颜色映射字段", "设置合适的radius值(建议0.8)", "配置label类型为outer提升可读性", "控制扇形数量避免过多分类", "使用angleField控制扇形大小", ], area: [ "设置合适的fillOpacity值", "使用seriesField实现堆叠面积图", "配置point属性增强数据点显示", "注意颜色搭配保证视觉效果", "支持多系列数据对比", ], heatmap: [ "使用colorField进行热力值映射", "选择合适的颜色渐变方案", "确保xField和yField数据格式正确", "配置合适的色阶范围", "添加数值标签提升可读性", ], wordcloud: [ "使用wordField和weightField配置词云", "设置合适的字体大小范围", "控制词汇数量避免过度拥挤", "选择合适的布局算法", "配置rotation属性控制文字方向", ], strip: [ "使用x和y字段命名保持一致性", "为每个类别添加多个数据点", "设置合适的坐标轴标题和范围", "配置共享tooltip提升用户体验", "图例位置优先设置在顶部", ], }; } async identifyChartType(description) { const normalizedDesc = description.toLowerCase(); const scores = {}; const matchedKeywords = {}; // 计算每种图表类型的匹配分数 for (const [chartType, keywords] of Object.entries(this.chartPatterns)) { scores[chartType] = 0; matchedKeywords[chartType] = []; for (const keyword of keywords) { if (normalizedDesc.includes(keyword.toLowerCase())) { scores[chartType] += 1; matchedKeywords[chartType].push(keyword); } } } // 找到得分最高的图表类型 const maxScore = Math.max(...Object.values(scores)); const bestType = Object.keys(scores).find((type) => scores[type] === maxScore) || "bar"; // 计算置信度 const totalKeywords = Object.values(this.chartPatterns).flat().length; const confidence = Math.min((maxScore / 5) * 100, 100); // 生成推理原因 const reasons = matchedKeywords[bestType].length > 0 ? [`匹配关键词: ${matchedKeywords[bestType].join(", ")}`] : ["基于默认推荐"]; // 生成建议 const suggestions = this.generateSuggestions(bestType, description); return { type: bestType, confidence, reasons, suggestions, }; } generateSuggestions(chartType, description) { const suggestions = [ `建议使用 ${this.getChartTypeName(chartType)} 来展示您的数据`, `推荐导入: import { ${this.getComponentName(chartType)}, ${this.getComponentName(chartType)}Props } from '@alife/bi-material-center-chart'`, ]; // 添加特定的配置建议 if (chartType === "bar" && description.includes("堆叠")) { suggestions.push("配置 isStack: true 实现堆叠效果"); } if (chartType === "line" && description.includes("多")) { suggestions.push("使用 seriesField 区分多条折线"); } if (chartType === "pie") { suggestions.push("使用 colorField 和 angleField 配置饼图"); } return suggestions; } getChartTypeName(type) { const names = { line: "折线图", bar: "柱状图", pie: "饼图", area: "面积图", scatter: "散点图", radar: "雷达图", heatmap: "热力图", wordcloud: "词云图", strip: "水平条形图", sankey: "桑基图", treemap: "矩形树图", }; return names[type] || type; } getComponentName(type) { const components = { line: "Line", bar: "Bar", pie: "Pie", area: "Area", scatter: "Scatter", radar: "Radar", heatmap: "Heatmap", wordcloud: "WordCloud", strip: "Strip", sankey: "Sankey", treemap: "Treemap", }; return components[type] || "Bar"; } async getChartRules(type) { if (type) { return { type, patterns: this.chartPatterns[type] || [], bestPractices: this.bestPractices[type] || [], componentName: this.getComponentName(type), typeName: this.getChartTypeName(type), }; } return { patterns: this.chartPatterns, bestPractices: this.bestPractices, supportedTypes: Object.keys(this.chartPatterns), }; } async getBestPractices(type) { return { type, typeName: this.getChartTypeName(type), practices: this.bestPractices[type] || [], generalPractices: [ "设置合适的图表高度(默认500px)", "配置图例位置(优先顶部)", "开启共享tooltip提升用户体验", "使用合适的颜色配置方案", "确保数据结构符合组件要求", ], }; } async validateChartConfig(type, config) { const errors = []; const warnings = []; const suggestions = []; // 基础验证 if (!config.data || !Array.isArray(config.data)) { errors.push("缺少有效的data数组"); } if (!config.height || typeof config.height !== "number") { warnings.push("建议设置图表高度,默认500px"); } // 特定图表类型验证 switch (type) { case "line": if (!config.xField) errors.push("折线图缺少xField配置"); if (!config.yField) errors.push("折线图缺少yField配置"); if (config.seriesField) suggestions.push("使用seriesField实现多条折线对比"); break; case "bar": if (!config.xField) errors.push("柱状图缺少xField配置"); if (!config.yField) errors.push("柱状图缺少yField配置"); if (config.isStack && !config.seriesField) { warnings.push("堆叠柱状图建议配置seriesField"); } break; case "pie": if (!config.angleField) errors.push("饼图缺少angleField配置"); if (!config.colorField) errors.push("饼图缺少colorField配置"); break; case "area": if (!config.xField) errors.push("面积图缺少xField配置"); if (!config.yField) errors.push("面积图缺少yField配置"); break; } // 颜色配置验证 if (config.colorField && config.seriesField) { warnings.push("同时配置colorField和seriesField可能导致冲突,建议优先使用seriesField"); } return { valid: errors.length === 0, errors, warnings, suggestions, }; } } exports.ChartRules = ChartRules; //# sourceMappingURL=rules.js.map