food/src/views/layout/components/main/order/stat.vue
tk 5abd57755e 【类 型】:factor 销售统计模块
【原  因】:
【过  程】:1.调整按需加载2.按选择条件日 月 年 分为三个 异步加载搜索内容 3.调整ui 包裹手机端竖屏自适应 4.点击跳转到订单管理页面,跳转前设置订单全局搜索条件
【影  响】:
2024-08-06 16:00:15 +08:00

486 lines
17 KiB
Vue

<template>
<div class="app-container">
<!-- 用户select选项 -->
<SelectionShopId class="w-40" v-model="shop_id" :allSel="true" />
<!-- 统计标签 -->
<el-row :gutter="10" class="m-t-20">
<!-- 日统计标签 -->
<el-col :span="8" :xs="24" v-loading="dayBoxLoading" class="m-b-10">
<div class="dayStatBox rad4 flex p-10 column" @click="handlerRouteCilck('day')">
<div @click.stop>
<el-date-picker class="w-100" v-model="dayTime" align="right" type="date" placeholder="今日"
:picker-options="dayPickerOptions" />
</div>
<div class="flex m-t-5">
<div class="flex3 flex mc column">
<div class="flex m-t-5">
<div class="w-40 flex ml p-l-5 p-r-5">
<div class="p-4 bg-white rad2 fc-b fb fc">营业额</div>
</div>
<div class="p-4 m-l-5 fr">{{ dayPaidTotal }}元</div>
</div>
<div class="flex m-t-5">
<div class="w-40 flex ml p-l-5 p-r-5">
<div class="p-4 bg-white rad2 fc-b fb fc">收款单</div>
</div>
<div class="p-4 m-l-5 fr">{{ dayPaid.length }}单</div>
</div>
<div class="flex m-t-5">
<div class="w-40 flex ml p-l-5 p-r-5">
<div class="p-4 bg-white rad2 fc-b fb fc">退款额</div>
</div>
<div class="p-4 m-l-5 fr">{{ dayRefundTotal }}元</div>
</div>
<div class="flex m-t-5">
<div class="w-40 flex ml p-l-5 p-r-5">
<div class="p-4 bg-white rad2 fc-b fb fc">已退单</div>
</div>
<div class="p-4 m-l-5 fr">{{ dayRefund.length }}单</div>
</div>
</div>
<div class="flex1 flex mc mac ofh">
<div class="rad-c w-50px h-50px bg-white fb fc f-s-32 fc-b l-h-50 no-select">日</div>
</div>
</div>
</div>
</el-col>
<!-- 月统计标签 -->
<el-col :span="8" :xs="24" v-loading="monthBoxLoading" class="m-b-10">
<div class="monthStatBox rad4 flex p-10 column" @click="handlerRouteCilck('month')">
<div @click.stop>
<el-date-picker class="w-100" v-model="monthTime" align="right" type="month" placeholder="本月"
:picker-options="monthPickerOptions" />
</div>
<div class="flex m-t-5">
<div class="flex3 flex mc column">
<div class="flex m-t-5">
<div class="w-40 flex ml p-l-5 p-r-5">
<div class="p-4 bg-white rad2 fc-s fb fc">营业额</div>
</div>
<div class="p-4 m-l-5 fr">{{ monthPaidTotal }}元</div>
</div>
<div class="flex m-t-5">
<div class="w-40 flex ml p-l-5 p-r-5">
<div class="p-4 bg-white rad2 fc-s fb fc">收款单</div>
</div>
<div class="p-4 m-l-5 fr">{{ monthPaid.length }}单</div>
</div>
<div class="flex m-t-5">
<div class="w-40 flex ml p-l-5 p-r-5">
<div class="p-4 bg-white rad2 fc-s fb fc">退款额</div>
</div>
<div class="p-4 m-l-5 fr">{{ monthRefundTotal }}元</div>
</div>
<div class="flex m-t-5">
<div class="w-40 flex ml p-l-5 p-r-5">
<div class="p-4 bg-white rad2 fc-s fb fc">已退单</div>
</div>
<div class="p-4 m-l-5 fr">{{ monthRefund.length }}单</div>
</div>
</div>
<div class="flex1 flex mc mac ofh">
<div class="rad-c w-50px h-50px bg-white fb fc f-s-32 fc-s l-h-50 no-select">月</div>
</div>
</div>
</div>
</el-col>
<!-- 年统计标签 -->
<el-col :span="8" :xs="24" v-loading="yearBoxLoading" class="m-b-10">
<div class="yearStatBox rad4 flex p-10 column" @click="handlerRouteCilck('year')">
<div @click.stop>
<el-date-picker class="w-100" v-model="yearTime" align="right" type="year" placeholder="本年"
:picker-options="yearPickerOptions" />
</div>
<div class="flex m-t-5">
<div class="flex3 flex mc column">
<div class="flex m-t-5">
<div class="w-40 flex ml p-l-5 p-r-5">
<div class="p-4 bg-white rad2 fc-w fb fc">营业额</div>
</div>
<div class="p-4 m-l-5 fr">{{ yearPaidTotal }}元</div>
</div>
<div class="flex m-t-5">
<div class="w-40 flex ml p-l-5 p-r-5">
<div class="p-4 bg-white rad2 fc-w fb fc">收款单</div>
</div>
<div class="p-4 m-l-5 fr">{{ yearPaid.length }}单</div>
</div>
<div class="flex m-t-5">
<div class="w-40 flex ml p-l-5 p-r-5">
<div class="p-4 bg-white rad2 fc-w fb fc">退款额</div>
</div>
<div class="p-4 m-l-5 fr">{{ yearRefundTotal }}元</div>
</div>
<div class="flex m-t-5">
<div class="w-40 flex ml p-l-5 p-r-5">
<div class="p-4 bg-white rad2 fc-w fb fc">已退单</div>
</div>
<div class="p-4 m-l-5 fr">{{ yearRefund.length }}单</div>
</div>
</div>
<div class="flex1 flex mc mac ofh">
<div class="rad-c w-50px h-50px bg-white fb fc f-s-32 fc-w l-h-50 no-select"></div>
</div>
</div>
</div>
</el-col>
</el-row>
</div>
</template>
<script>
import SelectionShopId from '@/components/SelectionShopId.vue'
import { formatPrice } from '@/utils'
import { getOrderList } from '@/utils/api/table'
export default {
name: 'Stat',
data () {
return {
shop_id: '', // 搜索条件 商铺id
dayOrderList: [], // 日统计 订单列表
monthOrderList: [], // 月统计 订单列表
yearOrderList: [], // 年统计 订单列表
dayBoxLoading: true, // 日统计框 加载
monthBoxLoading: true, // 月统计框 加载
yearBoxLoading: true, // 年统计框 加载
// 日选择器
dayPickerOptions: {
disabledDate (time) {
return time.getTime() > Date.now()
},
shortcuts: [{
text: '今天',
onClick (picker) {
const start = new Date()
start.setHours(0, 0, 0, 0)
picker.$emit('pick', start)
}
}, {
text: '昨天',
onClick (picker) {
const start = new Date()
start.setDate(start.getDate() - 1)
start.setHours(0, 0, 0, 0)
picker.$emit('pick', start)
}
}, {
text: '前天',
onClick (picker) {
const start = new Date()
start.setDate(start.getDate() - 2)
start.setHours(0, 0, 0, 0)
picker.$emit('pick', start)
}
}]
},
dayTime: new Date(), // 默认值为今天
monthPickerOptions: {
disabledDate (time) {
return time.getTime() > Date.now()
},
shortcuts: [{
text: '本月',
onClick (picker) {
const start = new Date()
start.setDate(1)
start.setHours(0, 0, 0, 0)
picker.$emit('pick', start)
}
}, {
text: '上月',
onClick (picker) {
const start = new Date()
start.setMonth(start.getMonth() - 1)
start.setDate(1)
start.setHours(0, 0, 0, 0)
picker.$emit('pick', start)
}
}, {
text: '前月',
onClick (picker) {
const start = new Date()
start.setMonth(start.getMonth() - 2)
start.setDate(1)
start.setHours(0, 0, 0, 0)
picker.$emit('pick', start)
}
}]
},
monthTime: new Date(), // 默认值为本月
yearPickerOptions: {
disabledDate (time) {
return time.getTime() > Date.now()
},
shortcuts: [{
text: '本年',
onClick (picker) {
const start = new Date()
start.setMonth(0)
start.setDate(1)
start.setHours(0, 0, 0, 0)
picker.$emit('pick', start)
}
}, {
text: '去年',
onClick (picker) {
const start = new Date()
start.setFullYear(start.getFullYear() - 1)
start.setMonth(0)
start.setDate(1)
start.setHours(0, 0, 0, 0)
picker.$emit('pick', start)
}
}, {
text: '前年',
onClick (picker) {
const start = new Date()
start.setFullYear(start.getFullYear() - 2)
start.setMonth(0)
start.setDate(1)
start.setHours(0, 0, 0, 0)
picker.$emit('pick', start)
}
}]
},
yearTime: new Date() // 默认值为本年
}
},
components: {
SelectionShopId
},
computed: {
// 日 统计组件 起始 结束时间戳
dayTimestamps () {
if (!this.dayTime) {
return { start: null, end: null }
}
const start = new Date(this.dayTime)
start.setHours(0, 0, 0, 0)
const end = new Date(this.dayTime)
end.setHours(23, 59, 59, 999)
return {
start: Math.floor(start.getTime() / 1000), // 转换为秒
end: Math.floor(end.getTime() / 1000) // 转换为秒
}
},
// 日搜索条件 集合
dayOrderSerch () {
return {
shop_id: this.shop_id, // 搜索条件 商铺id
start_time: Math.floor(this.dayTimestamps.start), // 搜索条件 起始时间
end_time: Math.floor(this.dayTimestamps.end), // 搜索条件 结束时间
main_status: ['已付款', '已退款', '已完成'], // 搜索条件 主状态
shipment_status: [], // 搜索条件 执行状态
refund_status: [], // 搜索条件 退款状态
search: ['orderSn', '']// 搜索条件 搜索
}
},
// 过滤出 日 收款订单 包括已付款 和 已完成
dayPaid () {
return this.dayOrderList
},
// 日收款订单 营业额总和
dayPaidTotal () {
return formatPrice(this.dayPaid.reduce((total, item) => total + Number(item.total_price) - Number(item.refund_price), 0))
},
// 过滤出 日 退款付点单
dayRefund () {
return this.dayOrderList.filter(item => item.main_status === '已退款')
},
// 日收款订单 退款额总和
dayRefundTotal () {
return formatPrice(this.dayRefund.reduce((total, item) => total + Number(item.refund_price), 0))
},
// 月 统计组件 起始 结束时间戳
monthTimestamps () {
if (!this.monthTime) {
return { start: null, end: null }
}
const start = new Date(this.monthTime)
start.setDate(1)
start.setHours(0, 0, 0, 0)
const end = new Date(this.monthTime)
end.setMonth(end.getMonth() + 1)
end.setDate(0)
end.setHours(23, 59, 59, 999)
return {
start: Math.floor(start.getTime() / 1000), // 转换为秒
end: Math.floor(end.getTime() / 1000) // 转换为秒
}
},
// 月搜索条件 集合
monthOrderSerch () {
return {
shop_id: this.shop_id, // 搜索条件 商铺id
start_time: Math.floor(this.monthTimestamps.start), // 搜索条件 起始时间
end_time: Math.floor(this.monthTimestamps.end), // 搜索条件 结束时间
main_status: ['已付款', '已退款', '已完成'], // 搜索条件 主状态
shipment_status: [], // 搜索条件 执行状态
refund_status: [], // 搜索条件 退款状态
search: ['orderSn', '']// 搜索条件 搜索
}
},
// 过滤出 月 收款订单 包括已付款 和 已完成
monthPaid () {
return this.monthOrderList
},
// 月收款订单 营业额总和
monthPaidTotal () {
return formatPrice(this.monthPaid.reduce((total, item) => total + Number(item.total_price) - Number(item.refund_price), 0))
},
// 过滤出 月 退款付点单
monthRefund () {
return this.monthOrderList.filter(item => item.main_status === '已退款')
},
// 月收款订单 退款额总和
monthRefundTotal () {
return formatPrice(this.monthRefund.reduce((total, item) => total + Number(item.refund_price), 0))
},
// 年 统计组件 起始 结束时间戳
yearTimestamps () {
if (!this.yearTime) {
return { start: null, end: null }
}
const start = new Date(this.yearTime)
start.setMonth(0)
start.setDate(1)
start.setHours(0, 0, 0, 0)
const end = new Date(this.yearTime)
end.setMonth(11)
end.setDate(31)
end.setHours(23, 59, 59, 999)
return {
start: Math.floor(start.getTime() / 1000), // 转换为秒
end: Math.floor(end.getTime() / 1000) // 转换为秒
}
},
// 年搜索条件 集合
yearOrderSerch () {
return {
shop_id: this.shop_id, // 搜索条件 商铺id
start_time: Math.floor(this.yearTimestamps.start), // 搜索条件 起始时间
end_time: Math.floor(this.yearTimestamps.end), // 搜索条件 结束时间
main_status: ['已付款', '已退款', '已完成'], // 搜索条件 主状态
shipment_status: [], // 搜索条件 执行状态
refund_status: [], // 搜索条件 退款状态
search: ['orderSn', '']// 搜索条件 搜索
}
},
// 过滤出 年 收款订单 包括已付款 和 已完成
yearPaid () {
return this.yearOrderList
},
// 年收款订单 营业额总和
yearPaidTotal () {
return formatPrice(this.yearPaid.reduce((total, item) => total + Number(item.total_price) - Number(item.refund_price), 0))
},
// 过滤出 年 退款付点单
yearRefund () {
return this.yearOrderList.filter(item => item.main_status === '已退款')
},
// 年收款订单 退款额总和
yearRefundTotal () {
return formatPrice(this.yearRefund.reduce((total, item) => total + Number(item.refund_price), 0))
}
},
methods: {
/**
* 获取订单列表
* @param orderSerch 搜索条件
* @param type 请求类型 day month year 按条件给对应 属性列表赋值
*/
async getOrderList (orderSerch, type) {
const res = await getOrderList(orderSerch)
if (type === 'day') {
if (res.data.status === 1) {
this.dayOrderList = res.data.orderList
} else {
this.$message.error('日订单列表获取失败')
}
this.dayBoxLoading = false // 结束加载动画
} else if (type === 'month') {
if (res.data.status === 1) {
this.monthOrderList = res.data.orderList
} else {
this.$message.error('月订单列表获取失败')
}
this.monthBoxLoading = false // 结束加载动画
} else if (type === 'year') {
if (res.data.status === 1) {
this.yearOrderList = res.data.orderList
} else {
this.$message.error('年订单列表获取失败')
}
this.yearBoxLoading = false // 结束加载动画
}
},
/**
* 点击路由到订单管理页面
* @param type 路由时 判断全局的搜索条件
*/
handlerRouteCilck (type) {
if (type === 'day') {
this.$store.commit('app/setOrderSerch', this.dayOrderSerch)
} else if (type === 'month') {
this.$store.commit('app/setOrderSerch', this.monthOrderSerch)
} else if (type === 'year') {
this.$store.commit('app/setOrderSerch', this.yearOrderSerch)
}
this.$router.push('/order/index')
}
},
watch: {
dayOrderSerch: {
handler (val) {
this.dayBoxLoading = true// 日统计框 加载动画
this.getOrderList(val, 'day')
},
deep: true
},
monthOrderSerch: {
handler (val) {
this.monthBoxLoading = true// 月统计框 加载动画
this.getOrderList(val, 'month')
},
deep: true
},
yearOrderSerch: {
handler (val) {
this.yearBoxLoading = true// 年统计框 加载动画
this.getOrderList(val, 'year')
},
deep: true
}
},
created () {
this.getOrderList(this.dayOrderSerch, 'day')
this.getOrderList(this.monthOrderSerch, 'month')
this.getOrderList(this.yearOrderSerch, 'year')
}
}
</script>
<style lang="scss" scoped>
@import "@/styles/theme.scss";
.dayStatBox {
background-color: $brand-color;
color: $white-color;
}
.monthStatBox {
background-color: $success-color;
color: $white-color;
}
.yearStatBox {
background-color: $warning-color;
color: $white-color;
}
</style>