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,282 @@
1
+ const path = require("path");
2
+ const fs = require("fs");
3
+ const dotenv = require("dotenv");
4
+ const { Configuration, DefinePlugin } = require("@rspack/core");
5
+ const HtmlRspackPlugin = require("html-rspack-plugin");
6
+ const { VueLoaderPlugin } = require("vue-loader");
7
+ const {
8
+ publicPath,
9
+ assetsDir,
10
+ outputDir,
11
+ title,
12
+ devPort,
13
+ } = require("./src/config");
14
+ const dayjs = require("dayjs");
15
+ const time = dayjs().format("YYYY-M-D HH:mm:ss");
16
+
17
+ // 加载环境变量文件(确保在 DefinePlugin 之前加载)
18
+ const mode = process.argv[2] === "build" ? "production" : "development";
19
+ const envFile = `.env.${mode}`;
20
+ const envPath = path.resolve(__dirname, envFile);
21
+
22
+ if (fs.existsSync(envPath)) {
23
+ const envConfig = dotenv.parse(fs.readFileSync(envPath));
24
+ // 将环境变量注入到 process.env
25
+ Object.keys(envConfig).forEach(key => {
26
+ process.env[key] = envConfig[key];
27
+ });
28
+ }
29
+
30
+ // 设置环境变量(优先使用 rspack.js 中已设置的环境变量)
31
+ process.env.VUE_APP_UPDATE_TIME = time;
32
+ process.env.BASE_URL = publicPath;
33
+ process.env.VUE_APP_BASE_API = process.env.VUE_APP_BASE_API || "/api";
34
+
35
+ const resolve = (dir) => path.join(__dirname, dir);
36
+
37
+ /**
38
+ * @type {Configuration}
39
+ */
40
+ module.exports = {
41
+ mode: mode,
42
+ context: __dirname,
43
+ entry: {
44
+ app: "./src/main.js",
45
+ },
46
+ output: {
47
+ path: resolve(outputDir),
48
+ publicPath: "",
49
+ filename: "js/[name].[contenthash:8].js",
50
+ chunkFilename: "js/[name].[contenthash:8].js",
51
+ assetModuleFilename: `${assetsDir}/[name].[ext][query]`,
52
+ },
53
+ // 增加性能提示配置
54
+ performance: {
55
+ // 提高阈值以减少警告
56
+ maxEntrypointSize: 3000000, // 3MB
57
+ maxAssetSize: 1000000, // 1MB
58
+ // 只在生产环境显示性能警告
59
+ hints: mode === "production" ? "warning" : false,
60
+ },
61
+ module: {
62
+ rules: [
63
+ {
64
+ test: /\.vue$/,
65
+ use: [
66
+ {
67
+ loader: "vue-loader",
68
+ options: {
69
+ // Vue 3无需preserveWhitespace选项
70
+ compilerOptions: {
71
+ isCustomElement: (tag) => tag.startsWith("ion-"),
72
+ },
73
+ },
74
+ },
75
+ ],
76
+ },
77
+ {
78
+ test: /\.js$/,
79
+ exclude: /node_modules/,
80
+ use: {
81
+ loader: "babel-loader",
82
+ options: {
83
+ presets: ["@babel/preset-env"],
84
+ },
85
+ },
86
+ },
87
+ {
88
+ test: /\.css$/,
89
+ use: ["style-loader", "css-loader"],
90
+ },
91
+ {
92
+ test: /\.scss$/,
93
+ use: [
94
+ "style-loader",
95
+ {
96
+ loader: "css-loader",
97
+ options: {
98
+ modules: {
99
+ auto: true,
100
+ localIdentName: "[path][name]__[local]--[hash:base64:5]",
101
+ },
102
+ },
103
+ },
104
+ {
105
+ loader: "sass-loader",
106
+ options: {
107
+ sassOptions: {
108
+ indentedSyntax: false,
109
+ includePaths: [resolve("src/styles")],
110
+ quietDeps: true,
111
+ },
112
+ additionalData: (content, loaderContext) => {
113
+ const { resourcePath, rootContext } = loaderContext;
114
+ const relativePath = path.relative(rootContext, resourcePath);
115
+ if (
116
+ relativePath.replace(/\\/g, "/") !==
117
+ "src/styles/variables.scss"
118
+ ) {
119
+ return `@import "~@/styles/variables.scss";${content}`;
120
+ }
121
+ return content;
122
+ },
123
+ },
124
+ },
125
+ ],
126
+ },
127
+ {
128
+ test: /\.(png|jpe?g|gif|svg)$/,
129
+ type: "asset",
130
+ parser: {
131
+ dataUrlCondition: {
132
+ maxSize: 10 * 1024, // 10KB
133
+ },
134
+ },
135
+ },
136
+ {
137
+ test: /\.(woff2?|eot|ttf|otf)$/,
138
+ type: "asset",
139
+ parser: {
140
+ dataUrlCondition: {
141
+ maxSize: 30 * 1024, // 增加到30KB
142
+ },
143
+ },
144
+ },
145
+ {
146
+ resourceQuery: /raw/,
147
+ type: "asset/source",
148
+ },
149
+ ],
150
+ },
151
+ resolve: {
152
+ extensions: [".js", ".vue", ".json"],
153
+ alias: {
154
+ "@": resolve("src"),
155
+ // 更新为Vue 3的运行时版本
156
+ vue$: "vue/dist/vue.esm-bundler.js",
157
+ path: "path-browserify",
158
+ fs: false,
159
+ },
160
+ fallback: {
161
+ path: require.resolve("path-browserify"),
162
+ },
163
+ },
164
+ plugins: [
165
+ new VueLoaderPlugin(),
166
+ new DefinePlugin({
167
+ // Vue 3需要的全局常量
168
+ __VUE_OPTIONS_API__: JSON.stringify(true),
169
+ __VUE_PROD_DEVTOOLS__: JSON.stringify(mode !== "production"),
170
+ // 直接赋值方式,避免嵌套对象
171
+ "process.env.NODE_ENV": JSON.stringify(mode),
172
+ "process.env.BASE_URL": JSON.stringify(process.env.BASE_URL),
173
+ "process.env.VUE_APP_TITLE": JSON.stringify(process.env.VUE_APP_TITLE),
174
+ "process.env.VUE_APP_MOCK_ENABLE": JSON.stringify("true"), // 确保在所有环境中mock都为true
175
+ "process.env.VUE_APP_AUTHOR": JSON.stringify(process.env.VUE_APP_AUTHOR),
176
+ "process.env.VUE_APP_BASE_API": JSON.stringify(process.env.VUE_APP_BASE_API),
177
+ "process.env.VUE_APP_UPDATE_TIME": JSON.stringify(
178
+ process.env.VUE_APP_UPDATE_TIME
179
+ ),
180
+ }),
181
+ new HtmlRspackPlugin({
182
+ template: "./public/index.html",
183
+ filename: "index.html",
184
+ title: title || "管理系统",
185
+ inject: "body",
186
+ templateParameters: {
187
+ BASE_URL: mode === "production" ? "./" : "/",
188
+ VUE_APP_TITLE: process.env.VUE_APP_TITLE,
189
+ VUE_APP_AUTHOR: process.env.VUE_APP_AUTHOR,
190
+ },
191
+ minify:
192
+ mode === "production"
193
+ ? {
194
+ removeComments: true,
195
+ collapseWhitespace: true,
196
+ removeAttributeQuotes: true,
197
+ collapseBooleanAttributes: true,
198
+ removeScriptTypeAttributes: true,
199
+ }
200
+ : false,
201
+ }),
202
+ ],
203
+ optimization: {
204
+ splitChunks: {
205
+ automaticNameDelimiter: "-",
206
+ chunks: "all",
207
+ // 增加maxInitialRequests以允许更多的初始化块
208
+ maxInitialRequests: 6,
209
+ // 减小最小块大小,允许更细粒度的分割
210
+ minSize: 20000,
211
+ cacheGroups: {
212
+ chunk: {
213
+ name: "vab-chunk",
214
+ test: /[\\/]node_modules[\\/]/,
215
+ minSize: 131072,
216
+ maxSize: 524288,
217
+ chunks: "async",
218
+ minChunks: 2,
219
+ priority: 10,
220
+ },
221
+ vue: {
222
+ name: "vue",
223
+ test: /[\\/]node_modules[\\/](vue(.*)|core-js)[\\/]/,
224
+ chunks: "initial",
225
+ priority: 20,
226
+ },
227
+ elementPlus: {
228
+ name: "element-plus",
229
+ test: /[\\/]node_modules[\\/]element-plus(.*)[\\/]/,
230
+ priority: 30,
231
+ },
232
+ // 单独拆分常用工具库
233
+ vendors: {
234
+ name: "vendors",
235
+ test: /[\\/]node_modules[\\/](lodash|axios|qs|dayjs)[\\/]/,
236
+ chunks: "all",
237
+ priority: 35,
238
+ },
239
+ // 拆分样式资源
240
+ styles: {
241
+ name: "styles",
242
+ test: /\.(css|scss)$/,
243
+ chunks: "all",
244
+ enforce: true,
245
+ priority: 40,
246
+ },
247
+ extra: {
248
+ name: "vab-layouts",
249
+ test: resolve("src/layouts"),
250
+ priority: 40,
251
+ },
252
+ },
253
+ },
254
+ // 添加压缩配置
255
+ minimize: mode === "production",
256
+ // 如果是生产环境,增加tree shaking
257
+ usedExports: mode === "production",
258
+ },
259
+ devServer: {
260
+ hot: true,
261
+ // 使用配置文件中的端口
262
+ port: devPort || 8091,
263
+ historyApiFallback: true,
264
+ static: {
265
+ directory: path.join(__dirname, "public"),
266
+ },
267
+ client: {
268
+ overlay: false, // 关闭错误遮罩(Element Plus 的 ResizeObserver 警告是已知问题,不影响功能)
269
+ },
270
+ open: {
271
+ target: [`http://localhost:${devPort || 8091}`],
272
+ },
273
+ proxy: [
274
+ {
275
+ context: ["/api"],
276
+ target: "https://cn.gempharmatech.com",
277
+ changeOrigin: true,
278
+ secure: true,
279
+ },
280
+ ],
281
+ },
282
+ };
package/rspack.js ADDED
@@ -0,0 +1,162 @@
1
+ #!/usr/bin/env node
2
+
3
+ // 禁用弃用警告
4
+ process.noDeprecation = true;
5
+
6
+ const { rspack } = require("@rspack/core");
7
+ const path = require("path");
8
+ const fs = require("fs");
9
+ const dotenv = require("dotenv");
10
+
11
+ const configPath = path.resolve(__dirname, "rspack.config.js");
12
+ const config = require(configPath);
13
+ const mode = process.argv[2] === "build" ? "production" : "development";
14
+
15
+ // 加载环境变量文件
16
+ const envFile = `.env.${mode}`;
17
+ const envPath = path.resolve(__dirname, envFile);
18
+
19
+ if (fs.existsSync(envPath)) {
20
+ const envConfig = dotenv.parse(fs.readFileSync(envPath));
21
+ // 将环境变量注入到 process.env
22
+ Object.keys(envConfig).forEach(key => {
23
+ process.env[key] = envConfig[key];
24
+ });
25
+ console.log(`已加载环境配置文件: ${envFile}`);
26
+ } else {
27
+ console.warn(`环境配置文件不存在: ${envFile}`);
28
+ }
29
+
30
+ // 增强环境变量设置
31
+ process.env.NODE_ENV = mode;
32
+ process.env.WEBPACK_ENV = mode;
33
+ process.env.BABEL_ENV = mode;
34
+
35
+ // 如果环境变量中没有设置,使用默认值
36
+ process.env.VUE_APP_TITLE = process.env.VUE_APP_TITLE || "管理系统";
37
+ process.env.VUE_APP_AUTHOR = process.env.VUE_APP_AUTHOR || "";
38
+ process.env.VUE_APP_BASE_API = process.env.VUE_APP_BASE_API || "/api";
39
+ process.env.VUE_APP_MOCK_ENABLE = process.env.VUE_APP_MOCK_ENABLE || "false";
40
+ process.env.BASE_URL = process.env.BASE_URL || "/";
41
+
42
+ console.log("当前环境:", mode);
43
+ console.log("系统标题:", process.env.VUE_APP_TITLE);
44
+ console.log("API地址:", process.env.VUE_APP_BASE_API);
45
+ console.log("Mock启用:", process.env.VUE_APP_MOCK_ENABLE);
46
+
47
+ // 读取配置
48
+ config.mode = mode;
49
+
50
+ if (mode === "production") {
51
+ // 生产环境配置
52
+ console.log("正在极速打包中,预计用时3秒,请稍后...");
53
+
54
+ // 生产环境下增加额外配置
55
+ config.optimization = {
56
+ ...config.optimization,
57
+ moduleIds: "deterministic", // 稳定的模块ID以优化长期缓存
58
+ chunkIds: "deterministic", // 稳定的chunk ID以优化长期缓存
59
+ removeEmptyChunks: true, // 移除空的chunks
60
+ };
61
+
62
+ rspack(config).run((err, stats) => {
63
+ if (err) {
64
+ console.error(err.stack || err);
65
+ if (err.details) {
66
+ console.error(err.details);
67
+ }
68
+ process.exit(1);
69
+ return;
70
+ }
71
+
72
+ const info = stats.toJson();
73
+
74
+ if (stats.hasErrors()) {
75
+ console.error(info.errors);
76
+ }
77
+
78
+ if (stats.hasWarnings()) {
79
+ console.warn(info.warnings);
80
+ }
81
+
82
+ console.log(
83
+ stats.toString({
84
+ colors: true,
85
+ modules: false,
86
+ children: false,
87
+ chunks: false,
88
+ chunkModules: false,
89
+ })
90
+ );
91
+ });
92
+ } else {
93
+ // 开发环境配置
94
+ try {
95
+ // 尝试使用rspack的dev server
96
+ const { RspackDevServer } = require("@rspack/dev-server");
97
+
98
+ const compiler = rspack(config);
99
+
100
+ // 使用rspack.config.js中的所有devServer配置
101
+ const devServerOptions = config.devServer || {};
102
+
103
+ // 设置mock服务器,不再检查环境变量,始终启用mock
104
+ // if (!devServerOptions.setupMiddlewares) {
105
+ // devServerOptions.setupMiddlewares = (middlewares, devServer) => {
106
+ // if (!devServer) {
107
+ // throw new Error("dev-server is not defined");
108
+ // }
109
+
110
+ // const mockServer = require("./mock/index");
111
+ // mockServer(devServer.app);
112
+
113
+ // return middlewares;
114
+ // };
115
+ // }
116
+
117
+ const server = new RspackDevServer(devServerOptions, compiler);
118
+
119
+ server.start().catch((err) => {
120
+ console.error("启动RspackDevServer失败:", err);
121
+ });
122
+ } catch (error) {
123
+ console.error(
124
+ "加载@rspack/dev-server失败,尝试使用webpack-dev-server:",
125
+ error
126
+ );
127
+
128
+ // 如果rspack dev server失败,尝试回退到webpack
129
+ try {
130
+ const webpack = require("webpack");
131
+ const WebpackDevServer = require("webpack-dev-server");
132
+
133
+ const webpackConfig = {
134
+ ...config,
135
+ // 添加webpack特定配置
136
+ mode: config.mode,
137
+ };
138
+
139
+ const compiler = webpack(webpackConfig);
140
+ const devServerOptions = config.devServer || {};
141
+
142
+ // 不再检查环境变量,始终启用mock
143
+ const originalBefore = devServerOptions.before;
144
+ devServerOptions.before = (app, server) => {
145
+ if (originalBefore) {
146
+ originalBefore(app, server);
147
+ }
148
+ const mockServer = require("./mock/index");
149
+ mockServer(app);
150
+ };
151
+
152
+ const server = new WebpackDevServer(devServerOptions, compiler);
153
+
154
+ server.start().catch((err) => {
155
+ console.error("启动WebpackDevServer失败:", err);
156
+ });
157
+ } catch (webpackError) {
158
+ console.error("回退到webpack-dev-server也失败:", webpackError);
159
+ process.exit(1);
160
+ }
161
+ }
162
+ }
package/src/App.vue ADDED
@@ -0,0 +1,9 @@
1
+ <template>
2
+ <div id="app">
3
+ <router-view />
4
+ </div>
5
+ </template>
6
+
7
+ <script setup>
8
+ // Vue 3 组合式 API
9
+ </script>
@@ -0,0 +1,9 @@
1
+ import request from '@/utils/request'
2
+
3
+ export function getIconList(data) {
4
+ return request({
5
+ url: '/icon/list',
6
+ method: 'post',
7
+ data,
8
+ })
9
+ }
@@ -0,0 +1,9 @@
1
+ import request from '@/utils/request'
2
+
3
+ export function getRouterList(data) {
4
+ return request({
5
+ url: '/menu/navigate',
6
+ method: 'post',
7
+ data,
8
+ })
9
+ }
@@ -0,0 +1,25 @@
1
+ import request from '@/utils/request'
2
+
3
+ export function getList(data) {
4
+ return request({
5
+ url: '/table/getList',
6
+ method: 'post',
7
+ data,
8
+ })
9
+ }
10
+
11
+ export function doEdit(data) {
12
+ return request({
13
+ url: '/table/doEdit',
14
+ method: 'post',
15
+ data,
16
+ })
17
+ }
18
+
19
+ export function doDelete(data) {
20
+ return request({
21
+ url: '/table/doDelete',
22
+ method: 'post',
23
+ data,
24
+ })
25
+ }
@@ -0,0 +1,9 @@
1
+ import request from '@/utils/request'
2
+
3
+ export function getTreeList(data) {
4
+ return request({
5
+ url: '/tree/list',
6
+ method: 'post',
7
+ data,
8
+ })
9
+ }
@@ -0,0 +1,34 @@
1
+ import request from "@/utils/request";
2
+ import { tokenName } from "@/config";
3
+
4
+ export async function login(data) {
5
+ return request({
6
+ url: "/xhr-cms/customer-info/passwordLogin",
7
+ method: "post",
8
+ data,
9
+ });
10
+ }
11
+
12
+ export function getUserInfo(accessToken) {
13
+ return request({
14
+ url: "/userInfo",
15
+ method: "post",
16
+ data: {
17
+ [tokenName]: accessToken,
18
+ },
19
+ });
20
+ }
21
+
22
+ export function logout() {
23
+ return request({
24
+ url: "/logout",
25
+ method: "post",
26
+ });
27
+ }
28
+
29
+ export function register() {
30
+ return request({
31
+ url: "/register",
32
+ method: "post",
33
+ });
34
+ }
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,4 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
2
+ <path fill="none" d="M0 0h24v24H0z"/>
3
+ <path d="M1 3h4l7 12 7-12h4L12 22 1 3zm8.667 0L12 7l2.333-4h4.035L12 14 5.632 3h4.035z"/>
4
+ </svg>
@@ -0,0 +1,133 @@
1
+ <template>
2
+ <div class="page-header" :class="customClass">
3
+ <div class="header-content">
4
+ <div class="header-left">
5
+ <h1 class="page-title">
6
+ <el-icon v-if="icon && icon.length" class="header-icon">
7
+ <component :is="convertIcon(icon)" />
8
+ </el-icon>
9
+ {{ title }}
10
+ </h1>
11
+ <p v-if="description" class="page-description">
12
+ {{ description }}
13
+ </p>
14
+ </div>
15
+ <div v-if="rightIcon || rightText" class="header-right">
16
+ <slot name="right">
17
+ <el-icon v-if="rightIcon && rightIcon.length" class="header-icon">
18
+ <component :is="convertIcon(rightIcon)" />
19
+ </el-icon>
20
+ <span v-if="rightText">{{ rightText }}</span>
21
+ </slot>
22
+ </div>
23
+ </div>
24
+ </div>
25
+ </template>
26
+
27
+ <script>
28
+ import { faToElIcon } from "@/utils/vab";
29
+
30
+ export default {
31
+ name: "VabPageHeader",
32
+ props: {
33
+ title: {
34
+ type: String,
35
+ required: true,
36
+ },
37
+ description: {
38
+ type: String,
39
+ default: "",
40
+ },
41
+ icon: {
42
+ type: Array,
43
+ default: () => [],
44
+ },
45
+ rightIcon: {
46
+ type: Array,
47
+ default: () => [],
48
+ },
49
+ rightText: {
50
+ type: String,
51
+ default: "",
52
+ },
53
+ customClass: {
54
+ type: String,
55
+ default: "",
56
+ },
57
+ },
58
+ methods: {
59
+ convertIcon(icon) {
60
+ return faToElIcon(icon);
61
+ },
62
+ },
63
+ };
64
+ </script>
65
+
66
+ <style lang="scss">
67
+ .page-header {
68
+ background: linear-gradient(135deg, #409EFF 0%, #69C0FF 100%);
69
+ border-radius: 12px;
70
+ padding: 30px;
71
+ margin-bottom: 24px;
72
+ color: white;
73
+ box-shadow: 0 8px 32px rgba(102, 126, 234, 0.3);
74
+
75
+ .header-content {
76
+ display: flex;
77
+ justify-content: space-between;
78
+ align-items: center;
79
+
80
+ .header-left {
81
+ .page-title {
82
+ font-size: 2rem;
83
+ font-weight: 700;
84
+ margin: 0 0 8px 0;
85
+ display: flex;
86
+ align-items: center;
87
+ gap: 12px;
88
+
89
+ .header-icon {
90
+ font-size: 1.8rem;
91
+ }
92
+ }
93
+
94
+ .page-description {
95
+ font-size: 1rem;
96
+ opacity: 0.9;
97
+ margin: 0;
98
+ }
99
+ }
100
+
101
+ .header-right {
102
+ display: flex;
103
+ align-items: center;
104
+ gap: 8px;
105
+ font-size: 1.1rem;
106
+ font-weight: 600;
107
+
108
+ .header-icon {
109
+ font-size: 1.3rem;
110
+ }
111
+ }
112
+ }
113
+ }
114
+
115
+ // 响应式设计
116
+ @media (max-width: 768px) {
117
+ .page-header {
118
+ padding: 20px;
119
+
120
+ .header-content {
121
+ flex-direction: column;
122
+ gap: 16px;
123
+ text-align: center;
124
+
125
+ .header-left {
126
+ .page-title {
127
+ font-size: 1.5rem;
128
+ }
129
+ }
130
+ }
131
+ }
132
+ }
133
+ </style>