283 lines
7.7 KiB
Vue
283 lines
7.7 KiB
Vue
<template>
|
|
<view>
|
|
<CuNavbar :isBack="false" title="数据报表"></CuNavbar>
|
|
<uv-sticky bgColor="#fff" v-if="checkPermission(['admin'])">
|
|
<StoreDown color="#333333" @change="storeChange"></StoreDown>
|
|
</uv-sticky>
|
|
|
|
<view class="card">
|
|
<uv-tabs
|
|
:lineColor="'#ee2c37'"
|
|
:list="tabsList"
|
|
:scrollable="false"
|
|
:current="tabIndex"
|
|
keyName="label"
|
|
@change="tabChange"
|
|
></uv-tabs>
|
|
|
|
<view class="text-center text-28rpx py-4rpx" v-if="tabIndex != 0"
|
|
>{{ currentC.start }} 至 {{ currentC.end }}
|
|
</view>
|
|
<view class="text-center text-28rpx" v-else>{{ currentC.start }}</view>
|
|
|
|
<view class="flex my-20rpx items-center table">
|
|
<view class="text-center flex-1 tr">
|
|
<view class="flex-center h-80rpx">销售金额</view>
|
|
<view class="font-600 flex-center h-80rpx">{{ ledger.sales }}</view>
|
|
</view>
|
|
|
|
<view class="text-center flex-1 tr">
|
|
<view class="flex-center h-80rpx" v-if="!isLotteryStore || checkPermission(['admin'])">
|
|
<view>支出金额</view>
|
|
</view>
|
|
<view class="flex-center h-80rpx" v-else>兑奖金额</view>
|
|
<view class="font-600 flex-center h-80rpx">{{ ledger.expenditure }}</view>
|
|
</view>
|
|
|
|
<view class="text-center flex-1 tr">
|
|
<view class="flex-center h-80rpx">销售涨幅</view>
|
|
<view
|
|
class="font-600 flex-center h-80rpx"
|
|
:class="[
|
|
ledger.sales_growth_rate > 0 ? 'text-primary' : 'text-green',
|
|
]"
|
|
>{{ ledger.sales_growth_rate }}%</view
|
|
>
|
|
</view>
|
|
</view>
|
|
|
|
<uv-tabs
|
|
@change="tabChange1"
|
|
:lineColor="'#ee2c37'"
|
|
:list="[{ name: '销售统计' }, { name: '门店统计' }]"
|
|
:scrollable="false"
|
|
:current="tabIndex1"
|
|
></uv-tabs>
|
|
<template v-if="tabIndex1 == 0">
|
|
<List0 :list="list"></List0>
|
|
</template>
|
|
<template v-if="tabIndex1 == 1">
|
|
<List1 :list="list"></List1>
|
|
</template>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
<script setup>
|
|
import StoreDown from '@/pages/home/components/store-down.vue'
|
|
import CuNavbar from '@/components/cu-navbar/index'
|
|
import { computed, reactive, ref } from 'vue'
|
|
import { timeFormat } from '@climblee/uv-ui/libs/function/index'
|
|
import { onShow } from '@dcloudio/uni-app'
|
|
import { http } from '@/utils/request'
|
|
import List0 from './components/list0.vue'
|
|
import List1 from './components/list1.vue'
|
|
import checkPermission from '@/utils/permission'
|
|
import dayjs from 'dayjs'
|
|
|
|
import { useUserStore } from '@/store/modules/user'
|
|
const userStore = useUserStore()
|
|
|
|
const isLotteryStore = computed(
|
|
() => userStore.userInfo?.store?.is_lottery_store
|
|
)
|
|
const tabIndex1 = ref(0)
|
|
const tabIndex = ref(0)
|
|
const tabsList = ref(generateTimeArrayWithLastPeriod())
|
|
const list = ref([])
|
|
const currentTabs = computed(() => tabsList.value[tabIndex.value])
|
|
const currentC = computed(() => {
|
|
const ob = currentTabs.value.current
|
|
return {
|
|
start: timeFormat(ob.startDate),
|
|
end: timeFormat(ob.endDate),
|
|
}
|
|
})
|
|
const currentL = computed(() => {
|
|
const ob = currentTabs.value.lastPeriod
|
|
return {
|
|
start: timeFormat(ob.startDate),
|
|
end: timeFormat(ob.endDate),
|
|
}
|
|
})
|
|
|
|
const shoreInfo = ref({})
|
|
|
|
if (!checkPermission(['admin'])) {
|
|
shoreInfo.value = { store_id: userStore?.userInfo?.store?.id }
|
|
}
|
|
|
|
const result = ref([])
|
|
const ledger = ref({
|
|
expenditure: '0',
|
|
sales: '0',
|
|
sales_growth_rate: '0',
|
|
})
|
|
|
|
const activeName = ref('area')
|
|
|
|
onShow(() => {
|
|
getCount()
|
|
getList()
|
|
})
|
|
|
|
const storeChange = (e) => {
|
|
shoreInfo.value = e
|
|
getCount()
|
|
getList()
|
|
}
|
|
|
|
const getCount = async () => {
|
|
const resData = await http.get('/statistics/ledger', {
|
|
params: {
|
|
start_at: currentC.value.start,
|
|
end_at: currentC.value.end,
|
|
before_start_at: currentL.value.start,
|
|
before_end_at: currentL.value.end,
|
|
...shoreInfo.value,
|
|
},
|
|
})
|
|
ledger.value = resData
|
|
}
|
|
|
|
function generateTimeArrayWithLastPeriod() {
|
|
const today = dayjs()
|
|
const yesterday = today.subtract(1, 'day')
|
|
|
|
let currentWeekStart = today.startOf('week').add(1, 'day') // 本周一
|
|
if (today.isBefore(currentWeekStart, 'day')) {
|
|
currentWeekStart = currentWeekStart.subtract(1, 'week')
|
|
}
|
|
const currentWeekEnd = today
|
|
|
|
let lastWeekStart = currentWeekStart.subtract(1, 'week')
|
|
const lastWeekEnd = currentWeekStart.subtract(1, 'day')
|
|
|
|
let currentMonthStart = today.startOf('month')
|
|
if (today.isBefore(currentMonthStart, 'day')) {
|
|
currentMonthStart = currentMonthStart.subtract(1, 'month')
|
|
}
|
|
const currentMonthEnd = today.endOf('day') // 本月最后一天到当天结束
|
|
|
|
let lastMonthStart = currentMonthStart.subtract(1, 'month')
|
|
const lastMonthEnd = currentMonthStart.subtract(1, 'day')
|
|
|
|
const timeArray = [
|
|
generateTimeRange('昨日', yesterday),
|
|
generateTimeRange('本周', currentWeekStart, currentWeekEnd),
|
|
generateTimeRange('上周', lastWeekStart, lastWeekEnd),
|
|
generateTimeRange('本月', currentMonthStart, currentMonthEnd),
|
|
generateTimeRange('上月', lastMonthStart, lastMonthEnd),
|
|
]
|
|
|
|
const lastPeriodTimeRanges = {}
|
|
|
|
// 计算同期的上次开始和结束时间
|
|
timeArray.forEach((timeRange) => {
|
|
switch (timeRange.label) {
|
|
case '昨日':
|
|
lastPeriodTimeRanges['昨日'] = {
|
|
startDate: dayjs(timeRange.current.startDate)
|
|
.subtract(1, 'day')
|
|
.toDate(),
|
|
endDate: dayjs(timeRange.current.endDate).subtract(1, 'day').toDate(),
|
|
}
|
|
break
|
|
case '本周':
|
|
lastPeriodTimeRanges['本周'] = {
|
|
startDate: dayjs(timeRange.current.startDate)
|
|
.subtract(1, 'week')
|
|
.toDate(),
|
|
endDate: dayjs(timeRange.current.endDate)
|
|
.subtract(1, 'week')
|
|
.toDate(),
|
|
}
|
|
break
|
|
case '上周':
|
|
lastPeriodTimeRanges['上周'] = {
|
|
startDate: dayjs(timeRange.current.startDate)
|
|
.subtract(1, 'week')
|
|
.toDate(),
|
|
endDate: dayjs(timeRange.current.endDate)
|
|
.subtract(1, 'week')
|
|
.toDate(),
|
|
}
|
|
break
|
|
case '本月':
|
|
lastPeriodTimeRanges['本月'] = {
|
|
startDate: dayjs(timeRange.current.startDate)
|
|
.subtract(1, 'month')
|
|
.toDate(),
|
|
endDate: dayjs(timeRange.current.endDate)
|
|
.subtract(1, 'month')
|
|
.toDate(),
|
|
}
|
|
break
|
|
case '上月':
|
|
lastPeriodTimeRanges['上月'] = {
|
|
startDate: dayjs(timeRange.current.startDate)
|
|
.subtract(1, 'month')
|
|
.toDate(),
|
|
endDate: dayjs(timeRange.current.endDate)
|
|
.subtract(1, 'month')
|
|
.toDate(),
|
|
}
|
|
break
|
|
default:
|
|
break
|
|
}
|
|
})
|
|
|
|
// 更新 timeArray 中的 lastPeriod 字段
|
|
timeArray.forEach((timeRange) => {
|
|
timeRange.lastPeriod = lastPeriodTimeRanges[timeRange.label]
|
|
})
|
|
|
|
return timeArray
|
|
}
|
|
|
|
function generateTimeRange(label, startDate, endDate) {
|
|
return {
|
|
label,
|
|
current: {
|
|
startDate: startDate.toDate(),
|
|
endDate: (endDate || startDate).toDate(),
|
|
},
|
|
lastPeriod: { startDate: null, endDate: null },
|
|
}
|
|
}
|
|
|
|
const tabChange = (e) => {
|
|
list.value = []
|
|
tabIndex.value = e.index
|
|
getCount()
|
|
getList()
|
|
}
|
|
|
|
const tabChange1 = (e) => {
|
|
list.value = []
|
|
tabIndex1.value = e.index
|
|
getList()
|
|
}
|
|
|
|
const getList = async () => {
|
|
const url = tabIndex1.value == 0 ? '/statistics/sales' : '/statistics/stores'
|
|
const resData = await http.get(url, {
|
|
params: {
|
|
start_at: currentC.value.start,
|
|
end_at: currentC.value.end,
|
|
...shoreInfo.value,
|
|
},
|
|
})
|
|
list.value = resData
|
|
}
|
|
</script>
|
|
<style lang="scss">
|
|
.table {
|
|
display: flex;
|
|
// border: 1px solid;
|
|
}
|
|
.tr {
|
|
border: 0.5px solid #f5f5f5;
|
|
}
|
|
</style>
|