vue3-admin-gpt 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. package/.env.development +14 -0
  2. package/.env.production +14 -0
  3. package/LICENSE +21 -0
  4. package/README.en.md +106 -0
  5. package/README.md +104 -0
  6. package/build-zip.cjs +53 -0
  7. package/cli.js +110 -0
  8. package/jsconfig.json +9 -0
  9. package/package.json +92 -0
  10. package/public/index.html +20 -0
  11. package/public/robots.txt +2 -0
  12. package/rspack.config.js +282 -0
  13. package/rspack.js +162 -0
  14. package/src/App.vue +9 -0
  15. package/src/api/icon.js +9 -0
  16. package/src/api/router.js +9 -0
  17. package/src/api/table.js +25 -0
  18. package/src/api/tree.js +9 -0
  19. package/src/api/user.js +34 -0
  20. package/src/assets/error_images/401.png +0 -0
  21. package/src/assets/error_images/404.png +0 -0
  22. package/src/assets/error_images/cloud.png +0 -0
  23. package/src/assets/login_images/background.jpg +0 -0
  24. package/src/assets/logo.png +0 -0
  25. package/src/assets/qr_logo/lqr_logo.png +0 -0
  26. package/src/assets/vuejs-fill.svg +4 -0
  27. package/src/components/VabPageHeader/index.vue +133 -0
  28. package/src/config/index.js +7 -0
  29. package/src/config/net.config.js +20 -0
  30. package/src/config/permission.js +136 -0
  31. package/src/config/setting.config.js +62 -0
  32. package/src/config/settings.js +6 -0
  33. package/src/config/theme.config.js +14 -0
  34. package/src/layouts/EmptyLayout.vue +3 -0
  35. package/src/layouts/components/VabAppMain/index.vue +109 -0
  36. package/src/layouts/components/VabAvatar/index.vue +255 -0
  37. package/src/layouts/components/VabBreadcrumb/index.vue +61 -0
  38. package/src/layouts/components/VabFullScreen/index.vue +61 -0
  39. package/src/layouts/components/VabLogo/index.vue +94 -0
  40. package/src/layouts/components/VabNav/index.vue +176 -0
  41. package/src/layouts/components/VabSide/components/VabMenuItem.vue +80 -0
  42. package/src/layouts/components/VabSide/components/VabSideItem.vue +100 -0
  43. package/src/layouts/components/VabSide/components/VabSubmenu.vue +56 -0
  44. package/src/layouts/components/VabSide/index.vue +123 -0
  45. package/src/layouts/components/VabTabs/index.vue +500 -0
  46. package/src/layouts/components/VabTheme/index.vue +603 -0
  47. package/src/layouts/components/VabTop/index.vue +286 -0
  48. package/src/layouts/export.js +29 -0
  49. package/src/layouts/index.vue +339 -0
  50. package/src/main.js +40 -0
  51. package/src/plugins/echarts.js +4 -0
  52. package/src/plugins/index.js +44 -0
  53. package/src/plugins/support.js +16 -0
  54. package/src/router/index.js +400 -0
  55. package/src/store/index.js +26 -0
  56. package/src/store/modules/errorLog.js +27 -0
  57. package/src/store/modules/routes.js +60 -0
  58. package/src/store/modules/settings.js +73 -0
  59. package/src/store/modules/table.js +22 -0
  60. package/src/store/modules/tabsBar.js +109 -0
  61. package/src/store/modules/user.js +131 -0
  62. package/src/styles/element-variables.scss +13 -0
  63. package/src/styles/loading.scss +345 -0
  64. package/src/styles/nav-icons.scss +52 -0
  65. package/src/styles/normalize.scss +353 -0
  66. package/src/styles/spinner/dots.css +68 -0
  67. package/src/styles/spinner/gauge.css +104 -0
  68. package/src/styles/spinner/inner-circles.css +51 -0
  69. package/src/styles/spinner/plus.css +341 -0
  70. package/src/styles/themes/default.scss +1 -0
  71. package/src/styles/transition.scss +18 -0
  72. package/src/styles/vab.scss +476 -0
  73. package/src/styles/variables.scss +69 -0
  74. package/src/utils/accessToken.js +56 -0
  75. package/src/utils/eventBus.js +8 -0
  76. package/src/utils/handleRoutes.js +100 -0
  77. package/src/utils/index.js +231 -0
  78. package/src/utils/message.js +67 -0
  79. package/src/utils/pageTitle.js +11 -0
  80. package/src/utils/password.js +43 -0
  81. package/src/utils/permission.js +19 -0
  82. package/src/utils/request.js +187 -0
  83. package/src/utils/static.js +81 -0
  84. package/src/utils/vab.js +218 -0
  85. package/src/utils/validate.js +48 -0
  86. package/src/views/401.vue +302 -0
  87. package/src/views/404.vue +302 -0
  88. package/src/views/demo/index.vue +591 -0
  89. package/src/views/index/index.vue +1489 -0
  90. package/src/views/login/index.vue +456 -0
  91. package/src/views/register/index.vue +524 -0
  92. package/src/views/vab/calendar.vue +488 -0
  93. package/src/views/vab/campaign.vue +1006 -0
  94. package/src/views/vab/chart.vue +189 -0
  95. package/src/views/vab/customer.vue +666 -0
  96. package/src/views/vab/editor.vue +84 -0
  97. package/src/views/vab/form.vue +151 -0
  98. package/src/views/vab/help.vue +390 -0
  99. package/src/views/vab/icon.vue +113 -0
  100. package/src/views/vab/knowledge.vue +820 -0
  101. package/src/views/vab/nested/menu1/menu2/menu3.vue +29 -0
  102. package/src/views/vab/nested/menu1/menu2.vue +33 -0
  103. package/src/views/vab/nested/menu1.vue +33 -0
  104. package/src/views/vab/nested.vue +97 -0
  105. package/src/views/vab/notification.vue +416 -0
  106. package/src/views/vab/order.vue +507 -0
  107. package/src/views/vab/permissions.vue +214 -0
  108. package/src/views/vab/product.vue +724 -0
  109. package/src/views/vab/project.vue +559 -0
  110. package/src/views/vab/settings.vue +319 -0
  111. package/src/views/vab/statistics.vue +431 -0
  112. package/src/views/vab/table.vue +110 -0
  113. package/src/views/vab/task.vue +613 -0
  114. package/src/views/vab/team.vue +662 -0
  115. package/src/views/vab/tree.vue +44 -0
  116. package/src/views/vab/upload.vue +180 -0
  117. package/src/views/vab/vue3Demo/index.vue +103 -0
  118. package/src/views/vab/workflow.vue +863 -0
@@ -0,0 +1,109 @@
1
+ /**
2
+ * @description tabsBar多标签页逻辑,前期借鉴了很多开源项目发现都有个共同的特点很繁琐并不符合框架设计的初衷,后来在github用户hipi的启发下完成了重构,请勿修改
3
+ */
4
+
5
+ const state = () => ({
6
+ visitedRoutes: [],
7
+ })
8
+ const getters = {
9
+ visitedRoutes: (state) => state.visitedRoutes,
10
+ }
11
+ const mutations = {
12
+ addVisitedRoute(state, route) {
13
+ let target = state.visitedRoutes.find((item) => item.path === route.path)
14
+ if (target) {
15
+ if (route.fullPath !== target.fullPath) Object.assign(target, route)
16
+ return
17
+ }
18
+ state.visitedRoutes.push(Object.assign({}, route))
19
+ },
20
+ delVisitedRoute(state, route) {
21
+ state.visitedRoutes.forEach((item, index) => {
22
+ if (item.path === route.path) state.visitedRoutes.splice(index, 1)
23
+ })
24
+ },
25
+ delOthersVisitedRoute(state, route) {
26
+ state.visitedRoutes = state.visitedRoutes.filter((item) => item.meta.affix || item.path === route.path)
27
+ },
28
+ delLeftVisitedRoute(state, route) {
29
+ let index = state.visitedRoutes.length
30
+ state.visitedRoutes = state.visitedRoutes.filter((item) => {
31
+ if (item.name === route.name) index = state.visitedRoutes.indexOf(item)
32
+ return item.meta.affix || index <= state.visitedRoutes.indexOf(item)
33
+ })
34
+ },
35
+ delRightVisitedRoute(state, route) {
36
+ let index = state.visitedRoutes.length
37
+ state.visitedRoutes = state.visitedRoutes.filter((item) => {
38
+ if (item.name === route.name) index = state.visitedRoutes.indexOf(item)
39
+ return item.meta.affix || index >= state.visitedRoutes.indexOf(item)
40
+ })
41
+ },
42
+ delAllVisitedRoutes(state) {
43
+ state.visitedRoutes = state.visitedRoutes.filter((item) => item.meta.affix)
44
+ },
45
+ updateVisitedRoute(state, route) {
46
+ state.visitedRoutes.forEach((item) => {
47
+ if (item.path === route.path) item = Object.assign(item, route)
48
+ })
49
+ },
50
+ }
51
+ const actions = {
52
+ addVisitedRoute({ commit }, route) {
53
+ commit('addVisitedRoute', route)
54
+ },
55
+ async delRoute({ dispatch, state }, route) {
56
+ await dispatch('delVisitedRoute', route)
57
+ return {
58
+ visitedRoutes: [...state.visitedRoutes],
59
+ }
60
+ },
61
+ delVisitedRoute({ commit, state }, route) {
62
+ commit('delVisitedRoute', route)
63
+ return [...state.visitedRoutes]
64
+ },
65
+ async delOthersRoutes({ dispatch, state }, route) {
66
+ await dispatch('delOthersVisitedRoute', route)
67
+ return {
68
+ visitedRoutes: [...state.visitedRoutes],
69
+ }
70
+ },
71
+ async delLeftRoutes({ dispatch, state }, route) {
72
+ await dispatch('delLeftVisitedRoute', route)
73
+ return {
74
+ visitedRoutes: [...state.visitedRoutes],
75
+ }
76
+ },
77
+ async delRightRoutes({ dispatch, state }, route) {
78
+ await dispatch('delRightVisitedRoute', route)
79
+ return {
80
+ visitedRoutes: [...state.visitedRoutes],
81
+ }
82
+ },
83
+ delOthersVisitedRoute({ commit, state }, route) {
84
+ commit('delOthersVisitedRoute', route)
85
+ return [...state.visitedRoutes]
86
+ },
87
+ delLeftVisitedRoute({ commit, state }, route) {
88
+ commit('delLeftVisitedRoute', route)
89
+ return [...state.visitedRoutes]
90
+ },
91
+ delRightVisitedRoute({ commit, state }, route) {
92
+ commit('delRightVisitedRoute', route)
93
+ return [...state.visitedRoutes]
94
+ },
95
+ async delAllRoutes({ dispatch, state }, route) {
96
+ await dispatch('delAllVisitedRoutes', route)
97
+ return {
98
+ visitedRoutes: [...state.visitedRoutes],
99
+ }
100
+ },
101
+ delAllVisitedRoutes({ commit, state }) {
102
+ commit('delAllVisitedRoutes')
103
+ return [...state.visitedRoutes]
104
+ },
105
+ updateVisitedRoute({ commit }, route) {
106
+ commit('updateVisitedRoute', route)
107
+ },
108
+ }
109
+ export default { state, getters, mutations, actions }
@@ -0,0 +1,131 @@
1
+ /**
2
+ * @description 登录、获取用户信息、退出登录、清除accessToken逻辑,不建议修改
3
+ */
4
+
5
+ // 默认头像列表
6
+ const defaultAvatars = [
7
+ "https://oss.gempharmatech.com/upload/file/20230918/0e900403-d8bc-4fc8-ae25-8eeeaa8df6e0.png",
8
+ "https://oss.gempharmatech.com/upload/file/20230918/246c4a2d-2e6e-41eb-890a-2cf1ba6b4744.png",
9
+ "https://oss.gempharmatech.com/upload/file/20230918/3f0a875a-502b-45bc-b26f-a2cb85477a31.png",
10
+ "https://oss.gempharmatech.com/upload/file/20230918/9345aac3-dcb7-4db3-a4ce-2a8dd258a753.png",
11
+ "https://oss.gempharmatech.com/upload/file/20230918/4f952091-6de6-464c-a1a6-12d7d5b51afb.png",
12
+ "https://oss.gempharmatech.com/upload/file/20230918/6d214d7b-bf3f-4dae-a94b-5606e94185c8.png",
13
+ "https://oss.gempharmatech.com/upload/file/20230918/60d7acc8-e9ca-4ad1-856a-d2af64e4451c.png",
14
+ "https://oss.gempharmatech.com/upload/file/20230918/50e58f52-379f-447f-9d85-ac2d7647571c.png",
15
+ "https://oss.gempharmatech.com/upload/file/20230918/9858572c-3573-465e-8a53-448ee49fb581.png",
16
+ "https://oss.gempharmatech.com/upload/file/20230918/247a199b-b69e-42b4-83e4-7f3ef76abe36.png",
17
+ "https://oss.gempharmatech.com/upload/file/20230918/e7f32c72-187c-47ed-894a-f25227711da2.png",
18
+ "https://oss.gempharmatech.com/upload/file/20230918/51d19975-d527-43ed-8cb3-afa3bf0ea7d2.png",
19
+ "https://oss.gempharmatech.com/upload/file/20230918/537a52d8-7d5e-41b9-ae3b-1a656c2971b3.png",
20
+ "https://oss.gempharmatech.com/upload/file/20230918/13812b25-f42f-4826-a2eb-ad7166a9b668.png"
21
+ ];
22
+
23
+ // 随机获取一个默认头像
24
+ const getRandomAvatar = () => {
25
+ return defaultAvatars[Math.floor(Math.random() * defaultAvatars.length)];
26
+ };
27
+
28
+ import { getUserInfo, login, logout } from "@/api/user";
29
+ import {
30
+ getAccessToken,
31
+ removeAccessToken,
32
+ setAccessToken,
33
+ } from "@/utils/accessToken";
34
+ import {RSA} from '@/utils/password'
35
+ import { resetRouter } from "@/router";
36
+ import { title, tokenName } from "@/config";
37
+ import { ElMessage } from "element-plus";
38
+
39
+ const state = () => ({
40
+ accessToken: getAccessToken(),
41
+ username: "",
42
+ avatar: getRandomAvatar(),
43
+ permissions: [],
44
+ });
45
+ const getters = {
46
+ accessToken: (state) => state.accessToken,
47
+ username: (state) => state.username,
48
+ avatar: (state) => state.avatar,
49
+ permissions: (state) => state.permissions,
50
+ };
51
+ const mutations = {
52
+ setAccessToken(state, accessToken) {
53
+ state.accessToken = accessToken;
54
+ setAccessToken(accessToken);
55
+ },
56
+ setUsername(state, username) {
57
+ state.username = username;
58
+ },
59
+ setAvatar(state, avatar) {
60
+ state.avatar = avatar;
61
+ },
62
+ setPermissions(state, permissions) {
63
+ state.permissions = permissions;
64
+ },
65
+ };
66
+ const actions = {
67
+ setPermissions({ commit }, permissions) {
68
+ commit("setPermissions", permissions);
69
+ },
70
+ async login({ commit }, userInfo) {
71
+ // const { data } = await login(userInfo);
72
+ let params = {
73
+ customerName: userInfo.username,
74
+ password: RSA(userInfo.password),
75
+ }
76
+ const { data } = await login(params);
77
+ const accessToken = data;
78
+ if (accessToken) {
79
+ commit("setAccessToken", accessToken);
80
+ const hour = new Date().getHours();
81
+ const thisTime =
82
+ hour < 8
83
+ ? "早上好"
84
+ : hour <= 11
85
+ ? "上午好"
86
+ : hour <= 13
87
+ ? "中午好"
88
+ : hour < 18
89
+ ? "下午好"
90
+ : "晚上好";
91
+ ElMessage.success(`欢迎登录${title},${thisTime}!`);
92
+ } else {
93
+ ElMessage.error(`登录接口异常,未正确返回${tokenName}...`);
94
+ }
95
+ },
96
+ async getUserInfo({ commit, state }) {
97
+ try {
98
+ const { data } = await getUserInfo(state.accessToken);
99
+ if (!data) {
100
+ ElMessage.error("验证失败,请重新登录...");
101
+ return false;
102
+ }
103
+ let { permissions, username, avatar } = data;
104
+ if (permissions && username && Array.isArray(permissions)) {
105
+ commit("setPermissions", permissions);
106
+ commit("setUsername", username);
107
+ commit("setAvatar", avatar);
108
+ return permissions;
109
+ } else {
110
+ ElMessage.error("用户信息接口异常");
111
+ return false;
112
+ }
113
+ } catch (error) {
114
+ console.error("获取用户信息失败:", error);
115
+ ElMessage.error("获取用户信息失败,请重新登录");
116
+ return false;
117
+ }
118
+ },
119
+ async logout({ dispatch }) {
120
+ await logout(state.accessToken);
121
+ await dispatch("resetAccessToken");
122
+ await resetRouter();
123
+ location.reload();
124
+ },
125
+ resetAccessToken({ commit }) {
126
+ commit("setPermissions", []);
127
+ commit("setAccessToken", "");
128
+ removeAccessToken();
129
+ },
130
+ };
131
+ export default { state, getters, mutations, actions };
@@ -0,0 +1,13 @@
1
+ // 引入Element Plus样式
2
+ @import "element-plus/dist/index.css";
3
+
4
+ // 自定义Element Plus主题变量
5
+ :root {
6
+ --el-color-primary: #409eff;
7
+ --el-color-success: #67c23a;
8
+ --el-color-warning: #e6a23c;
9
+ --el-color-danger: #f56c6c;
10
+ --el-color-error: #f56c6c;
11
+ --el-color-info: #909399;
12
+ }
13
+
@@ -0,0 +1,345 @@
1
+ /**
2
+ * @description 全局加载动画
3
+ */
4
+
5
+ @charset "utf-8";
6
+
7
+ @import "./spinner/dots.css";
8
+ @import "./spinner/gauge.css";
9
+ @import "./spinner/inner-circles.css";
10
+ @import "./spinner/plus.css";
11
+
12
+ $base-loading: ".vab-loading-type";
13
+
14
+ /* 自定义loading开始 */
15
+ #{$base-loading}1 {
16
+ display: flex;
17
+ width: 36px;
18
+ height: 36px;
19
+ margin: 0 auto 15px;
20
+ border: 3px solid transparent;
21
+ border-top-color: $base-color-blue;
22
+ border-bottom-color: $base-color-blue;
23
+ border-radius: 50%;
24
+ animation: vabLoading1-0 0.8s linear infinite;
25
+ }
26
+
27
+ #{$base-loading}1::before {
28
+ display: block;
29
+ width: 8px;
30
+ height: 8px;
31
+ margin: auto;
32
+ content: "";
33
+ border: 3px solid $base-color-blue;
34
+ border-radius: 50%;
35
+ animation: vabLoading1 0.5s alternate ease-in infinite;
36
+ }
37
+
38
+ @keyframes vabLoading1-0 {
39
+ to {
40
+ transform: rotate(360deg);
41
+ }
42
+ }
43
+
44
+ @keyframes vabLoading1 {
45
+ from {
46
+ transform: scale(0.5);
47
+ }
48
+
49
+ to {
50
+ transform: scale(1.2);
51
+ }
52
+ }
53
+
54
+ #{$base-loading}2 {
55
+ width: 20px;
56
+ height: 20px;
57
+ margin-top: -40px;
58
+ margin-left: -10px;
59
+ animation: vabLoading2 1s linear reverse infinite;
60
+ }
61
+
62
+ #{$base-loading}2::before {
63
+ display: block;
64
+ width: 36px;
65
+ height: 36px;
66
+ margin-top: -17px;
67
+ margin-left: -18px;
68
+ content: "";
69
+ animation: vabLoading2 0.4s linear infinite;
70
+ }
71
+
72
+ #{$base-loading}2::after {
73
+ display: block;
74
+ width: 8px;
75
+ height: 8px;
76
+ margin-top: -3px;
77
+ margin-left: -4px;
78
+ content: "";
79
+ animation: vabLoading2 0.4s linear infinite;
80
+ }
81
+
82
+ #{$base-loading}2::before,
83
+ #{$base-loading}2,
84
+ #{$base-loading}2::after {
85
+ position: absolute;
86
+ top: 40%;
87
+ left: 50%;
88
+ border: 3px solid transparent;
89
+ border-top-color: $base-color-blue;
90
+ border-right-color: $base-color-blue;
91
+ border-radius: 50%;
92
+ }
93
+
94
+ @keyframes vabLoading2 {
95
+ to {
96
+ transform: rotate(360deg);
97
+ }
98
+ }
99
+
100
+ #{$base-loading}3 {
101
+ display: inline-block;
102
+ width: 2.5em;
103
+ height: 3em;
104
+ margin-bottom: 15px;
105
+ border: 3px solid transparent;
106
+ border-top-color: $base-color-blue;
107
+ border-bottom-color: $base-color-blue;
108
+ border-radius: 50%;
109
+ animation: vabLoading3 2s ease infinite;
110
+ }
111
+
112
+ @keyframes vabLoading3 {
113
+ 50% {
114
+ border-width: 8px;
115
+ transform: rotate(360deg) scale(0.4, 0.33);
116
+ }
117
+
118
+ 100% {
119
+ border-width: 3px;
120
+ transform: rotate(720deg) scale(1, 1);
121
+ }
122
+ }
123
+
124
+ #{$base-loading}4 {
125
+ display: inline-block;
126
+ width: 30px;
127
+ height: 30px;
128
+ margin: 0 auto 10px;
129
+ border: 8px solid transparent;
130
+ border-bottom-color: $base-color-blue;
131
+ border-left-color: $base-color-blue;
132
+ border-radius: 50%;
133
+ animation: vabLoading4 1s linear infinite normal;
134
+ }
135
+
136
+ #{$base-loading}4::after {
137
+ display: block;
138
+ width: 15px;
139
+ height: 15px;
140
+ margin: 0;
141
+ content: " ";
142
+ border: 6px solid $base-color-blue;
143
+ border-bottom-color: transparent;
144
+ border-left-color: transparent;
145
+ border-radius: 50%;
146
+ }
147
+
148
+ @keyframes vabLoading4 {
149
+ 0% {
150
+ opacity: 0.2;
151
+ transform: rotate(0deg);
152
+ }
153
+
154
+ 50% {
155
+ opacity: 1;
156
+ transform: rotate(180deg);
157
+ }
158
+
159
+ 100% {
160
+ opacity: 0.2;
161
+ transform: rotate(360deg);
162
+ }
163
+ }
164
+
165
+ #{$base-loading}5 {
166
+ display: block;
167
+ width: 0;
168
+ height: 0;
169
+ margin: 0 auto 15px;
170
+ border: solid 1.5em $base-color-blue;
171
+ border-right: solid 1.5em transparent;
172
+ border-left: solid 1.5em transparent;
173
+ border-radius: 100%;
174
+ animation: vabLoading5 1s linear infinite;
175
+ }
176
+
177
+ @keyframes vabLoading5 {
178
+ 0% {
179
+ transform: rotate(0deg);
180
+ }
181
+
182
+ 50% {
183
+ transform: rotate(60deg);
184
+ }
185
+
186
+ 100% {
187
+ transform: rotate(360deg);
188
+ }
189
+ }
190
+
191
+ #{$base-loading}6 {
192
+ display: block;
193
+ width: 0;
194
+ height: 0;
195
+ margin: 0 auto 25px auto;
196
+ perspective: 200px;
197
+ }
198
+
199
+ #{$base-loading}6::before,
200
+ #{$base-loading}6::after {
201
+ position: absolute;
202
+ width: 20px;
203
+ height: 20px;
204
+ content: "";
205
+ background: rgba(0, 0, 0, 0);
206
+ animation: vabLoading6 0.5s infinite alternate;
207
+ }
208
+
209
+ #{$base-loading}6::before {
210
+ left: 0;
211
+ }
212
+
213
+ #{$base-loading}6::after {
214
+ right: 0;
215
+ animation-delay: 0.15s;
216
+ }
217
+
218
+ @keyframes vabLoading6 {
219
+ 0% {
220
+ box-shadow: 0 0 0 rgba(0, 0, 0, 0);
221
+ transform: scale(1) translateY(0) rotateX(0deg);
222
+ }
223
+
224
+ 100% {
225
+ background: $base-color-blue;
226
+ box-shadow: 0 25px 40px rgba($base-color-blue, 0.5);
227
+ transform: scale(1.2) translateY(-25px) rotateX(45deg);
228
+ }
229
+ }
230
+
231
+ #{$base-loading}7 {
232
+ display: block;
233
+ width: 25px;
234
+ height: 25px;
235
+ margin: 0 auto 15px auto;
236
+ border: 2px solid $base-color-blue;
237
+ border-top-color: rgba($base-color-blue, 0.2);
238
+ border-right-color: rgba($base-color-blue, 0.2);
239
+ border-bottom-color: rgba($base-color-blue, 0.2);
240
+ border-radius: 100%;
241
+ animation: vabLoading7 infinite 0.75s linear;
242
+ }
243
+
244
+ @keyframes vabLoading7 {
245
+ 0% {
246
+ transform: rotate(0);
247
+ }
248
+
249
+ 100% {
250
+ transform: rotate(360deg);
251
+ }
252
+ }
253
+
254
+ #{$base-loading}8 {
255
+ position: relative;
256
+ box-sizing: border-box;
257
+ display: block;
258
+ width: 20px;
259
+ height: 20px;
260
+ margin: 0 auto 15px auto;
261
+ background-color: $base-color-blue;
262
+ border-radius: 50%;
263
+ box-shadow: 30px 0 0 0 $base-color-blue;
264
+ transform: translateX(-15px);
265
+ }
266
+
267
+ #{$base-loading}8::after {
268
+ position: absolute;
269
+ top: 8px;
270
+ left: 9px;
271
+ width: 10px;
272
+ height: 10px;
273
+ content: "";
274
+ background-color: $base-color-white;
275
+ border-radius: 50%;
276
+ box-shadow: 30px 0 0 0 $base-color-white;
277
+ animation: vabLoading8 2s ease-in-out infinite alternate;
278
+ }
279
+
280
+ @keyframes vabLoading8 {
281
+ 0% {
282
+ left: 9px;
283
+ }
284
+
285
+ 100% {
286
+ left: 1px;
287
+ }
288
+ }
289
+
290
+ #{$base-loading}9 {
291
+ position: relative;
292
+ box-sizing: border-box;
293
+ display: block;
294
+ width: 20px;
295
+ height: 20px;
296
+ margin: 0 auto 15px auto;
297
+ border: 1px $base-color-blue solid;
298
+ animation: vabLoading9 5s linear infinite;
299
+ }
300
+
301
+ #{$base-loading}9::after {
302
+ position: absolute;
303
+ top: -8px;
304
+ left: 0;
305
+ width: 4px;
306
+ height: 4px;
307
+ content: "";
308
+ background-color: $base-color-blue;
309
+ animation: vabLoading9_check 1s ease-in-out infinite;
310
+ }
311
+
312
+ @keyframes vabLoading9_check {
313
+ 25% {
314
+ top: -8px;
315
+ left: 22px;
316
+ }
317
+
318
+ 50% {
319
+ top: 22px;
320
+ left: 22px;
321
+ }
322
+
323
+ 75% {
324
+ top: 22px;
325
+ left: -9px;
326
+ }
327
+
328
+ 100% {
329
+ top: -7px;
330
+ left: -9px;
331
+ }
332
+ }
333
+
334
+ @keyframes vabLoading9 {
335
+ 0% {
336
+ box-shadow: inset 0 0 0 0 rgba($base-color-blue, 0.5);
337
+ opacity: 0.5;
338
+ }
339
+
340
+ 100% {
341
+ box-shadow: inset 0 -20px 0 0 $base-color-blue;
342
+ }
343
+ }
344
+
345
+ /* 自定义loading结束 */
@@ -0,0 +1,52 @@
1
+ /* 全局导航图标样式 */
2
+ body {
3
+ .nav-icon {
4
+ display: flex !important;
5
+ align-items: center !important;
6
+ justify-content: center !important;
7
+ width: 18px !important;
8
+ height: 18px !important;
9
+ margin: 0 4px !important;
10
+ color: rgba(0, 0, 0, 0.7) !important;
11
+ background: rgba(255, 255, 255, 0.6) !important;
12
+ border: 1px solid rgba(255, 255, 255, 0.8) !important;
13
+ border-radius: 8px !important;
14
+ cursor: pointer !important;
15
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important;
16
+ backdrop-filter: blur(10px) !important;
17
+ -webkit-backdrop-filter: blur(10px) !important;
18
+ font-size: 0.9em !important;
19
+ background: rgba(255, 255, 255, 0.8) !important;
20
+ border-color: rgba(255, 255, 255, 1) !important;
21
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1), 0 2px 4px rgba(0, 0, 0, 0.05) !important;
22
+
23
+ &:hover {
24
+ background: rgba(255, 255, 255, 0.8) !important;
25
+ border-color: rgba(255, 255, 255, 1) !important;
26
+ transform: translateY(-1px) !important;
27
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1), 0 2px 4px rgba(0, 0, 0, 0.05) !important;
28
+ }
29
+
30
+ &:active {
31
+ transform: translateY(0) !important;
32
+ box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1), 0 1px 2px rgba(0, 0, 0, 0.05) !important;
33
+ }
34
+ }
35
+
36
+ /* 头像组件下拉图标 */
37
+ .avatar-dropdown-icon {
38
+ margin-left: 8px !important;
39
+ color: #666 !important;
40
+ font-size: 12px !important;
41
+ }
42
+
43
+ /* 下拉菜单项图标 */
44
+ .dropdown-icon {
45
+ margin-right: 6px !important;
46
+ font-size: 14px !important;
47
+ width: 18px !important;
48
+ height: 18px !important;
49
+ display: flex !important;
50
+ align-items: center !important;
51
+ }
52
+ }