befly-vite 1.1.10 → 1.1.12
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.
- package/README.md +4 -4
- package/configs/uno.config.js +11 -11
- package/index.js +55 -82
- package/package.json +23 -26
- package/plugins/analyzer.js +3 -3
- package/plugins/auto-import.js +7 -7
- package/plugins/components.js +6 -6
- package/plugins/compression.js +2 -2
- package/plugins/devtools.js +7 -1
- package/plugins/icons.js +4 -4
- package/plugins/reactivity-transform.js +8 -0
- package/plugins/router.js +5 -5
- package/plugins/unocss.js +1 -1
- package/plugins/vue.js +8 -14
- package/utils/arrayToTree.js +55 -0
- package/utils/createUnoConfig.js +7 -0
- package/utils/fieldClear.js +94 -0
- package/utils/hashPassword.js +21 -0
- package/utils/layouts.js +103 -0
- package/utils/router.js +109 -0
- package/utils/scanViews.js +55 -0
- package/utils/withDefaultColumns.js +40 -0
- package/plugins/inspect.js +0 -11
package/README.md
CHANGED
|
@@ -21,7 +21,7 @@ bun add -d befly-vite vite
|
|
|
21
21
|
|
|
22
22
|
```javascript
|
|
23
23
|
// vite.config.js
|
|
24
|
-
import { createBeflyViteConfig } from
|
|
24
|
+
import { createBeflyViteConfig } from "befly-vite";
|
|
25
25
|
|
|
26
26
|
export default createBeflyViteConfig();
|
|
27
27
|
```
|
|
@@ -29,11 +29,11 @@ export default createBeflyViteConfig();
|
|
|
29
29
|
### 自定义配置
|
|
30
30
|
|
|
31
31
|
```javascript
|
|
32
|
-
import { createBeflyViteConfig } from
|
|
33
|
-
import { fileURLToPath } from
|
|
32
|
+
import { createBeflyViteConfig } from "befly-vite";
|
|
33
|
+
import { fileURLToPath } from "node:url";
|
|
34
34
|
|
|
35
35
|
export default createBeflyViteConfig({
|
|
36
|
-
root: fileURLToPath(new URL(
|
|
36
|
+
root: fileURLToPath(new URL(".", import.meta.url)),
|
|
37
37
|
|
|
38
38
|
// 自定义配置
|
|
39
39
|
userConfig: {
|
package/configs/uno.config.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { defineConfig, presetAttributify, presetUno } from
|
|
1
|
+
import { defineConfig, presetAttributify, presetUno } from "unocss";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* 创建 UnoCSS 配置
|
|
@@ -7,17 +7,17 @@ export function createUnoConfig(userConfig = {}) {
|
|
|
7
7
|
const defaultConfig = {
|
|
8
8
|
presets: [presetUno(), presetAttributify()],
|
|
9
9
|
shortcuts: {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
"flex-center": "flex items-center justify-center",
|
|
11
|
+
"flex-between": "flex items-center justify-between",
|
|
12
|
+
"flex-col-center": "flex flex-col items-center justify-center"
|
|
13
13
|
},
|
|
14
14
|
theme: {
|
|
15
15
|
colors: {
|
|
16
|
-
primary:
|
|
17
|
-
success:
|
|
18
|
-
warning:
|
|
19
|
-
danger:
|
|
20
|
-
info:
|
|
16
|
+
primary: "#1890ff",
|
|
17
|
+
success: "#52c41a",
|
|
18
|
+
warning: "#faad14",
|
|
19
|
+
danger: "#ff4d4f",
|
|
20
|
+
info: "#1890ff"
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
23
|
};
|
|
@@ -27,11 +27,11 @@ export function createUnoConfig(userConfig = {}) {
|
|
|
27
27
|
...userConfig,
|
|
28
28
|
theme: {
|
|
29
29
|
...defaultConfig.theme,
|
|
30
|
-
...
|
|
30
|
+
...userConfig.theme
|
|
31
31
|
},
|
|
32
32
|
shortcuts: {
|
|
33
33
|
...defaultConfig.shortcuts,
|
|
34
|
-
...
|
|
34
|
+
...userConfig.shortcuts
|
|
35
35
|
}
|
|
36
36
|
});
|
|
37
37
|
}
|
package/index.js
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import { createDevToolsPlugin } from
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
1
|
+
import { fileURLToPath } from "node:url";
|
|
2
|
+
|
|
3
|
+
import { defineConfig, mergeConfig } from "vite";
|
|
4
|
+
|
|
5
|
+
import { createAnalyzerPlugin } from "./plugins/analyzer.js";
|
|
6
|
+
import { createAutoImportPlugin } from "./plugins/auto-import.js";
|
|
7
|
+
import { createComponentsPlugin } from "./plugins/components.js";
|
|
8
|
+
import { createCompressionPlugin } from "./plugins/compression.js";
|
|
9
|
+
import { createDevToolsPlugin } from "./plugins/devtools.js";
|
|
10
|
+
import { createIconsPlugin } from "./plugins/icons.js";
|
|
11
|
+
import { createReactivityTransformPlugin } from "./plugins/reactivity-transform.js";
|
|
12
|
+
import { createRouterPlugin } from "./plugins/router.js";
|
|
13
|
+
import { createUnoCSSPlugin } from "./plugins/unocss.js";
|
|
14
|
+
import { createVuePlugin } from "./plugins/vue.js";
|
|
13
15
|
|
|
14
16
|
/**
|
|
15
17
|
* 默认分包策略
|
|
@@ -19,59 +21,59 @@ function defaultManualChunks(id) {
|
|
|
19
21
|
// 注意:必须在 befly-addon 之前判断,因为 addon 会引用这些库
|
|
20
22
|
|
|
21
23
|
// vue-router(优先级最高)
|
|
22
|
-
if (id.match(/node_modules[
|
|
23
|
-
return
|
|
24
|
+
if (id.match(/node_modules[/\\]vue-router[/\\]/)) {
|
|
25
|
+
return "vue-router";
|
|
24
26
|
}
|
|
25
27
|
|
|
26
28
|
// pinia
|
|
27
|
-
if (id.match(/node_modules[
|
|
28
|
-
return
|
|
29
|
+
if (id.match(/node_modules[/\\]pinia[/\\]/)) {
|
|
30
|
+
return "pinia";
|
|
29
31
|
}
|
|
30
32
|
|
|
31
33
|
// vue 核心和运行时(@vue/* 包)
|
|
32
|
-
if (id.match(/node_modules[
|
|
33
|
-
return
|
|
34
|
+
if (id.match(/node_modules[/\\](vue[/\\]|@vue[/\\])/)) {
|
|
35
|
+
return "vue";
|
|
34
36
|
}
|
|
35
37
|
|
|
36
38
|
// TDesign Vue Next
|
|
37
|
-
if (id.includes(
|
|
38
|
-
return
|
|
39
|
+
if (id.includes("tdesign-vue-next")) {
|
|
40
|
+
return "tdesign";
|
|
39
41
|
}
|
|
40
42
|
|
|
41
43
|
// 工具库
|
|
42
|
-
if (id.match(/node_modules[
|
|
43
|
-
return
|
|
44
|
+
if (id.match(/node_modules[/\\]axios[/\\]/)) {
|
|
45
|
+
return "axios";
|
|
44
46
|
}
|
|
45
|
-
if (id.match(/node_modules[
|
|
46
|
-
return
|
|
47
|
+
if (id.match(/node_modules[/\\]lodash-es[/\\]/)) {
|
|
48
|
+
return "lodash";
|
|
47
49
|
}
|
|
48
50
|
|
|
49
51
|
// echarts
|
|
50
|
-
if (id.match(/node_modules[
|
|
51
|
-
return
|
|
52
|
+
if (id.match(/node_modules[/\\]echarts[/\\]/)) {
|
|
53
|
+
return "echarts";
|
|
52
54
|
}
|
|
53
|
-
if (id.match(/node_modules[
|
|
54
|
-
return
|
|
55
|
+
if (id.match(/node_modules[/\\]zrender[/\\]/)) {
|
|
56
|
+
return "zrender";
|
|
55
57
|
}
|
|
56
58
|
|
|
57
59
|
// 图标
|
|
58
|
-
if (id.includes(
|
|
59
|
-
return
|
|
60
|
+
if (id.includes("/@iconify/") || id.includes("~icons/")) {
|
|
61
|
+
return "icons";
|
|
60
62
|
}
|
|
61
63
|
|
|
62
64
|
// Vue Macros
|
|
63
|
-
if (id.match(/node_modules[
|
|
64
|
-
return
|
|
65
|
+
if (id.match(/node_modules[/\\](@vue-macros|vue-macros)[/\\]/)) {
|
|
66
|
+
return "vue-macros";
|
|
65
67
|
}
|
|
66
68
|
|
|
67
69
|
// befly-addon(必须在 Vue 判断之后)
|
|
68
|
-
if (id.includes(
|
|
69
|
-
return
|
|
70
|
+
if (id.includes("@befly-addon/") || id.includes("packages/addonAdmin/") || id.includes("packages\\addonAdmin\\")) {
|
|
71
|
+
return "befly-addon";
|
|
70
72
|
}
|
|
71
73
|
|
|
72
74
|
// 其他 node_modules 依赖
|
|
73
|
-
if (id.includes(
|
|
74
|
-
return
|
|
75
|
+
if (id.includes("node_modules/")) {
|
|
76
|
+
return "vendor";
|
|
75
77
|
}
|
|
76
78
|
}
|
|
77
79
|
|
|
@@ -92,25 +94,25 @@ export function createBeflyViteConfig(options = {}) {
|
|
|
92
94
|
const projectRoot = root || process.cwd();
|
|
93
95
|
|
|
94
96
|
const baseConfig = defineConfig({
|
|
95
|
-
base:
|
|
97
|
+
base: "./",
|
|
96
98
|
|
|
97
99
|
plugins: [
|
|
98
100
|
//
|
|
99
101
|
createUnoCSSPlugin(),
|
|
100
|
-
createDevToolsPlugin(),
|
|
101
102
|
createRouterPlugin({ scanViews: scanViews }),
|
|
102
|
-
|
|
103
|
+
createVuePlugin(),
|
|
104
|
+
createReactivityTransformPlugin(),
|
|
105
|
+
createDevToolsPlugin(),
|
|
103
106
|
createAutoImportPlugin({ resolvers: resolvers }),
|
|
104
107
|
createComponentsPlugin({ resolvers: resolvers }),
|
|
105
108
|
createIconsPlugin(),
|
|
106
109
|
createAnalyzerPlugin(),
|
|
107
|
-
createInspectPlugin(),
|
|
108
110
|
createCompressionPlugin()
|
|
109
111
|
],
|
|
110
112
|
|
|
111
113
|
resolve: {
|
|
112
114
|
alias: {
|
|
113
|
-
|
|
115
|
+
"@": fileURLToPath(new URL("src", `file:///${projectRoot.replace(/\\/g, "/")}/`))
|
|
114
116
|
}
|
|
115
117
|
},
|
|
116
118
|
|
|
@@ -120,11 +122,11 @@ export function createBeflyViteConfig(options = {}) {
|
|
|
120
122
|
},
|
|
121
123
|
|
|
122
124
|
build: {
|
|
123
|
-
target:
|
|
124
|
-
outDir:
|
|
125
|
-
assetsDir:
|
|
125
|
+
target: "es2020",
|
|
126
|
+
outDir: "dist",
|
|
127
|
+
assetsDir: "assets",
|
|
126
128
|
sourcemap: false,
|
|
127
|
-
minify:
|
|
129
|
+
minify: "esbuild",
|
|
128
130
|
chunkSizeWarningLimit: 1000,
|
|
129
131
|
commonjsOptions: {
|
|
130
132
|
include: [/node_modules/],
|
|
@@ -132,53 +134,24 @@ export function createBeflyViteConfig(options = {}) {
|
|
|
132
134
|
},
|
|
133
135
|
rollupOptions: {
|
|
134
136
|
output: {
|
|
135
|
-
chunkFileNames:
|
|
136
|
-
entryFileNames:
|
|
137
|
-
assetFileNames:
|
|
137
|
+
chunkFileNames: "assets/js/[name]-[hash].js",
|
|
138
|
+
entryFileNames: "assets/js/[name]-[hash].js",
|
|
139
|
+
assetFileNames: "assets/[ext]/[name]-[hash].[ext]",
|
|
138
140
|
manualChunks(id) {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
if (id.includes('/vue-router/')) return 'vue-router';
|
|
143
|
-
// pinia
|
|
144
|
-
if (id.includes('/pinia/')) return 'pinia';
|
|
145
|
-
// vue 核心(包括 @vue/*)
|
|
146
|
-
if (id.includes('/vue/') || id.includes('/@vue/')) return 'vue';
|
|
147
|
-
// tdesign
|
|
148
|
-
if (id.includes('/tdesign-vue-next/')) return 'tdesign';
|
|
149
|
-
// axios
|
|
150
|
-
if (id.includes('/axios/')) return 'axios';
|
|
151
|
-
// 其他第三方库
|
|
152
|
-
return 'vendor';
|
|
153
|
-
}
|
|
154
|
-
// befly-addon(workspace 包)
|
|
155
|
-
if (id.includes('@befly-addon/') || id.includes('/addonAdmin/')) {
|
|
156
|
-
return 'befly-addon';
|
|
141
|
+
if (typeof manualChunks === "function") {
|
|
142
|
+
const chunkName = manualChunks(id);
|
|
143
|
+
if (chunkName) return chunkName;
|
|
157
144
|
}
|
|
145
|
+
return defaultManualChunks(id);
|
|
158
146
|
}
|
|
159
147
|
}
|
|
160
148
|
}
|
|
161
149
|
},
|
|
162
150
|
|
|
163
151
|
optimizeDeps: {
|
|
164
|
-
include: [
|
|
152
|
+
include: ["vue", "vue-router", "pinia", "axios", "tdesign-vue-next"]
|
|
165
153
|
}
|
|
166
154
|
});
|
|
167
155
|
|
|
168
156
|
return mergeConfig(baseConfig, userConfig);
|
|
169
157
|
}
|
|
170
|
-
|
|
171
|
-
// 导出 UnoCSS 配置创建函数
|
|
172
|
-
export { createUnoConfig } from './configs/uno.config.js';
|
|
173
|
-
|
|
174
|
-
// 导出所有插件创建函数(供高级用户自定义)
|
|
175
|
-
export { createVuePlugins } from './plugins/vue.js';
|
|
176
|
-
export { createRouterPlugin } from './plugins/router.js';
|
|
177
|
-
export { createAutoImportPlugin } from './plugins/auto-import.js';
|
|
178
|
-
export { createComponentsPlugin } from './plugins/components.js';
|
|
179
|
-
export { createIconsPlugin } from './plugins/icons.js';
|
|
180
|
-
export { createUnoCSSPlugin } from './plugins/unocss.js';
|
|
181
|
-
export { createDevToolsPlugin } from './plugins/devtools.js';
|
|
182
|
-
export { createAnalyzerPlugin } from './plugins/analyzer.js';
|
|
183
|
-
export { createCompressionPlugin } from './plugins/compression.js';
|
|
184
|
-
export { createInspectPlugin } from './plugins/inspect.js';
|
package/package.json
CHANGED
|
@@ -1,43 +1,37 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "befly-vite",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.12",
|
|
4
|
+
"private": false,
|
|
4
5
|
"description": "Befly Vite 配置预设和插件集合",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"befly",
|
|
8
|
+
"config",
|
|
9
|
+
"preset",
|
|
10
|
+
"vite",
|
|
11
|
+
"vue"
|
|
12
|
+
],
|
|
13
|
+
"homepage": "https://chensuiyi.me",
|
|
14
|
+
"author": "chensuiyi <bimostyle@qq.com>",
|
|
15
|
+
"license": "Apache-2.0",
|
|
5
16
|
"type": "module",
|
|
6
|
-
"private": false,
|
|
7
|
-
"publishConfig": {
|
|
8
|
-
"access": "public",
|
|
9
|
-
"registry": "https://registry.npmjs.org"
|
|
10
|
-
},
|
|
11
17
|
"main": "index.js",
|
|
12
18
|
"exports": {
|
|
13
19
|
".": "./index.js",
|
|
14
|
-
"./configs/*": "./configs/*.js",
|
|
15
|
-
"./plugins/*": "./plugins/*.js",
|
|
16
20
|
"./utils/*": "./utils/*.js"
|
|
17
21
|
},
|
|
18
22
|
"files": [
|
|
23
|
+
"README.md",
|
|
19
24
|
"configs/",
|
|
20
|
-
"plugins/",
|
|
21
25
|
"index.js",
|
|
22
26
|
"package.json",
|
|
23
|
-
"
|
|
24
|
-
|
|
25
|
-
"keywords": [
|
|
26
|
-
"vite",
|
|
27
|
-
"vue",
|
|
28
|
-
"config",
|
|
29
|
-
"preset",
|
|
30
|
-
"befly"
|
|
27
|
+
"plugins/",
|
|
28
|
+
"utils/"
|
|
31
29
|
],
|
|
32
|
-
"author": "chensuiyi <bimostyle@qq.com>",
|
|
33
|
-
"homepage": "https://chensuiyi.me",
|
|
34
|
-
"license": "Apache-2.0",
|
|
35
30
|
"dependencies": {
|
|
36
31
|
"@unocss/preset-attributify": "^66.5.10",
|
|
37
32
|
"@unocss/preset-uno": "^66.5.10",
|
|
38
|
-
"@vitejs/plugin-vue": "^6.0.
|
|
33
|
+
"@vitejs/plugin-vue": "^6.0.3",
|
|
39
34
|
"@vue-macros/reactivity-transform": "^3.1.1",
|
|
40
|
-
"befly-shared": "^1.2.7",
|
|
41
35
|
"sass": "^1.96.0",
|
|
42
36
|
"unocss": "^66.5.10",
|
|
43
37
|
"unplugin-auto-import": "^20.3.0",
|
|
@@ -46,15 +40,18 @@
|
|
|
46
40
|
"unplugin-vue-router": "^0.19.0",
|
|
47
41
|
"vite-bundle-analyzer": "^1.3.1",
|
|
48
42
|
"vite-plugin-compression2": "^2.4.0",
|
|
49
|
-
"vite-plugin-inspect": "^11.3.3",
|
|
50
43
|
"vite-plugin-vue-devtools": "^8.0.5"
|
|
51
44
|
},
|
|
52
45
|
"peerDependencies": {
|
|
53
|
-
"vite": "^8.0.0-beta.
|
|
54
|
-
"vue": "^3.5.
|
|
46
|
+
"vite": "^8.0.0-beta.3",
|
|
47
|
+
"vue": "^3.5.26"
|
|
55
48
|
},
|
|
56
49
|
"engines": {
|
|
57
50
|
"bun": ">=1.3.0"
|
|
58
51
|
},
|
|
59
|
-
"
|
|
52
|
+
"publishConfig": {
|
|
53
|
+
"access": "public",
|
|
54
|
+
"registry": "https://registry.npmjs.org"
|
|
55
|
+
},
|
|
56
|
+
"gitHead": "d42bf60ba6b8b11fef7e759fa008ada075829772"
|
|
60
57
|
}
|
package/plugins/analyzer.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import { analyzer } from
|
|
1
|
+
import { analyzer } from "vite-bundle-analyzer";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* 创建打包分析插件配置
|
|
5
5
|
*/
|
|
6
6
|
export function createAnalyzerPlugin(options = {}) {
|
|
7
|
-
const { analyzerMode =
|
|
7
|
+
const { analyzerMode = "static", fileName = "bundle-report", reportTitle = "打包分析", openAnalyzer = false } = options;
|
|
8
8
|
|
|
9
9
|
return analyzer({
|
|
10
10
|
analyzerMode: analyzerMode,
|
|
11
11
|
fileName: fileName,
|
|
12
12
|
reportTitle: reportTitle,
|
|
13
|
-
defaultSizes:
|
|
13
|
+
defaultSizes: "gzip",
|
|
14
14
|
gzipOptions: {},
|
|
15
15
|
brotliOptions: {},
|
|
16
16
|
openAnalyzer: openAnalyzer,
|
package/plugins/auto-import.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import AutoImport from
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import AutoImport from "unplugin-auto-import/vite";
|
|
2
|
+
import { TDesignResolver } from "unplugin-vue-components/resolvers";
|
|
3
|
+
import { VueRouterAutoImports } from "unplugin-vue-router";
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* 创建自动导入插件配置
|
|
@@ -9,15 +9,15 @@ export function createAutoImportPlugin(options = {}) {
|
|
|
9
9
|
const { resolvers = {} } = options;
|
|
10
10
|
|
|
11
11
|
return AutoImport({
|
|
12
|
-
imports: [
|
|
12
|
+
imports: ["vue", "pinia", VueRouterAutoImports],
|
|
13
13
|
resolvers: [
|
|
14
14
|
TDesignResolver({
|
|
15
|
-
library:
|
|
15
|
+
library: "vue-next"
|
|
16
16
|
}),
|
|
17
17
|
...(resolvers.auto || [])
|
|
18
18
|
],
|
|
19
|
-
dts:
|
|
20
|
-
dirs: [
|
|
19
|
+
dts: "src/types/auto-imports.d.ts",
|
|
20
|
+
dirs: ["src/utils", "src/plugins", "src/config"],
|
|
21
21
|
vueTemplate: true
|
|
22
22
|
});
|
|
23
23
|
}
|
package/plugins/components.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { TDesignResolver } from
|
|
3
|
-
import
|
|
1
|
+
import IconsResolver from "unplugin-icons/resolver";
|
|
2
|
+
import { TDesignResolver } from "unplugin-vue-components/resolvers";
|
|
3
|
+
import Components from "unplugin-vue-components/vite";
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* 创建组件自动导入插件配置
|
|
@@ -11,13 +11,13 @@ export function createComponentsPlugin(options = {}) {
|
|
|
11
11
|
return Components({
|
|
12
12
|
resolvers: [
|
|
13
13
|
TDesignResolver({
|
|
14
|
-
library:
|
|
14
|
+
library: "vue-next"
|
|
15
15
|
}),
|
|
16
16
|
IconsResolver({}),
|
|
17
17
|
...(resolvers.components || [])
|
|
18
18
|
],
|
|
19
|
-
dirs: [
|
|
19
|
+
dirs: ["src/components"],
|
|
20
20
|
deep: true,
|
|
21
|
-
dts:
|
|
21
|
+
dts: "src/types/components.d.ts"
|
|
22
22
|
});
|
|
23
23
|
}
|
package/plugins/compression.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { compression } from
|
|
1
|
+
import { compression } from "vite-plugin-compression2";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* 创建文件压缩插件配置
|
|
5
5
|
*/
|
|
6
6
|
export function createCompressionPlugin(options = {}) {
|
|
7
|
-
const { threshold = 10240, algorithms = [
|
|
7
|
+
const { threshold = 10240, algorithms = ["gzip", "brotliCompress"] } = options;
|
|
8
8
|
|
|
9
9
|
return compression({
|
|
10
10
|
include: /\.(html|xml|css|json|js|mjs|svg)$/i,
|
package/plugins/devtools.js
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
|
-
import VueDevTools from
|
|
1
|
+
import VueDevTools from "vite-plugin-vue-devtools";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* 创建 Vue DevTools 插件配置(仅开发环境)
|
|
5
5
|
*/
|
|
6
6
|
export function createDevToolsPlugin() {
|
|
7
|
+
// 该插件内部会引入 inspector 能力;如果在非开发环境启用,容易引入不必要的解析开销/兼容性风险。
|
|
8
|
+
// Vite 的 plugins 数组允许包含 null/false,会被自动忽略。
|
|
9
|
+
if (process.env.NODE_ENV === "production") {
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
|
|
7
13
|
return VueDevTools();
|
|
8
14
|
}
|
package/plugins/icons.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import Icons from
|
|
1
|
+
import Icons from "unplugin-icons/vite";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* 创建图标插件配置
|
|
5
5
|
*/
|
|
6
6
|
export function createIconsPlugin() {
|
|
7
7
|
return Icons({
|
|
8
|
-
compiler:
|
|
8
|
+
compiler: "vue3",
|
|
9
9
|
autoInstall: false,
|
|
10
|
-
defaultClass:
|
|
11
|
-
defaultStyle:
|
|
10
|
+
defaultClass: "icon-befly",
|
|
11
|
+
defaultStyle: "vertical-align: middle;"
|
|
12
12
|
});
|
|
13
13
|
}
|
package/plugins/router.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import VueRouter from
|
|
1
|
+
import VueRouter from "unplugin-vue-router/vite";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* 创建路由插件配置
|
|
@@ -8,9 +8,9 @@ export function createRouterPlugin(options = {}) {
|
|
|
8
8
|
|
|
9
9
|
return VueRouter({
|
|
10
10
|
routesFolder: scanViews(),
|
|
11
|
-
dts:
|
|
12
|
-
extensions: [
|
|
13
|
-
importMode:
|
|
14
|
-
exclude: [
|
|
11
|
+
dts: "./src/types/typed-router.d.ts",
|
|
12
|
+
extensions: [".vue"],
|
|
13
|
+
importMode: "async",
|
|
14
|
+
exclude: ["**/components/**"]
|
|
15
15
|
});
|
|
16
16
|
}
|
package/plugins/unocss.js
CHANGED
package/plugins/vue.js
CHANGED
|
@@ -1,19 +1,13 @@
|
|
|
1
|
-
import vue from
|
|
2
|
-
import ReactivityTransform from '@vue-macros/reactivity-transform/vite';
|
|
1
|
+
import vue from "@vitejs/plugin-vue";
|
|
3
2
|
|
|
4
3
|
/**
|
|
5
4
|
* 创建 Vue 插件配置
|
|
6
5
|
*/
|
|
7
|
-
export function
|
|
8
|
-
return
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}),
|
|
15
|
-
ReactivityTransform({
|
|
16
|
-
exclude: []
|
|
17
|
-
})
|
|
18
|
-
];
|
|
6
|
+
export function createVuePlugin() {
|
|
7
|
+
return vue({
|
|
8
|
+
script: {
|
|
9
|
+
defineModel: true,
|
|
10
|
+
propsDestructure: true
|
|
11
|
+
}
|
|
12
|
+
});
|
|
19
13
|
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {Object} ArrayToTreeOptions
|
|
3
|
+
* @property {string=} idField
|
|
4
|
+
* @property {string=} pidField
|
|
5
|
+
* @property {string=} childrenField
|
|
6
|
+
* @property {any=} rootPid
|
|
7
|
+
* @property {(node: any) => any=} mapFn
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @template T
|
|
12
|
+
* @param {T[]} items
|
|
13
|
+
* @param {ArrayToTreeOptions=} options
|
|
14
|
+
* @returns {T[]}
|
|
15
|
+
*/
|
|
16
|
+
export function arrayToTree(items, options = {}) {
|
|
17
|
+
const idField = typeof options.idField === "string" ? options.idField : "id";
|
|
18
|
+
const pidField = typeof options.pidField === "string" ? options.pidField : "pid";
|
|
19
|
+
const childrenField = typeof options.childrenField === "string" ? options.childrenField : "children";
|
|
20
|
+
const rootPid = "rootPid" in options ? options.rootPid : 0;
|
|
21
|
+
const mapFn = typeof options.mapFn === "function" ? options.mapFn : null;
|
|
22
|
+
|
|
23
|
+
/** @type {T[]} */
|
|
24
|
+
const tree = [];
|
|
25
|
+
|
|
26
|
+
for (const item of items) {
|
|
27
|
+
// @ts-ignore
|
|
28
|
+
const pid = item[pidField];
|
|
29
|
+
|
|
30
|
+
if (Object.is(pid, rootPid)) {
|
|
31
|
+
const node = Object.assign({}, item);
|
|
32
|
+
const mappedNode = mapFn ? mapFn(node) : node;
|
|
33
|
+
|
|
34
|
+
// 子节点 rootPid = node[id]
|
|
35
|
+
// @ts-ignore
|
|
36
|
+
const nextRootPid = mappedNode[idField];
|
|
37
|
+
const children = arrayToTree(items, {
|
|
38
|
+
idField: idField,
|
|
39
|
+
pidField: pidField,
|
|
40
|
+
childrenField: childrenField,
|
|
41
|
+
rootPid: nextRootPid,
|
|
42
|
+
mapFn: mapFn
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
if (children.length > 0) {
|
|
46
|
+
// @ts-ignore
|
|
47
|
+
mappedNode[childrenField] = children;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
tree.push(mappedNode);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return tree;
|
|
55
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {Object} FieldClearOptions
|
|
3
|
+
* @property {string[]=} pickKeys
|
|
4
|
+
* @property {string[]=} omitKeys
|
|
5
|
+
* @property {any[]=} keepValues
|
|
6
|
+
* @property {any[]=} excludeValues
|
|
7
|
+
* @property {Record<string, any>=} keepMap
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
function isObject(val) {
|
|
11
|
+
return val !== null && typeof val === "object" && !Array.isArray(val);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function isArray(val) {
|
|
15
|
+
return Array.isArray(val);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* 清理对象/数组字段
|
|
20
|
+
* - 支持 pick/omit/keepValues/excludeValues
|
|
21
|
+
* - 支持 keepMap 强制保留
|
|
22
|
+
* @template T
|
|
23
|
+
* @param {T|T[]} data
|
|
24
|
+
* @param {FieldClearOptions=} options
|
|
25
|
+
* @returns {any}
|
|
26
|
+
*/
|
|
27
|
+
export function fieldClear(data, options = {}) {
|
|
28
|
+
const pickKeys = options.pickKeys;
|
|
29
|
+
const omitKeys = options.omitKeys;
|
|
30
|
+
const keepValues = options.keepValues;
|
|
31
|
+
const excludeValues = options.excludeValues;
|
|
32
|
+
const keepMap = options.keepMap;
|
|
33
|
+
|
|
34
|
+
const filterObj = (obj) => {
|
|
35
|
+
/** @type {Record<string, any>} */
|
|
36
|
+
const result = {};
|
|
37
|
+
|
|
38
|
+
let keys = Object.keys(obj);
|
|
39
|
+
if (pickKeys && pickKeys.length) {
|
|
40
|
+
keys = keys.filter((k) => pickKeys.includes(k));
|
|
41
|
+
}
|
|
42
|
+
if (omitKeys && omitKeys.length) {
|
|
43
|
+
keys = keys.filter((k) => !omitKeys.includes(k));
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
for (const key of keys) {
|
|
47
|
+
const value = obj[key];
|
|
48
|
+
|
|
49
|
+
// 1. keepMap 优先
|
|
50
|
+
if (keepMap && Object.prototype.hasOwnProperty.call(keepMap, key)) {
|
|
51
|
+
if (Object.is(keepMap[key], value)) {
|
|
52
|
+
result[key] = value;
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// 2. keepValues
|
|
58
|
+
if (keepValues && keepValues.length && !keepValues.includes(value)) {
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// 3. excludeValues
|
|
63
|
+
if (excludeValues && excludeValues.length && excludeValues.includes(value)) {
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
result[key] = value;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return result;
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
if (isArray(data)) {
|
|
74
|
+
return data
|
|
75
|
+
.map((item) => {
|
|
76
|
+
if (isObject(item)) {
|
|
77
|
+
return filterObj(item);
|
|
78
|
+
}
|
|
79
|
+
return item;
|
|
80
|
+
})
|
|
81
|
+
.filter((item) => {
|
|
82
|
+
if (isObject(item)) {
|
|
83
|
+
return Object.keys(item).length > 0;
|
|
84
|
+
}
|
|
85
|
+
return true;
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (isObject(data)) {
|
|
90
|
+
return filterObj(data);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return data;
|
|
94
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 密码哈希工具(浏览器侧)
|
|
3
|
+
* 使用 SHA-256 + 盐值对密码进行单向哈希
|
|
4
|
+
* @param {string} password
|
|
5
|
+
* @param {string=} salt
|
|
6
|
+
* @returns {Promise<string>} 十六进制哈希
|
|
7
|
+
*/
|
|
8
|
+
export async function hashPassword(password, salt = "befly") {
|
|
9
|
+
const data = String(password) + String(salt);
|
|
10
|
+
|
|
11
|
+
const encoder = new TextEncoder();
|
|
12
|
+
const dataBuffer = encoder.encode(data);
|
|
13
|
+
|
|
14
|
+
// Web Crypto API
|
|
15
|
+
const hashBuffer = await crypto.subtle.digest("SHA-256", dataBuffer);
|
|
16
|
+
|
|
17
|
+
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
|
18
|
+
const hashHex = hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
19
|
+
|
|
20
|
+
return hashHex;
|
|
21
|
+
}
|
package/utils/layouts.js
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 自定义布局处理函数
|
|
3
|
+
* 根据文件名后缀 _数字 判断使用哪个布局
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @typedef {Object} RouteConfig
|
|
8
|
+
* @property {string=} path
|
|
9
|
+
* @property {any=} component
|
|
10
|
+
* @property {RouteConfig[]=} children
|
|
11
|
+
* @property {Record<string, any>=} meta
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @typedef {Object} LayoutConfig
|
|
16
|
+
* @property {string} path
|
|
17
|
+
* @property {string} layoutName
|
|
18
|
+
* @property {any} component
|
|
19
|
+
* @property {Record<string, any>=} meta
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @param {RouteConfig[]} routes
|
|
24
|
+
* @param {string=} inheritLayout
|
|
25
|
+
* @returns {LayoutConfig[]}
|
|
26
|
+
*/
|
|
27
|
+
export function Layouts(routes, inheritLayout = "") {
|
|
28
|
+
/** @type {LayoutConfig[]} */
|
|
29
|
+
const result = [];
|
|
30
|
+
|
|
31
|
+
for (const route of routes) {
|
|
32
|
+
const currentPath = route.path || "";
|
|
33
|
+
|
|
34
|
+
const pathMatch = currentPath.match(/_(\d+)$/);
|
|
35
|
+
const currentLayout = pathMatch ? pathMatch[1] : inheritLayout;
|
|
36
|
+
|
|
37
|
+
// 中间节点:递归处理子路由,不包裹布局
|
|
38
|
+
if (route.children && route.children.length > 0) {
|
|
39
|
+
const cleanPath = pathMatch ? currentPath.replace(/_\d+$/, "") : currentPath;
|
|
40
|
+
const childConfigs = Layouts(route.children, currentLayout);
|
|
41
|
+
|
|
42
|
+
for (const child of childConfigs) {
|
|
43
|
+
const mergedPath = cleanPath ? `${cleanPath}/${child.path}`.replace(/\/+/, "/") : child.path;
|
|
44
|
+
result.push({
|
|
45
|
+
path: mergedPath,
|
|
46
|
+
layoutName: child.layoutName,
|
|
47
|
+
component: child.component,
|
|
48
|
+
meta: child.meta
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// 叶子节点:包裹布局
|
|
55
|
+
const lastPart = currentPath;
|
|
56
|
+
const match = lastPart.match(/_(\d+)$/);
|
|
57
|
+
const layoutName = match ? match[1] : currentLayout || "default";
|
|
58
|
+
|
|
59
|
+
let cleanPath = "";
|
|
60
|
+
if (lastPart === "index" || (lastPart.startsWith("index_") && match)) {
|
|
61
|
+
cleanPath = "";
|
|
62
|
+
} else if (match) {
|
|
63
|
+
cleanPath = lastPart.replace(/_\d+$/, "");
|
|
64
|
+
} else {
|
|
65
|
+
cleanPath = lastPart;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
result.push({
|
|
69
|
+
path: cleanPath,
|
|
70
|
+
layoutName: layoutName,
|
|
71
|
+
component: route.component,
|
|
72
|
+
meta: route.meta
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return result;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* 将 Layouts 输出的扁平配置转换为 Vue Router 的 RouteRecordRaw
|
|
81
|
+
* 说明:resolveLayoutComponent 由业务方提供,以避免 utils 强耦合具体项目的布局路径。
|
|
82
|
+
*
|
|
83
|
+
* @param {LayoutConfig[]} configs
|
|
84
|
+
* @param {(layoutName: string) => any} resolveLayoutComponent
|
|
85
|
+
* @returns {import('vue-router').RouteRecordRaw[]}
|
|
86
|
+
*/
|
|
87
|
+
export function applyLayouts(configs, resolveLayoutComponent) {
|
|
88
|
+
return configs.map((config) => {
|
|
89
|
+
const layoutComponent = resolveLayoutComponent(config.layoutName);
|
|
90
|
+
|
|
91
|
+
return {
|
|
92
|
+
path: config.path,
|
|
93
|
+
component: layoutComponent,
|
|
94
|
+
meta: config.meta,
|
|
95
|
+
children: [
|
|
96
|
+
{
|
|
97
|
+
path: "",
|
|
98
|
+
component: config.component
|
|
99
|
+
}
|
|
100
|
+
]
|
|
101
|
+
};
|
|
102
|
+
});
|
|
103
|
+
}
|
package/utils/router.js
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 路由相关工具函数(守卫 / 布局装配 / resolver 等)
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { Layouts, applyLayouts } from "./layouts.js";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* 规范化路由 path:去尾随 "/"(根路径 "/" 例外)。
|
|
9
|
+
*
|
|
10
|
+
* @param {any} path
|
|
11
|
+
* @returns {any}
|
|
12
|
+
*/
|
|
13
|
+
export function normalizeRoutePath(path) {
|
|
14
|
+
if (typeof path !== "string") {
|
|
15
|
+
return path;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const normalized = path.replace(/\/+$/, "");
|
|
19
|
+
return normalized.length === 0 ? "/" : normalized;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* 应用一个最小可用的 token 鉴权守卫(业务方提供 token 获取方式与路径)。
|
|
24
|
+
*
|
|
25
|
+
* 约定:当路由 meta.public === true 时认为是公开路由。
|
|
26
|
+
*
|
|
27
|
+
* @param {import('vue-router').Router} router
|
|
28
|
+
* @param {{
|
|
29
|
+
* getToken: () => any,
|
|
30
|
+
* loginPath: string,
|
|
31
|
+
* homePath: string
|
|
32
|
+
* }} options
|
|
33
|
+
*/
|
|
34
|
+
export function applyTokenAuthGuard(router, options) {
|
|
35
|
+
const normalizedLoginPath = normalizeRoutePath(options.loginPath);
|
|
36
|
+
const normalizedHomePath = normalizeRoutePath(options.homePath);
|
|
37
|
+
|
|
38
|
+
router.beforeEach(async (to, _from, next) => {
|
|
39
|
+
const token = options.getToken();
|
|
40
|
+
const toPath = normalizeRoutePath(to.path);
|
|
41
|
+
|
|
42
|
+
// 0. 根路径重定向
|
|
43
|
+
if (toPath === "/") {
|
|
44
|
+
return next(token ? normalizedHomePath : normalizedLoginPath);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// 1. 未登录且访问非公开路由 → 跳转登录
|
|
48
|
+
if (!token && to.meta?.public !== true && toPath !== normalizedLoginPath) {
|
|
49
|
+
return next(normalizedLoginPath);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// 2. 已登录访问登录页 → 跳转首页
|
|
53
|
+
if (token && toPath === normalizedLoginPath) {
|
|
54
|
+
return next(normalizedHomePath);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
next();
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* 将“组件/懒加载函数/Promise”统一转换为 Vue Router 可接受的懒加载 component 函数。
|
|
63
|
+
*
|
|
64
|
+
* - 如果已经是函数(通常是 `() => import(...)`),直接返回。
|
|
65
|
+
* - 否则包一层函数(使其变成 lazy component)。
|
|
66
|
+
*
|
|
67
|
+
* @param {any} value
|
|
68
|
+
* @returns {any}
|
|
69
|
+
*/
|
|
70
|
+
function toLazyComponent(value) {
|
|
71
|
+
if (typeof value === "function") {
|
|
72
|
+
return value;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return () => value;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* 创建布局组件解析器(resolver)。
|
|
80
|
+
*
|
|
81
|
+
* @param {{
|
|
82
|
+
* resolveDefaultLayout: () => any,
|
|
83
|
+
* resolveNamedLayout: (layoutName: string) => any,
|
|
84
|
+
* defaultLayoutName?: string
|
|
85
|
+
* }} options
|
|
86
|
+
* @returns {(layoutName: string) => any}
|
|
87
|
+
*/
|
|
88
|
+
export function createLayoutComponentResolver(options) {
|
|
89
|
+
const defaultLayoutName = options.defaultLayoutName || "default";
|
|
90
|
+
|
|
91
|
+
return (layoutName) => {
|
|
92
|
+
if (layoutName === defaultLayoutName) {
|
|
93
|
+
return toLazyComponent(options.resolveDefaultLayout());
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return toLazyComponent(options.resolveNamedLayout(layoutName));
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* 将 auto-routes 的 routes 按 `_数字` 规则套用布局组件,并输出 Vue Router 的 RouteRecordRaw[]。
|
|
102
|
+
*
|
|
103
|
+
* @param {any[]} routes
|
|
104
|
+
* @param {(layoutName: string) => any} resolveLayoutComponent
|
|
105
|
+
* @returns {import('vue-router').RouteRecordRaw[]}
|
|
106
|
+
*/
|
|
107
|
+
export function buildLayoutRoutes(routes, resolveLayoutComponent) {
|
|
108
|
+
return applyLayouts(Layouts(routes), resolveLayoutComponent);
|
|
109
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { existsSync, readdirSync, realpathSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* 扫描项目和所有 @befly-addon 包的 views 目录
|
|
6
|
+
* 用于 unplugin-vue-router 的 routesFolder 配置
|
|
7
|
+
* 注意:此函数只能在 vite.config.js 中使用(Node.js 环境),不能在浏览器中使用
|
|
8
|
+
* @returns {Array<{ src: string, path: string, exclude: string[] }>} 路由文件夹配置数组
|
|
9
|
+
*/
|
|
10
|
+
export function scanViews() {
|
|
11
|
+
const projectRoot = process.cwd();
|
|
12
|
+
const addonBasePath = join(projectRoot, "node_modules", "@befly-addon");
|
|
13
|
+
|
|
14
|
+
/** @type {Array<{ src: string, path: string, exclude: string[] }>} */
|
|
15
|
+
const routesFolders = [];
|
|
16
|
+
|
|
17
|
+
// 1. 项目自身 views
|
|
18
|
+
const projectViewsPath = join(projectRoot, "src", "views");
|
|
19
|
+
if (existsSync(projectViewsPath)) {
|
|
20
|
+
routesFolders.push({
|
|
21
|
+
src: realpathSync(projectViewsPath),
|
|
22
|
+
path: "",
|
|
23
|
+
exclude: ["**/components/**"]
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// 2. 扫描 @befly-addon/*/views
|
|
28
|
+
if (!existsSync(addonBasePath)) {
|
|
29
|
+
return routesFolders;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
try {
|
|
33
|
+
const addonDirs = readdirSync(addonBasePath);
|
|
34
|
+
|
|
35
|
+
for (const addonName of addonDirs) {
|
|
36
|
+
const addonPath = join(addonBasePath, addonName);
|
|
37
|
+
if (!existsSync(addonPath)) {
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const viewsPath = join(addonPath, "views");
|
|
42
|
+
if (existsSync(viewsPath)) {
|
|
43
|
+
routesFolders.push({
|
|
44
|
+
src: realpathSync(viewsPath),
|
|
45
|
+
path: `addon/${addonName}/`,
|
|
46
|
+
exclude: ["**/components/**"]
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
} catch {
|
|
51
|
+
// 扫描失败保持静默,避免影响 Vite 启动
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return routesFolders;
|
|
55
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 为表格列添加默认配置
|
|
3
|
+
* @param {any[]} columns
|
|
4
|
+
* @param {Record<string, any>=} customConfig
|
|
5
|
+
* @returns {any[]}
|
|
6
|
+
*/
|
|
7
|
+
export function withDefaultColumns(columns, customConfig = {}) {
|
|
8
|
+
/** @type {Record<string, any>} */
|
|
9
|
+
const specialColumnConfig = Object.assign(
|
|
10
|
+
{
|
|
11
|
+
operation: { width: 100, align: "center", fixed: "right" },
|
|
12
|
+
state: { width: 100, align: "center" },
|
|
13
|
+
id: { width: 200, align: "center" }
|
|
14
|
+
},
|
|
15
|
+
customConfig
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
return columns.map((col) => {
|
|
19
|
+
const colKey = col && col.colKey;
|
|
20
|
+
|
|
21
|
+
let specialConfig = colKey ? specialColumnConfig[colKey] : undefined;
|
|
22
|
+
|
|
23
|
+
if (!specialConfig && colKey && (colKey.endsWith("At") || colKey.endsWith("At2"))) {
|
|
24
|
+
specialConfig = { align: "center" };
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const base = {
|
|
28
|
+
width: 200,
|
|
29
|
+
ellipsis: true
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const merged = Object.assign({}, base);
|
|
33
|
+
if (specialConfig) {
|
|
34
|
+
Object.assign(merged, specialConfig);
|
|
35
|
+
}
|
|
36
|
+
Object.assign(merged, col);
|
|
37
|
+
|
|
38
|
+
return merged;
|
|
39
|
+
});
|
|
40
|
+
}
|