This commit is contained in:
Mrking 2024-09-15 21:42:01 +08:00
parent b33aea368a
commit 355e94cc2e
5 changed files with 505 additions and 505 deletions

View File

@ -1,42 +1,42 @@
<template>
<div class="flex flex-col gap-2 bg-[var(--el-bg-color-overlay)] p-6">
<div class="flex items-center justify-between text-gray-500">
<span>{{ title }}</span>
<el-tag>{{ tag }}</el-tag>
</div>
<div class="flex flex-row items-baseline justify-between">
<CountTo :prefix="prefix" :end-val="value" :decimals="decimals" class="text-3xl" />
<span :class="toNumber(percent) > 0 ? 'text-red-500' : 'text-green-500'">
{{ Math.abs(toNumber(percent)) }}%
<Icon :icon="toNumber(percent) > 0 ? 'ep:caret-top' : 'ep:caret-bottom'" class="!text-sm" />
</span>
</div>
<el-divider class="mb-1! mt-2!" />
<div class="flex flex-row items-center justify-between text-sm">
<span class="text-gray-500">昨日数据</span>
<span>{{ prefix || '' }}{{ reference }}</span>
</div>
</div>
</template>
<script lang="ts" setup>
import { propTypes } from '@/utils/propTypes'
import { toNumber } from 'lodash-es'
import { calculateRelativeRate } from '@/utils'
<!--<template>-->
<!-- <div class="flex flex-col gap-2 bg-[var(&#45;&#45;el-bg-color-overlay)] p-6">-->
<!-- <div class="flex items-center justify-between text-gray-500">-->
<!-- <span>{{ title }}</span>-->
<!-- <el-tag>{{ tag }}</el-tag>-->
<!-- </div>-->
<!-- <div class="flex flex-row items-baseline justify-between">-->
<!-- <CountTo :prefix="prefix" :end-val="value" :decimals="decimals" class="text-3xl" />-->
<!-- <span :class="toNumber(percent) > 0 ? 'text-red-500' : 'text-green-500'">-->
<!-- {{ Math.abs(toNumber(percent)) }}%-->
<!-- <Icon :icon="toNumber(percent) > 0 ? 'ep:caret-top' : 'ep:caret-bottom'" class="!text-sm" />-->
<!-- </span>-->
<!-- </div>-->
<!-- <el-divider class="mb-1! mt-2!" />-->
<!-- <div class="flex flex-row items-center justify-between text-sm">-->
<!-- <span class="text-gray-500">昨日数据</span>-->
<!-- <span>{{ prefix || '' }}{{ reference }}</span>-->
<!-- </div>-->
<!-- </div>-->
<!--</template>-->
<!--<script lang="ts" setup>-->
<!--import { propTypes } from '@/utils/propTypes'-->
<!--import { toNumber } from 'lodash-es'-->
<!--import { calculateRelativeRate } from '@/utils'-->
/** 交易对照卡片 */
defineOptions({ name: 'ComparisonCard' })
<!--/** 交易对照卡片 */-->
<!--defineOptions({ name: 'ComparisonCard' })-->
const props = defineProps({
title: propTypes.string.def('').isRequired,
tag: propTypes.string.def(''),
prefix: propTypes.string.def(''),
value: propTypes.number.def(0).isRequired,
reference: propTypes.number.def(0).isRequired,
decimals: propTypes.number.def(0)
})
<!--const props = defineProps({-->
<!-- title: propTypes.string.def('').isRequired,-->
<!-- tag: propTypes.string.def(''),-->
<!-- prefix: propTypes.string.def(''),-->
<!-- value: propTypes.number.def(0).isRequired,-->
<!-- reference: propTypes.number.def(0).isRequired,-->
<!-- decimals: propTypes.number.def(0)-->
<!--})-->
//
const percent = computed(() =>
calculateRelativeRate(props.value as number, props.reference as number)
)
</script>
<!--// -->
<!--const percent = computed(() =>-->
<!-- calculateRelativeRate(props.value as number, props.reference as number)-->
<!--)-->
<!--</script>-->

View File

@ -1,91 +1,91 @@
<template>
<el-card shadow="never">
<template #header>
<CardTitle title="用户统计" />
</template>
<!-- 折线图 -->
<Echart :height="300" :options="lineChartOptions" />
</el-card>
</template>
<script lang="ts" setup>
import dayjs from 'dayjs'
import { EChartsOption } from 'echarts'
import * as MemberStatisticsApi from '@/api/mall/statistics/member'
import { formatDate } from '@/utils/formatTime'
import { CardTitle } from '@/components/Card'
<!--<template>-->
<!-- <el-card shadow="never">-->
<!-- <template #header>-->
<!-- <CardTitle title="用户统计" />-->
<!-- </template>-->
<!-- &lt;!&ndash; 折线图 &ndash;&gt;-->
<!-- <Echart :height="300" :options="lineChartOptions" />-->
<!-- </el-card>-->
<!--</template>-->
<!--<script lang="ts" setup>-->
<!--import dayjs from 'dayjs'-->
<!--import { EChartsOption } from 'echarts'-->
<!--import * as MemberStatisticsApi from '@/api/mall/statistics/member'-->
<!--import { formatDate } from '@/utils/formatTime'-->
<!--import { CardTitle } from '@/components/Card'-->
/** 会员用户统计卡片 */
defineOptions({ name: 'MemberStatisticsCard' })
<!--/** 会员用户统计卡片 */-->
<!--defineOptions({ name: 'MemberStatisticsCard' })-->
const loading = ref(true) //
/** 折线图配置 */
const lineChartOptions = reactive<EChartsOption>({
dataset: {
dimensions: ['date', 'count'],
source: []
},
grid: {
left: 20,
right: 20,
bottom: 20,
top: 80,
containLabel: true
},
legend: {
top: 50
},
series: [{ name: '注册量', type: 'line', smooth: true, areaStyle: {} }],
toolbox: {
feature: {
//
dataZoom: {
yAxisIndex: false // Y
},
brush: {
type: ['lineX', 'clear'] //
},
saveAsImage: { show: true, name: '会员统计' } //
}
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross'
},
padding: [5, 10]
},
xAxis: {
type: 'category',
boundaryGap: false,
axisTick: {
show: false
},
axisLabel: {
formatter: (date: string) => formatDate(date, 'MM-DD')
}
},
yAxis: {
axisTick: {
show: false
}
}
}) as EChartsOption
<!--const loading = ref(true) // -->
<!--/** 折线图配置 */-->
<!--const lineChartOptions = reactive<EChartsOption>({-->
<!-- dataset: {-->
<!-- dimensions: ['date', 'count'],-->
<!-- source: []-->
<!-- },-->
<!-- grid: {-->
<!-- left: 20,-->
<!-- right: 20,-->
<!-- bottom: 20,-->
<!-- top: 80,-->
<!-- containLabel: true-->
<!-- },-->
<!-- legend: {-->
<!-- top: 50-->
<!-- },-->
<!-- series: [{ name: '注册量', type: 'line', smooth: true, areaStyle: {} }],-->
<!-- toolbox: {-->
<!-- feature: {-->
<!-- // -->
<!-- dataZoom: {-->
<!-- yAxisIndex: false // Y-->
<!-- },-->
<!-- brush: {-->
<!-- type: ['lineX', 'clear'] // -->
<!-- },-->
<!-- saveAsImage: { show: true, name: '会员统计' } // -->
<!-- }-->
<!-- },-->
<!-- tooltip: {-->
<!-- trigger: 'axis',-->
<!-- axisPointer: {-->
<!-- type: 'cross'-->
<!-- },-->
<!-- padding: [5, 10]-->
<!-- },-->
<!-- xAxis: {-->
<!-- type: 'category',-->
<!-- boundaryGap: false,-->
<!-- axisTick: {-->
<!-- show: false-->
<!-- },-->
<!-- axisLabel: {-->
<!-- formatter: (date: string) => formatDate(date, 'MM-DD')-->
<!-- }-->
<!-- },-->
<!-- yAxis: {-->
<!-- axisTick: {-->
<!-- show: false-->
<!-- }-->
<!-- }-->
<!--}) as EChartsOption-->
const getMemberRegisterCountList = async () => {
loading.value = true
//
const beginTime = dayjs().subtract(30, 'd').startOf('d')
const endTime = dayjs().endOf('d')
const list = await MemberStatisticsApi.getMemberRegisterCountList(beginTime, endTime)
// Echarts
if (lineChartOptions.dataset && lineChartOptions.dataset['source']) {
lineChartOptions.dataset['source'] = list
}
loading.value = false
}
<!--const getMemberRegisterCountList = async () => {-->
<!-- loading.value = true-->
<!-- // -->
<!-- const beginTime = dayjs().subtract(30, 'd').startOf('d')-->
<!-- const endTime = dayjs().endOf('d')-->
<!-- const list = await MemberStatisticsApi.getMemberRegisterCountList(beginTime, endTime)-->
<!-- // Echarts -->
<!-- if (lineChartOptions.dataset && lineChartOptions.dataset['source']) {-->
<!-- lineChartOptions.dataset['source'] = list-->
<!-- }-->
<!-- loading.value = false-->
<!--}-->
/** 初始化 **/
onMounted(() => {
getMemberRegisterCountList()
})
</script>
<!--/** 初始化 **/-->
<!--onMounted(() => {-->
<!-- getMemberRegisterCountList()-->
<!--})-->
<!--</script>-->

View File

@ -1,107 +1,107 @@
<template>
<el-card shadow="never">
<template #header>
<CardTitle title="运营数据" />
</template>
<div class="flex flex-row flex-wrap items-center gap-8 p-4">
<div
v-for="item in data"
:key="item.name"
class="h-20 w-20% flex flex-col cursor-pointer items-center justify-center gap-2"
@click="handleClick(item.routerName)"
>
<CountTo
:prefix="item.prefix"
:end-val="item.value"
:decimals="item.decimals"
class="text-3xl"
/>
<span class="text-center">{{ item.name }}</span>
</div>
</div>
</el-card>
</template>
<script lang="ts" setup>
import * as ProductSpuApi from '@/api/mall/product/spu'
import * as TradeStatisticsApi from '@/api/mall/statistics/trade'
import * as PayStatisticsApi from '@/api/mall/statistics/pay'
import { CardTitle } from '@/components/Card'
<!--<template>-->
<!-- <el-card shadow="never">-->
<!-- <template #header>-->
<!-- <CardTitle title="运营数据" />-->
<!-- </template>-->
<!-- <div class="flex flex-row flex-wrap items-center gap-8 p-4">-->
<!-- <div-->
<!-- v-for="item in data"-->
<!-- :key="item.name"-->
<!-- class="h-20 w-20% flex flex-col cursor-pointer items-center justify-center gap-2"-->
<!-- @click="handleClick(item.routerName)"-->
<!-- >-->
<!-- <CountTo-->
<!-- :prefix="item.prefix"-->
<!-- :end-val="item.value"-->
<!-- :decimals="item.decimals"-->
<!-- class="text-3xl"-->
<!-- />-->
<!-- <span class="text-center">{{ item.name }}</span>-->
<!-- </div>-->
<!-- </div>-->
<!-- </el-card>-->
<!--</template>-->
<!--<script lang="ts" setup>-->
<!--import * as ProductSpuApi from '@/api/mall/product/spu'-->
<!--import * as TradeStatisticsApi from '@/api/mall/statistics/trade'-->
<!--import * as PayStatisticsApi from '@/api/mall/statistics/pay'-->
<!--import { CardTitle } from '@/components/Card'-->
/** 运营数据卡片 */
defineOptions({ name: 'OperationDataCard' })
<!--/** 运营数据卡片 */-->
<!--defineOptions({ name: 'OperationDataCard' })-->
const router = useRouter() //
<!--const router = useRouter() // -->
/** 数据 */
const data = reactive({
orderUndelivered: { name: '待发货订单', value: 9, routerName: 'TradeOrder' },
orderAfterSaleApply: { name: '退款中订单', value: 4, routerName: 'TradeAfterSale' },
orderWaitePickUp: { name: '待核销订单', value: 0, routerName: 'TradeOrder' },
productAlertStock: { name: '库存预警', value: 0, routerName: 'ProductSpu' },
productForSale: { name: '上架商品', value: 0, routerName: 'ProductSpu' },
productInWarehouse: { name: '仓库商品', value: 0, routerName: 'ProductSpu' },
withdrawAuditing: { name: '提现待审核', value: 0, routerName: 'TradeBrokerageWithdraw' },
rechargePrice: {
name: '账户充值',
value: 0.0,
prefix: '¥',
decimals: 2,
routerName: 'PayWalletRecharge'
}
})
<!--/** 数据 */-->
<!--const data = reactive({-->
<!-- orderUndelivered: { name: '待发货订单', value: 9, routerName: 'TradeOrder' },-->
<!-- orderAfterSaleApply: { name: '退款中订单', value: 4, routerName: 'TradeAfterSale' },-->
<!-- orderWaitePickUp: { name: '待核销订单', value: 0, routerName: 'TradeOrder' },-->
<!-- productAlertStock: { name: '库存预警', value: 0, routerName: 'ProductSpu' },-->
<!-- productForSale: { name: '上架商品', value: 0, routerName: 'ProductSpu' },-->
<!-- productInWarehouse: { name: '仓库商品', value: 0, routerName: 'ProductSpu' },-->
<!-- withdrawAuditing: { name: '提现待审核', value: 0, routerName: 'TradeBrokerageWithdraw' },-->
<!-- rechargePrice: {-->
<!-- name: '账户充值',-->
<!-- value: 0.0,-->
<!-- prefix: '¥',-->
<!-- decimals: 2,-->
<!-- routerName: 'PayWalletRecharge'-->
<!-- }-->
<!--})-->
/** 查询订单数据 */
const getOrderData = async () => {
const orderCount = await TradeStatisticsApi.getOrderCount()
if (orderCount.undelivered != null) {
data.orderUndelivered.value = orderCount.undelivered
}
if (orderCount.afterSaleApply != null) {
data.orderAfterSaleApply.value = orderCount.afterSaleApply
}
if (orderCount.pickUp != null) {
data.orderWaitePickUp.value = orderCount.pickUp
}
if (orderCount.auditingWithdraw != null) {
data.withdrawAuditing.value = orderCount.auditingWithdraw
}
}
<!--/** 查询订单数据 */-->
<!--const getOrderData = async () => {-->
<!-- const orderCount = await TradeStatisticsApi.getOrderCount()-->
<!-- if (orderCount.undelivered != null) {-->
<!-- data.orderUndelivered.value = orderCount.undelivered-->
<!-- }-->
<!-- if (orderCount.afterSaleApply != null) {-->
<!-- data.orderAfterSaleApply.value = orderCount.afterSaleApply-->
<!-- }-->
<!-- if (orderCount.pickUp != null) {-->
<!-- data.orderWaitePickUp.value = orderCount.pickUp-->
<!-- }-->
<!-- if (orderCount.auditingWithdraw != null) {-->
<!-- data.withdrawAuditing.value = orderCount.auditingWithdraw-->
<!-- }-->
<!--}-->
/** 查询商品数据 */
const getProductData = async () => {
// TODO: @
const productCount = await ProductSpuApi.getTabsCount()
data.productForSale.value = productCount['0']
data.productInWarehouse.value = productCount['1']
data.productAlertStock.value = productCount['3']
}
<!--/** 查询商品数据 */-->
<!--const getProductData = async () => {-->
<!-- // TODO: @-->
<!-- const productCount = await ProductSpuApi.getTabsCount()-->
<!-- data.productForSale.value = productCount['0']-->
<!-- data.productInWarehouse.value = productCount['1']-->
<!-- data.productAlertStock.value = productCount['3']-->
<!--}-->
/** 查询钱包充值数据 */
const getWalletRechargeData = async () => {
const paySummary = await PayStatisticsApi.getWalletRechargePrice()
data.rechargePrice.value = paySummary.rechargePrice
}
<!--/** 查询钱包充值数据 */-->
<!--const getWalletRechargeData = async () => {-->
<!-- const paySummary = await PayStatisticsApi.getWalletRechargePrice()-->
<!-- data.rechargePrice.value = paySummary.rechargePrice-->
<!--}-->
/**
* 跳转到对应页面
*
* @param routerName 路由页面组件的名称
*/
const handleClick = (routerName: string) => {
router.push({ name: routerName })
}
<!--/**-->
<!-- * 跳转到对应页面-->
<!-- *-->
<!-- * @param routerName 路由页面组件的名称-->
<!-- */-->
<!--const handleClick = (routerName: string) => {-->
<!-- router.push({ name: routerName })-->
<!--}-->
/** 激活时 */
onActivated(() => {
getOrderData()
getProductData()
getWalletRechargeData()
})
<!--/** 激活时 */-->
<!--onActivated(() => {-->
<!-- getOrderData()-->
<!-- getProductData()-->
<!-- getWalletRechargeData()-->
<!--})-->
/** 初始化 **/
onMounted(() => {
getOrderData()
getProductData()
getWalletRechargeData()
})
</script>
<!--/** 初始化 **/-->
<!--onMounted(() => {-->
<!-- getOrderData()-->
<!-- getProductData()-->
<!-- getWalletRechargeData()-->
<!--})-->
<!--</script>-->

View File

@ -1,82 +1,82 @@
<template>
<el-card shadow="never">
<template #header>
<CardTitle title="快捷入口" />
</template>
<div class="flex flex-row flex-wrap gap-8 p-4">
<div
v-for="menu in menuList"
:key="menu.name"
class="h-20 w-20% flex flex-col cursor-pointer items-center justify-center gap-2"
@click="handleMenuClick(menu.routerName)"
>
<div
:class="menu.bgColor"
class="h-48px w-48px flex items-center justify-center rounded text-white"
>
<Icon :icon="menu.icon" class="text-7.5!" />
</div>
<span>{{ menu.name }}</span>
</div>
</div>
</el-card>
</template>
<script lang="ts" setup>
/** 快捷入口卡片 */
import { CardTitle } from '@/components/Card'
<!--<template>-->
<!-- <el-card shadow="never">-->
<!-- <template #header>-->
<!-- <CardTitle title="快捷入口" />-->
<!-- </template>-->
<!-- <div class="flex flex-row flex-wrap gap-8 p-4">-->
<!-- <div-->
<!-- v-for="menu in menuList"-->
<!-- :key="menu.name"-->
<!-- class="h-20 w-20% flex flex-col cursor-pointer items-center justify-center gap-2"-->
<!-- @click="handleMenuClick(menu.routerName)"-->
<!-- >-->
<!-- <div-->
<!-- :class="menu.bgColor"-->
<!-- class="h-48px w-48px flex items-center justify-center rounded text-white"-->
<!-- >-->
<!-- <Icon :icon="menu.icon" class="text-7.5!" />-->
<!-- </div>-->
<!-- <span>{{ menu.name }}</span>-->
<!-- </div>-->
<!-- </div>-->
<!-- </el-card>-->
<!--</template>-->
<!--<script lang="ts" setup>-->
<!--/** 快捷入口卡片 */-->
<!--import { CardTitle } from '@/components/Card'-->
defineOptions({ name: 'ShortcutCard' })
<!--defineOptions({ name: 'ShortcutCard' })-->
const router = useRouter() //
<!--const router = useRouter() // -->
/** 菜单列表 */
const menuList = [
{ name: '用户管理', icon: 'ep:user-filled', bgColor: 'bg-red-400', routerName: 'MemberUser' },
{
name: '商品管理',
icon: 'fluent-mdl2:product',
bgColor: 'bg-orange-400',
routerName: 'ProductSpu'
},
{ name: '订单管理', icon: 'ep:list', bgColor: 'bg-yellow-500', routerName: 'TradeOrder' },
{
name: '售后管理',
icon: 'ri:refund-2-line',
bgColor: 'bg-green-600',
routerName: 'TradeAfterSale'
},
{
name: '分销管理',
icon: 'fa-solid:project-diagram',
bgColor: 'bg-cyan-500',
routerName: 'TradeBrokerageUser'
},
{
name: '优惠券',
icon: 'ep:ticket',
bgColor: 'bg-blue-500',
routerName: 'PromotionCoupon'
},
{
name: '拼团活动',
icon: 'fa:group',
bgColor: 'bg-purple-500',
routerName: 'PromotionBargainActivity'
},
{
name: '佣金提现',
icon: 'vaadin:money-withdraw',
bgColor: 'bg-rose-500',
routerName: 'TradeBrokerageWithdraw'
}
]
<!--/** 菜单列表 */-->
<!--const menuList = [-->
<!-- { name: '用户管理', icon: 'ep:user-filled', bgColor: 'bg-red-400', routerName: 'MemberUser' },-->
<!-- {-->
<!-- name: '商品管理',-->
<!-- icon: 'fluent-mdl2:product',-->
<!-- bgColor: 'bg-orange-400',-->
<!-- routerName: 'ProductSpu'-->
<!-- },-->
<!-- { name: '订单管理', icon: 'ep:list', bgColor: 'bg-yellow-500', routerName: 'TradeOrder' },-->
<!-- {-->
<!-- name: '售后管理',-->
<!-- icon: 'ri:refund-2-line',-->
<!-- bgColor: 'bg-green-600',-->
<!-- routerName: 'TradeAfterSale'-->
<!-- },-->
<!-- {-->
<!-- name: '分销管理',-->
<!-- icon: 'fa-solid:project-diagram',-->
<!-- bgColor: 'bg-cyan-500',-->
<!-- routerName: 'TradeBrokerageUser'-->
<!-- },-->
<!-- {-->
<!-- name: '优惠券',-->
<!-- icon: 'ep:ticket',-->
<!-- bgColor: 'bg-blue-500',-->
<!-- routerName: 'PromotionCoupon'-->
<!-- },-->
<!-- {-->
<!-- name: '拼团活动',-->
<!-- icon: 'fa:group',-->
<!-- bgColor: 'bg-purple-500',-->
<!-- routerName: 'PromotionBargainActivity'-->
<!-- },-->
<!-- {-->
<!-- name: '佣金提现',-->
<!-- icon: 'vaadin:money-withdraw',-->
<!-- bgColor: 'bg-rose-500',-->
<!-- routerName: 'TradeBrokerageWithdraw'-->
<!-- }-->
<!--]-->
/**
* 跳转到菜单对应页面
*
* @param routerName 路由页面组件的名称
*/
const handleMenuClick = (routerName: string) => {
router.push({ name: routerName })
}
</script>
<!--/**-->
<!-- * 跳转到菜单对应页面-->
<!-- *-->
<!-- * @param routerName 路由页面组件的名称-->
<!-- */-->
<!--const handleMenuClick = (routerName: string) => {-->
<!-- router.push({ name: routerName })-->
<!--}-->
<!--</script>-->

View File

@ -1,208 +1,208 @@
<template>
<el-card shadow="never">
<template #header>
<div class="flex flex-row items-center justify-between">
<CardTitle title="交易量趋势" />
<!-- 查询条件 -->
<div class="flex flex-row items-center gap-2">
<el-radio-group v-model="timeRangeType" @change="handleTimeRangeTypeChange">
<el-radio-button v-for="[key, value] in timeRange.entries()" :key="key" :label="key">
{{ value.name }}
</el-radio-button>
</el-radio-group>
</div>
</div>
</template>
<!-- 折线图 -->
<Echart :height="300" :options="eChartOptions" />
</el-card>
</template>
<script lang="ts" setup>
import dayjs, { Dayjs } from 'dayjs'
import { EChartsOption } from 'echarts'
import * as TradeStatisticsApi from '@/api/mall/statistics/trade'
import { fenToYuan } from '@/utils'
import { formatDate } from '@/utils/formatTime'
import { CardTitle } from '@/components/Card'
<!--<template>-->
<!-- <el-card shadow="never">-->
<!-- <template #header>-->
<!-- <div class="flex flex-row items-center justify-between">-->
<!-- <CardTitle title="交易量趋势" />-->
<!-- &lt;!&ndash; 查询条件 &ndash;&gt;-->
<!-- <div class="flex flex-row items-center gap-2">-->
<!-- <el-radio-group v-model="timeRangeType" @change="handleTimeRangeTypeChange">-->
<!-- <el-radio-button v-for="[key, value] in timeRange.entries()" :key="key" :label="key">-->
<!-- {{ value.name }}-->
<!-- </el-radio-button>-->
<!-- </el-radio-group>-->
<!-- </div>-->
<!-- </div>-->
<!-- </template>-->
<!-- &lt;!&ndash; 折线图 &ndash;&gt;-->
<!-- <Echart :height="300" :options="eChartOptions" />-->
<!-- </el-card>-->
<!--</template>-->
<!--<script lang="ts" setup>-->
<!--import dayjs, { Dayjs } from 'dayjs'-->
<!--import { EChartsOption } from 'echarts'-->
<!--import * as TradeStatisticsApi from '@/api/mall/statistics/trade'-->
<!--import { fenToYuan } from '@/utils'-->
<!--import { formatDate } from '@/utils/formatTime'-->
<!--import { CardTitle } from '@/components/Card'-->
/** 交易量趋势 */
defineOptions({ name: 'TradeTrendCard' })
<!--/** 交易量趋势 */-->
<!--defineOptions({ name: 'TradeTrendCard' })-->
enum TimeRangeTypeEnum {
DAY30 = 1,
WEEK = 7,
MONTH = 30,
YEAR = 365
} //
const timeRangeType = ref(TimeRangeTypeEnum.DAY30) // , 30
const loading = ref(true) //
// Map
const timeRange = new Map()
.set(TimeRangeTypeEnum.DAY30, {
name: '30天',
series: [
{ name: '订单金额', type: 'bar', smooth: true, data: [] },
{ name: '订单数量', type: 'line', smooth: true, data: [] }
]
})
.set(TimeRangeTypeEnum.WEEK, {
name: '周',
series: [
{ name: '上周金额', type: 'bar', smooth: true, data: [] },
{ name: '本周金额', type: 'bar', smooth: true, data: [] },
{ name: '上周数量', type: 'line', smooth: true, data: [] },
{ name: '本周数量', type: 'line', smooth: true, data: [] }
]
})
.set(TimeRangeTypeEnum.MONTH, {
name: '月',
series: [
{ name: '上月金额', type: 'bar', smooth: true, data: [] },
{ name: '本月金额', type: 'bar', smooth: true, data: [] },
{ name: '上月数量', type: 'line', smooth: true, data: [] },
{ name: '本月数量', type: 'line', smooth: true, data: [] }
]
})
.set(TimeRangeTypeEnum.YEAR, {
name: '年',
series: [
{ name: '去年金额', type: 'bar', smooth: true, data: [] },
{ name: '今年金额', type: 'bar', smooth: true, data: [] },
{ name: '去年数量', type: 'line', smooth: true, data: [] },
{ name: '今年数量', type: 'line', smooth: true, data: [] }
]
})
/** 图表配置 */
const eChartOptions = reactive<EChartsOption>({
grid: {
left: 20,
right: 20,
bottom: 20,
top: 80,
containLabel: true
},
legend: {
top: 50,
data: []
},
series: [],
toolbox: {
feature: {
//
dataZoom: {
yAxisIndex: false // Y
},
brush: {
type: ['lineX', 'clear'] //
},
saveAsImage: { show: true, name: '订单量趋势' } //
}
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross'
},
padding: [5, 10]
},
xAxis: {
type: 'category',
inverse: true,
boundaryGap: false,
axisTick: {
show: false
},
data: [],
axisLabel: {
formatter: (date: string) => {
switch (timeRangeType.value) {
case TimeRangeTypeEnum.DAY30:
return formatDate(date, 'MM-DD')
case TimeRangeTypeEnum.WEEK:
let weekDay = formatDate(date, 'ddd')
if (weekDay == '0') weekDay = '日'
return '周' + weekDay
case TimeRangeTypeEnum.MONTH:
return formatDate(date, 'D')
case TimeRangeTypeEnum.YEAR:
return formatDate(date, 'M') + '月'
default:
return date
}
}
}
},
yAxis: {
axisTick: {
show: false
}
}
}) as EChartsOption
<!--enum TimeRangeTypeEnum {-->
<!-- DAY30 = 1,-->
<!-- WEEK = 7,-->
<!-- MONTH = 30,-->
<!-- YEAR = 365-->
<!--} // -->
<!--const timeRangeType = ref(TimeRangeTypeEnum.DAY30) // , 30-->
<!--const loading = ref(true) // -->
<!--// Map-->
<!--const timeRange = new Map()-->
<!-- .set(TimeRangeTypeEnum.DAY30, {-->
<!-- name: '30天',-->
<!-- series: [-->
<!-- { name: '订单金额', type: 'bar', smooth: true, data: [] },-->
<!-- { name: '订单数量', type: 'line', smooth: true, data: [] }-->
<!-- ]-->
<!-- })-->
<!-- .set(TimeRangeTypeEnum.WEEK, {-->
<!-- name: '周',-->
<!-- series: [-->
<!-- { name: '上周金额', type: 'bar', smooth: true, data: [] },-->
<!-- { name: '本周金额', type: 'bar', smooth: true, data: [] },-->
<!-- { name: '上周数量', type: 'line', smooth: true, data: [] },-->
<!-- { name: '本周数量', type: 'line', smooth: true, data: [] }-->
<!-- ]-->
<!-- })-->
<!-- .set(TimeRangeTypeEnum.MONTH, {-->
<!-- name: '月',-->
<!-- series: [-->
<!-- { name: '上月金额', type: 'bar', smooth: true, data: [] },-->
<!-- { name: '本月金额', type: 'bar', smooth: true, data: [] },-->
<!-- { name: '上月数量', type: 'line', smooth: true, data: [] },-->
<!-- { name: '本月数量', type: 'line', smooth: true, data: [] }-->
<!-- ]-->
<!-- })-->
<!-- .set(TimeRangeTypeEnum.YEAR, {-->
<!-- name: '年',-->
<!-- series: [-->
<!-- { name: '去年金额', type: 'bar', smooth: true, data: [] },-->
<!-- { name: '今年金额', type: 'bar', smooth: true, data: [] },-->
<!-- { name: '去年数量', type: 'line', smooth: true, data: [] },-->
<!-- { name: '今年数量', type: 'line', smooth: true, data: [] }-->
<!-- ]-->
<!-- })-->
<!--/** 图表配置 */-->
<!--const eChartOptions = reactive<EChartsOption>({-->
<!-- grid: {-->
<!-- left: 20,-->
<!-- right: 20,-->
<!-- bottom: 20,-->
<!-- top: 80,-->
<!-- containLabel: true-->
<!-- },-->
<!-- legend: {-->
<!-- top: 50,-->
<!-- data: []-->
<!-- },-->
<!-- series: [],-->
<!-- toolbox: {-->
<!-- feature: {-->
<!-- // -->
<!-- dataZoom: {-->
<!-- yAxisIndex: false // Y-->
<!-- },-->
<!-- brush: {-->
<!-- type: ['lineX', 'clear'] // -->
<!-- },-->
<!-- saveAsImage: { show: true, name: '订单量趋势' } // -->
<!-- }-->
<!-- },-->
<!-- tooltip: {-->
<!-- trigger: 'axis',-->
<!-- axisPointer: {-->
<!-- type: 'cross'-->
<!-- },-->
<!-- padding: [5, 10]-->
<!-- },-->
<!-- xAxis: {-->
<!-- type: 'category',-->
<!-- inverse: true,-->
<!-- boundaryGap: false,-->
<!-- axisTick: {-->
<!-- show: false-->
<!-- },-->
<!-- data: [],-->
<!-- axisLabel: {-->
<!-- formatter: (date: string) => {-->
<!-- switch (timeRangeType.value) {-->
<!-- case TimeRangeTypeEnum.DAY30:-->
<!-- return formatDate(date, 'MM-DD')-->
<!-- case TimeRangeTypeEnum.WEEK:-->
<!-- let weekDay = formatDate(date, 'ddd')-->
<!-- if (weekDay == '0') weekDay = '日'-->
<!-- return '周' + weekDay-->
<!-- case TimeRangeTypeEnum.MONTH:-->
<!-- return formatDate(date, 'D')-->
<!-- case TimeRangeTypeEnum.YEAR:-->
<!-- return formatDate(date, 'M') + '月'-->
<!-- default:-->
<!-- return date-->
<!-- }-->
<!-- }-->
<!-- }-->
<!-- },-->
<!-- yAxis: {-->
<!-- axisTick: {-->
<!-- show: false-->
<!-- }-->
<!-- }-->
<!--}) as EChartsOption-->
/** 时间范围类型单选按钮选中 */
const handleTimeRangeTypeChange = async () => {
//
let beginTime: Dayjs
let endTime: Dayjs
switch (timeRangeType.value) {
case TimeRangeTypeEnum.WEEK:
beginTime = dayjs().startOf('week')
endTime = dayjs().endOf('week')
break
case TimeRangeTypeEnum.MONTH:
beginTime = dayjs().startOf('month')
endTime = dayjs().endOf('month')
break
case TimeRangeTypeEnum.YEAR:
beginTime = dayjs().startOf('year')
endTime = dayjs().endOf('year')
break
case TimeRangeTypeEnum.DAY30:
default:
beginTime = dayjs().subtract(30, 'day').startOf('d')
endTime = dayjs().endOf('d')
break
}
//
await getOrderCountTrendComparison(beginTime, endTime)
}
<!--/** 时间范围类型单选按钮选中 */-->
<!--const handleTimeRangeTypeChange = async () => {-->
<!-- // -->
<!-- let beginTime: Dayjs-->
<!-- let endTime: Dayjs-->
<!-- switch (timeRangeType.value) {-->
<!-- case TimeRangeTypeEnum.WEEK:-->
<!-- beginTime = dayjs().startOf('week')-->
<!-- endTime = dayjs().endOf('week')-->
<!-- break-->
<!-- case TimeRangeTypeEnum.MONTH:-->
<!-- beginTime = dayjs().startOf('month')-->
<!-- endTime = dayjs().endOf('month')-->
<!-- break-->
<!-- case TimeRangeTypeEnum.YEAR:-->
<!-- beginTime = dayjs().startOf('year')-->
<!-- endTime = dayjs().endOf('year')-->
<!-- break-->
<!-- case TimeRangeTypeEnum.DAY30:-->
<!-- default:-->
<!-- beginTime = dayjs().subtract(30, 'day').startOf('d')-->
<!-- endTime = dayjs().endOf('d')-->
<!-- break-->
<!-- }-->
<!-- // -->
<!-- await getOrderCountTrendComparison(beginTime, endTime)-->
<!--}-->
/** 查询订单数量趋势对照数据 */
const getOrderCountTrendComparison = async (
beginTime: dayjs.ConfigType,
endTime: dayjs.ConfigType
) => {
loading.value = true
//
const list = await TradeStatisticsApi.getOrderCountTrendComparison(
timeRangeType.value,
beginTime,
endTime
)
//
const dates: string[] = []
const series = [...timeRange.get(timeRangeType.value).series]
for (let item of list) {
dates.push(item.value.date)
if (series.length === 2) {
series[0].data.push(fenToYuan(item?.value?.orderPayPrice || 0)) //
series[1].data.push(item?.value?.orderPayCount || 0) //
} else {
series[0].data.push(fenToYuan(item?.reference?.orderPayPrice || 0)) //
series[1].data.push(fenToYuan(item?.value?.orderPayPrice || 0)) //
series[2].data.push(item?.reference?.orderPayCount || 0) //
series[3].data.push(item?.value?.orderPayCount || 0) //
}
}
eChartOptions.xAxis!['data'] = dates
eChartOptions.series = series
// legend424
eChartOptions.legend['data'] = series.map((item) => item.name)
loading.value = false
}
<!--/** 查询订单数量趋势对照数据 */-->
<!--const getOrderCountTrendComparison = async (-->
<!-- beginTime: dayjs.ConfigType,-->
<!-- endTime: dayjs.ConfigType-->
<!--) => {-->
<!-- loading.value = true-->
<!-- // -->
<!-- const list = await TradeStatisticsApi.getOrderCountTrendComparison(-->
<!-- timeRangeType.value,-->
<!-- beginTime,-->
<!-- endTime-->
<!-- )-->
<!-- // -->
<!-- const dates: string[] = []-->
<!-- const series = [...timeRange.get(timeRangeType.value).series]-->
<!-- for (let item of list) {-->
<!-- dates.push(item.value.date)-->
<!-- if (series.length === 2) {-->
<!-- series[0].data.push(fenToYuan(item?.value?.orderPayPrice || 0)) // -->
<!-- series[1].data.push(item?.value?.orderPayCount || 0) // -->
<!-- } else {-->
<!-- series[0].data.push(fenToYuan(item?.reference?.orderPayPrice || 0)) // -->
<!-- series[1].data.push(fenToYuan(item?.value?.orderPayPrice || 0)) // -->
<!-- series[2].data.push(item?.reference?.orderPayCount || 0) // -->
<!-- series[3].data.push(item?.value?.orderPayCount || 0) // -->
<!-- }-->
<!-- }-->
<!-- eChartOptions.xAxis!['data'] = dates-->
<!-- eChartOptions.series = series-->
<!-- // legend424-->
<!-- eChartOptions.legend['data'] = series.map((item) => item.name)-->
<!-- loading.value = false-->
<!--}-->
/** 初始化 **/
onMounted(() => {
handleTimeRangeTypeChange()
})
</script>
<!--/** 初始化 **/-->
<!--onMounted(() => {-->
<!-- handleTimeRangeTypeChange()-->
<!--})-->
<!--</script>-->