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,500 @@
1
+ <template>
2
+ <div id="tabs-container" class="tabs-container">
3
+ <el-tabs
4
+ v-model="tabActive"
5
+ class="tabs-content"
6
+ type="card"
7
+ @tab-click="handleTabClick"
8
+ @tab-remove="handleTabRemove"
9
+ >
10
+ <el-tab-pane
11
+ v-for="item in visitedRoutes"
12
+ :key="item.path"
13
+ :closable="!isAffix(item)"
14
+ :name="item.path"
15
+ >
16
+ <template #label>
17
+ <el-icon v-if="getTabIcon(item)" class="tab-icon">
18
+ <component :is="getTabIcon(item)"></component>
19
+ </el-icon>
20
+ <span>{{ item.meta.title }}</span>
21
+ </template>
22
+ </el-tab-pane>
23
+ </el-tabs>
24
+
25
+ <el-dropdown @command="handleCommand">
26
+ <span style="cursor: pointer">
27
+ 更多操作
28
+ <el-icon class="el-icon--right"><arrow-down /></el-icon>
29
+ </span>
30
+ <template #dropdown>
31
+ <el-dropdown-menu class="tabs-more">
32
+ <el-dropdown-item command="closeOtherstabs">
33
+ <el-icon><circle-close /></el-icon>
34
+ 关闭其他
35
+ </el-dropdown-item>
36
+ <el-dropdown-item command="closeLefttabs">
37
+ <el-icon><back /></el-icon>
38
+ 关闭左侧
39
+ </el-dropdown-item>
40
+ <el-dropdown-item command="closeRighttabs">
41
+ <el-icon><right /></el-icon>
42
+ 关闭右侧
43
+ </el-dropdown-item>
44
+ <el-dropdown-item command="closeAlltabs">
45
+ <el-icon><remove /></el-icon>
46
+ 关闭全部
47
+ </el-dropdown-item>
48
+ </el-dropdown-menu>
49
+ </template>
50
+ </el-dropdown>
51
+ </div>
52
+ </template>
53
+
54
+ <script>
55
+ import path from "path";
56
+ import { mapGetters } from "vuex";
57
+ import {
58
+ ArrowDown,
59
+ CircleClose,
60
+ Back,
61
+ Right,
62
+ Remove,
63
+ Document,
64
+ HomeFilled,
65
+ User,
66
+ UserFilled,
67
+ Setting,
68
+ TrendCharts,
69
+ Grid,
70
+ FolderOpened,
71
+ List,
72
+ Odometer,
73
+ } from "@element-plus/icons-vue";
74
+
75
+ export default {
76
+ name: "VabTabs",
77
+ components: {
78
+ ArrowDown,
79
+ CircleClose,
80
+ Back,
81
+ Right,
82
+ Remove,
83
+ Document,
84
+ HomeFilled,
85
+ User,
86
+ UserFilled,
87
+ Setting,
88
+ TrendCharts,
89
+ Grid,
90
+ FolderOpened,
91
+ List,
92
+ Odometer,
93
+ },
94
+ data() {
95
+ return {
96
+ affixtabs: [],
97
+ tabActive: "",
98
+ };
99
+ },
100
+
101
+ computed: {
102
+ ...mapGetters({
103
+ visitedRoutes: "tabsBar/visitedRoutes",
104
+ routes: "routes/routes",
105
+ }),
106
+ },
107
+ watch: {
108
+ $route: {
109
+ handler(route) {
110
+ this.inittabs();
111
+ this.addtabs();
112
+ let tabActive = "";
113
+ this.visitedRoutes.forEach((item, index) => {
114
+ if (item.path === this.$route.path) {
115
+ tabActive = item.path;
116
+ }
117
+ });
118
+ this.tabActive = tabActive;
119
+ },
120
+ immediate: true,
121
+ },
122
+ },
123
+ mounted() {
124
+ //console.log(this.visitedRoutes);
125
+ },
126
+ methods: {
127
+ async handleTabRemove(tabActive) {
128
+ let view;
129
+ this.visitedRoutes.forEach((item, index) => {
130
+ if (tabActive == item.path) {
131
+ view = item;
132
+ }
133
+ });
134
+ const { visitedRoutes } = await this.$store.dispatch(
135
+ "tabsBar/delRoute",
136
+ view
137
+ );
138
+ if (this.isActive(view)) {
139
+ this.toLastTag(visitedRoutes, view);
140
+ }
141
+ },
142
+ handleTabClick(tab) {
143
+ const route = this.visitedRoutes.filter((item, index) => {
144
+ if (tab.index == index) return item;
145
+ })[0];
146
+ if (this.$route.path !== route.path) {
147
+ this.$router.push({
148
+ path: route.path,
149
+ query: route.query,
150
+ fullPath: route.fullPath,
151
+ });
152
+ } else {
153
+ return false;
154
+ }
155
+ },
156
+ isActive(route) {
157
+ return route.path === this.$route.path;
158
+ },
159
+ isAffix(tag) {
160
+ return tag.meta && tag.meta.affix;
161
+ },
162
+ filterAffixtabs(routes, basePath = "/") {
163
+ let tabs = [];
164
+ routes.forEach((route) => {
165
+ if (route.meta && route.meta.affix) {
166
+ const tagPath = path.resolve(basePath, route.path);
167
+ tabs.push({
168
+ fullPath: tagPath,
169
+ path: tagPath,
170
+ name: route.name,
171
+ meta: { ...route.meta },
172
+ });
173
+ }
174
+ if (route.children) {
175
+ const temptabs = this.filterAffixtabs(route.children, route.path);
176
+ if (temptabs.length >= 1) {
177
+ tabs = [...tabs, ...temptabs];
178
+ }
179
+ }
180
+ });
181
+ return tabs;
182
+ },
183
+ inittabs() {
184
+ const affixtabs = (this.affixtabs = this.filterAffixtabs(this.routes));
185
+ for (const tag of affixtabs) {
186
+ if (tag.name) {
187
+ this.$store.dispatch("tabsBar/addVisitedRoute", tag);
188
+ }
189
+ }
190
+ },
191
+ addtabs() {
192
+ const { name } = this.$route;
193
+ if (name) {
194
+ this.$store.dispatch("tabsBar/addVisitedRoute", this.$route);
195
+ }
196
+ return false;
197
+ },
198
+ handleCommand(command) {
199
+ switch (command) {
200
+ case "refreshRoute":
201
+ this.refreshRoute();
202
+ break;
203
+ case "closeOtherstabs":
204
+ this.closeOtherstabs();
205
+ break;
206
+ case "closeLefttabs":
207
+ this.closeLefttabs();
208
+ break;
209
+ case "closeRighttabs":
210
+ this.closeRighttabs();
211
+ break;
212
+ case "closeAlltabs":
213
+ this.closeAlltabs();
214
+ break;
215
+ }
216
+ },
217
+ async refreshRoute() {
218
+ // Vue 3不再支持$baseEventBus,这里需要替代方案
219
+ // 可以考虑使用mitt或tiny-emitter作为事件总线
220
+ // 这里暂时注释掉
221
+ // this.$baseEventBus.$emit('reloadrouter-view')
222
+ },
223
+ async closeSelectedTag(view) {
224
+ const { visitedRoutes } = await this.$store.dispatch(
225
+ "tabsBar/delRoute",
226
+ view
227
+ );
228
+ if (this.isActive(view)) {
229
+ this.toLastTag(visitedRoutes, view);
230
+ }
231
+ },
232
+ async closeOtherstabs() {
233
+ const view = await this.toThisTag();
234
+ await this.$store.dispatch("tabsBar/delOthersRoutes", view);
235
+ },
236
+ async closeLefttabs() {
237
+ const view = await this.toThisTag();
238
+ await this.$store.dispatch("tabsBar/delLeftRoutes", view);
239
+ },
240
+ async closeRighttabs() {
241
+ const view = await this.toThisTag();
242
+ await this.$store.dispatch("tabsBar/delRightRoutes", view);
243
+ },
244
+ async closeAlltabs() {
245
+ const view = await this.toThisTag();
246
+ const { visitedRoutes } = await this.$store.dispatch(
247
+ "tabsBar/delAllRoutes"
248
+ );
249
+ if (this.affixtabs.some((tag) => tag.path === view.path)) {
250
+ return;
251
+ }
252
+ this.toLastTag(visitedRoutes, view);
253
+ },
254
+ toLastTag(visitedRoutes, view) {
255
+ const latestView = visitedRoutes.slice(-1)[0];
256
+ if (latestView) {
257
+ this.$router.push(latestView);
258
+ } else {
259
+ this.$router.push("/");
260
+ }
261
+ },
262
+ async toThisTag() {
263
+ const view = this.visitedRoutes.filter((item, index) => {
264
+ if (item.path === this.$route.fullPath) {
265
+ return item;
266
+ }
267
+ })[0];
268
+ if (this.$route.path !== view.path) this.$router.push(view);
269
+ return view;
270
+ },
271
+ getTabIcon(item) {
272
+ // 将FontAwesome图标映射到Element Plus图标
273
+ if (item.meta && item.meta.icon) {
274
+ // 简单的图标名映射,可以根据需要扩展
275
+ const iconMap = {
276
+ home: "HomeFilled",
277
+ user: "User",
278
+ users: "UserFilled",
279
+ cog: "Setting",
280
+ "chart-line": "TrendCharts",
281
+ table: "Grid",
282
+ tree: "FolderOpened",
283
+ code: "Document",
284
+ list: "List",
285
+ "tachometer-alt": "Odometer",
286
+ "times-circle": "CircleClose",
287
+ "arrow-alt-circle-left": "Back",
288
+ "arrow-alt-circle-right": "Right",
289
+ ban: "Remove",
290
+ // 可以添加更多映射
291
+ };
292
+
293
+ return iconMap[item.meta.icon] || "Document";
294
+ }
295
+
296
+ return null;
297
+ },
298
+ },
299
+ };
300
+ </script>
301
+
302
+ <style lang="scss" scoped>
303
+ .tabs-container {
304
+ position: relative;
305
+ box-sizing: border-box;
306
+ display: flex;
307
+ align-content: center;
308
+ align-items: center;
309
+ justify-content: space-between;
310
+ height: 54px;
311
+ padding-right: $base-padding;
312
+ padding-left: $base-padding;
313
+ user-select: none;
314
+ background: rgba(255, 255, 255, 0.8);
315
+ backdrop-filter: blur(20px) saturate(180%);
316
+ -webkit-backdrop-filter: blur(20px) saturate(180%);
317
+ border-top: 1px solid rgba(255, 255, 255, 0.3);
318
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1),
319
+ 0 2px 4px -1px rgba(0, 0, 0, 0.06), inset 0 1px 0 rgba(255, 255, 255, 0.6);
320
+
321
+ &::before {
322
+ content: "";
323
+ position: absolute;
324
+ top: 0;
325
+ left: 0;
326
+ right: 0;
327
+ bottom: 0;
328
+ background: linear-gradient(
329
+ 135deg,
330
+ rgba(255, 255, 255, 0.4) 0%,
331
+ rgba(255, 255, 255, 0.1) 50%,
332
+ rgba(255, 255, 255, 0.2) 100%
333
+ );
334
+ pointer-events: none;
335
+ }
336
+
337
+ :deep(.fold-unfold) {
338
+ margin-right: $base-padding;
339
+ }
340
+
341
+ .tabs-content {
342
+ position: relative;
343
+ width: calc(100% - 90px);
344
+ height: $base-tag-item-height;
345
+
346
+ :deep(.el-tabs__nav-next),
347
+ :deep(.el-tabs__nav-prev) {
348
+ height: $base-tag-item-height;
349
+ line-height: $base-tag-item-height;
350
+ color: rgba(0, 0, 0, 0.6);
351
+ background: rgba(255, 255, 255, 0.6);
352
+ border: 1px solid rgba(255, 255, 255, 0.8);
353
+ border-radius: 12px;
354
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
355
+ backdrop-filter: blur(10px);
356
+ -webkit-backdrop-filter: blur(10px);
357
+
358
+ &:hover {
359
+ color: rgba(0, 0, 0, 0.8);
360
+ background: rgba(255, 255, 255, 0.8);
361
+ border-color: rgba(255, 255, 255, 1);
362
+ transform: translateY(-1px);
363
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1), 0 2px 4px rgba(0, 0, 0, 0.05);
364
+ }
365
+ }
366
+
367
+ :deep(.el-tabs__header) {
368
+ border-bottom: 0;
369
+
370
+ .el-tabs__nav {
371
+ border: 0;
372
+ }
373
+
374
+ .el-tabs__item {
375
+ position: relative;
376
+ box-sizing: border-box;
377
+ height: $base-tag-item-height;
378
+ margin-right: 8px;
379
+ margin-top: 3px;
380
+ padding: 0 20px;
381
+ line-height: $base-tag-item-height;
382
+ border: 1px solid $base-color-default;
383
+ color: $base-color-default;
384
+ border-radius: 5px;
385
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
386
+ backdrop-filter: blur(10px);
387
+ -webkit-backdrop-filter: blur(10px);
388
+ overflow: hidden;
389
+
390
+ .tab-icon {
391
+ margin-right: 6px;
392
+ font-size: 12px;
393
+ }
394
+
395
+ &::before {
396
+ content: "";
397
+ position: absolute;
398
+ top: 0;
399
+ left: -100%;
400
+ width: 100%;
401
+ height: 100%;
402
+ background: linear-gradient(
403
+ 90deg,
404
+ transparent,
405
+ rgba(255, 255, 255, 0.2),
406
+ transparent
407
+ );
408
+ transition: left 0.6s cubic-bezier(0.4, 0, 0.2, 1);
409
+ }
410
+
411
+ &:hover {
412
+ color: rgba(255, 255, 255, 0.95);
413
+ background: $base-color-default;
414
+ border-color: $base-color-default;
415
+
416
+ &::before {
417
+ left: 100%;
418
+ }
419
+ }
420
+
421
+ &.is-active {
422
+ color: rgba(255, 255, 255, 0.95);
423
+ background: $base-color-default;
424
+ border-color: $base-color-default;
425
+ }
426
+
427
+ .el-icon-close {
428
+ position: relative;
429
+ margin-left: 8px;
430
+ font-size: 12px;
431
+ color: rgba(255, 255, 255, 0.7);
432
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
433
+ border-radius: 5px;
434
+ padding: 2px;
435
+
436
+ &:hover {
437
+ color: rgba(255, 255, 255, 0.9);
438
+ background: rgba(255, 255, 255, 0.2);
439
+ transform: scale(1.2);
440
+ }
441
+ }
442
+ }
443
+ }
444
+ }
445
+
446
+ .more {
447
+ position: relative;
448
+ display: flex;
449
+ align-content: center;
450
+ align-items: center;
451
+ padding: 8px 16px;
452
+ color: rgba(0, 0, 0, 0.7);
453
+ background: rgba(255, 255, 255, 0.6);
454
+ border: 1px solid rgba(255, 255, 255, 0.8);
455
+ border-radius: 16px;
456
+ cursor: pointer;
457
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
458
+ backdrop-filter: blur(10px);
459
+ -webkit-backdrop-filter: blur(10px);
460
+
461
+ &:hover {
462
+ color: rgba(0, 0, 0, 0.9);
463
+ background: rgba(255, 255, 255, 0.8);
464
+ border-color: rgba(255, 255, 255, 1);
465
+ transform: translateY(-1px);
466
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1), 0 2px 4px rgba(0, 0, 0, 0.05);
467
+ }
468
+
469
+ &:active {
470
+ transform: translateY(0);
471
+ box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1), 0 1px 2px rgba(0, 0, 0, 0.05);
472
+ }
473
+ }
474
+ }
475
+
476
+ // 响应式设计
477
+ @media (max-width: 768px) {
478
+ .tabs-container {
479
+ padding: 0 12px;
480
+
481
+ .tabs-content {
482
+ width: calc(100% - 80px);
483
+
484
+ :deep() {
485
+ .el-tabs__item {
486
+ padding: 0 12px;
487
+ margin-right: 6px;
488
+ font-size: 12px;
489
+ border-radius: 12px;
490
+ }
491
+ }
492
+ }
493
+
494
+ .more {
495
+ padding: 6px 12px;
496
+ font-size: 12px;
497
+ }
498
+ }
499
+ }
500
+ </style>