import { cloneDeep } from 'lodash'; const returnFields = (str) => { let _arr = []; let list = str.matchAll(/\$\{[^}\s]+}/g); // ${水箱个数} // _arr = [...list].map(item => item[0].replace(/[${}]/g, '')); [...list].forEach(item => { let _item = item[0].replace(/[${}]/g, '').split(','); _arr = _arr.concat(_item); }); return _arr; }; const handleMaxValue = (value) => { if (value <= 1) return value.toFixed(2); if (value >= 100000) return `${(value / 1000).toFixed(2)}k`; return value.toFixed(2); }; const reduceYAxis = (arr, opt) => { let _offsetValue = []; // 1. 合并相同单位的坐标轴 let _arr = arr.reduce((final, cur) => { let _key = cur.name === null ? 'null' : cur.name; if (!final[_key]) { final[_key] = cur; } return final; }, {}); // 2. 合并相同单位的数据,找出最大值 let _maxValueArr = Object.values( opt.series.reduce((final, cur, index) => { let _key = `${opt.title.text || 'NoKey'}_${index}`; let _maxValue = cur?.data?.reduce((final, num) => { // eslint-disable-next-line no-param-reassign if (Number(num) > final) final = Number(num); return final; }, 0); if (final[_key] === undefined) { final[_key] = _maxValue; } else { final[_key] = Math.max([final[_key], _maxValue]); } return final; }, {}), ); // 3. 合并,生成Y轴配置 return Object.values(_arr).map((item, index) => { let _key = item.name === null ? 'null' : item.name; let _lastAxisNumber = _maxValueArr[index - 2]; let _baseOffset = _offsetValue[index - 2] ?? 0; let _finalOffset = (_lastAxisNumber !== undefined // 没有相邻的轴 ? (_lastAxisNumber === 0 ? 20 : _lastAxisNumber.toFixed(2).replaceAll('.', '').length) * 12 : 0) + _baseOffset; _offsetValue.push(_finalOffset); return { ...item, offset: _finalOffset, position: index % 2 === 0 ? 'left' : 'right', nameTextStyle: { align: index % 2 === 0 ? 'right' : 'left', }, }; }); }; const handleYAxis = (opt) => { const yAxisMap = new Map(); // 1. 找出最大值; 2. 计算出y轴最大宽度动态计算偏移距离; opt?.series?.forEach((item, index) => { const { custom_config } = item; const key = custom_config.unit; if (!yAxisMap.has(key)) { const axis = { type: 'value', name: custom_config.unit, axisLabel: { formatter: (value) => { return handleMaxValue(value); }, }, axisLine: { show: true, }, minorTick: { lineStyle: { color: '#e2e2e2', }, }, minorSplitLine: { lineStyle: { color: '#e2e2e2', type: 'dashed', }, }, }; yAxisMap.set(key, axis); } }); return yAxisMap.size > 0 ? reduceYAxis([...yAxisMap.values()], opt) : { type: 'value' }; }; /** * 1. 解析图表的配置,并且处理数据 * @param {Array} chartOptions 配置的json字符串 * @param {Array:[{[string]:[any]}]} columnsData 配置的数据数组 [{分公司:'',业绩:100}] * @param rowData * */ const returnOptionsArr = (chartOptions, columnsData, rowData) => { let _keysArr = []; //1. 将数据转换成 { // 分公司:[江西,湖北,湖南] // 业绩: [1,2,3] // } let _dataMap = columnsData.reduce((final, cur, index) => { if (index === 0) _keysArr = Object.keys(cur); _keysArr.forEach(key => { if (!final[key]) final[key] = []; final[key].push(cur[key]); }); return final; }, {}); //2. 解析${分公司}这种字符串,替换掉数据 let _optionsArr = cloneDeep(chartOptions).map(item => { let _item = cloneDeep(item); if (!_item) return null; if (_item?.custom_config?.renderBy === 'allData') { // ${分公司} -> 分公司 let _key = _item.xAxis.data.replace(/[${}]/g, ''); // 给x轴赋值 _item.xAxis.data = _dataMap[_key]; // 处理系列内的配置 _item.series = _item.series.map(obj => { let _obj = { ...obj }; let _objKey = _obj.data.replace(/[${}]/g, ''); // 赋值数据 _obj.data = _dataMap[_objKey]; return _obj; }); } if (_item?.custom_config?.renderBy === 'selectedData') { // 勾选的交互方式,只允许配置一种类型的曲线 let _config = _item?.series?.[0] ?? {}; let _keys = _config?.data?.replaceAll(/[$\[\]]/g, '')?.split(',') ?? []; let _xAxisArr = _item.xAxis.data; _item.series = rowData.map(row => { return { ..._config, data: _xAxisArr.map(field => row[field]), name: _keys.map(key => row[key]).join('-'), }; }); } return _item; }); // 3. 配置通用属性,未在配置功能里展示 _optionsArr = cloneDeep(_optionsArr).map(item => { if (!item) return null; item.grid = { ...item.grid, containLabel: true, }; item.legend = { ...item.legend, padding: [2, 8] }; if (item?.dataZoom?.show) { item.dataZoom = [ { show: true, start: 0, end: 100, type: 'slider', height: 20 }, { type: 'inside', start: 0, end: 100 }, ]; } // 多轴问题 let yAxis = handleYAxis(item); item.yAxis = yAxis; item.series.forEach(_series => { _series.yAxisIndex = yAxis.find(axis => axis.unit === _series.custom_config.unit); }); return item; }); return _optionsArr; }; export { returnFields, returnOptionsArr, };