|
@@ -3,52 +3,40 @@
|
|
|
<!-- 累积统计卡片行 -->
|
|
|
<el-row :gutter="20" class="panel-group">
|
|
|
<el-col :xs="12" :sm="12" :lg="6">
|
|
|
- <div class="card-panel">
|
|
|
- <div class="card-panel-icon-wrapper icon-orders">
|
|
|
- <svg-icon icon-class="form" class-name="card-panel-icon" />
|
|
|
- </div>
|
|
|
- <div class="card-panel-description">
|
|
|
- <div class="card-panel-text">累积洗衣件数</div>
|
|
|
- <count-to :start-val="0" :end-val="statistics.totalClothCount" :duration="2600" class="card-panel-num"/>
|
|
|
+ <div class="stat-card stat-card-blue">
|
|
|
+ <div class="stat-card-title">累积洗衣件数</div>
|
|
|
+ <div class="stat-card-value">
|
|
|
+ <count-to :start-val="0" :end-val="statistics.dailyInFactoryCount" :duration="2600" />
|
|
|
</div>
|
|
|
</div>
|
|
|
</el-col>
|
|
|
<el-col :xs="12" :sm="12" :lg="6">
|
|
|
- <div class="card-panel">
|
|
|
- <div class="card-panel-icon-wrapper icon-revenue">
|
|
|
- <svg-icon icon-class="money" class-name="card-panel-icon" />
|
|
|
- </div>
|
|
|
- <div class="card-panel-description">
|
|
|
- <div class="card-panel-text">累积洗衣金额</div>
|
|
|
- <count-to :start-val="0" :end-val="statistics.totalClothAmount" :duration="2600" class="card-panel-num" prefix="¥"/>
|
|
|
+ <div class="stat-card stat-card-green">
|
|
|
+ <div class="stat-card-title">累积洗衣金额</div>
|
|
|
+ <div class="stat-card-value">
|
|
|
+ <count-to :start-val="0" :end-val="statistics.dailyInFactoryAmount" :duration="2600" prefix="¥" />
|
|
|
</div>
|
|
|
</div>
|
|
|
</el-col>
|
|
|
<el-col :xs="12" :sm="12" :lg="6">
|
|
|
- <div class="card-panel">
|
|
|
- <div class="card-panel-icon-wrapper icon-cancel">
|
|
|
- <svg-icon icon-class="close" class-name="card-panel-icon" />
|
|
|
- </div>
|
|
|
- <div class="card-panel-description">
|
|
|
- <div class="card-panel-text">累积撤单件数</div>
|
|
|
- <count-to :start-val="0" :end-val="statistics.totalCancelCount" :duration="2600" class="card-panel-num"/>
|
|
|
+ <div class="stat-card stat-card-red">
|
|
|
+ <div class="stat-card-title">累积撤衣件数</div>
|
|
|
+ <div class="stat-card-value">
|
|
|
+ <count-to :start-val="0" :end-val="statistics.dailyRefundCount" :duration="2600" />
|
|
|
</div>
|
|
|
</div>
|
|
|
</el-col>
|
|
|
<el-col :xs="12" :sm="12" :lg="6">
|
|
|
- <div class="card-panel">
|
|
|
- <div class="card-panel-icon-wrapper icon-cancel-amount">
|
|
|
- <svg-icon icon-class="money" class-name="card-panel-icon" />
|
|
|
- </div>
|
|
|
- <div class="card-panel-description">
|
|
|
- <div class="card-panel-text">累积撤单金额</div>
|
|
|
- <count-to :start-val="0" :end-val="statistics.totalCancelAmount" :duration="2600" class="card-panel-num" prefix="¥"/>
|
|
|
+ <div class="stat-card stat-card-orange">
|
|
|
+ <div class="stat-card-title">累积撤衣金额</div>
|
|
|
+ <div class="stat-card-value">
|
|
|
+ <count-to :start-val="0" :end-val="statistics.dailyRefundAmount" :duration="2600" prefix="¥" />
|
|
|
</div>
|
|
|
</div>
|
|
|
</el-col>
|
|
|
</el-row>
|
|
|
|
|
|
- <!-- 今日营收概览 -->
|
|
|
+ <!-- 营收概览 -->
|
|
|
<el-row :gutter="20" class="panel-group" style="margin-top: 20px">
|
|
|
<el-col :span="24">
|
|
|
<div class="chart-wrapper">
|
|
@@ -56,14 +44,60 @@
|
|
|
<div class="chart-title">营收概览</div>
|
|
|
<div class="chart-actions">
|
|
|
<el-radio-group v-model="revenueTimeRange" size="small" @change="handleRevenueTimeRangeChange">
|
|
|
+ <el-radio-button label="today">今日</el-radio-button>
|
|
|
<el-radio-button label="week">近一周</el-radio-button>
|
|
|
<el-radio-button label="halfMonth">近半个月</el-radio-button>
|
|
|
<el-radio-button label="month">近一个月</el-radio-button>
|
|
|
</el-radio-group>
|
|
|
</div>
|
|
|
</div>
|
|
|
- <div class="chart-content">
|
|
|
- <revenue-chart :data="revenueData" />
|
|
|
+ <div class="chart-content-1">
|
|
|
+ <el-row :gutter="20" class="panel-group">
|
|
|
+ <el-col :xs="12" :sm="12" :lg="6">
|
|
|
+ <div class="card-panel">
|
|
|
+ <div class="card-panel-icon-wrapper icon-orders">
|
|
|
+ <svg-icon icon-class="form" class-name="card-panel-icon" />
|
|
|
+ </div>
|
|
|
+ <div class="card-panel-description">
|
|
|
+ <div class="card-panel-text">洗衣件数</div>
|
|
|
+ <count-to :start-val="0" :end-val="factoryStatistics.dailyInFactoryCount" :duration="2600" class="card-panel-num" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </el-col>
|
|
|
+ <el-col :xs="12" :sm="12" :lg="6">
|
|
|
+ <div class="card-panel">
|
|
|
+ <div class="card-panel-icon-wrapper icon-revenue">
|
|
|
+ <svg-icon icon-class="money" class-name="card-panel-icon" />
|
|
|
+ </div>
|
|
|
+ <div class="card-panel-description">
|
|
|
+ <div class="card-panel-text">洗衣金额</div>
|
|
|
+ <count-to :start-val="0" :end-val="factoryStatistics.dailyInFactoryAmount" :duration="2600" class="card-panel-num" prefix="¥" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </el-col>
|
|
|
+ <el-col :xs="12" :sm="12" :lg="6">
|
|
|
+ <div class="card-panel">
|
|
|
+ <div class="card-panel-icon-wrapper icon-cancel">
|
|
|
+ <svg-icon icon-class="form" class-name="card-panel-icon" />
|
|
|
+ </div>
|
|
|
+ <div class="card-panel-description">
|
|
|
+ <div class="card-panel-text">撤单件数</div>
|
|
|
+ <count-to :start-val="0" :end-val="factoryStatistics.dailyRefundCount" :duration="2600" class="card-panel-num" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </el-col>
|
|
|
+ <el-col :xs="12" :sm="12" :lg="6">
|
|
|
+ <div class="card-panel">
|
|
|
+ <div class="card-panel-icon-wrapper icon-cancel-amount">
|
|
|
+ <svg-icon icon-class="money" class-name="card-panel-icon" />
|
|
|
+ </div>
|
|
|
+ <div class="card-panel-description">
|
|
|
+ <div class="card-panel-text">撤单金额</div>
|
|
|
+ <count-to :start-val="0" :end-val="factoryStatistics.dailyRefundAmount" :duration="2600" class="card-panel-num" prefix="¥" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
</div>
|
|
|
</div>
|
|
|
</el-col>
|
|
@@ -94,7 +128,7 @@
|
|
|
<el-col :xs="24" :sm="24" :lg="24">
|
|
|
<div class="chart-wrapper">
|
|
|
<div class="chart-header">
|
|
|
- <div class="chart-title">门店业绩排行</div>
|
|
|
+ <div class="chart-title">门店洗衣排行</div>
|
|
|
<div class="chart-actions">
|
|
|
<el-radio-group v-model="rankingTimeRange" size="small" @change="handleRankingTimeRangeChange">
|
|
|
<el-radio-button label="week">近一周</el-radio-button>
|
|
@@ -105,12 +139,21 @@
|
|
|
</div>
|
|
|
<div class="chart-content">
|
|
|
<el-table :data="storeRankings" style="width: 100%" :show-header="true">
|
|
|
- <el-table-column prop="rank" label="排名" width="80"/>
|
|
|
- <el-table-column prop="storeName" label="门店名称"/>
|
|
|
- <el-table-column prop="orderCount" label="订单数" width="120"/>
|
|
|
- <el-table-column prop="clothCount" label="洗衣件数" width="120"/>
|
|
|
- <el-table-column prop="revenue" label="营收额" width="150"/>
|
|
|
- <el-table-column prop="completionRate" label="完成率" width="120"/>
|
|
|
+ <el-table-column prop="index" type="index" label="排名" width="80" />
|
|
|
+ <el-table-column label="门店名称" align="center" prop="storeName" />
|
|
|
+ <el-table-column label="入厂金额" align="center" prop="dailyInFactoryAmount">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ ¥{{ scope.row.dailyInFactoryAmount }}
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="退单金额" align="center" prop="dailyRefundAmount">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ ¥{{ scope.row.dailyRefundAmount }}
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="入厂衣服数" align="center" prop="dailyInFactoryCount" />
|
|
|
+ <el-table-column label="检查衣服数" align="center" prop="dailyCheckedCount" />
|
|
|
+ <el-table-column label="出厂衣服数" align="center" prop="dailyOutFactoryCount" />
|
|
|
</el-table>
|
|
|
</div>
|
|
|
</div>
|
|
@@ -121,19 +164,16 @@
|
|
|
|
|
|
<script>
|
|
|
import CountTo from 'vue-count-to'
|
|
|
-import { getTimeoutClothing } from "@/api/statistics/reception"
|
|
|
-import { listFinancialStatisticsByClothOrderDay, listFinancialStatisticsByClothOrderMonth } from "@/api/order/cloth"
|
|
|
-import { listStatistics } from "@/api/settlement/statistics"
|
|
|
-import RevenueChart from './components/RevenueChart'
|
|
|
+import { getTotalStatistics, listStatisticsByDate, listFactoryStatisticsByStore, factoryDashborad } from '@/api/settlement/statistics'
|
|
|
+import { getTimeoutClothing } from '@/api/statistics/reception'
|
|
|
import AmountTrendChart from './components/AmountTrendChart'
|
|
|
import CountTrendChart from './components/CountTrendChart'
|
|
|
|
|
|
export default {
|
|
|
- name: "Index",
|
|
|
+ name: 'Index',
|
|
|
dicts: ['sys_source_type'],
|
|
|
components: {
|
|
|
CountTo,
|
|
|
- RevenueChart,
|
|
|
AmountTrendChart,
|
|
|
CountTrendChart
|
|
|
},
|
|
@@ -148,71 +188,142 @@ export default {
|
|
|
totalCancelCount: 0,
|
|
|
totalCancelAmount: 0
|
|
|
},
|
|
|
- revenueTimeRange: 'week',
|
|
|
+ factoryStatistics: {
|
|
|
+ dailyInFactoryCount: 0,
|
|
|
+ dailyInFactoryAmount: 0,
|
|
|
+ dailyRefundCount: 0,
|
|
|
+ dailyRefundAmount: 0,
|
|
|
+ dailyActualSettlementAmount: 0
|
|
|
+ },
|
|
|
+ revenueTimeRange: 'today',
|
|
|
rankingTimeRange: 'week',
|
|
|
- revenueData: [],
|
|
|
amountTrendData: [],
|
|
|
countTrendData: [],
|
|
|
storeRankings: []
|
|
|
}
|
|
|
},
|
|
|
- mounted() {
|
|
|
- this.getroletype()
|
|
|
- this.getTimeout()
|
|
|
+ created() {
|
|
|
+ // this.getroletype()
|
|
|
+ // this.getTimeout()
|
|
|
this.getStatistics()
|
|
|
- this.getRevenueData()
|
|
|
+ this.getFactoryStatisticsData()
|
|
|
this.getStoreRankings()
|
|
|
+ this.getTrendData()
|
|
|
},
|
|
|
methods: {
|
|
|
- getroletype(){
|
|
|
+ getroletype() {
|
|
|
let name = ''
|
|
|
- this.dict.type.sys_source_type.map(item=>{
|
|
|
- if( item.value === this.$store.getters.user.userType ){
|
|
|
+ this.dict.type.sys_source_type.map(item => {
|
|
|
+ if (item.value === this.$store.getters.user.userType) {
|
|
|
name = item.label
|
|
|
}
|
|
|
})
|
|
|
-
|
|
|
- if( name === '工厂' || name === '门店' ){
|
|
|
- this.roleType = true;
|
|
|
- }
|
|
|
},
|
|
|
goTarget(href) {
|
|
|
window.open(href, "_blank");
|
|
|
},
|
|
|
- getTimeout(){
|
|
|
+ getTimeout() {
|
|
|
getTimeoutClothing(this.queryParams).then(response => {
|
|
|
this.timeoutClothing = response.data;
|
|
|
});
|
|
|
},
|
|
|
- btn_goto(type){
|
|
|
+ btn_goto(type) {
|
|
|
this.$router.push({ path: '/query/overtimeOrders' })
|
|
|
},
|
|
|
getStatistics() {
|
|
|
// 获取累积统计数据
|
|
|
- listFinancialStatisticsByClothOrderMonth({}).then(response => {
|
|
|
+ factoryDashborad({}).then(response => {
|
|
|
this.statistics = response.data
|
|
|
})
|
|
|
},
|
|
|
handleRevenueTimeRangeChange() {
|
|
|
- this.getRevenueData()
|
|
|
+ this.getFactoryStatisticsData()
|
|
|
},
|
|
|
handleRankingTimeRangeChange() {
|
|
|
this.getStoreRankings()
|
|
|
},
|
|
|
- getRevenueData() {
|
|
|
+ getFactoryStatisticsData() {
|
|
|
+ // 根据选择的时间范围获取工厂统计数据
|
|
|
const params = {
|
|
|
- timeRange: this.revenueTimeRange
|
|
|
+ startDate: this.getStartDateByTimeRange(),
|
|
|
+ endDate: this.formatDate(new Date())
|
|
|
}
|
|
|
- listFinancialStatisticsByClothOrderDay(params).then(response => {
|
|
|
- this.revenueData = response.data
|
|
|
+ getTotalStatistics(params).then(response => {
|
|
|
+ this.factoryStatistics = response.data
|
|
|
})
|
|
|
},
|
|
|
+ getStartDateByTimeRange() {
|
|
|
+ const today = new Date()
|
|
|
+ let startDate = new Date()
|
|
|
+
|
|
|
+ switch (this.revenueTimeRange) {
|
|
|
+ case 'today':
|
|
|
+ startDate = today
|
|
|
+ break
|
|
|
+ case 'week':
|
|
|
+ startDate.setDate(today.getDate() - 7)
|
|
|
+ break
|
|
|
+ case 'halfMonth':
|
|
|
+ startDate.setDate(today.getDate() - 15)
|
|
|
+ break
|
|
|
+ case 'month':
|
|
|
+ startDate.setDate(today.getDate() - 30)
|
|
|
+ break
|
|
|
+ }
|
|
|
+
|
|
|
+ return this.formatDate(startDate)
|
|
|
+ },
|
|
|
+ formatDate(date) {
|
|
|
+ const year = date.getFullYear()
|
|
|
+ const month = String(date.getMonth() + 1).padStart(2, '0')
|
|
|
+ const day = String(date.getDate()).padStart(2, '0')
|
|
|
+ return `${year}-${month}-${day}`
|
|
|
+ },
|
|
|
getStoreRankings() {
|
|
|
+ // 获取最近一周的日期范围
|
|
|
+ const endDate = new Date()
|
|
|
+ const startDate = new Date()
|
|
|
+ startDate.setDate(endDate.getDate() - 7)
|
|
|
+
|
|
|
const params = {
|
|
|
- timeRange: this.rankingTimeRange
|
|
|
+ startDate: this.formatDate(startDate),
|
|
|
+ endDate: this.formatDate(endDate),
|
|
|
+ pageSize: 10
|
|
|
}
|
|
|
- listStatistics(params).then(response => {
|
|
|
- this.storeRankings = response.data
|
|
|
+
|
|
|
+ // 使用 listFactoryStatisticsByStore 方法获取门店排行数据
|
|
|
+ listFactoryStatisticsByStore(params).then(response => {
|
|
|
+ this.storeRankings = response.rows || []
|
|
|
+ })
|
|
|
+ },
|
|
|
+ getTrendData() {
|
|
|
+ // 获取最近一周的日期范围
|
|
|
+ const endDate = new Date()
|
|
|
+ const startDate = new Date()
|
|
|
+ startDate.setDate(endDate.getDate() - 7)
|
|
|
+
|
|
|
+ const params = {
|
|
|
+ startDate: this.formatDate(startDate),
|
|
|
+ endDate: this.formatDate(endDate)
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取趋势数据
|
|
|
+ listStatisticsByDate(params).then(response => {
|
|
|
+ const data = response.rows || []
|
|
|
+
|
|
|
+ // 处理金额趋势数据
|
|
|
+ this.amountTrendData = data.map(item => ({
|
|
|
+ date: item.statisticsDate,
|
|
|
+ value: item.dailyInFactoryAmount || 0
|
|
|
+ }))
|
|
|
+
|
|
|
+ // 处理件数趋势数据 - 确保格式正确
|
|
|
+ this.countTrendData = {
|
|
|
+ dates: data.map(item => item.statisticsDate || ''),
|
|
|
+ inFactory: data.map(item => item.dailyInFactoryCount || 0),
|
|
|
+ checked: data.map(item => item.dailyCheckedCount || 0),
|
|
|
+ outFactory: data.map(item => item.dailyOutFactoryCount || 0)
|
|
|
+ }
|
|
|
})
|
|
|
}
|
|
|
}
|
|
@@ -223,6 +334,51 @@ export default {
|
|
|
.home {
|
|
|
.panel-group {
|
|
|
margin-top: 18px;
|
|
|
+
|
|
|
+ .stat-card {
|
|
|
+ height: 120px;
|
|
|
+ border-radius: 8px;
|
|
|
+ padding: 20px;
|
|
|
+ color: #fff;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ justify-content: center;
|
|
|
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
|
|
+ transition: all 0.3s;
|
|
|
+
|
|
|
+ &:hover {
|
|
|
+ transform: translateY(-5px);
|
|
|
+ box-shadow: 0 8px 16px rgba(0, 0, 0, 0.15);
|
|
|
+ }
|
|
|
+
|
|
|
+ .stat-card-title {
|
|
|
+ font-size: 16px;
|
|
|
+ margin-bottom: 10px;
|
|
|
+ opacity: 0.9;
|
|
|
+ }
|
|
|
+
|
|
|
+ .stat-card-value {
|
|
|
+ font-size: 28px;
|
|
|
+ font-weight: bold;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .stat-card-blue {
|
|
|
+ background: linear-gradient(135deg, #1890ff, #36cfc9);
|
|
|
+ }
|
|
|
+
|
|
|
+ .stat-card-green {
|
|
|
+ background: linear-gradient(135deg, #52c41a, #73d13d);
|
|
|
+ }
|
|
|
+
|
|
|
+ .stat-card-red {
|
|
|
+ background: linear-gradient(135deg, #f5222d, #ff4d4f);
|
|
|
+ }
|
|
|
+
|
|
|
+ .stat-card-orange {
|
|
|
+ background: linear-gradient(135deg, #fa8c16, #ffa940);
|
|
|
+ }
|
|
|
+
|
|
|
.card-panel {
|
|
|
height: 108px;
|
|
|
cursor: pointer;
|
|
@@ -278,31 +434,34 @@ export default {
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
.chart-wrapper {
|
|
|
background: #fff;
|
|
|
padding: 20px;
|
|
|
border-radius: 4px;
|
|
|
box-shadow: 0 2px 12px 0 rgba(0,0,0,.1);
|
|
|
-
|
|
|
+
|
|
|
.chart-header {
|
|
|
display: flex;
|
|
|
justify-content: space-between;
|
|
|
align-items: center;
|
|
|
margin-bottom: 20px;
|
|
|
-
|
|
|
+
|
|
|
.chart-title {
|
|
|
font-size: 16px;
|
|
|
font-weight: bold;
|
|
|
color: #303133;
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
.chart-content {
|
|
|
height: 300px;
|
|
|
}
|
|
|
+
|
|
|
+ .chart-content-1 {
|
|
|
+ height: 130px;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
</style>
|
|
|
|
|
|
-
|