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,456 @@
1
+ <template>
2
+ <div class="login-container">
3
+ <div class="login-box">
4
+ <div class="login-form-container">
5
+ <div class="logo-container">
6
+ <h2 class="welcome-text">欢迎回来</h2>
7
+ <h3 class="system-title">{{ title }}</h3>
8
+ </div>
9
+
10
+ <el-form
11
+ ref="loginForm"
12
+ :model="form"
13
+ :rules="rules"
14
+ class="login-form"
15
+ >
16
+ <el-form-item prop="username">
17
+ <el-input
18
+ v-model="form.username"
19
+ placeholder="请输入用户名"
20
+ tabindex="1"
21
+ type="text"
22
+ >
23
+ <template #prefix>
24
+ <el-icon><User /></el-icon>
25
+ </template>
26
+ </el-input>
27
+ </el-form-item>
28
+
29
+ <el-form-item prop="password">
30
+ <el-input
31
+ :key="passwordType"
32
+ ref="password"
33
+ v-model="form.password"
34
+ :type="passwordType"
35
+ tabindex="2"
36
+ placeholder="请输入密码"
37
+ @keyup.enter="handleLogin"
38
+ >
39
+ <template #prefix>
40
+ <el-icon><Lock /></el-icon>
41
+ </template>
42
+ </el-input>
43
+ <span class="show-pwd" @click="showPwd">
44
+ <el-icon v-if="passwordType === 'password'">
45
+ <Hide />
46
+ </el-icon>
47
+ <el-icon v-else>
48
+ <View />
49
+ </el-icon>
50
+ </span>
51
+ </el-form-item>
52
+
53
+ <div class="form-actions">
54
+ <el-checkbox v-model="rememberMe">记住我</el-checkbox>
55
+ <a href="javascript:;" class="forgot-password">忘记密码?</a>
56
+ </div>
57
+
58
+ <el-button
59
+ :loading="loading"
60
+ type="primary"
61
+ class="login-button"
62
+ @click.prevent="handleLogin"
63
+ >
64
+ 登录
65
+ </el-button>
66
+
67
+ <div class="register-link">
68
+ <span>还没有账号?</span>
69
+ <router-link to="/register" class="create-account">
70
+ 立即注册
71
+ </router-link>
72
+ </div>
73
+ </el-form>
74
+ </div>
75
+
76
+ <div class="login-image">
77
+ <div class="overlay">
78
+ <h2 class="slogan">高效 · 便捷 · 安全</h2>
79
+ <p class="description">基于Vue3的现代化管理系统</p>
80
+ </div>
81
+ </div>
82
+ </div>
83
+ </div>
84
+ </template>
85
+
86
+ <script setup>
87
+ import { reactive, ref, toRefs, onMounted, computed, nextTick } from "vue";
88
+ import { useRouter } from "vue-router";
89
+ import { useStore } from "vuex";
90
+ import { title } from "@/config";
91
+ import { isPassword } from "@/utils/validate";
92
+ import { ElMessage } from "element-plus";
93
+ import { Hide, View, User, Lock } from "@element-plus/icons-vue";
94
+
95
+ // 创建路由实例
96
+ const router = useRouter();
97
+ const store = useStore();
98
+
99
+ // 响应式状态
100
+ const state = reactive({
101
+ form: {
102
+ username: "admin",
103
+ password: "123456",
104
+ },
105
+ rules: {
106
+ username: [{ required: true, trigger: "blur", message: "请输入用户名" }],
107
+ password: [
108
+ { required: true, trigger: "blur", message: "请输入密码" },
109
+ {
110
+ validator: (rule, value, callback) => {
111
+ if (!isPassword(value)) {
112
+ callback(new Error("密码长度必须大于等于6位"));
113
+ } else {
114
+ callback();
115
+ }
116
+ },
117
+ trigger: "blur",
118
+ },
119
+ ],
120
+ },
121
+ loading: false,
122
+ passwordType: "password",
123
+ redirect: undefined,
124
+ });
125
+
126
+ // 使用refs获取表单DOM引用
127
+ const loginForm = ref(null);
128
+ const password = ref(null);
129
+ const rememberMe = ref(false);
130
+
131
+ // 计算属性
132
+ const otherQuery = computed(() => {
133
+ return Object.keys(router.currentRoute.value.query).reduce((acc, cur) => {
134
+ if (cur !== "redirect") {
135
+ acc[cur] = router.currentRoute.value.query[cur];
136
+ }
137
+ return acc;
138
+ }, {});
139
+ });
140
+
141
+ // 显示/隐藏密码
142
+ const showPwd = () => {
143
+ state.passwordType = state.passwordType === "password" ? "" : "password";
144
+ // 等待DOM更新后聚焦
145
+ nextTick(() => {
146
+ password.value?.focus();
147
+ });
148
+ };
149
+
150
+ // 处理登录
151
+ const handleLogin = () => {
152
+ loginForm.value?.validate(async (valid) => {
153
+ if (valid) {
154
+ if (!isPassword(state.form.password)) {
155
+ ElMessage.error("密码长度必须大于等于6位");
156
+ return;
157
+ }
158
+
159
+ state.loading = true;
160
+ try {
161
+ // 使用命名空间调用login action
162
+ await store.dispatch("user/login", state.form);
163
+
164
+ // 登录成功后,让导航守卫处理路由跳转
165
+ // 不需要手动获取用户信息和添加路由,导航守卫会处理
166
+ const { query } = router.currentRoute.value;
167
+ const targetPath = query.redirect || "/";
168
+
169
+ // 跳转到目标页面
170
+ router.replace({
171
+ path: targetPath,
172
+ query: otherQuery.value,
173
+ });
174
+
175
+ // 不再手动处理后续逻辑,让导航守卫处理
176
+ } catch (error) {
177
+ console.error("登录失败:", error);
178
+ ElMessage.error(error.message || "登录失败,请检查用户名和密码");
179
+ state.loading = false;
180
+ }
181
+ }
182
+ });
183
+ };
184
+
185
+ // 生命周期钩子
186
+ onMounted(() => {
187
+ if (router.currentRoute.value.query.redirect) {
188
+ state.redirect = router.currentRoute.value.query.redirect;
189
+ }
190
+ });
191
+
192
+ // 暴露给模板的变量
193
+ const { form, rules, loading, passwordType, redirect } = toRefs(state);
194
+ </script>
195
+
196
+ <style lang="scss" scoped>
197
+ .login-container {
198
+ height: 100vh;
199
+ width: 100vw;
200
+ display: flex;
201
+ justify-content: center;
202
+ align-items: center;
203
+ background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
204
+ }
205
+
206
+ .login-box {
207
+ width: 80%;
208
+ max-width: 1000px;
209
+ height: 700px;
210
+ border-radius: 16px;
211
+ overflow: hidden;
212
+ box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
213
+ display: flex;
214
+ background-color: #fff;
215
+ }
216
+
217
+ .login-form-container {
218
+ width: 50%;
219
+ padding: 50px;
220
+ display: flex;
221
+ flex-direction: column;
222
+ }
223
+
224
+ .logo-container {
225
+ margin-bottom: 40px;
226
+ text-align: center;
227
+
228
+ .welcome-text {
229
+ font-size: 28px;
230
+ color: #333;
231
+ margin-bottom: 10px;
232
+ font-weight: 600;
233
+ }
234
+
235
+ .system-title {
236
+ font-size: 18px;
237
+ color: #666;
238
+ font-weight: 400;
239
+ }
240
+ }
241
+
242
+ .login-form {
243
+ flex: 1;
244
+
245
+ .el-form-item {
246
+ margin-bottom: 24px;
247
+ }
248
+
249
+ .el-input {
250
+ height: 50px;
251
+
252
+ :deep(.el-input__wrapper) {
253
+ padding-left: 15px;
254
+ box-shadow: 0 0 0 1px #dcdfe6 inset;
255
+ }
256
+
257
+ :deep(.el-input__prefix) {
258
+ color: #909399;
259
+ font-size: 18px;
260
+ }
261
+ }
262
+
263
+ .show-pwd {
264
+ position: absolute;
265
+ right: 15px;
266
+ top: 14px;
267
+ font-size: 16px;
268
+ color: #889aa4;
269
+ cursor: pointer;
270
+ user-select: none;
271
+ }
272
+ }
273
+
274
+ .form-actions {
275
+ display: flex;
276
+ justify-content: space-between;
277
+ margin-bottom: 20px;
278
+
279
+ .forgot-password {
280
+ color: #409eff;
281
+ text-decoration: none;
282
+
283
+ &:hover {
284
+ text-decoration: underline;
285
+ }
286
+ }
287
+ }
288
+
289
+ .login-button {
290
+ width: 100%;
291
+ height: 50px;
292
+ border-radius: 25px;
293
+ font-size: 16px;
294
+ font-weight: 500;
295
+ letter-spacing: 1px;
296
+ background: linear-gradient(90deg, #409eff 0%, #007aff 100%);
297
+ border: none;
298
+ margin-top: 10px;
299
+
300
+ &:hover {
301
+ background: linear-gradient(90deg, #007aff 0%, #409eff 100%);
302
+ }
303
+ }
304
+
305
+ .register-link {
306
+ margin-top: 20px;
307
+ text-align: center;
308
+ font-size: 14px;
309
+ color: #606266;
310
+
311
+ .create-account {
312
+ color: #409eff;
313
+ text-decoration: none;
314
+ margin-left: 5px;
315
+
316
+ &:hover {
317
+ text-decoration: underline;
318
+ }
319
+ }
320
+ }
321
+
322
+ .login-image {
323
+ width: 50%;
324
+ position: relative;
325
+ background: url("~@/assets/login_images/background.jpg") center center
326
+ no-repeat;
327
+ background-size: cover;
328
+
329
+ .overlay {
330
+ position: absolute;
331
+ top: 0;
332
+ left: 0;
333
+ right: 0;
334
+ bottom: 0;
335
+ background: rgba(0, 0, 0, 0.4);
336
+ display: flex;
337
+ flex-direction: column;
338
+ justify-content: center;
339
+ align-items: center;
340
+ padding: 40px;
341
+
342
+ .slogan {
343
+ color: #fff;
344
+ font-size: 32px;
345
+ font-weight: 600;
346
+ margin-bottom: 20px;
347
+ text-align: center;
348
+ }
349
+
350
+ .description {
351
+ color: rgba(255, 255, 255, 0.9);
352
+ font-size: 16px;
353
+ text-align: center;
354
+ }
355
+ }
356
+ }
357
+
358
+ // 响应式设计
359
+ @media screen and (max-width: 992px) {
360
+ .login-box {
361
+ width: 100%;
362
+ max-width: 100%;
363
+ flex-direction: column;
364
+ height: auto;
365
+ max-height: 90vh;
366
+ overflow-y: auto;
367
+ }
368
+
369
+ .login-form-container,
370
+ .login-image {
371
+ width: 100%;
372
+ }
373
+
374
+ .login-image {
375
+ height: 200px;
376
+ order: -1;
377
+ }
378
+ }
379
+
380
+ @media screen and (max-width: 576px) {
381
+ .login-container {
382
+ padding: 0;
383
+ height: 100%;
384
+ background: #fff;
385
+ }
386
+
387
+ .login-box {
388
+ width: 100%;
389
+ max-width: 100%;
390
+ height: 100%;
391
+ border-radius: 0;
392
+ box-shadow: none;
393
+ }
394
+
395
+ .login-form-container {
396
+ padding: 20px;
397
+ width: 100%;
398
+ box-sizing: border-box;
399
+ }
400
+
401
+ .logo-container {
402
+ margin-bottom: 20px;
403
+
404
+ .welcome-text {
405
+ font-size: 24px;
406
+ }
407
+
408
+ .system-title {
409
+ font-size: 16px;
410
+ }
411
+ }
412
+
413
+ .login-form {
414
+ .el-form-item {
415
+ margin-bottom: 15px;
416
+ width: 100%;
417
+ }
418
+
419
+ :deep(.el-input) {
420
+ width: 100%;
421
+
422
+ .el-input__wrapper {
423
+ width: 100%;
424
+ box-sizing: border-box;
425
+ }
426
+ }
427
+ }
428
+
429
+ .login-button {
430
+ height: 45px;
431
+ font-size: 15px;
432
+ width: 100%;
433
+ }
434
+
435
+ .form-actions {
436
+ flex-direction: column;
437
+ align-items: flex-start;
438
+ width: 100%;
439
+
440
+ .forgot-password {
441
+ margin-top: 8px;
442
+ }
443
+ }
444
+ }
445
+
446
+ // 添加额外的小屏幕适配
447
+ @media screen and (max-width: 375px) {
448
+ .login-form-container {
449
+ padding: 15px 10px;
450
+ }
451
+
452
+ .login-image {
453
+ height: 150px;
454
+ }
455
+ }
456
+ </style>