chart-mcp-service
Version:
MCP服务,实现根据输入自动生成对应图表的功能
395 lines • 13.2 kB
JavaScript
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
;