|
|
|
@ -1,12 +1,158 @@
|
|
|
|
|
// 词云可视化(Cirrus)相关功能模块
|
|
|
|
|
// 负责词云数据生成、处理与可视化配置
|
|
|
|
|
|
|
|
|
|
export function generateWordCloudData(text) {
|
|
|
|
|
// TODO: 实现分词与词频统计,返回词云数据结构
|
|
|
|
|
return [];
|
|
|
|
|
// 中文常用停用词列表
|
|
|
|
|
const STOPWORDS = ['的', '了', '在', '是', '我', '有', '和', '就', '不', '人', '都', '一', '一个', '上', '也', '很', '到', '说', '要', '去', '你', '会', '着', '没有', '看', '好', '自己', '这'];
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 生成词云数据
|
|
|
|
|
* @param {string} text 输入文本
|
|
|
|
|
* @param {number} limit 最大词数
|
|
|
|
|
* @returns {Array} 词云数据数组
|
|
|
|
|
*/
|
|
|
|
|
export function generateWordCloudData(text, limit = 100) {
|
|
|
|
|
if (!text) return [];
|
|
|
|
|
|
|
|
|
|
// 简单分词 (仅用于示例,实际项目建议使用专业分词库)
|
|
|
|
|
let words = text
|
|
|
|
|
.replace(/[^\w\u4e00-\u9fa5]/g, ' ')
|
|
|
|
|
.split(/\s+/)
|
|
|
|
|
.filter(w => w && w.length > 1 && !STOPWORDS.includes(w));
|
|
|
|
|
|
|
|
|
|
// 统计词频
|
|
|
|
|
const freq = {};
|
|
|
|
|
words.forEach(w => {
|
|
|
|
|
freq[w] = (freq[w] || 0) + 1;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 转为数组并按频率排序
|
|
|
|
|
let arr = Object.entries(freq)
|
|
|
|
|
.map(([text, value]) => ({ text, value }))
|
|
|
|
|
.sort((a, b) => b.value - a.value)
|
|
|
|
|
.slice(0, limit);
|
|
|
|
|
|
|
|
|
|
return arr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 获取示例词云数据
|
|
|
|
|
* @returns {Array} 示例词云数据
|
|
|
|
|
*/
|
|
|
|
|
export function getSampleWordCloudData() {
|
|
|
|
|
return [
|
|
|
|
|
{ text: '航空', value: 120 },
|
|
|
|
|
{ text: '航班', value: 98 },
|
|
|
|
|
{ text: '飞机', value: 85 },
|
|
|
|
|
{ text: '数据', value: 76 },
|
|
|
|
|
{ text: '分析', value: 65 },
|
|
|
|
|
{ text: '系统', value: 60 },
|
|
|
|
|
{ text: '处理', value: 55 },
|
|
|
|
|
{ text: '可视化', value: 50 },
|
|
|
|
|
{ text: '统计', value: 48 },
|
|
|
|
|
{ text: '机场', value: 45 },
|
|
|
|
|
{ text: '旅客', value: 40 },
|
|
|
|
|
{ text: '信息', value: 38 },
|
|
|
|
|
{ text: '服务', value: 36 },
|
|
|
|
|
{ text: '航线', value: 34 },
|
|
|
|
|
{ text: '出发', value: 32 },
|
|
|
|
|
{ text: '到达', value: 30 },
|
|
|
|
|
{ text: '延误', value: 28 },
|
|
|
|
|
{ text: '安全', value: 26 },
|
|
|
|
|
{ text: '乘客', value: 25 },
|
|
|
|
|
{ text: '行李', value: 24 },
|
|
|
|
|
{ text: '票价', value: 22 },
|
|
|
|
|
{ text: '订票', value: 20 },
|
|
|
|
|
{ text: '登机', value: 18 },
|
|
|
|
|
{ text: '起飞', value: 16 },
|
|
|
|
|
{ text: '降落', value: 15 },
|
|
|
|
|
{ text: '国际', value: 45 },
|
|
|
|
|
{ text: '航空公司', value: 75 },
|
|
|
|
|
{ text: '时刻表', value: 35 },
|
|
|
|
|
{ text: '客运', value: 28 },
|
|
|
|
|
{ text: '联程', value: 23 },
|
|
|
|
|
{ text: '机组', value: 22 },
|
|
|
|
|
{ text: '头等舱', value: 19 },
|
|
|
|
|
{ text: '商务舱', value: 17 },
|
|
|
|
|
{ text: '经济舱', value: 15 },
|
|
|
|
|
{ text: '转机', value: 32 },
|
|
|
|
|
{ text: '值机', value: 26 }
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function getWordCloudOptions(data) {
|
|
|
|
|
// TODO: 返回词云图表的配置项
|
|
|
|
|
return {};
|
|
|
|
|
/**
|
|
|
|
|
* 获取词云配置
|
|
|
|
|
* @param {Array} data 词云数据
|
|
|
|
|
* @param {Object} options 自定义配置
|
|
|
|
|
* @returns {Object} ECharts配置项
|
|
|
|
|
*/
|
|
|
|
|
export function getWordCloudOptions(data, options = {}) {
|
|
|
|
|
const defaultOptions = {
|
|
|
|
|
sizeRange: [14, 60],
|
|
|
|
|
rotationRange: [-90, 90],
|
|
|
|
|
shape: 'circle',
|
|
|
|
|
fontFamily: '"Microsoft YaHei", "微软雅黑", Arial, sans-serif',
|
|
|
|
|
colorMode: 'random' // 'random' 或 'gradient'
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const mergedOptions = { ...defaultOptions, ...options };
|
|
|
|
|
|
|
|
|
|
// 颜色函数
|
|
|
|
|
let colorFunction;
|
|
|
|
|
if (mergedOptions.colorMode === 'random') {
|
|
|
|
|
const colors = [
|
|
|
|
|
'#1890FF', '#2FC25B', '#FACC14', '#223273', '#8543E0',
|
|
|
|
|
'#13C2C2', '#3436C7', '#F04864', '#EE6666', '#749F83',
|
|
|
|
|
'#CA8622', '#409EFF', '#36CBCB', '#FFA74D', '#4B7AF0'
|
|
|
|
|
];
|
|
|
|
|
colorFunction = function(params) {
|
|
|
|
|
return colors[Math.abs(params.data.text.charCodeAt(0)) % colors.length];
|
|
|
|
|
};
|
|
|
|
|
} else {
|
|
|
|
|
// 渐变色
|
|
|
|
|
colorFunction = function(params) {
|
|
|
|
|
// 根据值大小返回不同深浅的颜色
|
|
|
|
|
const maxValue = data.length > 0 ? data[0].value : 100;
|
|
|
|
|
const ratio = params.data.value / maxValue;
|
|
|
|
|
// 从蓝色到红色的渐变
|
|
|
|
|
const r = Math.round(255 * ratio);
|
|
|
|
|
const b = Math.round(255 * (1 - ratio));
|
|
|
|
|
return `rgb(${r}, 100, ${b})`;
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
series: [{
|
|
|
|
|
type: 'wordCloud',
|
|
|
|
|
shape: mergedOptions.shape,
|
|
|
|
|
left: 'center',
|
|
|
|
|
top: 'center',
|
|
|
|
|
width: '90%',
|
|
|
|
|
height: '90%',
|
|
|
|
|
sizeRange: mergedOptions.sizeRange,
|
|
|
|
|
rotationRange: mergedOptions.rotationRange,
|
|
|
|
|
rotationStep: 45,
|
|
|
|
|
gridSize: 8,
|
|
|
|
|
drawOutOfBound: false,
|
|
|
|
|
textStyle: {
|
|
|
|
|
fontFamily: mergedOptions.fontFamily,
|
|
|
|
|
fontWeight: 'bold',
|
|
|
|
|
color: colorFunction
|
|
|
|
|
},
|
|
|
|
|
emphasis: {
|
|
|
|
|
textStyle: {
|
|
|
|
|
fontWeight: 'bold',
|
|
|
|
|
shadowBlur: 10,
|
|
|
|
|
shadowColor: '#333'
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
// 新增动画配置
|
|
|
|
|
layoutAnimation: true,
|
|
|
|
|
animationDuration: 1000,
|
|
|
|
|
animationEasing: 'cubicOut',
|
|
|
|
|
animationDelay: function (idx) {
|
|
|
|
|
return idx * 100;
|
|
|
|
|
},
|
|
|
|
|
data: data
|
|
|
|
|
}]
|
|
|
|
|
};
|
|
|
|
|
}
|