| | |
| | | <el-button :type="currentDateType === 2 ? 'primary' : 'default'" @click="onDateTypeChange(2)">近30日</el-button> |
| | | <el-button :type="currentDateType === 3 ? 'primary' : 'default'" @click="onDateTypeChange(3)">半年</el-button> |
| | | <el-button :type="currentDateType === 4 ? 'primary' : 'default'" @click="onDateTypeChange(4)">一年</el-button> |
| | | <el-button :type="currentDateType === 5 ? 'primary' : 'default'" @click="onDateTypeChange(5)">自定义</el-button> |
| | | </el-button-group> |
| | | <el-date-picker v-if="currentDateType === 5" v-model="customDateRange" type="daterange" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期" value-format="yyyy-MM-dd" style="margin-left: 10px;" :picker-options="customDatePickerOptions" clearable></el-date-picker> |
| | | <el-select v-model="currentShopId" filterable placeholder="请选择寄存点" style="width: 200px; margin: 0 10px;"> |
| | | <el-option |
| | | v-for="shop in shopList" |
| | |
| | | :value="month" |
| | | ></el-option> |
| | | </el-select> |
| | | <el-button type="success" size="mini" @click="exportRevenueTrend">导出</el-button> |
| | | </div> |
| | | </div> |
| | | <div class="chart-content"> |
| | |
| | | <div class="chart-header"> |
| | | <span class="chart-title">平台财务总览</span> |
| | | <div class="filter-group"> |
| | | <el-date-picker type="daterange" range-separator="至" start-placeholder="开始月份" end-placeholder="结束月份" v-model="financeDateRange" value-format="yyyy-MM" style="margin-right: 10px" :picker-options="financePickerOptions" clearable></el-date-picker> |
| | | <el-date-picker type="monthrange" range-separator="至" start-placeholder="开始月份" end-placeholder="结束月份" v-model="financeDateRange" value-format="yyyy-MM" style="margin-right: 10px" :picker-options="financePickerOptions" clearable></el-date-picker> |
| | | <el-button type="primary" size="mini" @click="getFinanceOverviewData">查询</el-button> |
| | | <el-button size="mini" @click="resetFinanceDate">重置</el-button> |
| | | <el-button type="success" size="mini" @click="exportFinanceData">导出</el-button> |
| | |
| | | |
| | | <!-- 业绩排名分析 --> |
| | | <div class="charts-row" style="margin-top: 20px; margin-bottom: 0;"> |
| | | <div class="chart-card" style="width: calc(50% - 20px);"> |
| | | <div class="chart-card"> |
| | | <div class="chart-header"> |
| | | <span class="chart-title">门店业绩TOP10</span> |
| | | </div> |
| | |
| | | </el-table> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="chart-card" style="width: calc(50% - 20px);"> |
| | | <div class="charts-row" style="margin-top: 20px; margin-bottom: 0;"> |
| | | <div class="chart-card"> |
| | | <div class="chart-header"> |
| | | <span class="chart-title">司机业绩TOP10</span> |
| | | </div> |
| | |
| | | </template> |
| | | |
| | | <script> |
| | | import { overview, memberTrend, orderTrend, revenueTrend, financeOverview, exportExcel, luggageTypeExport, shopTop, driverTop } from '@/api/business/dataBoard' |
| | | import { overview, memberTrend, orderTrend, revenueTrend, financeOverview, exportExcel, luggageTypeExport, shopTop, driverTop, revenueTrendExport } from '@/api/business/dataBoard' |
| | | import { fetchList } from '@/api/business/shopInfo' |
| | | import * as echarts from 'echarts' |
| | | |
| | |
| | | }, |
| | | financeMinDate: null, |
| | | financeList: [], |
| | | customDateRange: null, |
| | | customDatePickerOptions: { |
| | | disabledDate: (time) => { |
| | | if (time.getTime() > Date.now()) { |
| | | return true |
| | | } |
| | | return false |
| | | }, |
| | | onPick: ({ maxDate, minDate }) => { |
| | | if (maxDate) { |
| | | const oneYear = 365 * 24 * 60 * 60 * 1000 |
| | | const diff = maxDate.getTime() - minDate.getTime() |
| | | if (diff > oneYear) { |
| | | this.$nextTick(() => { |
| | | this.customDateRange = [minDate, new Date(minDate.getTime() + oneYear)] |
| | | }) |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | storeTopList: [], |
| | | driverTopList: [ |
| | | { driverName: '张伟大', phone: '18356981111', totalOrder: '100', totalIncome: '90720.00', driverShare: '90720.00', refundCount: '100', deductionTotal: '90720.00' }, |
| | |
| | | } |
| | | }, |
| | | methods: { |
| | | async exportRevenueTrend() { |
| | | try { |
| | | const params = {} |
| | | if (this.revenueMonth) { |
| | | params.month = `${this.revenueYear}-${String(this.revenueMonth).padStart(2, '0')}` |
| | | } else { |
| | | params.year = this.revenueYear |
| | | } |
| | | const response = await revenueTrendExport(params) |
| | | |
| | | // 创建下载链接 |
| | | const blob = new Blob([response.data], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' }) |
| | | const url = window.URL.createObjectURL(blob) |
| | | const link = document.createElement('a') |
| | | link.href = url |
| | | |
| | | let fileName |
| | | if (this.revenueMonth) { |
| | | fileName = `行李寄存门店${this.revenueYear}年${String(this.revenueMonth).padStart(2, '0')}月日.xlsx` |
| | | } else { |
| | | fileName = `行李寄存门店${this.revenueYear}年月.xlsx` |
| | | } |
| | | |
| | | link.setAttribute('download', fileName) |
| | | document.body.appendChild(link) |
| | | link.click() |
| | | document.body.removeChild(link) |
| | | window.URL.revokeObjectURL(url) |
| | | |
| | | this.$message.success('导出成功') |
| | | } catch (error) { |
| | | console.error('导出行李类型数据失败:', error) |
| | | this.$message.error('导出失败,请稍后重试') |
| | | } |
| | | }, |
| | | async getOverviewData(dateType = 0, shopId = null) { |
| | | const response = await overview({ dateType, shopId }) |
| | | const params = { dateType, shopId } |
| | | if (dateType === 5 && this.customDateRange && this.customDateRange.length === 2) { |
| | | params.startDate = this.customDateRange[0] |
| | | params.endDate = this.customDateRange[1] |
| | | } |
| | | const response = await overview(params) |
| | | this.overviewData = response || null |
| | | this.$nextTick(() => { |
| | | this.renderPieChart() |
| | |
| | | }, |
| | | onDateTypeChange(dateType) { |
| | | this.currentDateType = dateType |
| | | this.getOverviewData(dateType, this.currentShopId) |
| | | if (dateType !== 5) { |
| | | this.getOverviewData(dateType, this.currentShopId) |
| | | } |
| | | }, |
| | | onSearch() { |
| | | this.getOverviewData(this.currentDateType, this.currentShopId) |
| | |
| | | onReset() { |
| | | this.currentDateType = 0 |
| | | this.currentShopId = null |
| | | this.customDateRange = null |
| | | this.getOverviewData(0, null) |
| | | }, |
| | | async getShopList() { |
| | |
| | | tooltip: { |
| | | trigger: 'item', |
| | | formatter: (params) => { |
| | | return `${params.name}<br/>行李数: ${params.data.luggageCount}` |
| | | return `${params.name}<br/>行李数: ${params.data.luggageCount}<br/>订单数: ${params.data.value}` |
| | | } |
| | | }, |
| | | series: [ |
| | |
| | | label: { |
| | | show: true, |
| | | position: 'outside', |
| | | formatter: '{b}' |
| | | formatter: '{b} {d}%' |
| | | }, |
| | | emphasis: { |
| | | label: { |