import { computed, reactive } from 'vue';
|
|
import * as Echarts from 'echarts';
|
import { upperFirst } from 'lodash-es';
|
|
import { getDataInterfaceRes } from '#/api/systemData/dataInterface';
|
import { $t } from '#/locales';
|
import { useBaseStore } from '#/store';
|
|
interface State {
|
searchSchemas: any[];
|
}
|
|
export const useReport = (formApi: any = {}) => {
|
const baseStore = useBaseStore();
|
const state = reactive<State>({
|
searchSchemas: [],
|
});
|
|
const searchSchemas = computed(() => state.searchSchemas);
|
|
// 更新图表数据
|
function getRealEchart(echarts, chartData) {
|
if (!echarts) return null;
|
Object.keys(echarts).forEach((key) => {
|
const chart = echarts[key];
|
const option = chart.option;
|
const styleType = option.styleType;
|
const colorList = option.color?.list || [];
|
let barTypeList = [];
|
if (chart.echartType === 'bar') barTypeList = option.bar.barTypeList;
|
const dataList = chartData.filter((o) => o.drawingId === key);
|
let data: any = {};
|
if (option.title.textI18nCode) option.title.text = $t(option.title.textI18nCode, option.title.text);
|
if (option.title.subtextI18nCode) option.title.subtext = $t(option.title.subtextI18nCode, option.title.subtext);
|
if (dataList.length) data = dataList[0].field;
|
const { classifyNameField = [], seriesDataField = [], seriesNameField = [], maxField = [] } = data;
|
// 柱状图和线性图
|
if (['bar', 'line'].includes(chart.echartType)) {
|
const series = seriesDataField?.map((o, index) => {
|
return {
|
name: seriesNameField[index],
|
data: o,
|
type: chart.echartType == 'bar' && styleType == 7 ? getEchartType(barTypeList, classifyNameField[index]) : chart.echartType,
|
itemStyle: { color: getColor(colorList, index) },
|
...(chart.echartType === 'line'
|
? {
|
smooth: styleType == 2,
|
step: styleType == 3,
|
stack: styleType == 4 ? 'total' : '',
|
lineStyle: { width: chart.line?.width },
|
symbolSize: chart.line?.symbolSize,
|
}
|
: {}),
|
...(chart.echartType === 'line' && option.areaStyle ? { areaStyle: option.areaStyle } : {}),
|
...(chart.echartType === 'bar'
|
? {
|
showBackground: styleType == 4,
|
stack: styleType == 5 || styleType == 7 ? seriesNameField[index] : styleType == 2 || styleType == 6 ? 'total' : '',
|
}
|
: ''),
|
};
|
});
|
chart.option.series = series;
|
chart.option.legend.data = seriesNameField;
|
chart.option.xAxis.data = classifyNameField;
|
}
|
// 饼图
|
if (chart.echartType === 'pie') {
|
const series = seriesDataField?.map((o, index) => {
|
const data = o?.map((item, sIndex) => {
|
return {
|
value: item,
|
name: classifyNameField?.[sIndex],
|
};
|
});
|
return {
|
name: seriesNameField[index],
|
type: 'pie',
|
radius: styleType == 2 ? ['30%', '60%'] : '50%',
|
center: [`${option.seriesCenter.seriesCenterLeft}%`, `${option.seriesCenter.seriesCenterTop}%`],
|
roseType: option.pie.roseType ? 'area' : '',
|
label: getLabel(option),
|
color: getPieColor(colorList),
|
data: getPieData(option.pie, data),
|
emphasis: {
|
itemStyle: {
|
shadowBlur: 10,
|
shadowOffsetX: 0,
|
shadowColor: 'rgba(0, 0, 0, 0.5)',
|
},
|
},
|
};
|
});
|
chart.option.series = series;
|
}
|
// 雷达图
|
if (chart.echartType === 'radar') {
|
let series: any = [];
|
const data: any = [];
|
const newMaxField: any = [];
|
for (const [index, element] of seriesDataField.entries()) {
|
if (!maxField.length) element.length && newMaxField.push(Math.max(...element));
|
const item = {
|
value: element,
|
name: seriesNameField?.[index],
|
areaStyle: { color: getColor(colorList, index), opacity: option.seriesAreaStyleOpacity },
|
};
|
data.push(item);
|
}
|
series = [
|
{
|
type: chart.echartType,
|
data,
|
},
|
];
|
if (!maxField.length) maxField.push(...newMaxField);
|
const indicator = maxField?.map((o, sIndex) => {
|
return {
|
max: o,
|
name: classifyNameField?.[sIndex],
|
};
|
});
|
const radarObj = {
|
axisName: option.radar.axisName,
|
indicator,
|
shape: styleType == 1 ? 'polygon' : 'circle',
|
center: [`${option.seriesCenter.seriesCenterLeft}%`, `${option.seriesCenter.seriesCenterTop}%`],
|
};
|
chart.option.series = series;
|
chart.option.radar = radarObj;
|
}
|
});
|
return echarts;
|
}
|
// 获取搜索内容
|
function getSearchSchema(queryList, sheetId?) {
|
if (!queryList.length) return (state.searchSchemas = []);
|
let item: any = [];
|
item = sheetId ? queryList.find((o) => o.sheet === sheetId) : queryList[0];
|
if (!item) return (state.searchSchemas = []);
|
const list = item.queryList || [];
|
const schemas = list.map((option: any) => {
|
const { label, type, vModel, config, searchMultiple } = option;
|
const field = vModel?.replace('.', '-');
|
const newType = getType(type);
|
if (type === 'select') {
|
config.fieldNames = { value: config.propsValue, label: config.propsLabel };
|
}
|
if (searchMultiple) config.multiple = true;
|
return {
|
field,
|
label,
|
component: newType,
|
componentProps: config,
|
};
|
});
|
// 异步更新 select 类型字段的 schema
|
for (const cur of schemas) {
|
const config = cur?.componentProps || {};
|
if (cur?.component === 'Select') {
|
if (config.dataType === 'dictionary' && config.dictionaryType) {
|
baseStore.getDicDataSelector(config.dictionaryType).then((res) => {
|
formApi.updateSchema([{ field: cur.field, componentProps: { options: res } }]);
|
});
|
} else if (config.dataType === 'dynamic' && config.propsUrl) {
|
const query = { paramList: config.templateJson || [] };
|
getDataInterfaceRes(config.propsUrl, query).then((res) => {
|
const data = Array.isArray(res.data) ? res.data : [];
|
formApi.updateSchema([{ field: cur.field, componentProps: { options: data } }]);
|
});
|
}
|
}
|
}
|
state.searchSchemas = schemas;
|
}
|
function clearSearchSchema() {
|
state.searchSchemas = [];
|
}
|
function getType(type) {
|
if (type == 'date') return 'DateRange';
|
if (type == 'time') return 'TimeRange';
|
if (type == 'inputNumber') return 'NumberRange';
|
return upperFirst(type);
|
}
|
function getColor(colorList, index) {
|
const barColor = colorList || [];
|
if (barColor[index]) {
|
const color1 = barColor[index].color1;
|
const color2 = barColor[index].color2;
|
if (color2 && color1)
|
return new Echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
{ offset: 0, color: color1 },
|
{ offset: 1, color: color2 },
|
]);
|
return color1;
|
}
|
}
|
function getLabel(option) {
|
const label: any = {};
|
label.show = option.label.show;
|
label.position = option.seriesLabelPosition;
|
const seriesLabelShowInfo = option.seriesLabelShowInfo;
|
if (seriesLabelShowInfo && seriesLabelShowInfo.length) {
|
if (seriesLabelShowInfo.includes('count') && seriesLabelShowInfo.includes('percent')) {
|
label.formatter = '{b}: {c} ({d}%)';
|
} else if (seriesLabelShowInfo.includes('count')) {
|
label.formatter = '{b}: {c} ';
|
} else if (seriesLabelShowInfo.includes('percent')) {
|
label.formatter = '{b}: ({d}%) ';
|
}
|
}
|
return label;
|
}
|
function getPieData(option, list) {
|
if (option.showZero) list = list.filter((item) => item.value != 0);
|
if (option.sortable) {
|
for (let i = 0; i < list.length - 1; i++) {
|
for (let j = 0; j < list.length - 1; j++) {
|
if (list[j].value > list[j + 1].value) {
|
const t = list[j];
|
list[j] = list[j + 1];
|
list[j + 1] = t;
|
}
|
}
|
}
|
}
|
return list;
|
}
|
function getPieColor(colorList) {
|
let colors: any = [];
|
if (colorList && colorList.length) {
|
const list: any[] = [];
|
colorList.map((item, index) => {
|
const color = getColor(colorList, index) || '#71B6F5';
|
list.push(color);
|
return item;
|
});
|
colors = list;
|
}
|
return colors;
|
}
|
function getEchartType(list, title) {
|
const arr = list.find((ele) => title == ele.id);
|
if (arr && arr.type) return arr.type;
|
}
|
|
return {
|
getRealEchart,
|
getSearchSchema,
|
searchSchemas,
|
clearSearchSchema,
|
};
|
};
|