Skip to content

Commit c0522dc

Browse files
authoredJul 9, 2024··
Merge branch 'youlaitech:master' into master
2 parents cc1c260 + 2f9953d commit c0522dc

File tree

13 files changed

+513
-112
lines changed

13 files changed

+513
-112
lines changed
 

‎mock/log.mock.ts

+225
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
import { defineMock } from "./base";
2+
3+
export default defineMock([
4+
{
5+
url: "logs/page",
6+
method: ["GET"],
7+
body: {
8+
code: "00000",
9+
data: {
10+
list: [
11+
{
12+
id: 36192,
13+
module: "菜单",
14+
content: "菜单列表",
15+
requestUri: "/api/v1/menus",
16+
method: null,
17+
ip: "183.156.148.241",
18+
region: "浙江省 杭州市",
19+
browser: "Chrome 109.0.0.0",
20+
os: "OSX",
21+
executionTime: 5,
22+
createBy: null,
23+
createTime: "2024-07-07 20:38:47",
24+
operator: "系统管理员",
25+
},
26+
{
27+
id: 36190,
28+
module: "字典",
29+
content: "字典分页列表",
30+
requestUri: "/api/v1/dict/page",
31+
method: null,
32+
ip: "183.156.148.241",
33+
region: "浙江省 杭州市",
34+
browser: "Chrome 109.0.0.0",
35+
os: "OSX",
36+
executionTime: 9,
37+
createBy: null,
38+
createTime: "2024-07-07 20:38:45",
39+
operator: "系统管理员",
40+
},
41+
{
42+
id: 36193,
43+
module: "部门",
44+
content: "部门列表",
45+
requestUri: "/api/v1/dept",
46+
method: null,
47+
ip: "192.168.31.134",
48+
region: "0 内网IP",
49+
browser: "Chrome 125.0.0.0",
50+
os: "Windows 10 or Windows Server 2016",
51+
executionTime: 27,
52+
createBy: null,
53+
createTime: "2024-07-07 20:38:45",
54+
operator: "系统管理员",
55+
},
56+
{
57+
id: 36191,
58+
module: "菜单",
59+
content: "菜单列表",
60+
requestUri: "/api/v1/menus",
61+
method: null,
62+
ip: "192.168.31.134",
63+
region: "0 内网IP",
64+
browser: "Chrome 125.0.0.0",
65+
os: "Windows 10 or Windows Server 2016",
66+
executionTime: 39,
67+
createBy: null,
68+
createTime: "2024-07-07 20:38:44",
69+
operator: "系统管理员",
70+
},
71+
{
72+
id: 36189,
73+
module: "角色",
74+
content: "角色分页列表",
75+
requestUri: "/api/v1/roles/page",
76+
method: null,
77+
ip: "192.168.31.134",
78+
region: "0 内网IP",
79+
browser: "Chrome 125.0.0.0",
80+
os: "Windows 10 or Windows Server 2016",
81+
executionTime: 55,
82+
createBy: null,
83+
createTime: "2024-07-07 20:38:43",
84+
operator: "系统管理员",
85+
},
86+
{
87+
id: 36188,
88+
module: "用户",
89+
content: "用户分页列表",
90+
requestUri: "/api/v1/users/page",
91+
method: null,
92+
ip: "192.168.31.134",
93+
region: "0 内网IP",
94+
browser: "Chrome 125.0.0.0",
95+
os: "Windows 10 or Windows Server 2016",
96+
executionTime: 92,
97+
createBy: null,
98+
createTime: "2024-07-07 20:38:42",
99+
operator: "系统管理员",
100+
},
101+
{
102+
id: 36187,
103+
module: "登录",
104+
content: "登录",
105+
requestUri: "/api/v1/auth/login",
106+
method: null,
107+
ip: "192.168.31.134",
108+
region: "0 内网IP",
109+
browser: "Chrome 125.0.0.0",
110+
os: "Windows 10 or Windows Server 2016",
111+
executionTime: 19340,
112+
createBy: null,
113+
createTime: "2024-07-07 20:38:09",
114+
operator: "系统管理员",
115+
},
116+
{
117+
id: 36186,
118+
module: "登录",
119+
content: "登录",
120+
requestUri: "/api/v1/auth/login",
121+
method: null,
122+
ip: "192.168.31.134",
123+
region: "0 内网IP",
124+
browser: "Chrome 125.0.0.0",
125+
os: "Windows 10 or Windows Server 2016",
126+
executionTime: 19869,
127+
createBy: null,
128+
createTime: "2024-07-07 20:37:59",
129+
operator: "系统管理员",
130+
},
131+
{
132+
id: 36185,
133+
module: "登录",
134+
content: "登录",
135+
requestUri: "/api/v1/auth/login",
136+
method: null,
137+
ip: "112.103.111.59",
138+
region: "黑龙江省 哈尔滨市",
139+
browser: "Chrome 97.0.4692.98",
140+
os: "Android",
141+
executionTime: 96,
142+
createBy: null,
143+
createTime: "2024-07-07 20:37:21",
144+
operator: "系统管理员",
145+
},
146+
{
147+
id: 36184,
148+
module: "登录",
149+
content: "登录",
150+
requestUri: "/api/v1/auth/login",
151+
method: null,
152+
ip: "114.86.204.190",
153+
region: "上海 上海市",
154+
browser: "Chrome 125.0.0.0",
155+
os: "Windows 10 or Windows Server 2016",
156+
executionTime: 89,
157+
createBy: null,
158+
createTime: "2024-07-07 20:29:37",
159+
operator: "系统管理员",
160+
},
161+
],
162+
total: 36188,
163+
},
164+
msg: "一切ok",
165+
},
166+
},
167+
{
168+
url: "logs/visit-trend",
169+
method: ["GET"],
170+
body: {
171+
code: "00000",
172+
data: {
173+
dates: [
174+
"2024-06-30",
175+
"2024-07-01",
176+
"2024-07-02",
177+
"2024-07-03",
178+
"2024-07-04",
179+
"2024-07-05",
180+
"2024-07-06",
181+
"2024-07-07",
182+
],
183+
pvList: [1751, 5168, 4882, 5301, 4721, 4885, 1901, 1003],
184+
uvList: null,
185+
ipList: [207, 566, 565, 631, 579, 496, 222, 152],
186+
},
187+
msg: "一切ok",
188+
},
189+
},
190+
191+
{
192+
url: "logs/visit-stats",
193+
method: ["GET"],
194+
body: {
195+
code: "00000",
196+
data: [
197+
{
198+
type: "pv",
199+
title: "浏览量",
200+
todayCount: 1003,
201+
totalCount: 36193,
202+
growthRate: -0.35,
203+
granularityLabel: "日",
204+
},
205+
{
206+
type: "uv",
207+
title: "访客数",
208+
todayCount: 100,
209+
totalCount: 2000,
210+
growthRate: 0,
211+
granularityLabel: "日",
212+
},
213+
{
214+
type: "ip",
215+
title: "IP数",
216+
todayCount: 152,
217+
totalCount: 3234,
218+
growthRate: -0.2,
219+
granularityLabel: "日",
220+
},
221+
],
222+
msg: "一切ok",
223+
},
224+
},
225+
]);

‎mock/menu.mock.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export default defineMock([
2626
name: "User",
2727
meta: {
2828
title: "用户管理",
29-
icon: "user",
29+
icon: "el-icon-User",
3030
hidden: false,
3131
keepAlive: true,
3232
alwaysShow: false,
@@ -144,7 +144,7 @@ export default defineMock([
144144
name: "Https://juejin.cn/post/7228990409909108793",
145145
meta: {
146146
title: "平台文档(外链)",
147-
icon: "link",
147+
icon: "el-icon-Link",
148148
hidden: false,
149149
alwaysShow: false,
150150
params: null,
@@ -443,7 +443,7 @@ export default defineMock([
443443
component: "system/user/index",
444444
sort: 1,
445445
visible: 1,
446-
icon: "user",
446+
icon: "el-icon-User",
447447
redirect: null,
448448
perm: null,
449449
children: [

‎mock/stats.mock.ts

-27
This file was deleted.

‎package.json

+16-16
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,8 @@
5252
"animate.css": "^4.1.1",
5353
"axios": "^1.7.2",
5454
"color": "^4.2.3",
55-
"echarts": "^5.5.0",
56-
"element-plus": "^2.7.5",
55+
"echarts": "^5.5.1",
56+
"element-plus": "^2.7.6",
5757
"exceljs": "^4.4.0",
5858
"lodash-es": "^4.17.21",
5959
"net": "^1.0.2",
@@ -64,24 +64,24 @@
6464
"sockjs-client": "1.6.1",
6565
"sortablejs": "^1.15.2",
6666
"stompjs": "^2.3.3",
67-
"vue": "^3.4.29",
67+
"vue": "^3.4.31",
6868
"vue-i18n": "9.9.1",
69-
"vue-router": "^4.3.3"
69+
"vue-router": "^4.4.0"
7070
},
7171
"devDependencies": {
7272
"@commitlint/cli": "^18.6.1",
7373
"@commitlint/config-conventional": "^18.6.3",
7474
"@iconify-json/ep": "^1.1.15",
7575
"@types/color": "^3.0.6",
76-
"@types/lodash": "^4.17.5",
77-
"@types/node": "^20.14.3",
76+
"@types/lodash": "^4.17.6",
77+
"@types/node": "^20.14.10",
7878
"@types/nprogress": "^0.2.3",
7979
"@types/path-browserify": "^1.0.2",
8080
"@types/sockjs-client": "^1.5.4",
8181
"@types/sortablejs": "^1.15.8",
8282
"@types/stompjs": "^2.3.9",
83-
"@typescript-eslint/eslint-plugin": "^7.13.1",
84-
"@typescript-eslint/parser": "^7.13.1",
83+
"@typescript-eslint/eslint-plugin": "^7.15.0",
84+
"@typescript-eslint/parser": "^7.15.0",
8585
"@vitejs/plugin-vue": "^5.0.5",
8686
"@vitejs/plugin-vue-jsx": "^3.1.0",
8787
"autoprefixer": "^10.4.19",
@@ -91,11 +91,11 @@
9191
"eslint-config-prettier": "^9.1.0",
9292
"eslint-plugin-import": "^2.29.1",
9393
"eslint-plugin-prettier": "^5.1.3",
94-
"eslint-plugin-vue": "^9.26.0",
94+
"eslint-plugin-vue": "^9.27.0",
9595
"fast-glob": "^3.3.2",
9696
"husky": "^9.0.11",
9797
"lint-staged": "^15.2.7",
98-
"postcss": "^8.4.38",
98+
"postcss": "^8.4.39",
9999
"postcss-html": "^1.7.0",
100100
"postcss-scss": "^4.0.9",
101101
"prettier": "^3.3.2",
@@ -105,18 +105,18 @@
105105
"stylelint-config-recess-order": "^4.6.0",
106106
"stylelint-config-recommended-scss": "^14.0.0",
107107
"stylelint-config-recommended-vue": "^1.5.0",
108-
"stylelint-config-standard": "^36.0.0",
108+
"stylelint-config-standard": "^36.0.1",
109109
"terser": "^5.31.1",
110-
"typescript": "^5.4.5",
110+
"typescript": "^5.5.3",
111111
"unocss": "^0.58.9",
112112
"unplugin-auto-import": "^0.17.6",
113113
"unplugin-icons": "^0.18.5",
114114
"unplugin-vue-components": "^0.26.0",
115-
"vite": "^5.3.1",
116-
"vite-plugin-mock-dev-server": "^1.5.0",
115+
"vite": "^5.3.3",
116+
"vite-plugin-mock-dev-server": "^1.5.1",
117117
"vite-plugin-svg-icons": "^2.0.1",
118-
"vite-plugin-vue-devtools": "^7.3.0",
119-
"vue-tsc": "^2.0.21"
118+
"vite-plugin-vue-devtools": "^7.3.5",
119+
"vue-tsc": "^2.0.26"
120120
},
121121
"repository": "https://gitee.com/youlaiorg/vue3-element-admin.git",
122122
"author": "有来开源组织",

‎src/assets/icons/collapse.svg

+1
Loading

‎src/components/GithubCorner/index.vue

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<template>
22
<a
3-
href="https://github.com/haoxianrui"
3+
href="https://github.com/youlaitech"
44
target="_blank"
55
class="github-corner"
66
aria-label="View source on Github"

‎src/components/Hamburger/index.vue

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
<svg-icon
77
class="hamburger"
88
:class="{ 'is-active': isActive }"
9-
icon-class="indent-decrease"
9+
icon-class="collapse"
1010
/>
1111
</div>
1212
</template>

‎src/enums/MessageTypeEnum.ts

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/* 消息类型枚举 */
2+
export const enum MessageTypeEnum {
3+
/* 消息 */
4+
MESSAGE = "MESSAGE",
5+
/* 通知 */
6+
NOTICE = "NOTICE",
7+
/* 待办 */
8+
TODO = "TODO",
9+
}
10+
11+
export const MessageTypeLabels = {
12+
[MessageTypeEnum.MESSAGE]: "消息",
13+
[MessageTypeEnum.NOTICE]: "通知",
14+
[MessageTypeEnum.TODO]: "待办",
15+
};

‎src/enums/NoticeTypeEnum.ts

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/* 通知类型枚举 */
2+
export const enum NoticeTypeEnum {
3+
/** 系统升级 */
4+
SYSTEM_UPGRADE = "SYSTEM_UPGRADE",
5+
/** 系统维护 */
6+
SYSTEM_MAINTENANCE = "SYSTEM_MAINTENANCE",
7+
/** 安全警告 */
8+
SECURITY_ALERT = "SECURITY_ALERT",
9+
/** 假期通知 */
10+
HOLIDAY_NOTICE = "HOLIDAY_NOTICE",
11+
/** 公司新闻 */
12+
COMPANY_NEWS = "COMPANY_NEWS",
13+
/** 其他通知 */
14+
OTHER = "OTHER",
15+
}
16+
17+
// 定义标签映射
18+
const NoticeTypeLabels: Record<NoticeTypeEnum, string> = {
19+
[NoticeTypeEnum.SYSTEM_UPGRADE]: "系统升级",
20+
[NoticeTypeEnum.SYSTEM_MAINTENANCE]: "系统维护",
21+
[NoticeTypeEnum.SECURITY_ALERT]: "安全警告",
22+
[NoticeTypeEnum.HOLIDAY_NOTICE]: "假期通知",
23+
[NoticeTypeEnum.COMPANY_NEWS]: "公司新闻",
24+
[NoticeTypeEnum.OTHER]: "其他通知",
25+
};
26+
27+
// 导出获取标签函数
28+
export const getNoticeLabel = (type: NoticeTypeEnum): string => {
29+
return NoticeTypeLabels[type] || "";
30+
};

‎src/layout/components/NavBar/components/NavbarAction.vue

+96-11
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,47 @@
2020
<!-- 语言选择 -->
2121
<lang-select class="nav-action-item" />
2222

23+
<!-- 消息通知 -->
2324
<el-dropdown class="message nav-action-item" trigger="click">
2425
<el-badge is-dot>
25-
<i-ep-bell />
26+
<div class="flex-center h100% p10px">
27+
<i-ep-bell />
28+
</div>
2629
</el-badge>
30+
<template #dropdown>
31+
<div class="px-5 py-2">
32+
<el-tabs v-model="activeTab">
33+
<el-tab-pane
34+
v-for="(label, key) in MessageTypeLabels"
35+
:label="label"
36+
:name="key"
37+
:key="key"
38+
>
39+
<div
40+
class="w-[380px] py-2"
41+
v-for="message in getFilteredMessages(key)"
42+
:key="message.id"
43+
>
44+
<el-link type="primary">
45+
<el-text class="w-350px" size="default" truncated>
46+
{{ message.title }}</el-text
47+
>
48+
</el-link>
49+
</div>
50+
</el-tab-pane>
51+
</el-tabs>
52+
<el-divider />
53+
<div class="flex-x-between">
54+
<el-link type="primary" :underline="false">
55+
<span class="text-xs">查看更多</span
56+
><el-icon class="text-xs"><ArrowRight /></el-icon
57+
></el-link>
58+
<el-link type="primary" :underline="false">
59+
<span class="text-xs">全部已读</span></el-link
60+
>
61+
</div>
62+
</div>
63+
</template>
2764
</el-dropdown>
2865
</template>
2966

@@ -71,6 +108,7 @@ import {
71108
} from "@/store";
72109
import defaultSettings from "@/settings";
73110
import { DeviceEnum } from "@/enums/DeviceEnum";
111+
import { MessageTypeEnum, MessageTypeLabels } from "@/enums/MessageTypeEnum";
74112
75113
const appStore = useAppStore();
76114
const tagsViewStore = useTagsViewStore();
@@ -84,9 +122,49 @@ const isMobile = computed(() => appStore.device === DeviceEnum.MOBILE);
84122
85123
const { isFullscreen, toggle } = useFullscreen();
86124
87-
/**
88-
* 注销
89-
*/
125+
const activeTab = ref(MessageTypeEnum.MESSAGE);
126+
127+
const messages = ref([
128+
{
129+
id: 1,
130+
title: "系统升级通知:服务器将于今晚12点进行升级维护,请提前保存工作内容。",
131+
type: MessageTypeEnum.MESSAGE,
132+
},
133+
{
134+
id: 2,
135+
title: "新功能发布:我们的应用程序现在支持多语言功能。",
136+
type: MessageTypeEnum.MESSAGE,
137+
},
138+
{
139+
id: 3,
140+
title: "重要提醒:请定期更改您的密码以保证账户安全。",
141+
type: MessageTypeEnum.MESSAGE,
142+
},
143+
{
144+
id: 4,
145+
title: "通知:您有一条未读的系统消息,请及时查看。",
146+
type: MessageTypeEnum.NOTICE,
147+
},
148+
{
149+
id: 5,
150+
title: "新订单通知:您有一笔新的订单需要处理。",
151+
type: MessageTypeEnum.NOTICE,
152+
},
153+
{
154+
id: 6,
155+
title: "审核提醒:您的审核请求已被批准。",
156+
type: MessageTypeEnum.NOTICE,
157+
},
158+
{ id: 7, title: "待办事项:完成用户权限设置。", type: MessageTypeEnum.TODO },
159+
{ id: 8, title: "待办事项:更新产品列表。", type: MessageTypeEnum.TODO },
160+
{ id: 9, title: "待办事项:备份数据库。", type: MessageTypeEnum.TODO },
161+
]);
162+
163+
const getFilteredMessages = (type: MessageTypeEnum) => {
164+
return messages.value.filter((message) => message.type === type);
165+
};
166+
167+
/* 注销 */
90168
function logout() {
91169
ElMessageBox.confirm("确定注销并退出系统吗?", "提示", {
92170
confirmButtonText: "确定",
@@ -121,18 +199,25 @@ function logout() {
121199
}
122200
123201
:deep(.message .el-badge__content.is-fixed.is-dot) {
124-
top: 10px;
202+
top: 5px;
203+
right: 10px;
125204
}
126205
127-
.layout-top,
128-
.layout-mix {
129-
.nav-action-item,
130-
.el-icon {
131-
color: var(--el-color-white);
132-
}
206+
:deep(.el-divider--horizontal) {
207+
margin: 10px 0;
133208
}
134209
135210
.dark .nav-action-item:hover {
136211
background: rgb(255 255 255 / 20%);
137212
}
213+
214+
.see-more {
215+
padding: 10px 0;
216+
text-align: center;
217+
}
218+
219+
.see-more a {
220+
color: var(--el-color-primary);
221+
text-decoration: none;
222+
}
138223
</style>

‎src/views/dashboard/components/VisitTrend.vue

+4-4
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
访问趋势
88
<el-tooltip effect="dark" content="点击试试下载" placement="bottom">
99
<i-ep-download
10-
class="cursor-pointer hover:color-#409eff ml-2"
10+
class="cursor-pointer hover:color-#409eff ml-1"
1111
@click="handleDownloadChart"
1212
/>
1313
</el-tooltip>
@@ -95,7 +95,7 @@ const setChartOptions = (data: VisitTrendVO) => {
9595
type: "line",
9696
data: data.pvList,
9797
areaStyle: {
98-
color: "rgba(64, 158, 255, 0.3)",
98+
color: "rgba(64, 158, 255, 0.1)",
9999
},
100100
smooth: true,
101101
itemStyle: {
@@ -110,7 +110,7 @@ const setChartOptions = (data: VisitTrendVO) => {
110110
type: "line",
111111
data: data.ipList,
112112
areaStyle: {
113-
color: "rgba(103, 194, 58, 0.3)",
113+
color: "rgba(103, 194, 58, 0.1)",
114114
},
115115
smooth: true,
116116
itemStyle: {
@@ -187,7 +187,7 @@ const handleDownloadChart = () => {
187187
if (ctx) {
188188
ctx.drawImage(img, 0, 0, img.width, img.height);
189189
const link = document.createElement("a");
190-
link.download = `业绩柱状图.png`;
190+
link.download = `访问趋势.png`;
191191
link.href = canvas.toDataURL("image/png", 0.9);
192192
document.body.appendChild(link);
193193
link.click();

‎src/views/dashboard/index.vue

+117-49
Original file line numberDiff line numberDiff line change
@@ -69,17 +69,20 @@
6969
v-for="(item, index) in visitStatsList"
7070
:key="index"
7171
>
72-
<el-skeleton :loading="loading" :rows="5" animated>
72+
<el-skeleton :loading="visitStatsLoading" :rows="5" animated>
7373
<template #template>
7474
<el-card>
75-
<div>
76-
<el-skeleton-item variant="h3" style="width: 40%" />
77-
<el-skeleton-item
78-
variant="rect"
79-
style="float: right; width: 1em; height: 1em"
80-
/>
81-
</div>
82-
<div class="mt-10 flex-x-between">
75+
<template #header>
76+
<div>
77+
<el-skeleton-item variant="h3" style="width: 40%" />
78+
<el-skeleton-item
79+
variant="rect"
80+
style="float: right; width: 1em; height: 1em"
81+
/>
82+
</div>
83+
</template>
84+
85+
<div class="flex-x-between">
8386
<el-skeleton-item variant="text" style="width: 30%" />
8487
<el-skeleton-item
8588
variant="circle"
@@ -92,7 +95,7 @@
9295
</div>
9396
</el-card>
9497
</template>
95-
<template v-if="!loading">
98+
<template v-if="!visitStatsLoading">
9699
<el-card shadow="never">
97100
<template #header>
98101
<div class="flex-x-between">
@@ -135,22 +138,43 @@
135138
</el-col>
136139
</el-row>
137140

138-
<!-- Echarts 图表 -->
139141
<el-row :gutter="10" class="mt-5">
140142
<el-col :xs="24" :span="16">
143+
<!-- 访问趋势统计图 -->
141144
<VisitTrend id="VisitTrend" width="100%" height="400px" />
142145
</el-col>
143146
<el-col :xs="24" :span="8">
144147
<el-card>
145148
<template #header>
146-
<span> 通知公告</span>
149+
<div class="flex-x-between">
150+
<div class="flex-y-center">
151+
通知公告<el-icon class="ml-1"><Notification /></el-icon>
152+
</div>
153+
<el-link type="primary">
154+
<span class="text-xs">查看更多</span
155+
><el-icon class="text-xs"><ArrowRight /></el-icon
156+
></el-link>
157+
</div>
147158
</template>
148159

149160
<el-scrollbar height="400px">
150-
<div v-for="(item, index) in notices" :key="index" class="mb-2">
151-
<el-alert :title="item.title" :closable="false" class="mb-2">
152-
<template #default>{{ item.description }} </template>
153-
</el-alert>
161+
<div
162+
v-for="(item, index) in notices"
163+
:key="index"
164+
class="flex-y-center py-3"
165+
>
166+
<el-tag :type="getNoticeLevelTag(item.level)" size="small">
167+
{{ getNoticeLabel(item.type) }}
168+
</el-tag>
169+
<el-text
170+
truncated
171+
class="!mx-2 flex-1 !text-xs !text-[var(--el-text-color-secondary)]"
172+
>
173+
{{ item.title }}
174+
</el-text>
175+
<el-link>
176+
<el-icon class="text-sm"><View /></el-icon>
177+
</el-link>
154178
</div>
155179
</el-scrollbar>
156180
</el-card>
@@ -166,7 +190,7 @@ defineOptions({
166190
});
167191
168192
import { useUserStore } from "@/store/modules/user";
169-
import { useTransition, TransitionPresets } from "@vueuse/core";
193+
import { NoticeTypeEnum, getNoticeLabel } from "@/enums/NoticeTypeEnum";
170194
171195
import StatsAPI, { VisitStatsVO } from "@/api/log";
172196
const userStore = useUserStore();
@@ -210,37 +234,8 @@ const statisticData = ref([
210234
},
211235
]);
212236
213-
const notices = ref([
214-
{
215-
title: "v2.12.0",
216-
description: "新增系统日志,访问趋势统计等功能。",
217-
},
218-
{
219-
title: "v2.11.5",
220-
description: "修复了一些问题,优化了一些代码。",
221-
},
222-
{
223-
title: "v2.11.4",
224-
description: "修复了一些问题,优化了一些代码。",
225-
},
226-
{
227-
title: "v2.11.3",
228-
description: "修复了一些问题,优化了一些代码。",
229-
},
230-
{
231-
title: "v2.11.2",
232-
description: "修复了一些问题,优化了一些代码。",
233-
},
234-
{
235-
title: "v2.11.1",
236-
description: "修复了一些问题,优化了一些代码。",
237-
},
238-
]);
239-
240-
const loading = ref(true);
241-
237+
const visitStatsLoading = ref(true);
242238
const visitStatsList = ref<VisitStats[] | null>(Array(3).fill({}));
243-
244239
interface VisitStats {
245240
title: string;
246241
icon: string;
@@ -252,7 +247,7 @@ interface VisitStats {
252247
todayCount: number;
253248
totalCount: number;
254249
}
255-
250+
/** 加载访问统计数据 */
256251
const loadVisitStatsData = async () => {
257252
const list: VisitStatsVO[] = await StatsAPI.getVisitStats();
258253
@@ -272,7 +267,7 @@ const loadVisitStatsData = async () => {
272267
totalCount: item.totalCount,
273268
}));
274269
visitStatsList.value = transformedList;
275-
loading.value = false;
270+
visitStatsLoading.value = false;
276271
}
277272
};
278273
@@ -313,6 +308,79 @@ const getVisitStatsIcon = (type: string) => {
313308
}
314309
};
315310
311+
const notices = ref([
312+
{
313+
level: 2,
314+
type: NoticeTypeEnum.SYSTEM_UPGRADE,
315+
title: "v2.12.0 新增系统日志,访问趋势统计功能。",
316+
},
317+
{
318+
level: 0,
319+
type: NoticeTypeEnum.COMPANY_NEWS,
320+
title: "公司将在 7 月 1 日举办年中总结大会,请各部门做好准备。",
321+
},
322+
{
323+
level: 3,
324+
type: NoticeTypeEnum.HOLIDAY_NOTICE,
325+
title: "端午节假期从 6 月 12 日至 6 月 14 日放假,共 3 天。",
326+
},
327+
328+
{
329+
level: 2,
330+
type: NoticeTypeEnum.SECURITY_ALERT,
331+
title: "最近发现一些钓鱼邮件,请大家提高警惕,不要点击陌生链接。",
332+
},
333+
{
334+
level: 2,
335+
type: NoticeTypeEnum.SYSTEM_MAINTENANCE,
336+
title: "系统将于本周六凌晨 2 点进行维护,预计维护时间为 2 小时。",
337+
},
338+
{
339+
level: 0,
340+
type: NoticeTypeEnum.OTHER,
341+
title: "公司新规章制度发布,请大家及时查阅。",
342+
},
343+
{
344+
level: 3,
345+
type: NoticeTypeEnum.HOLIDAY_NOTICE,
346+
title: "中秋节假期从 9 月 22 日至 9 月 24 日放假,共 3 天。",
347+
},
348+
{
349+
level: 1,
350+
type: NoticeTypeEnum.COMPANY_NEWS,
351+
title: "公司将在 10 月 15 日举办新产品发布会,敬请期待。",
352+
},
353+
{
354+
level: 2,
355+
type: NoticeTypeEnum.SECURITY_ALERT,
356+
title:
357+
"请注意,近期有恶意软件通过即时通讯工具传播,请勿下载不明来源的文件。",
358+
},
359+
{
360+
level: 2,
361+
type: NoticeTypeEnum.SYSTEM_MAINTENANCE,
362+
title: "系统将于下周日凌晨 3 点进行升级,预计维护时间为 1 小时。",
363+
},
364+
{
365+
level: 3,
366+
type: NoticeTypeEnum.OTHER,
367+
title: "公司年度体检通知已发布,请各位员工按时参加。",
368+
},
369+
]);
370+
371+
const getNoticeLevelTag = (type: number) => {
372+
switch (type) {
373+
case 0:
374+
return "danger";
375+
case 1:
376+
return "warning";
377+
case 2:
378+
return "primary";
379+
default:
380+
return "success";
381+
}
382+
};
383+
316384
onMounted(() => {
317385
loadVisitStatsData();
318386
});

‎vite.config.ts

+4
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,10 @@ export default defineConfig(({ mode }: ConfigEnv): UserConfig => {
201201
"element-plus/es/components/color-picker/style/css",
202202
"element-plus/es/components/backtop/style/css",
203203
"element-plus/es/components/message-box/style/css",
204+
"element-plus/es/components/skeleton/style/css",
205+
"element-plus/es/components/skeleton/style/css",
206+
"element-plus/es/components/skeleton-item/style/css",
207+
"element-plus/es/components/badge/style/css",
204208
],
205209
},
206210
// 构建配置

0 commit comments

Comments
 (0)
Please sign in to comment.