利用:
import ECharts from 'vue-echarts';
Vue.component('MyChart', ECharts);
mixins: [ShopAnalysisChartMixin],
props: {
params: {
type: Object,
default: () => ({})
}
},
<my-chart
ref="queueChart"
class="charts"
autoresize
:options="queueOptions"
:key="queueChartKey"
></my-chart>
// 方法
/** 渲染请求的服务端报表数据, 业务重写实现 */
async renderReportDataResult() {
// 进店客流
this.enterOptions = this.getOneOptions(0);
// 店外客流
this.passOptions = this.getOneOptions(1);
// 进店转化率
this.rateOptions = this.getOneOptions(2);
// 平均排队时长
this.queueOptions = this.getOneOptions(3);
this.tableData[2].shop1 = this.tableData[2].shop1 + "%";
this.tableData[2].shop2 = this.tableData[2].shop2 + "%";
this.isNoData = false;
this.$emit('noDataChange', this.isNoData);
},
// options格式化数据
getOneOptions(index) {
let [legends, xAxis, series] = [[], [], []];
let options = {};
let barColor;
switch (index) {
case 0:
barColor = COLOR_SINGLE[0];
this.enterChartKey++;
break;
case 1:
barColor = COLOR_SINGLE[5];
this.passChartKey++;
break;
case 2:
barColor = COLOR_SINGLE[17];
this.rateChartKey++;
break;
case 3:
barColor = COLOR_SINGLE[4];
this.queueChartKey++;
break;
default:
barColor = COLOR_SINGLE[0];
}
// X轴
xAxis = [this.shop1Name, this.shop2Name];
// @TODO 根据传入的类型更改对应的数据
let needPercent = index === 2;
let Series = compareBarItem({
color: barColor,
name: legends[0],
type: 'bar',
barMaxWidth: 32,
data: [this.tableData[index].shop1, this.tableData[index].shop2]
}, needPercent);
series = [Series];
let obj = {
xAxis,
series,
dataType: index
};
options = Object.assign({}, getCompareOptions(obj));
return options;
},
ShopAnalysisChartMixin
watch: {
params: {
immediate: true,
handler(newVal) {
if (JSON.stringify(newVal) !== '{}') {
// 直接深拷贝params,后续如果要操作,操作这个
this.paramsDataCopy = _.cloneDeep(newVal);
this.onParamsChangeHandle();
this.afterParamsChangeHandle();
}
}
}
},
methods: {
/** @abstract params变更的同步处理,业务重写实现 */
onParamsChangeHandle() {
return;
},
// params变更后的异步处理
async afterParamsChangeHandle() {
await this.getReportData();
this.renderReportDataResult();
this.handleExtendReportRender();
},
/** @abstract 请求bi模块服务端报表数据,业务重写实现,仅获取数据+解析数据赋值,不渲染,不后续处理 */
async getReportData() {
return;
},
/** @abstract 渲染请求的服务端报表数据, 业务重写实现 */
async renderReportDataResult() {
return;
},
/** @abstract [可选]报表需要额外异步查询进行渲染判断的处理, 业务重写实现 */
async handleExtendReportRender() {
return;
},
}
方法库
/**
* 柱状图series项的基本配置
* @param {object} item 传入的基本配置
* @param {boolean} needPercent 是否需要百分号
*/
const compareBarItem = (item, needPercent = false) => {
let itemColor = item.color;
const baseItem = {
type: 'bar',
showAllSymbol: true,
connectNulls: true,
animation: true,
itemStyle: {
emphasis: {
borderWidth: 3
}
},
...item
};
baseItem.markPoint = {
data: [
{
value: needPercent ? item.data[0] + "%" : item.data[0],
xAxis: 0,
yAxis: item.data[0]
},
{
value: needPercent ? item.data[1] + "%" : item.data[1],
xAxis: 1,
yAxis: item.data[1]
}
],
symbol: 'circle',
symbolSize: 7,
itemStyle: {
normal: {
color: '#fff',
borderWidth: '2',
borderColor: itemColor
}
},
label: {
normal: {
position: 'top',
color: itemColor,
fontWeight: 'bold'
}
}
};
return baseItem;
};
export {
compareBarItem
};
/**
* 获取门店对比报表配置
* @param {*} xAxis x轴
* @param {*} series 渲染用到的数据
* @param {*} dataType 0 进, 1 外, 2 转化率
*/
export const getCompareOptions = (paramInfos) => {
let { xAxis, series, dataType } = paramInfos;
let formatter = (isNeedHeader, isNeedAll, params) => {
let [all, list, xAxis] = [0, [], params[0].axisValue];
params.forEach((item) => {
all += item.data * 1;
list.push({
name: item.name,
value: dataType === 2 ? item.data + '%' : item.data,
color: item.color
});
});
let suffix = '';
let rows = '';
list.forEach((r, index) => {
rows +=
'<div class="tooltip-row ' +
// (!isOne && inOrOut !== 3 && index === 0 ? 'all' : '') +
'">' +
'<i class="tooltip-row-icon" style="background: ' +
r.color +
'"></i>' +
'<span class="tooltip-row-text">' +
+
'</span>' +
'<span class="tooltip-row-num">' +
r.value +
suffix +
'</span>' +
'</div>';
});
let str = '';
str += rows;
return `<div class="tooptip-20200610">${str}</div>`;
};
let options;
options = {
tooltip: {
formatter: formatter.bind(this, false, false)
},
xAxis: {
data: xAxis,
axisTick: {
alignWithLabel: true
}
},
series
};
if (dataType === 0 || dataType === 1) {
options.yAxis = { name: i18n.t('people_num'), nameRotate: 0.5 };
} else if (dataType === 2) {
options.yAxis = { name: i18n.t('hcp_bi_conversion_rate'), nameRotate: 0 };
} else {
options.yAxis = { name: i18n.t('hcp_bi_unit_second'), nameRotate: 0 };
}
let mergeOption = deepMerge(deepClone(base), options);
if (dataType === 2) {
mergeOption.yAxis = {
type: 'value',
name: i18n.t('hcp_bi_conversion_rate'),
min: 0,
max: 100,
nameGap: 28,
nameRotate: 0,
nameTextStyle: {
color: '#999999',
fontSize: 13,
fontWeight: 600
},
splitLine: {
//坐标值分割线
show: false
},
splitArea: {
show: true,
areaStyle: {
color: ['#fff', '#fafbfc'],
opacity: 0.5
}
},
axisLine: {
lineStyle: {
color: '#bfbfbf'
}
},
axisLabel: {
show: true,
interval: 'auto',
formatter: '{value}%'
}
};
}
console.log(mergeOption);
return mergeOption;
};