create-secra 0.1.5 → 0.1.7
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 +6 -0
- package/README.zh-CN.md +6 -0
- package/antd-adapter-template/apps/core/index.html +13 -0
- package/antd-adapter-template/apps/core/package.json +18 -0
- package/antd-adapter-template/apps/core/public/favicon.ico +1 -0
- package/antd-adapter-template/apps/core/public/favicon.svg +1 -0
- package/antd-adapter-template/apps/core/public/logo.svg +1 -0
- package/antd-adapter-template/apps/core/src/api/auth.ts +49 -0
- package/antd-adapter-template/apps/core/src/assets/react.svg +1 -0
- package/antd-adapter-template/apps/core/src/components/AntdGlobalProvider.tsx +87 -0
- package/antd-adapter-template/apps/core/src/components/AntdRootLayout.tsx +10 -0
- package/antd-adapter-template/apps/core/src/components/layout.tsx +387 -0
- package/antd-adapter-template/apps/core/src/guards/auth-route-guard.ts +45 -0
- package/antd-adapter-template/apps/core/src/main.tsx +65 -0
- package/antd-adapter-template/apps/core/src/pages/auth/components/account-login-fields.tsx +60 -0
- package/antd-adapter-template/apps/core/src/pages/auth/components/phone-login-fields.tsx +60 -0
- package/antd-adapter-template/apps/core/src/pages/auth/login.tsx +169 -0
- package/antd-adapter-template/apps/core/src/pages/index.tsx +156 -0
- package/antd-adapter-template/apps/core/src/router.ts +42 -0
- package/antd-adapter-template/apps/core/src/shims/use-sync-external-store-shim.ts +3 -0
- package/antd-adapter-template/apps/core/src/theme/theme.css +48 -0
- package/antd-adapter-template/apps/core/src/types/crypto-js.d.ts +5 -0
- package/antd-adapter-template/apps/core/src/utils/index.ts +12 -0
- package/antd-adapter-template/apps/core/src/utils/md5.ts +6 -0
- package/antd-adapter-template/apps/core/tsconfig.app.json +11 -0
- package/antd-adapter-template/apps/core/tsconfig.json +13 -0
- package/antd-adapter-template/apps/core/tsconfig.node.json +7 -0
- package/antd-adapter-template/apps/core/vite.config.ts +118 -0
- package/antd-adapter-template/eslint.config.js +23 -0
- package/antd-adapter-template/package.json +63 -0
- package/antd-adapter-template/packages/sdk/.swcrc +18 -0
- package/antd-adapter-template/packages/sdk/package.json +52 -0
- package/antd-adapter-template/packages/sdk/src/build/index.ts +28 -0
- package/antd-adapter-template/packages/sdk/src/build/plugins/auto-import.ts +46 -0
- package/antd-adapter-template/packages/sdk/src/build/plugins/bundle-analyzer.ts +33 -0
- package/antd-adapter-template/packages/sdk/src/build/plugins/remove-console.ts +23 -0
- package/antd-adapter-template/packages/sdk/src/build/plugins/unocss.ts +202 -0
- package/antd-adapter-template/packages/sdk/src/build/plugins/unplugin-icon.ts +43 -0
- package/antd-adapter-template/packages/sdk/src/components/i18n-switch-dropdown.tsx +139 -0
- package/antd-adapter-template/packages/sdk/src/components/index.ts +2 -0
- package/antd-adapter-template/packages/sdk/src/components/theme-switch-dropdown.tsx +131 -0
- package/antd-adapter-template/packages/sdk/src/hooks/auth/core.ts +101 -0
- package/antd-adapter-template/packages/sdk/src/hooks/auth/index.ts +139 -0
- package/antd-adapter-template/packages/sdk/src/hooks/auth/with-auth.tsx +41 -0
- package/antd-adapter-template/packages/sdk/src/hooks/index.ts +1 -0
- package/antd-adapter-template/packages/sdk/src/i18n/index.ts +150 -0
- package/antd-adapter-template/packages/sdk/src/index.ts +11 -0
- package/antd-adapter-template/packages/sdk/src/request/index.ts +436 -0
- package/antd-adapter-template/packages/sdk/src/storage/README.md +30 -0
- package/antd-adapter-template/packages/sdk/src/storage/index.ts +57 -0
- package/antd-adapter-template/packages/sdk/src/styles/reset.css +111 -0
- package/antd-adapter-template/packages/sdk/src/theme/index.ts +466 -0
- package/antd-adapter-template/packages/sdk/tsconfig.json +16 -0
- package/antd-adapter-template/pnpm-workspace.yaml +3 -0
- package/antd-adapter-template/tsconfig.app.json +29 -0
- package/antd-adapter-template/tsconfig.json +7 -0
- package/antd-adapter-template/tsconfig.node.json +27 -0
- package/antd-adapter-template/turbo.json +17 -0
- package/bin/index.mjs +165 -33
- package/package.json +3 -2
- package/template/apps/core/src/main.tsx +11 -18
- package/template/apps/core/src/router.ts +5 -1
- package/template/package.json +1 -1
- package/template/packages/sdk/src/build/plugins/unocss.ts +3 -0
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { defineConfig } from 'vite'
|
|
2
|
+
import react from '@vitejs/plugin-react'
|
|
3
|
+
import Inspect from 'vite-plugin-inspect'
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import {
|
|
6
|
+
setupAutoImport,
|
|
7
|
+
setupUnocss,
|
|
8
|
+
setupUnPluginIcon,
|
|
9
|
+
setupRemoveConsole,
|
|
10
|
+
include,
|
|
11
|
+
} from '@vlian/sdk/build';
|
|
12
|
+
|
|
13
|
+
// https://vite.dev/config/
|
|
14
|
+
export default defineConfig(({ mode }) => {
|
|
15
|
+
void mode;
|
|
16
|
+
|
|
17
|
+
return {
|
|
18
|
+
plugins: [
|
|
19
|
+
react(),
|
|
20
|
+
// 开发环境:打包检查工具(可选,需要 vite@^6.0.0)
|
|
21
|
+
// 注意:vite-plugin-inspect 在某些情况下可能不兼容,如遇错误请注释掉
|
|
22
|
+
...(process.env.NODE_ENV === 'development' ? [Inspect()] : []),
|
|
23
|
+
|
|
24
|
+
// 生产环境:移除 console
|
|
25
|
+
setupRemoveConsole(),
|
|
26
|
+
|
|
27
|
+
// 自动导入
|
|
28
|
+
setupAutoImport(),
|
|
29
|
+
|
|
30
|
+
// UnoCSS(需要指定本地图标路径)
|
|
31
|
+
setupUnocss(
|
|
32
|
+
path.join(process.cwd(), 'src/assets/svg-icon'),
|
|
33
|
+
{
|
|
34
|
+
// 覆盖 content 配置,扫描主应用代码
|
|
35
|
+
content: {
|
|
36
|
+
filesystem: ['./src/**/*.{tsx,ts,jsx,js}'],
|
|
37
|
+
},
|
|
38
|
+
}
|
|
39
|
+
),
|
|
40
|
+
|
|
41
|
+
// 图标插件(SVG 支持)
|
|
42
|
+
...setupUnPluginIcon(
|
|
43
|
+
path.join(process.cwd(), 'src/assets/svg-icon')
|
|
44
|
+
),
|
|
45
|
+
|
|
46
|
+
// 打包分析(可选,建议仅在需要时启用)
|
|
47
|
+
// setupBundleAnalyzer({
|
|
48
|
+
// filename: '../../dist/main/stats.html',
|
|
49
|
+
// open: true,
|
|
50
|
+
// }),
|
|
51
|
+
],
|
|
52
|
+
resolve: {
|
|
53
|
+
alias: {
|
|
54
|
+
'@': path.resolve(__dirname, './src'),
|
|
55
|
+
'use-sync-external-store/shim': path.resolve(__dirname, './src/shims/use-sync-external-store-shim.ts'),
|
|
56
|
+
'use-sync-external-store/shim/index.js': path.resolve(__dirname, './src/shims/use-sync-external-store-shim.ts'),
|
|
57
|
+
},
|
|
58
|
+
preserveSymlinks: false,
|
|
59
|
+
},
|
|
60
|
+
// 依赖优化
|
|
61
|
+
optimizeDeps: {
|
|
62
|
+
include: [...include],
|
|
63
|
+
// exclude: ["@vlian/sdk", "@vlian/sdk/request", "@vlian/sdk/build", "lightningcss"],
|
|
64
|
+
},
|
|
65
|
+
server: {
|
|
66
|
+
host: '127.0.0.1',
|
|
67
|
+
port: 5173,
|
|
68
|
+
open: true,
|
|
69
|
+
},
|
|
70
|
+
build: {
|
|
71
|
+
outDir: '../../dist/core',
|
|
72
|
+
sourcemap: false,
|
|
73
|
+
manifest: true,
|
|
74
|
+
// 确保 CSS 被提取到单独文件
|
|
75
|
+
cssCodeSplit: true,
|
|
76
|
+
chunkSizeWarningLimit: 700,
|
|
77
|
+
modulePreload: {
|
|
78
|
+
// Keep HTML preload list focused to avoid over-eager first-wave requests.
|
|
79
|
+
resolveDependencies: (_filename, deps, context) => {
|
|
80
|
+
if (context.hostType !== 'html') return deps;
|
|
81
|
+
return deps.filter(
|
|
82
|
+
(dep) =>
|
|
83
|
+
dep.includes('rolldown-runtime') ||
|
|
84
|
+
dep.includes('/index-') ||
|
|
85
|
+
dep.includes('/index.'),
|
|
86
|
+
);
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
rollupOptions: {
|
|
90
|
+
// Node-only adapter dependency used by framework optional path.
|
|
91
|
+
// Keep it external to avoid browser bundle resolution failure.
|
|
92
|
+
external: ['undici'],
|
|
93
|
+
output: {
|
|
94
|
+
manualChunks(id) {
|
|
95
|
+
if (id.includes('node_modules')) {
|
|
96
|
+
if (id.includes('/node_modules/@ant-design/pro-components/')) return 'pro-vendor';
|
|
97
|
+
if (
|
|
98
|
+
id.includes('/node_modules/react/') ||
|
|
99
|
+
id.includes('/node_modules/react-dom/') ||
|
|
100
|
+
id.includes('/node_modules/scheduler/')
|
|
101
|
+
) return 'react-vendor';
|
|
102
|
+
if (id.includes('/node_modules/@ant-design/icons/')) return 'antd-icons-vendor';
|
|
103
|
+
if (
|
|
104
|
+
id.includes('/node_modules/antd/') ||
|
|
105
|
+
(id.includes('/node_modules/@ant-design/') && !id.includes('/node_modules/@ant-design/pro-components/'))
|
|
106
|
+
) return 'antd-vendor';
|
|
107
|
+
if (id.includes('@vlian/framework/dist/request/')) return 'framework-request-vendor';
|
|
108
|
+
if (id.includes('@vlian/framework/dist/state/')) return 'framework-state-vendor';
|
|
109
|
+
if (id.includes('@vlian/framework/dist/core/')) return 'framework-core-vendor';
|
|
110
|
+
if (id.includes('@vlian/framework')) return 'framework-misc-vendor';
|
|
111
|
+
if (id.includes('i18next') || id.includes('react-i18next')) return 'i18n-vendor';
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
},
|
|
117
|
+
};
|
|
118
|
+
})
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import js from '@eslint/js'
|
|
2
|
+
import globals from 'globals'
|
|
3
|
+
import reactHooks from 'eslint-plugin-react-hooks'
|
|
4
|
+
import reactRefresh from 'eslint-plugin-react-refresh'
|
|
5
|
+
import tseslint from 'typescript-eslint'
|
|
6
|
+
import { defineConfig, globalIgnores } from 'eslint/config'
|
|
7
|
+
|
|
8
|
+
export default defineConfig([
|
|
9
|
+
globalIgnores(['dist']),
|
|
10
|
+
{
|
|
11
|
+
files: ['**/*.{ts,tsx}'],
|
|
12
|
+
extends: [
|
|
13
|
+
js.configs.recommended,
|
|
14
|
+
tseslint.configs.recommended,
|
|
15
|
+
reactHooks.configs.flat.recommended,
|
|
16
|
+
reactRefresh.configs.vite,
|
|
17
|
+
],
|
|
18
|
+
languageOptions: {
|
|
19
|
+
ecmaVersion: 2020,
|
|
20
|
+
globals: globals.browser,
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
])
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "secra-admin",
|
|
3
|
+
"private": true,
|
|
4
|
+
"version": "0.0.15",
|
|
5
|
+
"packageManager": "pnpm@9.12.3",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"build": "turbo run build",
|
|
8
|
+
"dev": "turbo run dev",
|
|
9
|
+
"lint": "turbo run lint",
|
|
10
|
+
"test": "turbo run test",
|
|
11
|
+
"clean:node_modules": "find . -type d -name 'node_modules' -prune -exec rm -rf '{}' +",
|
|
12
|
+
"build:packages": "pnpm -r --filter \"./packages/*\" build"
|
|
13
|
+
},
|
|
14
|
+
"dependencies": {
|
|
15
|
+
"@ant-design/icons": "^6.1.0",
|
|
16
|
+
"@ant-design/pro-components": "^2.8.10",
|
|
17
|
+
"@ant-design/v5-patch-for-react-19": "^1.0.3",
|
|
18
|
+
"@vlian/framework": "^1.2.16",
|
|
19
|
+
"@vlian/infrastructure": "^0.9.11",
|
|
20
|
+
"@vlian/sdk": "workspace:*",
|
|
21
|
+
"ahooks": "^3.8.5",
|
|
22
|
+
"antd": "^5.29.3",
|
|
23
|
+
"i18next": "^25.7.4",
|
|
24
|
+
"immer": "^10.1.3",
|
|
25
|
+
"ky": "^1.14.2",
|
|
26
|
+
"lodash": "^4.17.21",
|
|
27
|
+
"react": "^19.2.0",
|
|
28
|
+
"react-dom": "^19.2.0",
|
|
29
|
+
"react-i18next": "^15.7.4",
|
|
30
|
+
"react-router-dom": "^7.8.2"
|
|
31
|
+
},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"@eslint/js": "^9.39.1",
|
|
34
|
+
"@iconify/utils": "^3.1.0",
|
|
35
|
+
"@types/lodash": "^4.17.21",
|
|
36
|
+
"@types/node": "^24.10.1",
|
|
37
|
+
"@types/react": "^19.2.5",
|
|
38
|
+
"@types/react-dom": "^19.2.3",
|
|
39
|
+
"@unocss/core": "^66.6.0",
|
|
40
|
+
"@unocss/preset-attributify": "^66.6.0",
|
|
41
|
+
"@unocss/preset-icons": "^66.6.0",
|
|
42
|
+
"@unocss/preset-uno": "^66.6.0",
|
|
43
|
+
"@unocss/transformer-directives": "^66.6.0",
|
|
44
|
+
"@unocss/transformer-variant-group": "^66.6.0",
|
|
45
|
+
"@unocss/vite": "^66.6.0",
|
|
46
|
+
"@vitejs/plugin-react": "^5.1.1",
|
|
47
|
+
"eslint": "^9.39.1",
|
|
48
|
+
"eslint-plugin-react-hooks": "^7.0.1",
|
|
49
|
+
"eslint-plugin-react-refresh": "^0.4.24",
|
|
50
|
+
"globals": "^16.5.0",
|
|
51
|
+
"gogocode": "^1.0.53",
|
|
52
|
+
"rollup-plugin-visualizer": "^5.14.0",
|
|
53
|
+
"turbo": "^2.7.5",
|
|
54
|
+
"typescript": "~5.9.3",
|
|
55
|
+
"typescript-eslint": "^8.46.4",
|
|
56
|
+
"unplugin-auto-import": "^0.17.8",
|
|
57
|
+
"unplugin-icons": "^0.20.1",
|
|
58
|
+
"vite": "npm:rolldown-vite@7.2.5",
|
|
59
|
+
"vite-plugin-inspect": "^11.3.3",
|
|
60
|
+
"vite-plugin-remove-console": "^1.3.0",
|
|
61
|
+
"vite-plugin-svg-icons": "^2.0.1"
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@vlian/sdk",
|
|
3
|
+
"version": "1.0.15",
|
|
4
|
+
"description": "",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"types": "dist/types/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/types/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"default": "./dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"./request": {
|
|
15
|
+
"types": "./dist/types/request/index.d.ts",
|
|
16
|
+
"import": "./dist/request/index.js",
|
|
17
|
+
"default": "./dist/request/index.js"
|
|
18
|
+
},
|
|
19
|
+
"./build": {
|
|
20
|
+
"types": "./dist/types/build/index.d.ts",
|
|
21
|
+
"import": "./dist/build/index.js",
|
|
22
|
+
"default": "./dist/build/index.js"
|
|
23
|
+
},
|
|
24
|
+
"./i18n": {
|
|
25
|
+
"types": "./dist/types/i18n/index.d.ts",
|
|
26
|
+
"import": "./dist/i18n/index.js",
|
|
27
|
+
"default": "./dist/i18n/index.js"
|
|
28
|
+
},
|
|
29
|
+
"./hooks": {
|
|
30
|
+
"types": "./dist/types/hooks/index.d.ts",
|
|
31
|
+
"import": "./dist/hooks/index.js",
|
|
32
|
+
"default": "./dist/hooks/index.js"
|
|
33
|
+
},
|
|
34
|
+
"./hooks/auth": {
|
|
35
|
+
"types": "./dist/types/hooks/auth/index.d.ts",
|
|
36
|
+
"import": "./dist/hooks/auth/index.js",
|
|
37
|
+
"default": "./dist/hooks/auth/index.js"
|
|
38
|
+
},
|
|
39
|
+
"./reset.css": "./dist/styles/reset.css"
|
|
40
|
+
},
|
|
41
|
+
"scripts": {
|
|
42
|
+
"build": "pnpm run build:js && pnpm run build:types && pnpm run build:assets",
|
|
43
|
+
"build:js": "swc src -d dist --config-file .swcrc --source-maps --strip-leading-paths",
|
|
44
|
+
"build:types": "tsc -p tsconfig.json --emitDeclarationOnly --declaration --declarationMap --outDir dist/types",
|
|
45
|
+
"build:assets": "mkdir -p dist/styles && cp src/styles/reset.css dist/styles/reset.css"
|
|
46
|
+
},
|
|
47
|
+
"devDependencies": {
|
|
48
|
+
"@swc/cli": "^0.7.3",
|
|
49
|
+
"@swc/core": "^1.13.5"
|
|
50
|
+
},
|
|
51
|
+
"private": true
|
|
52
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @vlian/sdk/build
|
|
3
|
+
* 构建工具和配置共享包
|
|
4
|
+
*
|
|
5
|
+
* 通过子路径 @vlian/sdk/build 暴露,避免污染根入口运行时依赖。
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// 导出版本
|
|
9
|
+
export const version = '0.0.1';
|
|
10
|
+
|
|
11
|
+
// 插件导出
|
|
12
|
+
export { setupAutoImport } from './plugins/auto-import.js';
|
|
13
|
+
export { setupUnocss } from './plugins/unocss.js';
|
|
14
|
+
export { setupUnPluginIcon } from './plugins/unplugin-icon.js';
|
|
15
|
+
export { setupRemoveConsole } from './plugins/remove-console.js';
|
|
16
|
+
export { setupBundleAnalyzer } from './plugins/bundle-analyzer.js';
|
|
17
|
+
|
|
18
|
+
// 依赖优化列表(用于 optimizeDeps.include)
|
|
19
|
+
export const include = [
|
|
20
|
+
'ahooks',
|
|
21
|
+
'i18next',
|
|
22
|
+
'lodash',
|
|
23
|
+
'immer',
|
|
24
|
+
'react-i18next',
|
|
25
|
+
] as const;
|
|
26
|
+
|
|
27
|
+
// 类型导出
|
|
28
|
+
export type { UserConfig } from '@unocss/core';
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import AutoImport from 'unplugin-auto-import/vite';
|
|
2
|
+
import IconsResolver from 'unplugin-icons/resolver';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* 自动导入配置
|
|
6
|
+
*
|
|
7
|
+
* 功能:
|
|
8
|
+
* - 自动导入 React、React Router、ahooks 等常用库
|
|
9
|
+
* - 自动导入图标组件
|
|
10
|
+
* - 自动导入自定义 hooks 和组件
|
|
11
|
+
*/
|
|
12
|
+
export function setupAutoImport() {
|
|
13
|
+
return AutoImport({
|
|
14
|
+
// 扫描目录,自动导入 hooks 和组件
|
|
15
|
+
dirs: ['src/hooks/**', 'src/components/**'],
|
|
16
|
+
|
|
17
|
+
// 自动导入类型声明文件
|
|
18
|
+
dts: 'src/types/auto-imports.d.ts',
|
|
19
|
+
|
|
20
|
+
// 自动导入的库
|
|
21
|
+
imports: [
|
|
22
|
+
'react',
|
|
23
|
+
'react-router-dom',
|
|
24
|
+
'react-i18next',
|
|
25
|
+
'ahooks',
|
|
26
|
+
// React 类型导入
|
|
27
|
+
{ from: 'react', imports: ['FC', 'ReactNode', 'ComponentType'], type: true },
|
|
28
|
+
],
|
|
29
|
+
|
|
30
|
+
// 匹配的文件
|
|
31
|
+
include: [/\.[tj]sx?$/],
|
|
32
|
+
|
|
33
|
+
// 排除的文件(排除文档文件和其他非代码文件)
|
|
34
|
+
exclude: [/\.md$/, /\.d\.ts$/, /\.test\.(ts|tsx)$/, /\.spec\.(ts|tsx)$/],
|
|
35
|
+
|
|
36
|
+
// 解析器
|
|
37
|
+
resolvers: [
|
|
38
|
+
// 图标解析器
|
|
39
|
+
IconsResolver({
|
|
40
|
+
customCollections: ['local'],
|
|
41
|
+
extension: 'tsx',
|
|
42
|
+
prefix: 'icon',
|
|
43
|
+
}),
|
|
44
|
+
],
|
|
45
|
+
});
|
|
46
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { visualizer } from 'rollup-plugin-visualizer';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 打包分析插件
|
|
5
|
+
*
|
|
6
|
+
* 功能:
|
|
7
|
+
* - 生成打包分析报告
|
|
8
|
+
* - 可视化 bundle 大小
|
|
9
|
+
* - 帮助优化打包体积
|
|
10
|
+
*
|
|
11
|
+
* @param options - 配置选项
|
|
12
|
+
* @returns Vite 插件
|
|
13
|
+
*/
|
|
14
|
+
export function setupBundleAnalyzer(options?: {
|
|
15
|
+
/** 输出文件名(默认: stats.html) */
|
|
16
|
+
filename?: string;
|
|
17
|
+
/** 是否自动打开浏览器 */
|
|
18
|
+
open?: boolean;
|
|
19
|
+
/** 输出格式(默认: html) */
|
|
20
|
+
template?: 'treemap' | 'sunburst' | 'network';
|
|
21
|
+
/** 是否 gzip 压缩 */
|
|
22
|
+
gzipSize?: boolean;
|
|
23
|
+
/** 是否 brotli 压缩 */
|
|
24
|
+
brotliSize?: boolean;
|
|
25
|
+
}) {
|
|
26
|
+
return visualizer({
|
|
27
|
+
filename: options?.filename || 'dist/stats.html',
|
|
28
|
+
open: options?.open ?? false,
|
|
29
|
+
template: options?.template || 'treemap',
|
|
30
|
+
gzipSize: options?.gzipSize ?? true,
|
|
31
|
+
brotliSize: options?.brotliSize ?? true,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import removeConsole from 'vite-plugin-remove-console';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 移除 console 插件
|
|
5
|
+
*
|
|
6
|
+
* 功能:
|
|
7
|
+
* - 生产环境自动移除 console 语句
|
|
8
|
+
* - 提升生产环境性能
|
|
9
|
+
*
|
|
10
|
+
* @param options - 配置选项
|
|
11
|
+
* @returns Vite 插件
|
|
12
|
+
*/
|
|
13
|
+
export function setupRemoveConsole(options?: {
|
|
14
|
+
/** 需要移除的 console 方法(兼容旧字段 include) */
|
|
15
|
+
methods?: string[];
|
|
16
|
+
/** @deprecated 请改用 methods */
|
|
17
|
+
include?: string[];
|
|
18
|
+
}) {
|
|
19
|
+
const methods = options?.methods ?? options?.include ?? ['log', 'info', 'debug', 'warn'];
|
|
20
|
+
return removeConsole({
|
|
21
|
+
external: methods,
|
|
22
|
+
});
|
|
23
|
+
}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import { FileSystemIconLoader } from '@iconify/utils/lib/loader/node-loaders';
|
|
2
|
+
import presetAttributify from '@unocss/preset-attributify';
|
|
3
|
+
import presetIcons from '@unocss/preset-icons';
|
|
4
|
+
import presetUno from '@unocss/preset-uno';
|
|
5
|
+
import transformerDirectives from '@unocss/transformer-directives';
|
|
6
|
+
import transformerVariantGroup from '@unocss/transformer-variant-group';
|
|
7
|
+
import unocss from '@unocss/vite';
|
|
8
|
+
import type { UserConfig } from '@unocss/core';
|
|
9
|
+
|
|
10
|
+
type ShortcutMap = Record<string, string>;
|
|
11
|
+
|
|
12
|
+
const DEFAULT_BREAKPOINTS = {
|
|
13
|
+
xs: '320px',
|
|
14
|
+
sm: '640px',
|
|
15
|
+
md: '768px',
|
|
16
|
+
lg: '1024px',
|
|
17
|
+
xl: '1280px',
|
|
18
|
+
'2xl': '1536px',
|
|
19
|
+
} as const;
|
|
20
|
+
|
|
21
|
+
const DEFAULT_SHORTCUTS: ShortcutMap = {
|
|
22
|
+
btn: 'px-4 py-2 rounded font-semibold transition-colors duration-200',
|
|
23
|
+
'btn-primary': 'btn bg-primary-500 text-white hover:bg-primary-600 active:bg-primary-700',
|
|
24
|
+
'btn-secondary': 'btn bg-gray-500 text-white hover:bg-gray-600 active:bg-gray-700',
|
|
25
|
+
'btn-success': 'btn bg-success-500 text-white hover:bg-success-600 active:bg-success-700',
|
|
26
|
+
'btn-warning': 'btn bg-warning-500 text-white hover:bg-warning-600 active:bg-warning-700',
|
|
27
|
+
'btn-error': 'btn bg-error-500 text-white hover:bg-error-600 active:bg-error-700',
|
|
28
|
+
'btn-outline': 'btn border-2 bg-transparent hover:bg-gray-100',
|
|
29
|
+
'btn-ghost': 'btn bg-transparent hover:bg-gray-100',
|
|
30
|
+
container: 'mx-auto px-4 sm:px-6 lg:px-8',
|
|
31
|
+
'container-sm': 'mx-auto px-4 sm:px-6 max-w-screen-sm',
|
|
32
|
+
'container-md': 'mx-auto px-4 sm:px-6 max-w-screen-md',
|
|
33
|
+
'container-lg': 'mx-auto px-4 sm:px-6 max-w-screen-lg',
|
|
34
|
+
'container-xl': 'mx-auto px-4 sm:px-6 max-w-screen-xl',
|
|
35
|
+
card: 'bg-white rounded-lg shadow-sm border border-gray-200',
|
|
36
|
+
'card-header': 'px-6 py-4 border-b border-gray-200',
|
|
37
|
+
'card-body': 'px-6 py-4',
|
|
38
|
+
'card-footer': 'px-6 py-4 border-t border-gray-200',
|
|
39
|
+
input: 'px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-primary-500 focus:border-transparent',
|
|
40
|
+
'input-error': 'input border-error-500 focus:ring-error-500',
|
|
41
|
+
'flex-center': 'flex items-center justify-center',
|
|
42
|
+
'flex-between': 'flex items-center justify-between',
|
|
43
|
+
'flex-start': 'flex items-center justify-start',
|
|
44
|
+
'flex-end': 'flex items-center justify-end',
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export interface SetupUnocssOptions {
|
|
48
|
+
userConfig?: Partial<UserConfig>;
|
|
49
|
+
enableTheme?: boolean;
|
|
50
|
+
enableShortcuts?: boolean;
|
|
51
|
+
enableIconPreset?: boolean;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const isPlainRecord = (value: unknown): value is Record<string, unknown> => {
|
|
55
|
+
if (!value || typeof value !== 'object') {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
return Object.prototype.toString.call(value) === '[object Object]';
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const isSetupUnocssOptions = (value: unknown): value is SetupUnocssOptions => {
|
|
62
|
+
if (!isPlainRecord(value)) {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
return (
|
|
66
|
+
'userConfig' in value ||
|
|
67
|
+
'enableTheme' in value ||
|
|
68
|
+
'enableShortcuts' in value ||
|
|
69
|
+
'enableIconPreset' in value
|
|
70
|
+
);
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
const mergeTheme = (
|
|
74
|
+
userTheme: UserConfig['theme'] | undefined,
|
|
75
|
+
enableTheme: boolean,
|
|
76
|
+
): UserConfig['theme'] | undefined => {
|
|
77
|
+
if (!enableTheme) {
|
|
78
|
+
return userTheme;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const userThemeRecord = isPlainRecord(userTheme) ? userTheme : {};
|
|
82
|
+
const userColors = isPlainRecord(userThemeRecord.colors) ? userThemeRecord.colors : {};
|
|
83
|
+
const userBreakpoints = isPlainRecord(userThemeRecord.breakpoints) ? userThemeRecord.breakpoints : {};
|
|
84
|
+
|
|
85
|
+
return {
|
|
86
|
+
...userThemeRecord,
|
|
87
|
+
colors: {
|
|
88
|
+
...userColors,
|
|
89
|
+
},
|
|
90
|
+
breakpoints: {
|
|
91
|
+
...DEFAULT_BREAKPOINTS,
|
|
92
|
+
...userBreakpoints,
|
|
93
|
+
},
|
|
94
|
+
} as UserConfig['theme'];
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const mergeShortcuts = (
|
|
98
|
+
userShortcuts: UserConfig['shortcuts'] | undefined,
|
|
99
|
+
enableShortcuts: boolean,
|
|
100
|
+
): UserConfig['shortcuts'] | undefined => {
|
|
101
|
+
if (!enableShortcuts) {
|
|
102
|
+
return userShortcuts;
|
|
103
|
+
}
|
|
104
|
+
if (!userShortcuts) {
|
|
105
|
+
return DEFAULT_SHORTCUTS;
|
|
106
|
+
}
|
|
107
|
+
if (Array.isArray(userShortcuts)) {
|
|
108
|
+
return [DEFAULT_SHORTCUTS, ...userShortcuts];
|
|
109
|
+
}
|
|
110
|
+
if (isPlainRecord(userShortcuts)) {
|
|
111
|
+
return {
|
|
112
|
+
...DEFAULT_SHORTCUTS,
|
|
113
|
+
...userShortcuts,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
return userShortcuts;
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* UnoCSS 配置
|
|
121
|
+
*
|
|
122
|
+
* 功能:
|
|
123
|
+
* - 集成 UnoCSS
|
|
124
|
+
* - 支持本地 SVG 图标
|
|
125
|
+
* - 包含完整的预设和转换器
|
|
126
|
+
* - 支持属性化模式(Attributify)
|
|
127
|
+
*
|
|
128
|
+
* @param localIconPath - 本地图标路径
|
|
129
|
+
* @param unocssConfig - UnoCSS 配置(可选,用于合并其他配置)
|
|
130
|
+
*/
|
|
131
|
+
export function setupUnocss(
|
|
132
|
+
localIconPath: string,
|
|
133
|
+
unocssConfig?: Partial<UserConfig> | SetupUnocssOptions
|
|
134
|
+
): ReturnType<typeof unocss> {
|
|
135
|
+
const options = isSetupUnocssOptions(unocssConfig) ? unocssConfig : { userConfig: unocssConfig };
|
|
136
|
+
const enableTheme = options.enableTheme ?? true;
|
|
137
|
+
const enableShortcuts = options.enableShortcuts ?? true;
|
|
138
|
+
const enableIconPreset = options.enableIconPreset ?? true;
|
|
139
|
+
const userConfig = options.userConfig ?? {};
|
|
140
|
+
const {
|
|
141
|
+
presets: userPresets,
|
|
142
|
+
transformers: userTransformers,
|
|
143
|
+
theme: userTheme,
|
|
144
|
+
shortcuts: userShortcuts,
|
|
145
|
+
...restUserConfig
|
|
146
|
+
} = userConfig;
|
|
147
|
+
|
|
148
|
+
return unocss({
|
|
149
|
+
// Disable auto-loading `uno.config.*` from cwd to avoid noisy
|
|
150
|
+
// "Config file not found" logs in template apps without standalone config files.
|
|
151
|
+
configFile: false,
|
|
152
|
+
presets: [
|
|
153
|
+
// 基础预设 - 包含 Tailwind CSS 兼容的工具类
|
|
154
|
+
presetUno(),
|
|
155
|
+
// 属性化模式 - 支持 <div bg="blue-400" /> 语法
|
|
156
|
+
presetAttributify(),
|
|
157
|
+
// 图标预设 - 支持本地 SVG 图标
|
|
158
|
+
...(enableIconPreset
|
|
159
|
+
? [
|
|
160
|
+
presetIcons({
|
|
161
|
+
collections: {
|
|
162
|
+
// 本地图标集合
|
|
163
|
+
local: FileSystemIconLoader(localIconPath, (svg) =>
|
|
164
|
+
svg.replace(/^<svg\s/, '<svg width="1em" height="1em" ')
|
|
165
|
+
),
|
|
166
|
+
},
|
|
167
|
+
extraProperties: {
|
|
168
|
+
display: 'inline-block',
|
|
169
|
+
},
|
|
170
|
+
prefix: 'icon-',
|
|
171
|
+
scale: 1,
|
|
172
|
+
warn: true,
|
|
173
|
+
}),
|
|
174
|
+
]
|
|
175
|
+
: []),
|
|
176
|
+
...(userPresets ?? []),
|
|
177
|
+
],
|
|
178
|
+
// 转换器
|
|
179
|
+
transformers: [
|
|
180
|
+
transformerDirectives(), // 支持 @apply、@screen 等指令
|
|
181
|
+
transformerVariantGroup(), // 支持 variant groups (hover:bg-gray-400 hover:text-white)
|
|
182
|
+
...(userTransformers ?? []),
|
|
183
|
+
],
|
|
184
|
+
// 主题配置
|
|
185
|
+
theme: mergeTheme(userTheme, enableTheme),
|
|
186
|
+
// 快捷方式 - 组合多个工具类
|
|
187
|
+
shortcuts: mergeShortcuts(userShortcuts, enableShortcuts),
|
|
188
|
+
// 自定义规则
|
|
189
|
+
rules: [
|
|
190
|
+
// 可以在这里添加项目特定的工具类
|
|
191
|
+
// 示例:['custom-rule', { color: 'red' }],
|
|
192
|
+
],
|
|
193
|
+
// 安全列表 - 确保这些类名始终被生成(即使没有被扫描到)
|
|
194
|
+
safelist: [
|
|
195
|
+
// 可以添加动态生成的类名
|
|
196
|
+
// 例如:'bg-red-500', 'bg-blue-500',
|
|
197
|
+
// 或者使用正则:/^bg-(red|blue|green)-\d+$/,
|
|
198
|
+
],
|
|
199
|
+
// 合并用户自定义配置(通过拆分字段避免覆盖默认合并策略)
|
|
200
|
+
...restUserConfig,
|
|
201
|
+
});
|
|
202
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { FileSystemIconLoader } from 'unplugin-icons/loaders';
|
|
2
|
+
import Icons from 'unplugin-icons/vite';
|
|
3
|
+
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* 图标插件配置
|
|
7
|
+
*
|
|
8
|
+
* 功能:
|
|
9
|
+
* - SVG 图标支持(vite-plugin-svg-icons)
|
|
10
|
+
* - 图标组件自动导入(unplugin-icons)
|
|
11
|
+
* - 支持本地 SVG 图标
|
|
12
|
+
*
|
|
13
|
+
* @param localIconPath - 本地图标路径
|
|
14
|
+
* @param customDomId - 自定义 DOM ID(默认: __SVG_ICON_LOCAL__)
|
|
15
|
+
* @returns 插件数组
|
|
16
|
+
*/
|
|
17
|
+
export function setupUnPluginIcon(
|
|
18
|
+
localIconPath: string,
|
|
19
|
+
customDomId = '__SVG_ICON_LOCAL__'
|
|
20
|
+
): Array<ReturnType<typeof createSvgIconsPlugin> | ReturnType<typeof Icons>> {
|
|
21
|
+
return [
|
|
22
|
+
// SVG 图标插件 - 用于 <svg><use xlink:href="#icon-local-xxx" /></svg> 方式
|
|
23
|
+
createSvgIconsPlugin({
|
|
24
|
+
customDomId,
|
|
25
|
+
iconDirs: [localIconPath],
|
|
26
|
+
inject: 'body-last',
|
|
27
|
+
symbolId: 'icon-local-[dir]-[name]',
|
|
28
|
+
}),
|
|
29
|
+
|
|
30
|
+
// 图标组件插件 - 用于 <IconLocalXxx /> 组件方式
|
|
31
|
+
Icons({
|
|
32
|
+
compiler: 'jsx',
|
|
33
|
+
customCollections: {
|
|
34
|
+
local: FileSystemIconLoader(localIconPath, (svg) =>
|
|
35
|
+
svg.replace(/^<svg\s/, '<svg width="1em" height="1em" ')
|
|
36
|
+
),
|
|
37
|
+
},
|
|
38
|
+
defaultClass: 'inline-block',
|
|
39
|
+
jsx: 'react',
|
|
40
|
+
scale: 1,
|
|
41
|
+
}),
|
|
42
|
+
];
|
|
43
|
+
}
|