Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
phsl
/
admin
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
3802fee6
authored
Oct 16, 2023
by
owen
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
商城:增加商城首页
parent
532b2377
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
1017 additions
and
83 deletions
+1017
-83
src/api/mall/statistics/member.ts
+32
-0
src/api/mall/statistics/pay.ts
+6
-0
src/api/mall/statistics/trade.ts
+54
-0
src/components/ShortcutDateRangePicker/index.vue
+89
-0
src/utils/index.ts
+13
-0
src/views/mall/home/components/ComparisonCard.vue
+42
-0
src/views/mall/home/components/MemberStatisticsCard.vue
+91
-0
src/views/mall/home/components/OperationDataCard.vue
+91
-0
src/views/mall/home/components/ShortcutCard.vue
+79
-0
src/views/mall/home/components/TradeTrendCard.vue
+208
-0
src/views/mall/home/index.vue
+113
-0
src/views/mall/statistics/member/components/MemberFunnelCard.vue
+119
-0
src/views/mall/statistics/member/components/MemberTerminalCard.vue
+69
-0
src/views/mall/statistics/member/index.vue
+0
-0
src/views/mall/statistics/trade/index.vue
+11
-83
No files found.
src/api/mall/statistics/member.ts
View file @
3802fee6
...
@@ -54,6 +54,20 @@ export interface MemberTerminalStatisticsRespVO {
...
@@ -54,6 +54,20 @@ export interface MemberTerminalStatisticsRespVO {
userCount
:
number
userCount
:
number
}
}
/** 会员数量统计 Response VO */
export
interface
MemberCountRespVO
{
/** 用户访问量 */
visitUserCount
:
string
/** 新增用户数量 */
createUserCount
:
number
}
/** 会员注册数量 Response VO */
export
interface
MemberRegisterCountRespVO
{
date
:
string
count
:
number
}
// 查询会员统计
// 查询会员统计
export
const
getMemberSummary
=
()
=>
{
export
const
getMemberSummary
=
()
=>
{
return
request
.
get
<
MemberSummaryRespVO
>
({
return
request
.
get
<
MemberSummaryRespVO
>
({
...
@@ -89,3 +103,21 @@ export const getMemberTerminalStatisticsList = () => {
...
@@ -89,3 +103,21 @@ export const getMemberTerminalStatisticsList = () => {
url
:
'/statistics/member/get-terminal-statistics-list'
url
:
'/statistics/member/get-terminal-statistics-list'
})
})
}
}
// 获得用户数量量对照
export
const
getUserCountComparison
=
()
=>
{
return
request
.
get
<
TradeStatisticsComparisonRespVO
<
MemberCountRespVO
>>
({
url
:
'/statistics/member/user-count-comparison'
})
}
// 获得会员注册数量列表
export
const
getMemberRegisterCountList
=
(
beginTime
:
dayjs
.
ConfigType
,
endTime
:
dayjs
.
ConfigType
)
=>
{
return
request
.
get
<
MemberRegisterCountRespVO
[]
>
({
url
:
'/statistics/member/register-count-list'
,
params
:
{
times
:
[
formatDate
(
beginTime
),
formatDate
(
endTime
)]
}
})
}
src/api/mall/statistics/pay.ts
0 → 100644
View file @
3802fee6
import
request
from
'@/config/axios'
/** 获取钱包充值金额 */
export
const
getWalletRechargePrice
=
async
()
=>
{
return
await
request
.
get
<
number
>
({
url
:
`/statistics/pay/wallet-recharge-price`
})
}
src/api/mall/statistics/trade.ts
View file @
3802fee6
...
@@ -33,6 +33,36 @@ export interface TradeTrendSummaryRespVO {
...
@@ -33,6 +33,36 @@ export interface TradeTrendSummaryRespVO {
orderRefundPrice
:
number
orderRefundPrice
:
number
}
}
/** 交易订单数量 Response VO */
export
interface
TradeOrderCountRespVO
{
/** 待发货 */
undelivered
?:
number
/** 待核销 */
pickUp
?:
number
/** 退款中 */
afterSaleApply
?:
number
/** 提现待审核 */
auditingWithdraw
?:
number
}
/** 交易订单统计 Response VO */
export
interface
TradeOrderSummaryRespVO
{
/** 支付订单商品数 */
orderPayCount
?:
number
/** 总支付金额,单位:分 */
orderPayPrice
?:
number
}
/** 订单量趋势统计 Response VO */
export
interface
TradeOrderTrendRespVO
{
/** 日期 */
date
:
string
/** 订单数量 */
orderPayCount
:
number
/** 订单支付金额 */
orderPayPrice
:
number
}
// 查询交易统计
// 查询交易统计
export
const
getTradeStatisticsSummary
=
()
=>
{
export
const
getTradeStatisticsSummary
=
()
=>
{
return
request
.
get
<
TradeStatisticsComparisonRespVO
<
TradeSummaryRespVO
>>
({
return
request
.
get
<
TradeStatisticsComparisonRespVO
<
TradeSummaryRespVO
>>
({
...
@@ -64,6 +94,30 @@ export const exportTradeTrend = (params: TradeTrendReqVO) => {
...
@@ -64,6 +94,30 @@ export const exportTradeTrend = (params: TradeTrendReqVO) => {
})
})
}
}
// 获得交易订单数量
export
const
getOrderCount
=
async
()
=>
{
return
await
request
.
get
<
TradeOrderCountRespVO
>
({
url
:
`/statistics/trade/order-count`
})
}
// 获得交易订单数量对照
export
const
getOrderComparison
=
async
()
=>
{
return
await
request
.
get
<
TradeStatisticsComparisonRespVO
<
TradeOrderSummaryRespVO
>>
({
url
:
`/statistics/trade/order-comparison`
})
}
// 获得订单量趋势统计
export
const
getOrderCountTrendComparison
=
(
type
:
number
,
beginTime
:
dayjs
.
ConfigType
,
endTime
:
dayjs
.
ConfigType
)
=>
{
return
request
.
get
<
TradeStatisticsComparisonRespVO
<
TradeOrderTrendRespVO
>
[]
>
({
url
:
'/statistics/trade/order-count-trend'
,
params
:
{
type
,
beginTime
:
formatDate
(
beginTime
),
endTime
:
formatDate
(
endTime
)
}
})
}
/** 时间参数需要格式化, 确保接口能识别 */
/** 时间参数需要格式化, 确保接口能识别 */
const
formatDateParam
=
(
params
:
TradeTrendReqVO
)
=>
{
const
formatDateParam
=
(
params
:
TradeTrendReqVO
)
=>
{
return
{
times
:
[
formatDate
(
params
.
times
[
0
]),
formatDate
(
params
.
times
[
1
])]
}
as
TradeTrendReqVO
return
{
times
:
[
formatDate
(
params
.
times
[
0
]),
formatDate
(
params
.
times
[
1
])]
}
as
TradeTrendReqVO
...
...
src/components/ShortcutDateRangePicker/index.vue
0 → 100644
View file @
3802fee6
<
template
>
<div
class=
"flex flex-row items-center gap-2"
>
<el-radio-group
v-model=
"shortcutDays"
@
change=
"handleShortcutDaysChange"
>
<el-radio-button
:label=
"1"
>
昨天
</el-radio-button>
<el-radio-button
:label=
"7"
>
最近7天
</el-radio-button>
<el-radio-button
:label=
"30"
>
最近30天
</el-radio-button>
</el-radio-group>
<el-date-picker
v-model=
"times"
value-format=
"YYYY-MM-DD HH:mm:ss"
type=
"daterange"
start-placeholder=
"开始日期"
end-placeholder=
"结束日期"
:default-time=
"[new Date('1 00:00:00'), new Date('1 23:59:59')]"
:shortcuts=
"shortcuts"
class=
"!w-240px"
@
change=
"emitDateRangePicker"
/>
<slot></slot>
</div>
</
template
>
<
script
lang=
"ts"
setup
>
import
dayjs
from
'dayjs'
import
*
as
DateUtil
from
'@/utils/formatTime'
/** 快捷日期范围选择组件 */
defineOptions
({
name
:
'ShortcutDateRangePicker'
})
const
shortcutDays
=
ref
(
7
)
// 日期快捷天数(单选按钮组), 默认7天
const
times
=
ref
<
[
dayjs
.
ConfigType
,
dayjs
.
ConfigType
]
>
([
''
,
''
])
// 时间范围参数
defineExpose
({
times
})
// 暴露时间范围参数
/** 日期快捷选择 */
const
shortcuts
=
[
{
text
:
'昨天'
,
value
:
()
=>
DateUtil
.
getDayRange
(
new
Date
(),
-
1
)
},
{
text
:
'最近7天'
,
value
:
()
=>
DateUtil
.
getLast7Days
()
},
{
text
:
'本月'
,
value
:
()
=>
[
dayjs
().
startOf
(
'M'
),
dayjs
().
subtract
(
1
,
'd'
)]
},
{
text
:
'最近30天'
,
value
:
()
=>
DateUtil
.
getLast30Days
()
},
{
text
:
'最近1年'
,
value
:
()
=>
DateUtil
.
getLast1Year
()
}
]
/** 设置时间范围 */
function
setTimes
()
{
const
beginDate
=
dayjs
().
subtract
(
shortcutDays
.
value
,
'd'
)
const
yesterday
=
dayjs
().
subtract
(
1
,
'd'
)
times
.
value
=
DateUtil
.
getDateRange
(
beginDate
,
yesterday
)
}
/** 快捷日期单选按钮选中 */
const
handleShortcutDaysChange
=
async
()
=>
{
// 设置时间范围
setTimes
()
// 发送时间范围选中事件
await
emitDateRangePicker
()
}
/** 触发事件:时间范围选中 */
const
emits
=
defineEmits
<
{
(
e
:
'change'
,
times
:
[
dayjs
.
ConfigType
,
dayjs
.
ConfigType
]):
void
}
>
()
/** 触发时间范围选中事件 */
const
emitDateRangePicker
=
async
()
=>
{
// 开始与截止在同一天的, 折线图出不来, 需要延长一天
if
(
DateUtil
.
isSameDay
(
times
.
value
[
0
],
times
.
value
[
1
]))
{
// 前天
times
.
value
[
0
]
=
DateUtil
.
formatDate
(
dayjs
(
times
.
value
[
0
]).
subtract
(
1
,
'd'
))
}
emits
(
'change'
,
times
.
value
)
}
/** 初始化 **/
onMounted
(()
=>
{
handleShortcutDaysChange
()
})
</
script
>
src/utils/index.ts
View file @
3802fee6
...
@@ -233,3 +233,16 @@ export const yuanToFen = (amount: string | number): number => {
...
@@ -233,3 +233,16 @@ export const yuanToFen = (amount: string | number): number => {
export
const
fenToYuan
=
(
price
:
string
|
number
):
number
=>
{
export
const
fenToYuan
=
(
price
:
string
|
number
):
number
=>
{
return
formatToFraction
(
price
)
return
formatToFraction
(
price
)
}
}
/**
* 计算环比
*
* @param value 当前数值
* @param reference 对比数值
*/
export
const
calculateRelativeRate
=
(
value
?:
number
,
reference
?:
number
)
=>
{
// 防止除0
if
(
!
reference
)
return
0
return
((
100
*
((
value
||
0
)
-
reference
))
/
reference
).
toFixed
(
0
)
}
src/views/mall/home/components/ComparisonCard.vue
0 → 100644
View file @
3802fee6
<
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'
/** 交易对照卡片 */
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
percent
=
computed
(()
=>
calculateRelativeRate
(
props
.
value
as
number
,
props
.
reference
as
number
)
)
</
script
>
src/views/mall/home/components/MemberStatisticsCard.vue
0 → 100644
View file @
3802fee6
<
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'
/** 会员用户统计卡片 */
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
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
>
src/views/mall/home/components/OperationDataCard.vue
0 → 100644
View file @
3802fee6
<
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'
})
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
getOrderData
=
async
()
=>
{
const
orderCount
=
await
TradeStatisticsApi
.
getOrderCount
()
data
.
orderUndelivered
.
value
=
orderCount
.
undelivered
data
.
orderAfterSaleApply
.
value
=
orderCount
.
afterSaleApply
data
.
orderWaitePickUp
.
value
=
orderCount
.
pickUp
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
getWalletRechargeData
=
async
()
=>
{
data
.
rechargePrice
.
value
=
await
PayStatisticsApi
.
getWalletRechargePrice
()
}
/**
* 跳转到对应页面
*
* @param routerName 路由页面组件的名称
*/
const
handleClick
=
(
routerName
:
string
)
=>
{
router
.
push
({
name
:
routerName
})
}
/** 初始化 **/
onMounted
(()
=>
{
getOrderData
()
getProductData
()
getWalletRechargeData
()
})
</
script
>
src/views/mall/home/components/ShortcutCard.vue
0 → 100644
View file @
3802fee6
<
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=
"rounded p-3 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'
})
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'
}
]
/**
* 跳转到菜单对应页面
*
* @param routerName 路由页面组件的名称
*/
const
handleMenuClick
=
(
routerName
:
string
)
=>
{
router
.
push
({
name
:
routerName
})
}
</
script
>
src/views/mall/home/components/TradeTrendCard.vue
0 → 100644
View file @
3802fee6
<
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'
/** 交易量趋势 */
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
/** 时间范围类型单选按钮选中 */
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
(
fenToYuan
(
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
// legend在4个切换到2个的时候,还是显示成4个,需要手动配置一下
eChartOptions
.
legend
[
'data'
]
=
series
.
map
((
item
)
=>
item
.
name
)
loading
.
value
=
false
}
/** 初始化 **/
onMounted
(()
=>
{
handleTimeRangeTypeChange
()
})
</
script
>
src/views/mall/home/index.vue
0 → 100644
View file @
3802fee6
<
template
>
<div
class=
"flex flex-col"
>
<!-- 数据对照 -->
<el-row
:gutter=
"16"
class=
"row"
>
<el-col
:md=
"6"
:sm=
"12"
:xs=
"24"
:loading=
"loading"
>
<ComparisonCard
tag=
"今日"
title=
"销售额"
prefix=
"¥"
::decimals=
"2"
:value=
"fenToYuan(orderComparison?.value?.orderPayPrice || 0)"
:reference=
"fenToYuan(orderComparison?.reference?.orderPayPrice || 0)"
/>
</el-col>
<el-col
:md=
"6"
:sm=
"12"
:xs=
"24"
:loading=
"loading"
>
<ComparisonCard
tag=
"今日"
title=
"用户访问量"
:value=
"userComparison?.value?.visitUserCount || 0"
:reference=
"userComparison?.reference?.visitUserCount || 0"
/>
</el-col>
<el-col
:md=
"6"
:sm=
"12"
:xs=
"24"
:loading=
"loading"
>
<ComparisonCard
tag=
"今日"
title=
"订单量"
:value=
"fenToYuan(orderComparison?.value?.orderPayCount || 0)"
:reference=
"fenToYuan(orderComparison?.reference?.orderPayCount || 0)"
/>
</el-col>
<el-col
:md=
"6"
:sm=
"12"
:xs=
"24"
:loading=
"loading"
>
<ComparisonCard
tag=
"今日"
title=
"新增用户"
:value=
"userComparison?.value?.createUserCount || 0"
:reference=
"userComparison?.reference?.createUserCount || 0"
/>
</el-col>
</el-row>
<el-row
:gutter=
"16"
class=
"row"
>
<el-col
:md=
"12"
>
<!-- 快捷入口 -->
<ShortcutCard
/>
</el-col>
<el-col
:md=
"12"
>
<!-- 运营数据 -->
<OperationDataCard
/>
</el-col>
</el-row>
<el-row
:gutter=
"16"
class=
"mb-4"
>
<el-col
:md=
"18"
:sm=
"24"
>
<!-- 会员概览 -->
<MemberFunnelCard
/>
</el-col>
<el-col
:md=
"6"
:sm=
"24"
>
<!-- 会员终端 -->
<MemberTerminalCard
/>
</el-col>
</el-row>
<!-- 交易量趋势 -->
<TradeTrendCard
class=
"mb-4"
/>
<!-- 会员统计 -->
<MemberStatisticsCard
/>
</div>
</
template
>
<
script
lang=
"ts"
setup
>
import
*
as
TradeStatisticsApi
from
'@/api/mall/statistics/trade'
import
*
as
MemberStatisticsApi
from
'@/api/mall/statistics/member'
import
{
TradeOrderSummaryRespVO
,
TradeStatisticsComparisonRespVO
}
from
'@/api/mall/statistics/trade'
import
{
MemberCountRespVO
}
from
'@/api/mall/statistics/member'
import
{
fenToYuan
}
from
'@/utils'
import
ComparisonCard
from
'./components/ComparisonCard.vue'
import
MemberStatisticsCard
from
'./components/MemberStatisticsCard.vue'
import
OperationDataCard
from
'./components/OperationDataCard.vue'
import
ShortcutCard
from
'./components/ShortcutCard.vue'
import
TradeTrendCard
from
'./components/TradeTrendCard.vue'
import
MemberTerminalCard
from
'@/views/mall/statistics/member/components/MemberTerminalCard.vue'
import
MemberFunnelCard
from
'@/views/mall/statistics/member/components/MemberFunnelCard.vue'
/** 商城首页 */
defineOptions
({
name
:
'MallHome'
})
const
loading
=
ref
(
true
)
// 加载中
const
orderComparison
=
ref
<
TradeStatisticsComparisonRespVO
<
TradeOrderSummaryRespVO
>>
()
// 交易对照数据
const
userComparison
=
ref
<
TradeStatisticsComparisonRespVO
<
MemberCountRespVO
>>
()
// 用户对照数据
/** 查询交易对照卡片数据 */
const
getOrderComparison
=
async
()
=>
{
orderComparison
.
value
=
await
TradeStatisticsApi
.
getOrderComparison
()
}
/** 查询会员用户数量对照卡片数据 */
const
getUserCountComparison
=
async
()
=>
{
userComparison
.
value
=
await
MemberStatisticsApi
.
getUserCountComparison
()
}
/** 初始化 **/
onMounted
(
async
()
=>
{
loading
.
value
=
true
await
Promise
.
all
([
getOrderComparison
(),
getUserCountComparison
()])
loading
.
value
=
false
})
</
script
>
<
style
lang=
"scss"
scoped
>
.row
{
.el-col
{
margin-bottom
:
1rem
;
}
}
</
style
>
src/views/mall/statistics/member/components/MemberFunnelCard.vue
0 → 100644
View file @
3802fee6
<
template
>
<el-card
shadow=
"never"
>
<template
#
header
>
<div
class=
"my--1.5 flex flex-row items-center justify-between"
>
<CardTitle
title=
"会员概览"
/>
<!-- 查询条件 -->
<ShortcutDateRangePicker
@
change=
"handleTimeRangeChange"
/>
</div>
</
template
>
<div
class=
"min-w-225 py-1.75"
v-loading=
"loading"
>
<div
class=
"relative h-24 flex"
>
<div
class=
"h-full w-75% bg-blue-50 <lg:w-35% <xl:w-55%"
>
<div
class=
"ml-15 h-full flex flex-col justify-center"
>
<div
class=
"font-bold"
>
注册用户数量:{{ analyseData?.comparison?.value?.userCount || 0 }}
</div>
<div
class=
"mt-2 text-3.5"
>
环比增长率:{{
calculateRelativeRate(
analyseData?.comparison?.value?.userCount,
analyseData?.comparison?.reference?.userCount
)
}}%
</div>
</div>
</div>
<div
class=
"trapezoid1 ml--38.5 mt-1.5 h-full w-77 flex flex-col items-center justify-center bg-blue-5 text-3.5 text-white"
>
<span
class=
"text-6 font-bold"
>
{{ analyseData?.visitorCount || 0 }}
</span>
<span>
访客
</span>
</div>
</div>
<div
class=
"relative h-24 flex"
>
<div
class=
"h-full w-75% flex bg-cyan-50 <lg:w-35% <xl:w-55%"
>
<div
class=
"ml-15 h-full flex flex-col justify-center"
>
<div
class=
"font-bold"
>
活跃用户数量:{{ analyseData?.comparison?.value?.activeUserCount || 0 }}
</div>
<div
class=
"mt-2 text-3.5"
>
环比增长率:{{
calculateRelativeRate(
analyseData?.comparison?.value?.activeUserCount,
analyseData?.comparison?.reference?.activeUserCount
)
}}%
</div>
</div>
</div>
<div
class=
"trapezoid2 ml--28 mt-1.7 h-25 w-56 flex flex-col items-center justify-center bg-cyan-5 text-3.5 text-white"
>
<span
class=
"text-6 font-bold"
>
{{ analyseData?.orderUserCount || 0 }}
</span>
<span>
下单
</span>
</div>
</div>
<div
class=
"relative h-24 flex"
>
<div
class=
"w-75% flex bg-slate-50 <lg:w-35% <xl:w-55%"
>
<div
class=
"ml-15 h-full flex flex-row gap-x-16"
>
<div
class=
"flex flex-col justify-center"
>
<div
class=
"font-bold"
>
充值用户数量:{{ analyseData?.comparison?.value?.rechargeUserCount || 0 }}
</div>
<div
class=
"mt-2 text-3.5"
>
环比增长率:{{
calculateRelativeRate(
analyseData?.comparison?.value?.rechargeUserCount,
analyseData?.comparison?.reference?.rechargeUserCount
)
}}%
</div>
</div>
<div
class=
"flex flex-col justify-center"
>
<div
class=
"font-bold"
>
客单价:{{ fenToYuan(analyseData?.atv || 0) }}
</div>
</div>
</div>
</div>
<div
class=
"trapezoid3 ml--18 mt-3.25 h-23 w-36 flex flex-col items-center justify-center bg-slate-5 text-3.5 text-white"
>
<span
class=
"text-6 font-bold"
>
{{ analyseData?.payUserCount || 0 }}
</span>
<span>
成交用户
</span>
</div>
</div>
</div>
</el-card>
</template>
<
script
lang=
"ts"
setup
>
import
*
as
MemberStatisticsApi
from
'@/api/mall/statistics/member'
import
dayjs
from
'dayjs'
import
{
calculateRelativeRate
,
fenToYuan
}
from
'@/utils'
import
{
MemberAnalyseRespVO
}
from
'@/api/mall/statistics/member'
import
{
CardTitle
}
from
'@/components/Card'
/** 会员概览卡片 */
defineOptions
({
name
:
'MemberFunnelCard'
})
const
loading
=
ref
(
true
)
// 加载中
const
analyseData
=
ref
<
MemberAnalyseRespVO
>
()
// 会员分析数据
/** 查询会员概览数据列表 */
const
handleTimeRangeChange
=
async
(
times
:
[
dayjs
.
ConfigType
,
dayjs
.
ConfigType
])
=>
{
loading
.
value
=
true
// 查询数据
analyseData
.
value
=
await
MemberStatisticsApi
.
getMemberAnalyse
({
times
})
loading
.
value
=
false
}
</
script
>
<
style
lang=
"scss"
scoped
>
.trapezoid1
{
transform
:
perspective
(
5em
)
rotateX
(
-11deg
);
}
.trapezoid2
{
transform
:
perspective
(
7em
)
rotateX
(
-20deg
);
}
.trapezoid3
{
transform
:
perspective
(
3em
)
rotateX
(
-13deg
);
}
</
style
>
src/views/mall/statistics/member/components/MemberTerminalCard.vue
0 → 100644
View file @
3802fee6
<
template
>
<el-card
shadow=
"never"
v-loading=
"loading"
>
<template
#
header
>
<CardTitle
title=
"会员终端"
/>
</
template
>
<Echart
:height=
"300"
:options=
"terminalChartOptions"
/>
</el-card>
</template>
<
script
lang=
"ts"
setup
>
import
*
as
MemberStatisticsApi
from
'@/api/mall/statistics/member'
import
{
EChartsOption
}
from
'echarts'
import
{
MemberTerminalStatisticsRespVO
}
from
'@/api/mall/statistics/member'
import
{
DICT_TYPE
,
DictDataType
,
getIntDictOptions
}
from
'@/utils/dict'
import
{
CardTitle
}
from
'@/components/Card'
/** 会员终端卡片 */
defineOptions
({
name
:
'MemberTerminalCard'
})
const
loading
=
ref
(
true
)
// 加载中
/** 会员终端统计图配置 */
const
terminalChartOptions
=
reactive
<
EChartsOption
>
({
tooltip
:
{
trigger
:
'item'
,
confine
:
true
,
formatter
:
'
{
a
}
<
br
/>
{
b
}
:
{
c
}
({
d
}
%
)
'
},
legend: {
orient: '
vertical
',
left: '
right
'
},
roseType: '
area
',
series: [
{
name: '
会员终端
',
type: '
pie
'
,
label
:
{
show
:
false
},
labelLine
:
{
show
:
false
},
data
:
[]
}
]
})
as
EChartsOption
/** 按照终端,查询会员统计列表 */
const
getMemberTerminalStatisticsList
=
async
()
=>
{
loading
.
value
=
true
const
list
=
await
MemberStatisticsApi
.
getMemberTerminalStatisticsList
()
const
dictDataList
=
getIntDictOptions
(
DICT_TYPE
.
TERMINAL
)
terminalChartOptions
.
series
!
[
0
].
data
=
dictDataList
.
map
((
dictData
:
DictDataType
)
=>
{
const
userCount
=
list
.
find
(
(
item
:
MemberTerminalStatisticsRespVO
)
=>
item
.
terminal
===
dictData
.
value
)?.
userCount
return
{
name
:
dictData
.
label
,
value
:
userCount
||
0
}
})
loading
.
value
=
false
}
/** 初始化 **/
onMounted
(()
=>
{
getMemberTerminalStatisticsList
()
})
</
script
>
src/views/mall/statistics/member/index.vue
View file @
3802fee6
This diff is collapsed.
Click to expand it.
src/views/mall/statistics/trade/index.vue
View file @
3802fee6
...
@@ -59,25 +59,9 @@
...
@@ -59,25 +59,9 @@
<template
#
header
>
<template
#
header
>
<!-- 标题 -->
<!-- 标题 -->
<div
class=
"flex flex-row items-center justify-between"
>
<div
class=
"flex flex-row items-center justify-between"
>
<
span>
交易状况
</span
>
<
CardTitle
title=
"交易状况"
/
>
<!-- 查询条件 -->
<!-- 查询条件 -->
<div
class=
"flex flex-row items-center gap-2"
>
<ShortcutDateRangePicker
ref=
"shortcutDateRangePicker"
@
change=
"getTradeTrendData"
>
<el-radio-group
v-model=
"shortcutDays"
@
change=
"handleDateTypeChange"
>
<el-radio-button
:label=
"1"
>
昨天
</el-radio-button>
<el-radio-button
:label=
"7"
>
最近7天
</el-radio-button>
<el-radio-button
:label=
"30"
>
最近30天
</el-radio-button>
</el-radio-group>
<el-date-picker
v-model=
"queryParams.times"
value-format=
"YYYY-MM-DD HH:mm:ss"
type=
"daterange"
start-placeholder=
"开始日期"
end-placeholder=
"结束日期"
:default-time=
"[new Date('1 00:00:00'), new Date('1 23:59:59')]"
:shortcuts=
"shortcuts"
class=
"!w-240px"
@
change=
"getTradeTrendData"
/>
<el-button
<el-button
class=
"ml-4"
class=
"ml-4"
@
click=
"handleExport"
@
click=
"handleExport"
...
@@ -86,7 +70,7 @@
...
@@ -86,7 +70,7 @@
>
>
<Icon
icon=
"ep:download"
class=
"mr-1"
/>
导出
<Icon
icon=
"ep:download"
class=
"mr-1"
/>
导出
</el-button>
</el-button>
</
div
>
</
ShortcutDateRangePicker
>
</div>
</div>
</
template
>
</
template
>
<!-- 统计值 -->
<!-- 统计值 -->
...
@@ -233,13 +217,11 @@ import { EChartsOption } from 'echarts'
...
@@ -233,13 +217,11 @@ import { EChartsOption } from 'echarts'
import
{
import
{
TradeStatisticsComparisonRespVO
,
TradeStatisticsComparisonRespVO
,
TradeSummaryRespVO
,
TradeSummaryRespVO
,
TradeTrendReqVO
,
TradeTrendSummaryRespVO
TradeTrendSummaryRespVO
}
from
'@/api/mall/statistics/trade'
}
from
'@/api/mall/statistics/trade'
import
dayjs
from
'dayjs'
import
{
calculateRelativeRate
,
fenToYuan
}
from
'@/utils'
import
{
fenToYuan
}
from
'@/utils'
import
*
as
DateUtil
from
'@/utils/formatTime'
import
download
from
'@/utils/download'
import
download
from
'@/utils/download'
import
{
CardTitle
}
from
'@/components/Card'
/** 交易统计 */
/** 交易统计 */
defineOptions
({
name
:
'TradeStatistics'
})
defineOptions
({
name
:
'TradeStatistics'
})
...
@@ -249,34 +231,9 @@ const message = useMessage() // 消息弹窗
...
@@ -249,34 +231,9 @@ const message = useMessage() // 消息弹窗
const
loading
=
ref
(
true
)
// 加载中
const
loading
=
ref
(
true
)
// 加载中
const
trendLoading
=
ref
(
true
)
// 交易状态加载中
const
trendLoading
=
ref
(
true
)
// 交易状态加载中
const
exportLoading
=
ref
(
false
)
// 导出的加载中
const
exportLoading
=
ref
(
false
)
// 导出的加载中
const
queryParams
=
reactive
<
TradeTrendReqVO
>
({
times
:
[
''
,
''
]
})
// 交易状况查询参数
const
shortcutDays
=
ref
(
7
)
// 日期快捷天数(单选按钮组), 默认7天
const
summary
=
ref
<
TradeStatisticsComparisonRespVO
<
TradeSummaryRespVO
>>
()
// 交易统计数据
const
summary
=
ref
<
TradeStatisticsComparisonRespVO
<
TradeSummaryRespVO
>>
()
// 交易统计数据
const
trendSummary
=
ref
<
TradeStatisticsComparisonRespVO
<
TradeTrendSummaryRespVO
>>
()
// 交易状况统计数据
const
trendSummary
=
ref
<
TradeStatisticsComparisonRespVO
<
TradeTrendSummaryRespVO
>>
()
// 交易状况统计数据
const
shortcutDateRangePicker
=
ref
()
/** 日期快捷选择 */
const
shortcuts
=
[
{
text
:
'昨天'
,
value
:
()
=>
DateUtil
.
getDayRange
(
new
Date
(),
-
1
)
},
{
text
:
'最近7天'
,
value
:
()
=>
DateUtil
.
getLast7Days
()
},
{
text
:
'本月'
,
value
:
()
=>
[
dayjs
().
startOf
(
'M'
),
dayjs
().
subtract
(
1
,
'd'
)]
},
{
text
:
'最近30天'
,
value
:
()
=>
DateUtil
.
getLast30Days
()
},
{
text
:
'最近1年'
,
value
:
()
=>
DateUtil
.
getLast1Year
()
}
]
/** 折线图配置 */
/** 折线图配置 */
const
lineChartOptions
=
reactive
<
EChartsOption
>
({
const
lineChartOptions
=
reactive
<
EChartsOption
>
({
...
@@ -333,29 +290,6 @@ const lineChartOptions = reactive<EChartsOption>({
...
@@ -333,29 +290,6 @@ const lineChartOptions = reactive<EChartsOption>({
}
}
})
as
EChartsOption
})
as
EChartsOption
/** 计算环比 */
const
calculateRelativeRate
=
(
value
?:
number
,
reference
?:
number
)
=>
{
// 防止除0
if
(
!
reference
)
return
0
return
((
100
*
((
value
||
0
)
-
reference
))
/
reference
).
toFixed
(
0
)
}
/** 设置时间范围 */
function
setTimes
()
{
const
beginDate
=
dayjs
().
subtract
(
shortcutDays
.
value
,
'd'
)
const
yesterday
=
dayjs
().
subtract
(
1
,
'd'
)
queryParams
.
times
=
DateUtil
.
getDateRange
(
beginDate
,
yesterday
)
}
/** 处理交易状况查询(日期单选按钮组选择后) */
const
handleDateTypeChange
=
async
()
=>
{
// 设置时间范围
setTimes
()
// 查询数据
await
getTradeTrendData
()
}
/** 处理交易状况查询 */
/** 处理交易状况查询 */
const
getTradeTrendData
=
async
()
=>
{
const
getTradeTrendData
=
async
()
=>
{
trendLoading
.
value
=
true
trendLoading
.
value
=
true
...
@@ -370,20 +304,14 @@ const getTradeStatisticsSummary = async () => {
...
@@ -370,20 +304,14 @@ const getTradeStatisticsSummary = async () => {
/** 查询交易状况数据统计 */
/** 查询交易状况数据统计 */
const
getTradeTrendSummary
=
async
()
=>
{
const
getTradeTrendSummary
=
async
()
=>
{
loading
.
value
=
true
const
times
=
shortcutDateRangePicker
.
value
.
times
trendSummary
.
value
=
await
TradeStatisticsApi
.
getTradeTrendSummary
(
queryParams
)
trendSummary
.
value
=
await
TradeStatisticsApi
.
getTradeTrendSummary
({
times
})
loading
.
value
=
false
}
}
/** 查询交易状况数据列表 */
/** 查询交易状况数据列表 */
const
getTradeTrendList
=
async
()
=>
{
const
getTradeTrendList
=
async
()
=>
{
const
times
=
queryParams
.
times
// 开始与截止在同一天的, 折线图出不来, 需要延长一天
if
(
DateUtil
.
isSameDay
(
times
[
0
],
times
[
1
]))
{
// 前天
times
[
0
]
=
DateUtil
.
formatDate
(
dayjs
(
times
[
0
]).
subtract
(
1
,
'd'
))
}
// 查询数据
// 查询数据
const
times
=
shortcutDateRangePicker
.
value
.
times
const
list
=
await
TradeStatisticsApi
.
getTradeTrendList
({
times
})
const
list
=
await
TradeStatisticsApi
.
getTradeTrendList
({
times
})
// 处理数据
// 处理数据
for
(
let
item
of
list
)
{
for
(
let
item
of
list
)
{
...
@@ -405,7 +333,8 @@ const handleExport = async () => {
...
@@ -405,7 +333,8 @@ const handleExport = async () => {
await
message
.
exportConfirm
()
await
message
.
exportConfirm
()
// 发起导出
// 发起导出
exportLoading
.
value
=
true
exportLoading
.
value
=
true
const
data
=
await
TradeStatisticsApi
.
exportTradeTrend
(
queryParams
)
const
times
=
shortcutDateRangePicker
.
value
.
times
const
data
=
await
TradeStatisticsApi
.
exportTradeTrend
({
times
})
download
.
excel
(
data
,
'交易状况.xls'
)
download
.
excel
(
data
,
'交易状况.xls'
)
}
catch
{
}
catch
{
}
finally
{
}
finally
{
...
@@ -416,7 +345,6 @@ const handleExport = async () => {
...
@@ -416,7 +345,6 @@ const handleExport = async () => {
/** 初始化 **/
/** 初始化 **/
onMounted
(
async
()
=>
{
onMounted
(
async
()
=>
{
await
getTradeStatisticsSummary
()
await
getTradeStatisticsSummary
()
await
handleDateTypeChange
()
})
})
</
script
>
</
script
>
<
style
lang=
"scss"
scoped
>
<
style
lang=
"scss"
scoped
>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment