1
This commit is contained in:
@@ -32,6 +32,9 @@
|
|||||||
<el-form-item label="商品名称" prop="skuName">
|
<el-form-item label="商品名称" prop="skuName">
|
||||||
<el-input v-model="queryParams.skuName" placeholder="请输入商品名称" clearable style="width: 240px" @keyup.enter.native="handleQuery" />
|
<el-input v-model="queryParams.skuName" placeholder="请输入商品名称" clearable style="width: 240px" @keyup.enter.native="handleQuery" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item label="商品SKU" prop="skuId">
|
||||||
|
<el-input v-model="queryParams.skuId" placeholder="SKU ID" clearable style="width: 200px" @keyup.enter.native="handleQuery" />
|
||||||
|
</el-form-item>
|
||||||
<el-form-item label="订单状态" prop="statusGroup">
|
<el-form-item label="订单状态" prop="statusGroup">
|
||||||
<el-select v-model="queryParams.statusGroup" placeholder="订单状态" clearable style="width: 240px">
|
<el-select v-model="queryParams.statusGroup" placeholder="订单状态" clearable style="width: 240px">
|
||||||
<el-option v-for="status in mergedStatusList" :key="status.value" :label="status.label" :value="status.value" />
|
<el-option v-for="status in mergedStatusList" :key="status.value" :label="status.label" :value="status.value" />
|
||||||
@@ -50,7 +53,7 @@
|
|||||||
</mobile-search-form>
|
</mobile-search-form>
|
||||||
|
|
||||||
<!-- 统计悬浮模块 -->
|
<!-- 统计悬浮模块 -->
|
||||||
<el-card class="statistics-card" shadow="hover" v-if="orderrowsList.length > 0">
|
<el-card class="statistics-card" shadow="hover">
|
||||||
<div slot="header" class="clearfix">
|
<div slot="header" class="clearfix">
|
||||||
<span><i class="el-icon-data-analysis"></i> 佣金统计</span>
|
<span><i class="el-icon-data-analysis"></i> 佣金统计</span>
|
||||||
<el-button style="float: right; padding: 3px 0" type="text" @click="toggleStatistics">
|
<el-button style="float: right; padding: 3px 0" type="text" @click="toggleStatistics">
|
||||||
@@ -367,6 +370,7 @@ export default {
|
|||||||
unionId: null,
|
unionId: null,
|
||||||
orderId: null,
|
orderId: null,
|
||||||
skuName: null,
|
skuName: null,
|
||||||
|
skuId: null,
|
||||||
validCode: null,
|
validCode: null,
|
||||||
statusGroup: null, // 新增
|
statusGroup: null, // 新增
|
||||||
orderBy: null, // 排序字段
|
orderBy: null, // 排序字段
|
||||||
@@ -725,21 +729,11 @@ export default {
|
|||||||
/** 搜索按钮操作 */
|
/** 搜索按钮操作 */
|
||||||
handleQuery() {
|
handleQuery() {
|
||||||
this.queryParams.pageNum = 1;
|
this.queryParams.pageNum = 1;
|
||||||
console.log(this.queryParams.validCode);
|
|
||||||
|
|
||||||
// 合并项转为原始code数组
|
|
||||||
if (this.queryParams.statusGroup) {
|
if (this.queryParams.statusGroup) {
|
||||||
this.queryParams.validCodes = this.statusValueMap[this.queryParams.statusGroup].map(code => Number(code));
|
const codes = this.statusValueMap[this.queryParams.statusGroup]
|
||||||
} else if (this.queryParams.validCodes && Array.isArray(this.queryParams.validCodes)) {
|
this.queryParams.validCodes = codes && codes.length ? codes.map(code => Number(code)) : null
|
||||||
this.queryParams.validCodes = this.queryParams.validCodes.map(code => Number(code));
|
|
||||||
} else {
|
} else {
|
||||||
this.queryParams.validCodes = null;
|
this.queryParams.validCodes = null
|
||||||
}
|
|
||||||
// 打印类型检查
|
|
||||||
if (this.queryParams.validCode) {
|
|
||||||
this.queryParams.validCode = this.queryParams.validCode.map(item => Number(item));
|
|
||||||
console.log('validCode值:', this.queryParams.validCodes);
|
|
||||||
console.log('validCode类型:', this.queryParams.validCodes.map(item => typeof item));
|
|
||||||
}
|
}
|
||||||
this.getList();
|
this.getList();
|
||||||
},
|
},
|
||||||
@@ -747,7 +741,7 @@ export default {
|
|||||||
resetQuery() {
|
resetQuery() {
|
||||||
this.dateRange = [];
|
this.dateRange = [];
|
||||||
this.resetForm("queryForm");
|
this.resetForm("queryForm");
|
||||||
this.queryParams.validCodes = [];
|
this.queryParams.validCodes = null;
|
||||||
// 重置时恢复默认分页条数
|
// 重置时恢复默认分页条数
|
||||||
this.queryParams.pageSize = 10;
|
this.queryParams.pageSize = 10;
|
||||||
this.queryParams.pageNum = 1;
|
this.queryParams.pageNum = 1;
|
||||||
|
|||||||
@@ -1,9 +1,19 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="app-container">
|
<div class="app-container" v-loading="loading">
|
||||||
<!-- 查询条件 -->
|
<!-- 查询条件 -->
|
||||||
<el-card style="margin-bottom: 20px;">
|
<el-card class="filter-card">
|
||||||
<el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch">
|
<el-form :model="queryParams" ref="queryForm" :inline="true" size="small" v-show="showSearch" label-width="88px">
|
||||||
<el-form-item label="时间范围" prop="dateRange">
|
<el-form-item label="京粉账号" prop="unionId">
|
||||||
|
<el-select v-model="queryParams.unionId" placeholder="全部京东联盟账号" clearable filterable style="width: 220px">
|
||||||
|
<el-option
|
||||||
|
v-for="admin in adminList"
|
||||||
|
:key="admin.value || admin.id"
|
||||||
|
:label="admin.label || (admin.name + ' (' + admin.wxid + ')')"
|
||||||
|
:value="admin.value || admin.id"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="时间范围">
|
||||||
<el-date-picker
|
<el-date-picker
|
||||||
v-model="dateRange"
|
v-model="dateRange"
|
||||||
type="daterange"
|
type="daterange"
|
||||||
@@ -11,131 +21,95 @@
|
|||||||
start-placeholder="开始日期"
|
start-placeholder="开始日期"
|
||||||
end-placeholder="结束日期"
|
end-placeholder="结束日期"
|
||||||
value-format="yyyy-MM-dd"
|
value-format="yyyy-MM-dd"
|
||||||
@change="handleDateRangeChange">
|
style="width: 260px"
|
||||||
</el-date-picker>
|
@change="handleDateRangeChange"
|
||||||
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="订单状态" prop="validCode">
|
<el-form-item label="订单状态" prop="validCode">
|
||||||
<el-select v-model="queryParams.validCode" placeholder="请选择订单状态" clearable>
|
<el-select v-model="queryParams.validCode" placeholder="全部状态" clearable style="width: 160px">
|
||||||
<el-option
|
<el-option
|
||||||
v-for="dict in validCodeOptions"
|
v-for="dict in validCodeOptions"
|
||||||
:key="dict.value"
|
:key="dict.value"
|
||||||
:label="dict.label"
|
:label="dict.label"
|
||||||
:value="dict.value">
|
:value="dict.value"
|
||||||
</el-option>
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="商品ID" prop="skuId">
|
<el-form-item label="商品SKU" prop="skuId">
|
||||||
<el-input
|
<el-input
|
||||||
v-model="queryParams.skuId"
|
v-model="queryParams.skuId"
|
||||||
placeholder="请输入商品ID"
|
placeholder="SKU ID"
|
||||||
clearable
|
clearable
|
||||||
style="width: 200px">
|
style="width: 160px"
|
||||||
</el-input>
|
@keyup.enter.native="handleQuery"
|
||||||
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
|
<el-button type="primary" icon="el-icon-search" @click="handleQuery">查询</el-button>
|
||||||
<el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
|
<el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
</el-card>
|
</el-card>
|
||||||
|
|
||||||
<!-- 统计卡片 -->
|
<!-- 统计卡片:与列表页口径对齐,总佣金=后端 totalCommission(预估佣金口径) -->
|
||||||
<el-row :gutter="20">
|
<el-row :gutter="16" class="summary-row">
|
||||||
<el-col :span="6">
|
<el-col v-for="item in summaryItems" :key="item.key" :xs="24" :sm="12" :md="8" :lg="4">
|
||||||
<el-card>
|
<el-card class="summary-card" shadow="hover">
|
||||||
<div slot="header">
|
<div class="summary-card-inner">
|
||||||
<span>总订单数</span>
|
<div class="summary-title">{{ item.title }}</div>
|
||||||
|
<div class="summary-value">
|
||||||
|
<template v-if="item.money">¥{{ item.display }}</template>
|
||||||
|
<template v-else>{{ item.display }}</template>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="summary-hint">{{ item.hint }}</div>
|
||||||
<h2>{{ statistics.totalOrders || 0 }}</h2>
|
|
||||||
<p>累计订单数量</p>
|
|
||||||
</div>
|
|
||||||
</el-card>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="6">
|
|
||||||
<el-card>
|
|
||||||
<div slot="header">
|
|
||||||
<span>总佣金</span>
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
|
||||||
<h2>¥{{ formatMoney(statistics.totalCommission) }}</h2>
|
|
||||||
<p>累计佣金收入</p>
|
|
||||||
</div>
|
|
||||||
</el-card>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="6">
|
|
||||||
<el-card>
|
|
||||||
<div slot="header">
|
|
||||||
<span>总商品数</span>
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
|
||||||
<h2>{{ statistics.totalSkuNum || 0 }}</h2>
|
|
||||||
<p>累计商品数量</p>
|
|
||||||
</div>
|
|
||||||
</el-card>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="6">
|
|
||||||
<el-card>
|
|
||||||
<div slot="header">
|
|
||||||
<span>实际费用</span>
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
|
||||||
<h2>¥{{ formatMoney(statistics.totalActualFee) }}</h2>
|
|
||||||
<p>累计实际费用</p>
|
|
||||||
</div>
|
</div>
|
||||||
</el-card>
|
</el-card>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
<!-- 图表区域 -->
|
<!-- 图表区域 -->
|
||||||
<el-row :gutter="20" style="margin-top: 20px;">
|
<el-row :gutter="16" class="charts-row">
|
||||||
<el-col :span="12">
|
<el-col :xs="24" :lg="12">
|
||||||
<el-card>
|
<el-card shadow="hover">
|
||||||
<div slot="header">
|
<div slot="header" class="card-header-plain">
|
||||||
<span>订单状态分布</span>
|
<span>订单状态分布</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="chart-container">
|
<div class="chart-container">
|
||||||
<div ref="statusChart" style="height: 300px;"></div>
|
<div ref="statusChart" class="chart-el" />
|
||||||
</div>
|
</div>
|
||||||
</el-card>
|
</el-card>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
<el-col :xs="24" :lg="12">
|
||||||
<el-card>
|
<el-card shadow="hover">
|
||||||
<div slot="header">
|
<div slot="header" class="card-header-plain">
|
||||||
<span>佣金分布</span>
|
<span>佣金分布(预估口径)</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="chart-container">
|
<div class="chart-container">
|
||||||
<div ref="commissionChart" style="height: 300px;"></div>
|
<div ref="commissionChart" class="chart-el" />
|
||||||
</div>
|
</div>
|
||||||
</el-card>
|
</el-card>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
<!-- 状态详情表格 -->
|
<!-- 状态详情表格(分组顺序与列表页一致) -->
|
||||||
<el-row :gutter="20" style="margin-top: 20px;">
|
<el-row :gutter="16" class="table-row">
|
||||||
<el-col :span="24">
|
<el-col :span="24">
|
||||||
<el-card>
|
<el-card shadow="hover">
|
||||||
<div slot="header">
|
<div slot="header" class="card-header-plain">
|
||||||
<span>订单状态详情</span>
|
<span>订单状态详情</span>
|
||||||
</div>
|
</div>
|
||||||
<el-table :data="statusDetails" style="width: 100%">
|
<el-table :data="statusDetails" stripe style="width: 100%">
|
||||||
<el-table-column prop="label" label="状态" width="120" />
|
<el-table-column prop="label" label="状态" min-width="100" />
|
||||||
<el-table-column prop="count" label="订单数量" width="120" align="center" />
|
<el-table-column prop="count" label="订单数" width="100" align="center" />
|
||||||
<el-table-column prop="skuNum" label="商品数量" width="120" align="center" />
|
<el-table-column prop="skuNum" label="商品件数" width="100" align="center" />
|
||||||
<el-table-column prop="commission" label="佣金" width="120" align="center">
|
<el-table-column prop="commission" label="预估佣金" min-width="110" align="right">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">¥{{ formatMoney(scope.row.commission) }}</template>
|
||||||
¥{{ formatMoney(scope.row.commission) }}
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="actualFee" label="实际费用" width="120" align="center">
|
<el-table-column prop="actualFee" label="实际费用" min-width="110" align="right">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">¥{{ formatMoney(scope.row.actualFee) }}</template>
|
||||||
¥{{ formatMoney(scope.row.actualFee) }}
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="percentage" label="占比" width="100" align="center">
|
<el-table-column prop="percentage" label="占比" width="88" align="center">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">{{ scope.row.percentage }}%</template>
|
||||||
{{ scope.row.percentage }}%
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
</el-card>
|
</el-card>
|
||||||
@@ -146,86 +120,173 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import * as echarts from 'echarts'
|
import * as echarts from 'echarts'
|
||||||
|
import { debounce } from '@/utils'
|
||||||
import { getOrderStatistics, getValidCodeSelectData } from '@/api/system/orderrows'
|
import { getOrderStatistics, getValidCodeSelectData } from '@/api/system/orderrows'
|
||||||
|
import { getAdminSelectData } from '@/api/system/superadmin'
|
||||||
|
|
||||||
|
/** 与列表页、后端 groupStats 逻辑顺序一致 */
|
||||||
|
const GROUP_STAT_ORDER = ['pending', 'paid', 'deposit', 'finished', 'cancel', 'invalid', 'illegal']
|
||||||
|
|
||||||
|
const PIE_COLORS = ['#e6a23c', '#409eff', '#909399', '#67c23a', '#f56c6c', '#c0c4cc', '#f78989']
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "OrderStatistics",
|
name: 'OrderStatistics',
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
// 遮罩层
|
loading: false,
|
||||||
loading: true,
|
|
||||||
// 显示搜索条件
|
|
||||||
showSearch: true,
|
showSearch: true,
|
||||||
// 查询参数
|
|
||||||
queryParams: {
|
queryParams: {
|
||||||
beginTime: null,
|
beginTime: null,
|
||||||
endTime: null,
|
endTime: null,
|
||||||
validCode: null,
|
validCode: null,
|
||||||
skuId: null
|
skuId: null,
|
||||||
|
unionId: null
|
||||||
},
|
},
|
||||||
// 日期范围
|
|
||||||
dateRange: [],
|
dateRange: [],
|
||||||
// 订单状态选项
|
|
||||||
validCodeOptions: [],
|
validCodeOptions: [],
|
||||||
// 统计数据
|
adminList: [],
|
||||||
statistics: {
|
statistics: {
|
||||||
totalOrders: 0,
|
totalOrders: 0,
|
||||||
|
totalCosPrice: 0,
|
||||||
totalCommission: 0,
|
totalCommission: 0,
|
||||||
totalSkuNum: 0,
|
totalSkuNum: 0,
|
||||||
totalActualFee: 0,
|
totalActualFee: 0,
|
||||||
groupStats: {}
|
groupStats: {}
|
||||||
},
|
},
|
||||||
// 状态详情数据
|
statusDetails: [],
|
||||||
statusDetails: []
|
_statusChart: null,
|
||||||
|
_commissionChart: null,
|
||||||
|
_chartResize: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
summaryItems() {
|
||||||
|
const s = this.statistics
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
key: 'orders',
|
||||||
|
title: '总订单数',
|
||||||
|
money: false,
|
||||||
|
display: s.totalOrders || 0,
|
||||||
|
hint: '符合当前筛选'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'cos',
|
||||||
|
title: '总计佣金额',
|
||||||
|
money: true,
|
||||||
|
display: this.formatMoney(s.totalCosPrice),
|
||||||
|
hint: 'estimateCosPrice 汇总'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'commission',
|
||||||
|
title: '预估佣金',
|
||||||
|
money: true,
|
||||||
|
display: this.formatMoney(s.totalCommission),
|
||||||
|
hint: '与列表页「预估佣金」同口径'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'sku',
|
||||||
|
title: '总商品件数',
|
||||||
|
money: false,
|
||||||
|
display: s.totalSkuNum || 0,
|
||||||
|
hint: 'skuNum 汇总'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'actual',
|
||||||
|
title: '实际费用',
|
||||||
|
money: true,
|
||||||
|
display: this.formatMoney(s.totalActualFee),
|
||||||
|
hint: 'actualFee 汇总'
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.getValidCodeOptions()
|
this.bootstrap()
|
||||||
this.getStatistics()
|
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.initCharts()
|
this._chartResize = debounce(() => {
|
||||||
|
this._statusChart && this._statusChart.resize()
|
||||||
|
this._commissionChart && this._commissionChart.resize()
|
||||||
|
}, 120)
|
||||||
|
window.addEventListener('resize', this._chartResize)
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
window.removeEventListener('resize', this._chartResize)
|
||||||
|
this._disposeCharts()
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
/** 获取订单状态选项 */
|
bootstrap() {
|
||||||
getValidCodeOptions() {
|
Promise.all([
|
||||||
getValidCodeSelectData().then(response => {
|
getValidCodeSelectData().then(res => {
|
||||||
this.validCodeOptions = response.data
|
this.validCodeOptions = res.data || []
|
||||||
|
}),
|
||||||
|
getAdminSelectData().then(res => {
|
||||||
|
this.adminList = res.data || res || []
|
||||||
|
})
|
||||||
|
])
|
||||||
|
.catch(() => {
|
||||||
|
this.$message.error('加载筛选项失败')
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.getStatistics()
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
/** 获取统计数据 */
|
_disposeCharts() {
|
||||||
|
if (this._statusChart) {
|
||||||
|
this._statusChart.dispose()
|
||||||
|
this._statusChart = null
|
||||||
|
}
|
||||||
|
if (this._commissionChart) {
|
||||||
|
this._commissionChart.dispose()
|
||||||
|
this._commissionChart = null
|
||||||
|
}
|
||||||
|
},
|
||||||
getStatistics() {
|
getStatistics() {
|
||||||
this.loading = true
|
this.loading = true
|
||||||
getOrderStatistics(this.queryParams).then(response => {
|
const params = { ...this.queryParams }
|
||||||
this.statistics = response.data
|
if (params.skuId === '' || params.skuId === undefined) {
|
||||||
|
params.skuId = null
|
||||||
|
}
|
||||||
|
getOrderStatistics(params)
|
||||||
|
.then(response => {
|
||||||
|
this.statistics = Object.assign(
|
||||||
|
{
|
||||||
|
totalOrders: 0,
|
||||||
|
totalCosPrice: 0,
|
||||||
|
totalCommission: 0,
|
||||||
|
totalSkuNum: 0,
|
||||||
|
totalActualFee: 0,
|
||||||
|
groupStats: {}
|
||||||
|
},
|
||||||
|
response.data || {}
|
||||||
|
)
|
||||||
this.processStatusDetails()
|
this.processStatusDetails()
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => this.updateCharts())
|
||||||
this.initCharts()
|
|
||||||
})
|
})
|
||||||
this.loading = false
|
.catch(() => {
|
||||||
}).catch(() => {
|
this.$message.error('加载统计数据失败')
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
this.loading = false
|
this.loading = false
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
/** 处理状态详情数据 */
|
|
||||||
processStatusDetails() {
|
processStatusDetails() {
|
||||||
const groupStats = this.statistics.groupStats || {}
|
const groupStats = this.statistics.groupStats || {}
|
||||||
this.statusDetails = Object.values(groupStats).map(item => {
|
const total = this.statistics.totalOrders || 0
|
||||||
const percentage = this.statistics.totalOrders > 0
|
this.statusDetails = GROUP_STAT_ORDER.map(key => groupStats[key])
|
||||||
? ((item.count / this.statistics.totalOrders) * 100).toFixed(2)
|
.filter(Boolean)
|
||||||
: '0.00'
|
.map(item => ({
|
||||||
return {
|
|
||||||
...item,
|
...item,
|
||||||
percentage
|
skuNum: item.skuNum != null ? item.skuNum : 0,
|
||||||
}
|
percentage: total > 0 ? ((item.count / total) * 100).toFixed(2) : '0.00'
|
||||||
})
|
}))
|
||||||
},
|
},
|
||||||
/** 格式化金额 */
|
|
||||||
formatMoney(amount) {
|
formatMoney(amount) {
|
||||||
if (!amount && amount !== 0) return '0.00'
|
if (amount == null || amount === '') return '0.00'
|
||||||
return parseFloat(amount).toFixed(2)
|
const n = parseFloat(amount)
|
||||||
|
return Number.isFinite(n) ? n.toFixed(2) : '0.00'
|
||||||
},
|
},
|
||||||
/** 日期范围变化处理 */
|
|
||||||
handleDateRangeChange(dates) {
|
handleDateRangeChange(dates) {
|
||||||
if (dates && dates.length === 2) {
|
if (dates && dates.length === 2) {
|
||||||
this.queryParams.beginTime = dates[0]
|
this.queryParams.beginTime = dates[0]
|
||||||
@@ -235,150 +296,175 @@ export default {
|
|||||||
this.queryParams.endTime = null
|
this.queryParams.endTime = null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
/** 搜索按钮操作 */
|
|
||||||
handleQuery() {
|
handleQuery() {
|
||||||
this.getStatistics()
|
this.getStatistics()
|
||||||
},
|
},
|
||||||
/** 重置按钮操作 */
|
|
||||||
resetQuery() {
|
resetQuery() {
|
||||||
this.dateRange = []
|
this.dateRange = []
|
||||||
this.resetForm("queryForm")
|
this.resetForm('queryForm')
|
||||||
this.queryParams = {
|
this.queryParams = {
|
||||||
beginTime: null,
|
beginTime: null,
|
||||||
endTime: null,
|
endTime: null,
|
||||||
validCode: null,
|
validCode: null,
|
||||||
skuId: null
|
skuId: null,
|
||||||
|
unionId: null
|
||||||
}
|
}
|
||||||
this.getStatistics()
|
this.getStatistics()
|
||||||
},
|
},
|
||||||
/** 初始化图表 */
|
updateCharts() {
|
||||||
initCharts() {
|
this._renderPie(this.$refs.statusChart, '_statusChart', (groupStats) => {
|
||||||
this.initStatusChart()
|
const data = GROUP_STAT_ORDER.map(k => groupStats[k]).filter(Boolean).map(item => ({
|
||||||
this.initCommissionChart()
|
|
||||||
},
|
|
||||||
/** 初始化状态分布图表 */
|
|
||||||
initStatusChart() {
|
|
||||||
const chartDom = this.$refs.statusChart
|
|
||||||
if (!chartDom) return
|
|
||||||
|
|
||||||
const myChart = echarts.init(chartDom)
|
|
||||||
|
|
||||||
const groupStats = this.statistics.groupStats || {}
|
|
||||||
const data = Object.values(groupStats).map(item => ({
|
|
||||||
value: item.count,
|
value: item.count,
|
||||||
name: item.label
|
name: item.label
|
||||||
}))
|
}))
|
||||||
|
return {
|
||||||
const option = {
|
|
||||||
tooltip: {
|
|
||||||
trigger: 'item',
|
|
||||||
formatter: '{a} <br/>{b}: {c} ({d}%)'
|
|
||||||
},
|
|
||||||
legend: {
|
|
||||||
orient: 'vertical',
|
|
||||||
left: 'left',
|
|
||||||
type: 'scroll'
|
|
||||||
},
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
name: '订单状态',
|
name: '订单状态',
|
||||||
type: 'pie',
|
data,
|
||||||
radius: ['40%', '70%'],
|
isAmount: false
|
||||||
avoidLabelOverlap: false,
|
|
||||||
label: {
|
|
||||||
show: false,
|
|
||||||
position: 'center'
|
|
||||||
},
|
|
||||||
emphasis: {
|
|
||||||
label: {
|
|
||||||
show: true,
|
|
||||||
fontSize: '18',
|
|
||||||
fontWeight: 'bold'
|
|
||||||
}
|
}
|
||||||
},
|
})
|
||||||
labelLine: {
|
this._renderPie(this.$refs.commissionChart, '_commissionChart', (groupStats) => {
|
||||||
show: false
|
const data = GROUP_STAT_ORDER.map(k => groupStats[k])
|
||||||
},
|
.filter(Boolean)
|
||||||
data: data
|
.filter(item => Number(item.commission) > 0)
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
myChart.setOption(option)
|
|
||||||
},
|
|
||||||
/** 初始化佣金分布图表 */
|
|
||||||
initCommissionChart() {
|
|
||||||
const chartDom = this.$refs.commissionChart
|
|
||||||
if (!chartDom) return
|
|
||||||
|
|
||||||
const myChart = echarts.init(chartDom)
|
|
||||||
|
|
||||||
const groupStats = this.statistics.groupStats || {}
|
|
||||||
const data = Object.values(groupStats)
|
|
||||||
.filter(item => item.commission > 0)
|
|
||||||
.map(item => ({
|
.map(item => ({
|
||||||
value: item.commission,
|
value: item.commission,
|
||||||
name: item.label
|
name: item.label
|
||||||
}))
|
}))
|
||||||
|
return {
|
||||||
const option = {
|
name: '佣金分布',
|
||||||
|
data,
|
||||||
|
isAmount: true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
this._chartResize && this._chartResize()
|
||||||
|
},
|
||||||
|
_renderPie(domRef, instKey, build) {
|
||||||
|
if (!domRef) return
|
||||||
|
const groupStats = this.statistics.groupStats || {}
|
||||||
|
const built = build(groupStats)
|
||||||
|
let chart = this[instKey]
|
||||||
|
if (!chart) {
|
||||||
|
chart = echarts.init(domRef)
|
||||||
|
this[instKey] = chart
|
||||||
|
}
|
||||||
|
if (!built.data.length) {
|
||||||
|
chart.setOption(
|
||||||
|
{
|
||||||
|
tooltip: { show: false },
|
||||||
|
color: PIE_COLORS,
|
||||||
|
graphic: [
|
||||||
|
{
|
||||||
|
type: 'text',
|
||||||
|
left: 'center',
|
||||||
|
top: 'middle',
|
||||||
|
style: { text: '暂无数据', fill: '#909399', fontSize: 14 }
|
||||||
|
}
|
||||||
|
],
|
||||||
|
series: []
|
||||||
|
},
|
||||||
|
true
|
||||||
|
)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
chart.setOption(
|
||||||
|
{
|
||||||
tooltip: {
|
tooltip: {
|
||||||
trigger: 'item',
|
trigger: 'item',
|
||||||
formatter: '{a} <br/>{b}: ¥{c} ({d}%)'
|
formatter: built.isAmount
|
||||||
},
|
? (p) => `${p.seriesName}<br/>${p.name}: ¥${this.formatMoney(p.value)} (${p.percent}%)`
|
||||||
legend: {
|
: '{a} <br/>{b}: {c} ({d}%)'
|
||||||
orient: 'vertical',
|
|
||||||
left: 'left',
|
|
||||||
type: 'scroll'
|
|
||||||
},
|
},
|
||||||
|
color: PIE_COLORS,
|
||||||
|
graphic: [],
|
||||||
|
legend: { orient: 'vertical', left: 'left', type: 'scroll' },
|
||||||
series: [
|
series: [
|
||||||
{
|
{
|
||||||
name: '佣金分布',
|
name: built.name,
|
||||||
type: 'pie',
|
type: 'pie',
|
||||||
radius: ['40%', '70%'],
|
radius: ['42%', '72%'],
|
||||||
avoidLabelOverlap: false,
|
center: ['56%', '52%'],
|
||||||
label: {
|
avoidLabelOverlap: true,
|
||||||
show: false,
|
itemStyle: { borderRadius: 4, borderColor: '#fff', borderWidth: 1 },
|
||||||
position: 'center'
|
label: { show: true, formatter: '{b}\n{d}%' },
|
||||||
},
|
|
||||||
emphasis: {
|
emphasis: {
|
||||||
label: {
|
label: { show: true, fontSize: 16, fontWeight: 'bold' }
|
||||||
show: true,
|
|
||||||
fontSize: '18',
|
|
||||||
fontWeight: 'bold'
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
labelLine: {
|
data: built.data
|
||||||
show: false
|
|
||||||
},
|
|
||||||
data: data
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
},
|
||||||
|
true
|
||||||
myChart.setOption(option)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.card-body {
|
.filter-card {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.summary-row {
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.summary-card {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.summary-card-inner {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
padding: 6px 4px 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-body h2 {
|
.summary-title {
|
||||||
color: #409EFF;
|
font-size: 13px;
|
||||||
margin: 10px 0;
|
color: #606266;
|
||||||
font-size: 28px;
|
margin-bottom: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-body p {
|
.summary-value {
|
||||||
color: #666;
|
font-size: 22px;
|
||||||
margin: 5px 0;
|
font-weight: 600;
|
||||||
|
color: #409eff;
|
||||||
|
line-height: 1.3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.summary-hint {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #909399;
|
||||||
|
margin-top: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.charts-row {
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-row {
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-header-plain {
|
||||||
|
font-weight: 600;
|
||||||
|
color: #303133;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chart-container {
|
.chart-container {
|
||||||
padding: 10px;
|
padding: 8px 8px 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-el {
|
||||||
|
width: 100%;
|
||||||
|
height: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.filter-card ::v-deep .el-form--inline .el-form-item {
|
||||||
|
display: block;
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
Reference in New Issue
Block a user