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
d3f64985
authored
Sep 12, 2025
by
lijinqi
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'origin/develop' into develop
parents
5576e65f
0c1c1ff7
Show whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
531 additions
and
348 deletions
+531
-348
src/api/Home/count/index.ts
+36
-0
src/api/mall/trade/order/index.ts
+9
-0
src/utils/constants.ts
+19
-0
src/utils/dict.ts
+1
-0
src/views/Home/Index.vue
+286
-343
src/views/Home/types.ts
+3
-3
src/views/mall/trade/order/components/OrderTableColumn.vue
+9
-1
src/views/mall/trade/order/form/OrderIssueInvoiceForm.vue
+79
-0
src/views/mall/trade/order/form/OrderViewInvoiceForm.vue
+61
-0
src/views/mall/trade/order/index.vue
+28
-1
No files found.
src/api/Home/count/index.ts
0 → 100644
View file @
d3f64985
import
request
from
'@/config/axios'
export
const
getUsersData
=
async
(
dateType
)
=>
{
return
await
request
.
get
({
url
:
`/index/count/getUsersData`
,
params
:{
dateType
:
dateType
}
})
}
export
const
getOrdersData
=
async
(
dateType
)
=>
{
return
await
request
.
get
({
url
:
`/index/count/getOrdersData`
,
params
:{
dateType
:
dateType
}
})
}
export
const
getApiCallsData
=
async
(
dateType
)
=>
{
return
await
request
.
get
({
url
:
`/index/count/getApiCallsData`
,
params
:{
dateType
:
dateType
}
})
}
export
const
getTopBarData
=
async
()
=>
{
return
await
request
.
get
({
url
:
`/index/count/getTopBarData`
,
})
}
src/api/mall/trade/order/index.ts
View file @
d3f64985
...
@@ -47,6 +47,10 @@ export interface OrderVO {
...
@@ -47,6 +47,10 @@ export interface OrderVO {
afterSaleStatus
?:
number
|
null
// 售后状态
afterSaleStatus
?:
number
|
null
// 售后状态
refundPrice
?:
number
|
null
// 退款金额
refundPrice
?:
number
|
null
// 退款金额
// ========== 发票基本信息 ==========
invoiceStatus
?:
number
|
null
//开票状态
invoiceUrl
?:
String
|
null
//发票链接
// ========== 营销基本信息 ==========
// ========== 营销基本信息 ==========
couponId
?:
number
|
null
// 优惠劵编号
couponId
?:
number
|
null
// 优惠劵编号
couponPrice
?:
number
|
null
// 优惠劵减免金额
couponPrice
?:
number
|
null
// 优惠劵减免金额
...
@@ -171,6 +175,11 @@ export const pickUpOrder = async (id: number) => {
...
@@ -171,6 +175,11 @@ export const pickUpOrder = async (id: number) => {
return
await
request
.
put
({
url
:
`/trade/order/pick-up-by-id?id=
${
id
}
`
})
return
await
request
.
put
({
url
:
`/trade/order/pick-up-by-id?id=
${
id
}
`
})
}
}
//开具发票
export
const
issueInvoice
=
async
(
data
:
any
)
=>
{
return
await
request
.
put
({
url
:
`/trade/order/issue-invoice`
,
data
})
}
// 订单核销
// 订单核销
export
const
pickUpOrderByVerifyCode
=
async
(
pickUpVerifyCode
:
string
)
=>
{
export
const
pickUpOrderByVerifyCode
=
async
(
pickUpVerifyCode
:
string
)
=>
{
return
await
request
.
put
({
return
await
request
.
put
({
...
...
src/utils/constants.ts
View file @
d3f64985
...
@@ -401,6 +401,25 @@ export const DeliveryTypeEnum = {
...
@@ -401,6 +401,25 @@ export const DeliveryTypeEnum = {
name
:
'到店自提'
name
:
'到店自提'
}
}
}
}
/**
* 开票状态枚举
*/
export
const
InvoiceRequestEnum
=
{
UNINVOICED
:
{
type
:
0
,
name
:
'未开票'
},
INVOICING
:
{
type
:
1
,
name
:
'开票中'
},
INVOICED
:
{
type
:
2
,
name
:
'已开票'
}
}
/**
/**
* 交易订单 - 状态
* 交易订单 - 状态
*/
*/
...
...
src/utils/dict.ts
View file @
d3f64985
...
@@ -185,6 +185,7 @@ export enum DICT_TYPE {
...
@@ -185,6 +185,7 @@ export enum DICT_TYPE {
TRADE_ORDER_STATUS
=
'trade_order_status'
,
// 订单 - 状态
TRADE_ORDER_STATUS
=
'trade_order_status'
,
// 订单 - 状态
TRADE_ORDER_ITEM_AFTER_SALE_STATUS
=
'trade_order_item_after_sale_status'
,
// 订单项 - 售后状态
TRADE_ORDER_ITEM_AFTER_SALE_STATUS
=
'trade_order_item_after_sale_status'
,
// 订单项 - 售后状态
TRADE_DELIVERY_TYPE
=
'trade_delivery_type'
,
// 配送方式
TRADE_DELIVERY_TYPE
=
'trade_delivery_type'
,
// 配送方式
TRADE_INVOICE_STATUS
=
'trade_invoice_status'
,
BROKERAGE_ENABLED_CONDITION
=
'brokerage_enabled_condition'
,
// 分佣模式
BROKERAGE_ENABLED_CONDITION
=
'brokerage_enabled_condition'
,
// 分佣模式
BROKERAGE_BIND_MODE
=
'brokerage_bind_mode'
,
// 分销关系绑定模式
BROKERAGE_BIND_MODE
=
'brokerage_bind_mode'
,
// 分销关系绑定模式
BROKERAGE_BANK_NAME
=
'brokerage_bank_name'
,
// 佣金提现银行
BROKERAGE_BANK_NAME
=
'brokerage_bank_name'
,
// 佣金提现银行
...
...
src/views/Home/Index.vue
View file @
d3f64985
...
@@ -6,7 +6,7 @@
...
@@ -6,7 +6,7 @@
<el-col
:xl=
"12"
:lg=
"12"
:md=
"12"
:sm=
"24"
:xs=
"24"
>
<el-col
:xl=
"12"
:lg=
"12"
:md=
"12"
:sm=
"24"
:xs=
"24"
>
<div
class=
"flex items-center"
>
<div
class=
"flex items-center"
>
<el-avatar
:src=
"avatar"
:size=
"70"
class=
"mr-16px"
>
<el-avatar
:src=
"avatar"
:size=
"70"
class=
"mr-16px"
>
<img
src=
"@/assets/imgs/avatar.gif"
alt=
"
"
/>
<img
src=
"@/assets/imgs/avatar.gif"
alt=
"
用户头像"
/>
</el-avatar>
</el-avatar>
<div>
<div>
<div
class=
"text-20px"
>
<div
class=
"text-20px"
>
...
@@ -18,405 +18,348 @@
...
@@ -18,405 +18,348 @@
</div>
</div>
</div>
</div>
</el-col>
</el-col>
<!--
<el-col
:xl=
"12"
:lg=
"12"
:md=
"12"
:sm=
"24"
:xs=
"24"
>
--
>
<el-col
:xl=
"12"
:lg=
"12"
:md=
"12"
:sm=
"24"
:xs=
"24"
>
<!--
<div
class=
"h-70px flex items-center justify-end lt-sm:mt-10px"
>
--
>
<div
class=
"h-70px flex items-center justify-end lt-sm:mt-10px"
>
<!--
<div
class=
"px-8px text-right"
>
--
>
<div
class=
"px-8px text-right"
>
<!--
<div
class=
"mb-16px text-14px text-gray-400"
>
{{
t
(
'workplace.project'
)
}}
</div>
--
>
<div
class=
"mb-16px text-14px text-gray-400"
>
{{
'今日新增用户'
}}
</div
>
<!--
<CountTo-->
<CountTo
<!-- class="text-20px"-->
class=
"text-20px"
<!-- :start-val="0"-->
:start-val=
"0"
<!-- :end-val="totalSate.project"-->
:end-val=
"todayData.newUsersCount"
<!-- :duration="2600"-->
:duration=
"2600"
<!-- />--
>
/
>
<!--
</div>
--
>
</div
>
<!--
<el-divider
direction=
"vertical"
/>
--
>
<el-divider
direction=
"vertical"
/
>
<!--
<div
class=
"px-8px text-right"
>
--
>
<div
class=
"px-8px text-right"
>
<!--
<div
class=
"mb-16px text-14px text-gray-400"
>
{{
t
(
'workplace.toDo'
)
}}
</div>
--
>
<div
class=
"mb-16px text-14px text-gray-400"
>
{{
'今日订单'
}}
</div
>
<!--
<CountTo-->
<CountTo
<!-- class="text-20px"-->
class=
"text-20px"
<!-- :start-val="0"-->
:start-val=
"0"
<!-- :end-val="totalSate.todo"-->
:end-val=
"todayData.newOrdersCount"
<!-- :duration="2600"-->
:duration=
"2600"
<!-- />--
>
/
>
<!--
</div>
--
>
</div
>
<!--
<el-divider
direction=
"vertical"
border-style=
"dashed"
/>
--
>
<el-divider
direction=
"vertical"
border-style=
"dashed"
/
>
<!--
<div
class=
"px-8px text-right"
>
--
>
<div
class=
"px-8px text-right"
>
<!--
<div
class=
"mb-16px text-14px text-gray-400"
>
{{
t
(
'workplace.access'
)
}}
</div>
--
>
<div
class=
"mb-16px text-14px text-gray-400"
>
{{
'今日订单金额'
}}
</div
>
<!--
<CountTo-->
<CountTo
<!-- class="text-20px"-->
class=
"text-20px"
<!-- :start-val="0"-->
:start-val=
"0"
<!-- :end-val="totalSate.access"-->
:end-val=
"todayData.newOrdersAmount"
<!-- :duration="2600"-->
:duration=
"2600"
<!-- />--
>
/
>
<!--
</div>
--
>
</div
>
<!--
</div>
--
>
</div
>
<!--
</el-col>
--
>
</el-col
>
</el-row>
</el-row>
</el-skeleton>
</el-skeleton>
</el-card>
</el-card>
<!-- 统计图 -->
<el-row
class=
"mt-8px"
:gutter=
"8"
justify=
"space-between"
>
<el-col
:xl=
"24"
:lg=
"24"
:md=
"24"
:sm=
"24"
:xs=
"24"
class=
"mb-8px"
>
<el-card
shadow=
"never"
class=
"mt-8px"
>
<el-skeleton
:loading=
"loading"
animated
>
<el-row
:gutter=
"20"
justify=
"space-between"
>
<!-- 用户统计图表 -->
<el-col
:xl=
"12"
:lg=
"12"
:md=
"12"
:sm=
"12"
:xs=
"12"
>
<div
style=
"display: flex; justify-content: flex-end; margin-bottom: 10px;"
>
<el-button
@
click=
"changeUserDateType"
type=
"primary"
size=
"small"
>
{{
userDateType
===
'd'
?
'切换月数据'
:
'切换日数据'
}}
</el-button>
</div>
<el-card
shadow=
"hover"
class=
"mb-8px"
>
<el-skeleton
:loading=
"loading"
animated
>
<Echart
:options=
"usersChartOption"
:height=
"340"
/>
</el-skeleton>
</el-card>
</el-col>
<el-col
:xl=
"12"
:lg=
"12"
:md=
"12"
:sm=
"12"
:xs=
"12"
>
<div
style=
"display: flex; justify-content: flex-end; margin-bottom: 10px;"
>
<el-button
@
click=
"changeApiCallsDateType"
type=
"primary"
size=
"small"
>
{{
apiCallsDateType
===
'd'
?
'切换月数据'
:
'切换日数据'
}}
</el-button>
</div>
<el-card
shadow=
"hover"
class=
"mb-8px"
>
<el-skeleton
:loading=
"loading"
animated
>
<Echart
:options=
"apiCallChartOptions"
:height=
"340"
/>
</el-skeleton>
</el-card>
</el-col>
<!-- 第三个图表:折线图-->
<el-col
:xl=
"24"
:lg=
"24"
:md=
"24"
:sm=
"24"
:xs=
"24"
>
<div
style=
"display: flex; justify-content: flex-end; margin-bottom: 10px;"
>
<el-button
@
click=
"changeOrderDateType"
type=
"primary"
size=
"small"
>
{{
orderDateType
===
'd'
?
'切换月数据'
:
'切换日数据'
}}
</el-button>
</div>
</div>
<el-card
shadow=
"hover"
class=
"mb-8px"
>
<el-skeleton
:loading=
"loading"
animated
>
<Echart
:options=
"orderChartOptions"
:height=
"420"
/>
</el-skeleton>
</el-card>
</el-col>
</el-row>
<!--
<el-row
class=
"mt-8px"
:gutter=
"8"
justify=
"space-between"
>
-->
<!--
<el-col
:xl=
"16"
:lg=
"16"
:md=
"24"
:sm=
"24"
:xs=
"24"
class=
"mb-8px"
>
-->
<!--
<el-card
shadow=
"never"
>
-->
<!--
<template
#
header
>
-->
<!--
<div
class=
"h-3 flex justify-between"
>
-->
<!--
<span>
{{
t
(
'workplace.project'
)
}}
</span>
-->
<!--
<el-link-->
<!-- type="primary"-->
<!-- :underline="false"-->
<!-- href="https://github.com/yudaocode"-->
<!-- target="_blank"-->
<!-- >-->
<!--
{{
t
(
'action.more'
)
}}
-->
<!--
</el-link>
-->
<!--
</div>
-->
<!--
</
template
>
-->
<!-- <el-skeleton :loading="loading" animated>-->
<!-- <el-row>-->
<!-- <el-col-->
<!-- v-for="(item, index) in projects"-->
<!-- :key="`card-${index}`"-->
<!-- :xl="8"-->
<!-- :lg="8"-->
<!-- :md="8"-->
<!-- :sm="24"-->
<!-- :xs="24"-->
<!-- >-->
<!-- <el-card-->
<!-- shadow="hover"-->
<!-- class="mr-5px mt-5px cursor-pointer"-->
<!-- @click="handleProjectClick(item.message)"-->
<!-- >-->
<!-- <div class="flex items-center">-->
<!-- <Icon-->
<!-- :icon="item.icon"-->
<!-- :size="25"-->
<!-- class="mr-8px"-->
<!-- :style="{ color: item.color }"-->
<!-- />-->
<!-- <span class="text-16px">{{ item.name }}</span>-->
<!-- </div>-->
<!-- <div class="mt-12px text-12px text-gray-400">{{ t(item.message) }}</div>-->
<!-- <div class="mt-12px flex justify-between text-12px text-gray-400">-->
<!-- <span>{{ item.personal }}</span>-->
<!-- <span>{{ formatTime(item.time, 'yyyy-MM-dd') }}</span>-->
<!-- </div>-->
<!-- </el-card>-->
<!-- </el-col>-->
<!-- </el-row>-->
<!-- </el-skeleton>-->
<!-- </el-card>-->
<!-- <el-card shadow="never" class="mt-8px">-->
</el-skeleton>
<!-- <el-skeleton :loading="loading" animated>-->
</el-card>
<!-- <el-row :gutter="20" justify="space-between">-->
</el-col>
<!-- <el-col :xl="10" :lg="10" :md="24" :sm="24" :xs="24">-->
</el-row>
<!-- <el-card shadow="hover" class="mb-8px">-->
</div>
<!-- <el-skeleton :loading="loading" animated>-->
<!-- <Echart :options="pieOptionsData" :height="280" />-->
<!-- </el-skeleton>-->
<!-- </el-card>-->
<!-- </el-col>-->
<!-- <el-col :xl="14" :lg="14" :md="24" :sm="24" :xs="24">-->
<!-- <el-card shadow="hover" class="mb-8px">-->
<!-- <el-skeleton :loading="loading" animated>-->
<!-- <Echart :options="barOptionsData" :height="280" />-->
<!-- </el-skeleton>-->
<!-- </el-card>-->
<!-- </el-col>-->
<!-- </el-row>-->
<!-- </el-skeleton>-->
<!-- </el-card>-->
<!-- </el-col>-->
<!-- <el-col :xl="8" :lg="8" :md="24" :sm="24" :xs="24" class="mb-8px">-->
<!-- <el-card shadow="never">-->
<!-- <template #header>-->
<!-- <div class="h-3 flex justify-between">-->
<!-- <span>{{ t('workplace.shortcutOperation') }}</span>-->
<!-- </div>-->
<!-- </template>-->
<!-- <el-skeleton :loading="loading" animated>-->
<!-- <el-row>-->
<!-- <el-col v-for="item in shortcut" :key="`team-${item.name}`" :span="8" class="mb-8px">-->
<!-- <div class="flex items-center">-->
<!-- <Icon :icon="item.icon" class="mr-8px" :style="{ color: item.color }" />-->
<!-- <el-link type="default" :underline="false" @click="handleShortcutClick(item.url)">-->
<!-- {{ item.name }}-->
<!-- </el-link>-->
<!-- </div>-->
<!-- </el-col>-->
<!-- </el-row>-->
<!-- </el-skeleton>-->
<!-- </el-card>-->
<!-- <el-card shadow="never" class="mt-8px">-->
<!-- <template #header>-->
<!-- <div class="h-3 flex justify-between">-->
<!-- <span>{{ t('workplace.notice') }}</span>-->
<!-- <el-link type="primary" :underline="false">{{ t('action.more') }}</el-link>-->
<!-- </div>-->
<!-- </template>-->
<!-- <el-skeleton :loading="loading" animated>-->
<!-- <div v-for="(item, index) in notice" :key="`dynamics-${index}`">-->
<!-- <div class="flex items-center">-->
<!-- <el-avatar :src="avatar" :size="35" class="mr-16px">-->
<!-- <img src="@/assets/imgs/avatar.gif" alt="" />-->
<!-- </el-avatar>-->
<!-- <div>-->
<!-- <div class="text-14px">-->
<!-- <Highlight :keys="item.keys.map((v) => t(v))">-->
<!-- {{ item.type }} : {{ item.title }}-->
<!-- </Highlight>-->
<!-- </div>-->
<!-- <div class="mt-16px text-12px text-gray-400">-->
<!-- {{ formatTime(item.date, 'yyyy-MM-dd') }}-->
<!-- </div>-->
<!-- </div>-->
<!-- </div>-->
<!-- <el-divider />-->
<!-- </div>-->
<!-- </el-skeleton>-->
<!-- </el-card>-->
<!-- </el-col>-->
<!-- </el-row>-->
</
template
>
</
template
>
<
script
lang=
"ts"
setup
>
<
script
lang=
"ts"
setup
>
import
{
set
}
from
'lodash-es'
import
{
ref
,
reactive
}
from
'vue'
import
{
EChartsOption
}
from
'echarts'
import
{
EChartsOption
}
from
'echarts'
import
{
formatTime
}
from
'@/utils'
import
{
useUserStore
}
from
'@/store/modules/user'
import
{
useUserStore
}
from
'@/store/modules/user'
// import { useWatermark } from '@/hooks/web/useWatermark'
import
type
{
WorkplaceTotal
}
from
'./types'
import
type
{
WorkplaceTotal
,
Project
,
Notice
,
Shortcut
}
from
'./types'
import
{
useRouter
}
from
'vue-router'
import
{
pieOptions
,
barOptions
}
from
'./echarts-data'
import
{
useI18n
}
from
'vue-i18n'
// 确保导入i18n
import
{
useRouter
}
from
'vue-router'
import
*
as
IndexCountApi
from
"@/api/Home/count"
;
import
Index
from
"@/views/ai/music/index/index.vue"
;
defineOptions
({
name
:
'Index'
})
defineOptions
({
name
:
'Index'
})
const
{
t
}
=
useI18n
()
// 国际化
const
{
t
}
=
useI18n
()
const
router
=
useRouter
()
const
router
=
useRouter
()
const
userStore
=
useUserStore
()
const
userStore
=
useUserStore
()
// const { setWatermark } = useWatermark()
const
loading
=
ref
(
true
)
const
loading
=
ref
(
true
)
const
avatar
=
userStore
.
getUser
.
avatar
const
avatar
=
userStore
.
getUser
.
avatar
const
username
=
userStore
.
getUser
.
nickname
const
username
=
userStore
.
getUser
.
nickname
const
pieOptionsData
=
reactive
<
EChartsOption
>
(
pieOptions
)
as
EChartsOption
// 获取统计数
let
totalSate
=
reactive
<
WorkplaceTotal
>
({
project
:
0
,
access
:
0
,
todo
:
0
})
const
getCount
=
async
()
=>
{
// 切换状态(d=日,m=月)
const
data
=
{
const
userDateType
=
ref
(
'd'
);
project
:
40
,
const
apiCallsDateType
=
ref
(
'd'
);
access
:
2340
,
const
orderDateType
=
ref
(
'd'
);
todo
:
10
}
const
changeUserDateType
=
()
=>
{
totalSate
=
Object
.
assign
(
totalSate
,
data
)
userDateType
.
value
=
userDateType
.
value
===
'd'
?
'm'
:
'd'
;
// 调用获取图表数据的方法,传入当前类型
getUsersChartData
(
userDateType
.
value
);
};
const
changeApiCallsDateType
=
()
=>
{
apiCallsDateType
.
value
=
apiCallsDateType
.
value
===
'd'
?
'm'
:
'd'
;
getApiCallsChartData
(
apiCallsDateType
.
value
);
}
}
// 获取项目数
const
changeOrderDateType
=
()
=>
{
let
projects
=
reactive
<
Project
[]
>
([])
orderDateType
.
value
=
orderDateType
.
value
===
'd'
?
'm'
:
'd'
;
const
getProject
=
async
()
=>
{
getOrderChartData
(
orderDateType
.
value
);
const
data
=
[
}
{
name
:
'ruoyi-vue-pro'
,
// 统计数据
icon
:
'simple-icons:springboot'
,
const
todayData
=
reactive
<
WorkplaceTotal
>
({
message
:
'github.com/YunaiV/ruoyi-vue-pro'
,
newUsersCount
:
0
,
personal
:
'Spring Boot 单体架构'
,
newOrdersCount
:
0
,
time
:
new
Date
(
'2025-01-02'
),
newOrdersAmount
:
0
color
:
'#6DB33F'
})
},
{
// 用户数柱状图配置
name
:
'yudao-ui-admin-vue3'
,
const
usersChartOption
=
ref
<
EChartsOption
>
({
icon
:
'ep:element-plus'
,
title
:
{
message
:
'github.com/yudaocode/yudao-ui-admin-vue3'
,
text
:
'用户数'
,
personal
:
'Vue3 + element-plus 管理后台'
,
left
:
'center'
time
:
new
Date
(
'2025-02-03'
),
color
:
'#409EFF'
},
},
{
tooltip
:
{
name
:
'yudao-ui-mall-uniapp'
,
trigger
:
'axis'
icon
:
'icon-park-outline:mall-bag'
,
message
:
'github.com/yudaocode/yudao-ui-mall-uniapp'
,
personal
:
'Vue3 + uniapp 商城手机端'
,
time
:
new
Date
(
'2025-03-04'
),
color
:
'#ff4d4f'
},
},
{
xAxis
:
{
name
:
'yudao-cloud'
,
type
:
'category'
,
icon
:
'material-symbols:cloud-outline'
,
data
:
[]
message
:
'github.com/YunaiV/yudao-cloud'
,
personal
:
'Spring Cloud 微服务架构'
,
time
:
new
Date
(
'2025-04-05'
),
color
:
'#1890ff'
},
},
{
yAxis
:
{
name
:
'yudao-ui-admin-vben'
,
type
:
'value'
icon
:
'devicon:antdesign'
,
message
:
'github.com/yudaocode/yudao-ui-admin-vben'
,
personal
:
'Vue3 + vben5(antd) 管理后台'
,
time
:
new
Date
(
'2025-05-06'
),
color
:
'#e18525'
},
},
series
:
[
{
{
name
:
'yudao-ui-admin-uniapp'
,
name
:
t
(
'analysis.activeQuantity'
)
,
icon
:
'ant-design:mobile'
,
data
:
[]
,
message
:
'github.com/yudaocode/yudao-ui-admin-uniapp'
,
type
:
'bar'
,
// 柱状图
personal
:
'Vue3 + uniapp 管理手机端'
,
itemStyle
:
{
time
:
new
Date
(
'2025-06-01'
),
color
:
'#409EFF'
// 自定义颜色
color
:
'#2979ff'
}
}
}
]
]
projects
=
Object
.
assign
(
projects
,
data
)
})
// 用户数柱状图数据
const
getUsersChartData
=
async
(
userDateType
)
=>
{
let
responseData
=
await
IndexCountApi
.
getUsersData
(
userDateType
);
// 直接修改图表配置
usersChartOption
.
value
.
xAxis
!
.
data
=
responseData
.
map
(
item
=>
t
(
item
.
countDate
))
usersChartOption
.
value
.
series
!
[
0
].
data
=
responseData
.
map
(
item
=>
item
.
usersCount
)
}
}
// 获取通知公告
// api调用折线图配置
let
notice
=
reactive
<
Notice
[]
>
([])
const
apiCallChartOptions
=
ref
<
EChartsOption
>
({
const
getNotice
=
async
()
=>
{
title
:
{
const
data
=
[
text
:
'api调用次数'
,
{
left
:
'center'
title
:
'系统支持 JDK 8/17/21,Vue 2/3'
,
type
:
'技术兼容性'
,
keys
:
[
'JDK'
,
'Vue'
],
date
:
new
Date
()
},
},
{
tooltip
:
{
title
:
'后端提供 Spring Boot 2.7/3.2 + Cloud 双架构'
,
trigger
:
'axis'
type
:
'架构灵活性'
,
keys
:
[
'Boot'
,
'Cloud'
],
date
:
new
Date
()
},
},
{
xAxis
:
{
title
:
'全部开源,个人与企业可 100% 直接使用,无需授权'
,
type
:
'category'
,
type
:
'开源免授权'
,
data
:
[]
// 后续会动态填充
keys
:
[
'无需授权'
],
date
:
new
Date
()
},
},
yAxis
:
{
type
:
'value'
},
series
:
[
{
{
title
:
'国内使用最广泛的快速开发平台,远超 10w+ 企业使用'
,
name
:
'API调用次数'
,
type
:
'广泛企业认可'
,
data
:
[],
// 后续会动态填充
keys
:
[
'最广泛'
,
'10w+'
],
type
:
'line'
,
// 明确指定为折线图
date
:
new
Date
()
smooth
:
false
,
// 平滑曲线
itemStyle
:
{
color
:
'#67C23A'
// 自定义颜色
}
}
}
]
]
notice
=
Object
.
assign
(
notice
,
data
)
})
}
// 获取快捷入口
// api调用折线图数据
let
shortcut
=
reactive
<
Shortcut
[]
>
([])
const
getApiCallsChartData
=
async
(
apiCallsDateType
)
=>
{
let
data
=
await
IndexCountApi
.
getApiCallsData
(
apiCallsDateType
)
// 直接修改图表配置
apiCallChartOptions
.
value
.
xAxis
!
.
data
=
data
.
map
(
item
=>
t
(
item
.
countDate
))
apiCallChartOptions
.
value
.
series
!
[
0
].
data
=
data
.
map
(
item
=>
item
.
callsCount
)
}
const
getShortcut
=
async
()
=>
{
//订单折线图配置
const
data
=
[
const
orderChartOptions
=
ref
<
EChartsOption
>
({
{
title
:
{
name
:
'首页'
,
text
:
'订单相关统计'
,
icon
:
'ion:home-outline'
,
left
:
'center'
url
:
'/'
,
},
color
:
'#1fdaca'
tooltip
:
{
trigger
:
'axis'
},
},
xAxis
:
{
type
:
'category'
,
data
:
[]
// 后续会动态填充
},
yAxis
:
[
{
{
name
:
'商城中心'
,
type
:
'value'
,
icon
:
'ep:shop'
,
name
:
'订单数量'
url
:
'/mall/home'
,
color
:
'#ff6b6b'
},
},
{
{
name
:
'AI 大模型'
,
// 右Y轴:金额(新增轴,index=1)
icon
:
'tabler:ai'
,
type
:
'value'
,
url
:
'/ai/chat'
,
name
:
'金额(元)'
,
// 轴名称
color
:
'#7c3aed'
position
:
'right'
// 放在右侧
}
],
series
:
[
{
name
:
'算力订单'
,
data
:
[],
// 后续会动态填充
type
:
'line'
,
// 明确指定为折线图
smooth
:
false
,
// 平滑曲线
itemStyle
:
{
color
:
'#67C23A'
// 自定义颜色
}
},
{
name
:
'API订单'
,
data
:
[],
// 后续会动态填充
type
:
'line'
,
// 明确指定为折线图
smooth
:
false
,
// 平滑曲线
itemStyle
:
{
color
:
'#409EFF'
// 自定义颜色
}
},
{
name
:
'总订单'
,
data
:
[],
// 后续会动态填充
type
:
'line'
,
// 明确指定为折线图
smooth
:
false
,
// 平滑曲线
itemStyle
:
{
color
:
'#F59E0B'
// 自定义颜色
}
},
},
// ---------------------- 新增3个金额系列(都绑右侧轴)----------------------
{
{
name
:
'ERP 系统'
,
name
:
'算力订单金额'
,
icon
:
'simple-icons:erpnext'
,
data
:
[],
// 算力金额数据
url
:
'/erp/home'
,
type
:
'line'
,
color
:
'#3fb27f'
smooth
:
false
,
itemStyle
:
{
color
:
'#94D274'
},
// 浅绿(和算力订单数颜色呼应)
yAxisIndex
:
1
// 关键:绑右侧金额轴
},
},
{
{
name
:
'CRM 系统'
,
name
:
'API订单金额'
,
icon
:
'simple-icons:civicrm'
,
data
:
[],
// API金额数据
url
:
'/crm/backlog'
,
type
:
'line'
,
color
:
'#4daf1bc9'
smooth
:
false
,
itemStyle
:
{
color
:
'#7CB6FF'
},
// 浅蓝(和API订单数颜色呼应)
yAxisIndex
:
1
// 绑右侧金额轴
},
},
{
{
name
:
'IoT 物联网'
,
name
:
'总金额'
,
icon
:
'fa-solid:hdd'
,
data
:
[],
// 总金额数据
url
:
'/iot/home'
,
type
:
'line'
,
color
:
'#1a73e8'
smooth
:
false
,
itemStyle
:
{
color
:
'#FFC53D'
},
// 浅黄(和总订单数颜色呼应)
yAxisIndex
:
1
// 绑右侧金额轴
}
}
]
]
shortcut
=
Object
.
assign
(
shortcut
,
data
)
})
}
// 用户来源
//订单折线图数据
const
getUserAccessSource
=
async
()
=>
{
const
getOrderChartData
=
async
(
orderDateType
)
=>
{
const
data
=
[
let
ordersData
=
await
IndexCountApi
.
getOrdersData
(
orderDateType
);
{
value
:
335
,
name
:
'analysis.directAccess'
},
{
value
:
310
,
name
:
'analysis.mailMarketing'
},
{
value
:
234
,
name
:
'analysis.allianceAdvertising'
},
{
value
:
135
,
name
:
'analysis.videoAdvertising'
},
{
value
:
1548
,
name
:
'analysis.searchEngines'
}
]
set
(
pieOptionsData
,
'legend.data'
,
data
.
map
((
v
)
=>
t
(
v
.
name
))
)
pieOptionsData
!
.
series
!
[
0
].
data
=
data
.
map
((
v
)
=>
{
return
{
name
:
t
(
v
.
name
),
value
:
v
.
value
}
})
}
const
barOptionsData
=
reactive
<
EChartsOption
>
(
barOptions
)
as
EChartsOption
// 周活跃量
orderChartOptions
.
value
.
xAxis
!
.
data
=
ordersData
.
map
(
item
=>
t
(
item
.
countDate
))
const
getWeeklyUserActivity
=
async
()
=>
{
orderChartOptions
.
value
.
series
!
[
0
].
data
=
ordersData
.
map
(
item
=>
item
.
computeOrdersCount
)
const
data
=
[
orderChartOptions
.
value
.
series
!
[
1
].
data
=
ordersData
.
map
(
item
=>
item
.
apiOrdersCount
)
{
value
:
13253
,
name
:
'analysis.monday'
},
orderChartOptions
.
value
.
series
!
[
2
].
data
=
ordersData
.
map
(
item
=>
item
.
totalOrdersCount
)
{
value
:
34235
,
name
:
'analysis.tuesday'
},
orderChartOptions
.
value
.
series
!
[
3
].
data
=
ordersData
.
map
(
item
=>
item
.
computeOrdersAmount
)
{
value
:
26321
,
name
:
'analysis.wednesday'
},
orderChartOptions
.
value
.
series
!
[
4
].
data
=
ordersData
.
map
(
item
=>
item
.
apiOrdersAmount
)
{
value
:
12340
,
name
:
'analysis.thursday'
},
orderChartOptions
.
value
.
series
!
[
5
].
data
=
ordersData
.
map
(
item
=>
item
.
totalOrdersAmount
)
{
value
:
24643
,
name
:
'analysis.friday'
},
{
value
:
1322
,
name
:
'analysis.saturday'
},
{
value
:
1324
,
name
:
'analysis.sunday'
}
]
set
(
barOptionsData
,
'xAxis.data'
,
data
.
map
((
v
)
=>
t
(
v
.
name
))
)
set
(
barOptionsData
,
'series'
,
[
{
name
:
t
(
'analysis.activeQuantity'
),
data
:
data
.
map
((
v
)
=>
v
.
value
),
type
:
'bar'
}
])
}
}
const
getAllApi
=
async
()
=>
{
// 初始化数据
const
initData
=
async
()
=>
{
await
Promise
.
all
([
await
Promise
.
all
([
getCount
(),
getCount
(),
getProject
(),
getUsersChartData
(
userDateType
.
value
),
getNotice
(),
getApiCallsChartData
(
apiCallsDateType
.
value
),
getShortcut
(),
getOrderChartData
(
orderDateType
.
value
)
getUserAccessSource
(),
getWeeklyUserActivity
()
])
])
loading
.
value
=
false
loading
.
value
=
false
}
}
const
handleProjectClick
=
(
message
:
string
)
=>
{
// 获取统计数
window
.
open
(
`https://
${
message
}
`
,
'_blank'
)
const
getCount
=
async
()
=>
{
}
// 模拟接口数据
// const data = {
const
handleShortcutClick
=
(
url
:
string
)
=>
{
// newUsersCount: 10,
router
.
push
(
url
)
// newOrdersCount: 40,
// newOrdersAmount: 2340
// }
let
res
=
await
IndexCountApi
.
getTopBarData
()
Object
.
assign
(
todayData
,
res
)
}
}
initData
()
getAllApi
()
</
script
>
</
script
>
src/views/Home/types.ts
View file @
d3f64985
export
type
WorkplaceTotal
=
{
export
type
WorkplaceTotal
=
{
projec
t
:
number
newUsersCoun
t
:
number
access
:
number
newOrdersCount
:
number
todo
:
number
newOrdersAmount
:
number
}
}
export
type
Project
=
{
export
type
Project
=
{
...
...
src/views/mall/trade/order/components/OrderTableColumn.vue
View file @
d3f64985
...
@@ -24,6 +24,9 @@
...
@@ -24,6 +24,9 @@
订单状态
订单状态
</div>
</div>
<div
:style=
"
{ width: orderTableHeadWidthList[7] + 'px' }" class="flex justify-center">
<div
:style=
"
{ width: orderTableHeadWidthList[7] + 'px' }" class="flex justify-center">
开票状态
</div>
<div
:style=
"
{ width: orderTableHeadWidthList[8] + 'px' }" class="flex justify-center">
操作
操作
</div>
</div>
</div>
</div>
...
@@ -156,6 +159,11 @@
...
@@ -156,6 +159,11 @@
<dict-tag
:type=
"DICT_TYPE.TRADE_ORDER_STATUS"
:value=
"scope.row.status"
/>
<dict-tag
:type=
"DICT_TYPE.TRADE_ORDER_STATUS"
:value=
"scope.row.status"
/>
</
template
>
</
template
>
</el-table-column>
</el-table-column>
<el-table-column
align=
"center"
label=
"开票状态"
width=
"120"
>
<
template
#
default
>
<dict-tag
:type=
"DICT_TYPE.TRADE_INVOICE_STATUS"
:value=
"scope.row.invoiceStatus"
/>
</
template
>
</el-table-column>
<el-table-column
align=
"center"
fixed=
"right"
label=
"操作"
width=
"160"
>
<el-table-column
align=
"center"
fixed=
"right"
label=
"操作"
width=
"160"
>
<
template
#
default
>
<
template
#
default
>
<slot
:row=
"scope.row"
></slot>
<slot
:row=
"scope.row"
></slot>
...
@@ -236,7 +244,7 @@ const setOrderTableRef = (el: TableInstance) => {
...
@@ -236,7 +244,7 @@ const setOrderTableRef = (el: TableInstance) => {
tableHeadWidthAuto
(
el
)
tableHeadWidthAuto
(
el
)
}
}
// 头部 col 宽度初始化
// 头部 col 宽度初始化
const
orderTableHeadWidthList
=
ref
([
300
,
150
,
120
,
120
,
160
,
120
,
120
,
160
])
const
orderTableHeadWidthList
=
ref
([
300
,
150
,
120
,
120
,
160
,
120
,
120
,
1
20
,
1
60
])
// 头部宽度自适应
// 头部宽度自适应
const
tableHeadWidthAuto
=
(
el
:
TableInstance
)
=>
{
const
tableHeadWidthAuto
=
(
el
:
TableInstance
)
=>
{
const
columns
=
el
.
store
.
states
.
columns
.
value
const
columns
=
el
.
store
.
states
.
columns
.
value
...
...
src/views/mall/trade/order/form/OrderIssueInvoiceForm.vue
0 → 100644
View file @
d3f64985
<
template
>
<Dialog
v-model=
"dialogVisible"
title=
"上传发票"
width=
"45%"
>
<el-form-item
label=
"发票地址"
prop=
"invoiceUrl"
>
<UploadImg
v-model=
"formData.invoiceUrl"
/>
<p
class=
"upload-tips"
>
请上传 大小不超过
<span
class=
"red-text"
>
5MB
</span>
格式为
<span
class=
"red-text"
>
png/jpg/jpeg
</span>
的文件
</p>
</el-form-item>
<template
#
footer
>
<el-button
:disabled=
"formLoading"
type=
"primary"
@
click=
"submitForm"
>
确 定
</el-button>
<el-button
@
click=
"dialogVisible = false"
>
取 消
</el-button>
</
template
>
</Dialog>
</template>
<
script
setup
lang=
"ts"
>
import
*
as
TradeOrderApi
from
"@/api/mall/trade/order"
;
const
{
t
}
=
useI18n
()
// 国际化
const
message
=
useMessage
()
// 消息弹窗
const
dialogVisible
=
ref
(
false
)
// 弹窗是否展示
const
formRef
=
ref
()
// 表单 Ref
const
formLoading
=
ref
(
false
)
// 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
/** 提交表单 */
const
emit
=
defineEmits
([
'success'
])
// 定义 success 事件,用于操作成功后的回调
const
submitForm
=
async
()
=>
{
// 提交请求
formLoading
.
value
=
true
try
{
const
data
=
unref
(
formData
)
await
TradeOrderApi
.
issueInvoice
(
data
)
message
.
success
(
t
(
'common.updateSuccess'
))
dialogVisible
.
value
=
false
// 发送操作成功的事件
emit
(
'success'
,
true
)
}
catch
(
error
)
{
console
.
error
(
error
);
}
finally
{
formLoading
.
value
=
false
}
}
const
formData
=
ref
({
id
:
undefined
,
// 订单编号
invoiceStatus
:
undefined
,
invoiceUrl
:
''
})
const
open
=
async
(
row
:
TradeOrderApi
.
OrderVO
)
=>
{
resetForm
()
// 设置数据
formData
.
value
.
id
=
row
.
id
formData
.
value
.
invoiceStatus
=
row
.
invoiceStatus
formData
.
value
.
invoiceUrl
=
row
.
invoiceUrl
dialogVisible
.
value
=
true
}
defineExpose
({
open
})
// 提供 open 方法,用于打开弹窗
/** 重置表单 */
const
resetForm
=
()
=>
{
formData
.
value
=
{
id
:
undefined
,
// 订单编号
invoiceStatus
:
undefined
,
invoiceUrl
:
''
}
formRef
.
value
?.
resetFields
()
}
</
script
>
<
style
scoped
lang=
"scss"
>
</
style
>
src/views/mall/trade/order/form/OrderViewInvoiceForm.vue
0 → 100644
View file @
d3f64985
<
template
>
<!-- 图片查看弹窗 -->
<el-dialog
v-model=
"dialogVisible"
title=
"查看发票图片"
:width=
"`600px`"
:close-on-click-modal=
"false"
>
<div
class=
"flex justify-center p-4"
>
<img
:src=
"formData.invoiceUrl"
alt=
"发票图片"
class=
"max-w-full max-h-[500px] object-contain"
@
error=
"handleImageError"
/>
</div>
</el-dialog>
</
template
>
<
script
setup
lang=
"ts"
>
import
*
as
TradeOrderApi
from
"@/api/mall/trade/order"
;
const
dialogVisible
=
ref
(
false
)
// 弹窗是否展示
const
formData
=
ref
({
id
:
undefined
,
// 订单编号
invoiceStatus
:
undefined
,
invoiceUrl
:
''
})
const
open
=
async
(
row
:
TradeOrderApi
.
OrderVO
)
=>
{
resetForm
()
// 设置数据
formData
.
value
.
id
=
row
.
id
formData
.
value
.
invoiceStatus
=
row
.
invoiceStatus
formData
.
value
.
invoiceUrl
=
row
.
invoiceUrl
dialogVisible
.
value
=
true
}
defineExpose
({
open
})
// 提供 open 方法,用于打开弹窗
/** 重置表单 */
const
resetForm
=
()
=>
{
formData
.
value
=
{
id
:
undefined
,
// 订单编号
invoiceStatus
:
undefined
,
invoiceUrl
:
''
}
}
const
handleImageError
=
(
e
)
=>
{
e
.
target
.
src
=
'https://picsum.photos/600/400?grayscale&blur=2'
;
// 占位图
e
.
target
.
alt
=
'图片加载失败'
;
};
</
script
>
<
style
scoped
lang=
"scss"
>
</
style
>
src/views/mall/trade/order/index.vue
View file @
d3f64985
...
@@ -201,6 +201,23 @@
...
@@ -201,6 +201,23 @@
<Icon
icon=
"ep:takeaway-box"
/>
<Icon
icon=
"ep:takeaway-box"
/>
发货
发货
</el-dropdown-item>
</el-dropdown-item>
<!-- 如果订单开票状态为【未开票】【开票中】,则展示【开票】按钮-->
<el-dropdown-item
v-if=
"
row.invoiceStatus === InvoiceRequestEnum.UNINVOICED.type ||
row.invoiceStatus === InvoiceRequestEnum.INVOICING.type
"
command=
"issueInvoice"
>
<Icon
icon=
"ep:takeaway-box"
/>
开票
</el-dropdown-item>
<el-dropdown-item
v-if=
"row.invoiceStatus === InvoiceRequestEnum.INVOICED.type"
command=
"viewInvoice"
>
<Icon
icon=
"ep:takeaway-box"
/>
展示发票
</el-dropdown-item>
<el-dropdown-item
command=
"remark"
>
<el-dropdown-item
command=
"remark"
>
<Icon
icon=
"ep:chat-line-square"
/>
<Icon
icon=
"ep:chat-line-square"
/>
备注
备注
...
@@ -224,6 +241,8 @@
...
@@ -224,6 +241,8 @@
<!-- 各种操作的弹窗 -->
<!-- 各种操作的弹窗 -->
<OrderDeliveryForm
ref=
"deliveryFormRef"
@
success=
"getList"
/>
<OrderDeliveryForm
ref=
"deliveryFormRef"
@
success=
"getList"
/>
<OrderUpdateRemarkForm
ref=
"updateRemarkForm"
@
success=
"getList"
/>
<OrderUpdateRemarkForm
ref=
"updateRemarkForm"
@
success=
"getList"
/>
<OrderIssueInvoiceForm
ref=
"issueInvoiceFormRef"
@
success=
"getList"
/>
<OrderViewInvoiceForm
ref=
"viewInvoiceFormRef"
@
success=
"getList"
/>
</template>
</template>
<
script
lang=
"ts"
setup
>
<
script
lang=
"ts"
setup
>
...
@@ -234,7 +253,7 @@ import * as TradeOrderApi from '@/api/mall/trade/order'
...
@@ -234,7 +253,7 @@ import * as TradeOrderApi from '@/api/mall/trade/order'
import
*
as
PickUpStoreApi
from
'@/api/mall/trade/delivery/pickUpStore'
import
*
as
PickUpStoreApi
from
'@/api/mall/trade/delivery/pickUpStore'
import
{
DICT_TYPE
,
getIntDictOptions
,
getStrDictOptions
}
from
'@/utils/dict'
import
{
DICT_TYPE
,
getIntDictOptions
,
getStrDictOptions
}
from
'@/utils/dict'
import
*
as
DeliveryExpressApi
from
'@/api/mall/trade/delivery/express'
import
*
as
DeliveryExpressApi
from
'@/api/mall/trade/delivery/express'
import
{
DeliveryTypeEnum
,
TradeOrderStatusEnum
}
from
'@/utils/constants'
import
{
DeliveryTypeEnum
,
InvoiceRequestEnum
,
TradeOrderStatusEnum
}
from
'@/utils/constants'
import
{
OrderTableColumn
}
from
'./components'
import
{
OrderTableColumn
}
from
'./components'
defineOptions
({
name
:
'TradeOrder'
})
defineOptions
({
name
:
'TradeOrder'
})
...
@@ -327,6 +346,8 @@ const openDetail = (id: number) => {
...
@@ -327,6 +346,8 @@ const openDetail = (id: number) => {
/** 操作分发 */
/** 操作分发 */
const
deliveryFormRef
=
ref
()
const
deliveryFormRef
=
ref
()
const
updateRemarkForm
=
ref
()
const
updateRemarkForm
=
ref
()
const
issueInvoiceFormRef
=
ref
()
const
viewInvoiceFormRef
=
ref
()
const
handleCommand
=
(
command
:
string
,
row
:
TradeOrderApi
.
OrderVO
)
=>
{
const
handleCommand
=
(
command
:
string
,
row
:
TradeOrderApi
.
OrderVO
)
=>
{
switch
(
command
)
{
switch
(
command
)
{
case
'remark'
:
case
'remark'
:
...
@@ -335,6 +356,12 @@ const handleCommand = (command: string, row: TradeOrderApi.OrderVO) => {
...
@@ -335,6 +356,12 @@ const handleCommand = (command: string, row: TradeOrderApi.OrderVO) => {
case
'delivery'
:
case
'delivery'
:
deliveryFormRef
.
value
?.
open
(
row
)
deliveryFormRef
.
value
?.
open
(
row
)
break
break
case
'issueInvoice'
:
issueInvoiceFormRef
.
value
?.
open
(
row
)
break
case
'viewInvoice'
:
viewInvoiceFormRef
.
value
?.
open
(
row
)
break
}
}
}
}
...
...
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