@moluoxixi/create-app 2.0.404 → 2.0.407
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 +41 -14
- package/dist/commands/create.js +9 -10
- package/dist/generators/react.js +0 -2
- package/dist/generators/vue.js +0 -2
- package/dist/test.js +8 -0
- package/dist/utils/deepMerge.js +1 -1
- package/dist/utils/featureMapping.d.ts +2 -2
- package/dist/utils/featureMapping.js +3 -5
- package/dist/utils/generateFrameworkProject.d.ts +0 -4
- package/dist/utils/generateFrameworkProject.js +1 -1
- package/dist/utils/install.d.ts +2 -1
- package/dist/utils/install.js +4 -3
- package/dist/utils/prompts.js +4 -30
- package/dist/utils/renderTemplate.js +9 -4
- package/package.json +2 -1
- package/templates/common/base/.gitmodules +4 -0
- package/templates/common/base/package.json +2 -0
- package/templates/common/base/vite.config.ts.ejs +13 -2
- package/templates/common/features/husky/package.json +2 -1
- package/templates/react/base/package.json +3 -1
- package/templates/react/{features/qiankun → base}/src/qiankun/index.ts +4 -0
- package/templates/react/base/src/stores/index.ts +5 -0
- package/templates/react/base/src/stores/user.ts +55 -0
- package/templates/react/{base/src/router/index.tsx.ejs → features/manualRoutes/src/router/index.tsx} +6 -5
- package/templates/react/features/pageRoutes/src/router/index.tsx +30 -0
- package/templates/vue/base/package.json +19 -15
- package/templates/vue/base/src/App.vue +1 -0
- package/templates/vue/base/src/assets/styles/base.scss +69 -0
- package/templates/vue/base/src/assets/styles/custom.scss +40 -0
- package/templates/vue/base/src/assets/styles/tailwind.scss +3 -0
- package/templates/vue/base/src/layouts/index.ts +22 -0
- package/templates/vue/base/src/main.ts.ejs +1 -0
- package/templates/vue/base/src/router/layout.vue +15 -0
- package/templates/vue/base/src/stores/index.ts +6 -0
- package/templates/vue/base/src/stores/modules/system.ts +51 -0
- package/templates/vue/base/src/stores/modules/user.ts +41 -0
- package/templates/vue/base/src/utils/index.ts +5 -0
- package/templates/vue/base/src/utils/modifyComponent.tsx +43 -0
- package/templates/vue/base/tsconfig.app.json +25 -16
- package/templates/vue/base/tsconfig.base.json +29 -22
- package/templates/vue/base/tsconfig.json +11 -11
- package/templates/vue/base/tsconfig.node.json +14 -14
- package/templates/vue/features/element-plus/src/assets/styles/element/fixQiankun.scss +10 -0
- package/templates/vue/features/element-plus/src/assets/styles/element/index.scss +3 -0
- package/templates/vue/features/element-plus/src/components/SubMenu/src/_types/index.ts +1 -5
- package/templates/vue/features/element-plus/src/components/SubMenu/src/_types/props.ts +16 -10
- package/templates/vue/features/element-plus/src/components/SubMenu/src/index.vue +60 -23
- package/templates/vue/features/element-plus/src/layouts/element.vue +106 -70
- package/templates/vue/features/manualRoutes/package.json +7 -0
- package/templates/vue/features/manualRoutes/src/router/index.ts +45 -0
- package/templates/vue/features/manualRoutes/src/router/layout.vue +11 -5
- package/templates/vue/features/manualRoutes/src/stores/index.ts +6 -0
- package/templates/vue/features/manualRoutes/src/stores/modules/system.ts +51 -0
- package/templates/vue/features/manualRoutes/src/stores/modules/user.ts +41 -0
- package/templates/vue/features/pageRoutes/package.json +4 -1
- package/templates/vue/features/pageRoutes/src/router/index.ts +46 -0
- package/templates/vue/features/pageRoutes/src/router/layout.vue +15 -0
- package/templates/vue/features/pageRoutes/src/stores/index.ts +6 -0
- package/templates/vue/features/pageRoutes/src/stores/modules/system.ts +51 -0
- package/templates/vue/features/pageRoutes/src/stores/modules/user.ts +41 -0
- package/templates/vue/features/sentry/package.json +3 -1
- package/templates/vue/features/sentry/src/stores/index.ts +13 -0
- package/templates/react/features/qiankun/package.json +0 -5
- package/templates/vue/base/src/router/index.ts.ejs +0 -36
- package/templates/vue/features/pinia/package.json +0 -7
- package/templates/vue/features/pinia/src/stores/index.ts +0 -15
- package/templates/vue/features/pinia/src/stores/system.ts +0 -59
- package/templates/vue/features/pinia/src/stores/user.ts +0 -56
- package/templates/vue/features/qiankun/node_modules/.bin/jiti +0 -17
- package/templates/vue/features/qiankun/node_modules/.bin/jiti.CMD +0 -12
- package/templates/vue/features/qiankun/node_modules/.bin/jiti.ps1 +0 -41
- package/templates/vue/features/qiankun/node_modules/.bin/sass +0 -17
- package/templates/vue/features/qiankun/node_modules/.bin/sass.CMD +0 -12
- package/templates/vue/features/qiankun/node_modules/.bin/sass.ps1 +0 -41
- package/templates/vue/features/qiankun/node_modules/.bin/terser +0 -17
- package/templates/vue/features/qiankun/node_modules/.bin/terser.CMD +0 -12
- package/templates/vue/features/qiankun/node_modules/.bin/terser.ps1 +0 -41
- package/templates/vue/features/qiankun/node_modules/.bin/tsc +0 -17
- package/templates/vue/features/qiankun/node_modules/.bin/tsc.CMD +0 -12
- package/templates/vue/features/qiankun/node_modules/.bin/tsc.ps1 +0 -41
- package/templates/vue/features/qiankun/node_modules/.bin/tsserver +0 -17
- package/templates/vue/features/qiankun/node_modules/.bin/tsserver.CMD +0 -12
- package/templates/vue/features/qiankun/node_modules/.bin/tsserver.ps1 +0 -41
- package/templates/vue/features/qiankun/node_modules/.bin/tsx +0 -17
- package/templates/vue/features/qiankun/node_modules/.bin/tsx.CMD +0 -12
- package/templates/vue/features/qiankun/node_modules/.bin/tsx.ps1 +0 -41
- package/templates/vue/features/qiankun/node_modules/.bin/vite +0 -17
- package/templates/vue/features/qiankun/node_modules/.bin/vite.CMD +0 -12
- package/templates/vue/features/qiankun/node_modules/.bin/vite.ps1 +0 -41
- package/templates/vue/features/qiankun/node_modules/.bin/yaml +0 -17
- package/templates/vue/features/qiankun/node_modules/.bin/yaml.CMD +0 -12
- package/templates/vue/features/qiankun/node_modules/.bin/yaml.ps1 +0 -41
- package/templates/vue/features/qiankun/package.json +0 -5
- package/templates/vue/features/qiankun/src/qiankun/index.ts +0 -74
- package/templates/vue/features/router/node_modules/.bin/tsc +0 -17
- package/templates/vue/features/router/node_modules/.bin/tsc.CMD +0 -12
- package/templates/vue/features/router/node_modules/.bin/tsc.ps1 +0 -41
- package/templates/vue/features/router/node_modules/.bin/tsserver +0 -17
- package/templates/vue/features/router/node_modules/.bin/tsserver.CMD +0 -12
- package/templates/vue/features/router/node_modules/.bin/tsserver.ps1 +0 -41
- package/templates/vue/features/router/package.json +0 -5
- /package/templates/{react/features/qiankun → vue/features/manualRoutes}/node_modules/.bin/jiti +0 -0
- /package/templates/{react/features/qiankun → vue/features/manualRoutes}/node_modules/.bin/jiti.CMD +0 -0
- /package/templates/{react/features/qiankun → vue/features/manualRoutes}/node_modules/.bin/jiti.ps1 +0 -0
- /package/templates/{react/features/qiankun → vue/features/manualRoutes}/node_modules/.bin/sass +0 -0
- /package/templates/{react/features/qiankun → vue/features/manualRoutes}/node_modules/.bin/sass.CMD +0 -0
- /package/templates/{react/features/qiankun → vue/features/manualRoutes}/node_modules/.bin/sass.ps1 +0 -0
- /package/templates/{react/features/qiankun → vue/features/manualRoutes}/node_modules/.bin/terser +0 -0
- /package/templates/{react/features/qiankun → vue/features/manualRoutes}/node_modules/.bin/terser.CMD +0 -0
- /package/templates/{react/features/qiankun → vue/features/manualRoutes}/node_modules/.bin/terser.ps1 +0 -0
- /package/templates/{react/features/qiankun → vue/features/manualRoutes}/node_modules/.bin/tsc +0 -0
- /package/templates/{react/features/qiankun → vue/features/manualRoutes}/node_modules/.bin/tsc.CMD +0 -0
- /package/templates/{react/features/qiankun → vue/features/manualRoutes}/node_modules/.bin/tsc.ps1 +0 -0
- /package/templates/{react/features/qiankun → vue/features/manualRoutes}/node_modules/.bin/tsserver +0 -0
- /package/templates/{react/features/qiankun → vue/features/manualRoutes}/node_modules/.bin/tsserver.CMD +0 -0
- /package/templates/{react/features/qiankun → vue/features/manualRoutes}/node_modules/.bin/tsserver.ps1 +0 -0
- /package/templates/{react/features/qiankun → vue/features/manualRoutes}/node_modules/.bin/tsx +0 -0
- /package/templates/{react/features/qiankun → vue/features/manualRoutes}/node_modules/.bin/tsx.CMD +0 -0
- /package/templates/{react/features/qiankun → vue/features/manualRoutes}/node_modules/.bin/tsx.ps1 +0 -0
- /package/templates/{react/features/qiankun → vue/features/manualRoutes}/node_modules/.bin/vite +0 -0
- /package/templates/{react/features/qiankun → vue/features/manualRoutes}/node_modules/.bin/vite.CMD +0 -0
- /package/templates/{react/features/qiankun → vue/features/manualRoutes}/node_modules/.bin/vite.ps1 +0 -0
- /package/templates/{react/features/qiankun → vue/features/manualRoutes}/node_modules/.bin/yaml +0 -0
- /package/templates/{react/features/qiankun → vue/features/manualRoutes}/node_modules/.bin/yaml.CMD +0 -0
- /package/templates/{react/features/qiankun → vue/features/manualRoutes}/node_modules/.bin/yaml.ps1 +0 -0
- /package/templates/vue/features/{pinia → pageRoutes}/node_modules/.bin/tsc +0 -0
- /package/templates/vue/features/{pinia → pageRoutes}/node_modules/.bin/tsc.CMD +0 -0
- /package/templates/vue/features/{pinia → pageRoutes}/node_modules/.bin/tsc.ps1 +0 -0
- /package/templates/vue/features/{pinia → pageRoutes}/node_modules/.bin/tsserver +0 -0
- /package/templates/vue/features/{pinia → pageRoutes}/node_modules/.bin/tsserver.CMD +0 -0
- /package/templates/vue/features/{pinia → pageRoutes}/node_modules/.bin/tsserver.ps1 +0 -0
package/README.md
CHANGED
|
@@ -20,12 +20,30 @@ npm create @moluoxixi/app
|
|
|
20
20
|
- 🚀 **原子化分层架构** - L0/L1/L2 三层模板,灵活组合
|
|
21
21
|
- 📦 **多框架支持** - Vue 3、React 18
|
|
22
22
|
- 🎨 **多 UI 库** - Element Plus、Ant Design Vue、Ant Design
|
|
23
|
-
- 🌍 **国际化** - 内置 vue-i18n / i18next 支持
|
|
24
|
-
- 📊 **错误监控** - 可选 Sentry 集成
|
|
25
|
-
- 🔗 **微前端** - 可选 Qiankun 支持 (Vue)
|
|
26
|
-
- ⚡ **文件系统路由** - 可选 vite-plugin-pages
|
|
27
23
|
- 📝 **TypeScript** - 全面的类型支持
|
|
28
|
-
|
|
24
|
+
|
|
25
|
+
### 内置功能(所有项目默认包含)
|
|
26
|
+
|
|
27
|
+
- ✅ **路由系统** - Vue Router / React Router DOM,支持手动配置和文件系统路由
|
|
28
|
+
- ✅ **状态管理** - Pinia (Vue) / Zustand (React)
|
|
29
|
+
- ✅ **微前端支持** - Qiankun 集成,开箱即用
|
|
30
|
+
|
|
31
|
+
### 可选功能
|
|
32
|
+
|
|
33
|
+
- 🌍 **国际化** - 可选 vue-i18n / i18next 支持
|
|
34
|
+
- 📊 **错误监控** - 可选 Sentry 集成
|
|
35
|
+
- ⚡ **文件系统路由** - 可选 vite-plugin-pages(替代手动路由)
|
|
36
|
+
- 🔧 **规范配置** - 可选 ESLint + Commitlint + Husky
|
|
37
|
+
|
|
38
|
+
## 📋 开发计划
|
|
39
|
+
|
|
40
|
+
以下功能正在规划中,欢迎贡献:
|
|
41
|
+
|
|
42
|
+
- [ ] 🔄 **Ant Design Vue 模板重构** - 优化 ant-design-vue 模板结构和配置
|
|
43
|
+
- [ ] 🔄 **Ant Design 模板重构** - 优化 ant-design 模板结构和配置
|
|
44
|
+
- [ ] 🔧 **main.ts.ejs 解耦** - 将 Vue 入口文件模板解耦,提高可维护性
|
|
45
|
+
- [ ] 🔧 **main.tsx.ejs 解耦** - 将 React 入口文件模板解耦,提高可维护性
|
|
46
|
+
- [ ] 🔧 **vite.config.ts.ejs 解耦** - 将 Vite 配置模板解耦,提高可维护性
|
|
29
47
|
|
|
30
48
|
## 内置依赖
|
|
31
49
|
|
|
@@ -63,9 +81,8 @@ my-project/
|
|
|
63
81
|
│ └── main.ts # 入口文件
|
|
64
82
|
├── .env # 环境变量
|
|
65
83
|
├── package.json # 项目配置
|
|
66
|
-
├── pnpm-workspace.yaml # pnpm 工作区
|
|
67
84
|
├── vite.config.ts # Vite 配置
|
|
68
|
-
├── eslint.config.ts # ESLint
|
|
85
|
+
├── eslint.config.ts # ESLint 配置(可选)
|
|
69
86
|
└── tsconfig.json # TypeScript 配置
|
|
70
87
|
```
|
|
71
88
|
|
|
@@ -93,17 +110,31 @@ pnpm commit
|
|
|
93
110
|
|
|
94
111
|
## 配置选项
|
|
95
112
|
|
|
113
|
+
### 必选配置
|
|
114
|
+
|
|
96
115
|
| 选项 | 类型 | 说明 |
|
|
97
116
|
|------|------|------|
|
|
98
117
|
| 项目名称 | string | 项目名称,用于 package.json |
|
|
99
118
|
| 框架 | vue / react | 前端框架 |
|
|
100
119
|
| UI 库 | element-plus / ant-design-vue / ant-design | UI 组件库 |
|
|
101
120
|
| 路由模式 | manual / file-system | 手动配置或文件系统路由 |
|
|
102
|
-
| 国际化 | boolean | 是否启用多语言支持 |
|
|
103
|
-
| 错误监控 | boolean | 是否集成 Sentry |
|
|
104
|
-
| 微前端 | boolean | 是否支持 Qiankun (仅 Vue) |
|
|
105
121
|
| 包管理器 | pnpm / npm / yarn | 包管理器 |
|
|
106
122
|
|
|
123
|
+
### 可选功能
|
|
124
|
+
|
|
125
|
+
| 选项 | 类型 | 默认值 | 说明 |
|
|
126
|
+
|------|------|--------|------|
|
|
127
|
+
| 国际化 | boolean | true | 是否启用多语言支持 (vue-i18n / i18next) |
|
|
128
|
+
| 错误监控 | boolean | false | 是否集成 Sentry |
|
|
129
|
+
| ESLint | boolean | true | 是否启用 ESLint 代码规范检查 |
|
|
130
|
+
| Git Hooks | boolean | true | 是否启用 Husky + Commitlint |
|
|
131
|
+
|
|
132
|
+
### 内置功能(无需配置)
|
|
133
|
+
|
|
134
|
+
- ✅ **路由系统** - 所有项目默认包含
|
|
135
|
+
- ✅ **状态管理** - Vue 使用 Pinia,React 使用 Zustand
|
|
136
|
+
- ✅ **微前端** - Qiankun 支持已内置
|
|
137
|
+
|
|
107
138
|
## 开发
|
|
108
139
|
|
|
109
140
|
```bash
|
|
@@ -120,10 +151,6 @@ pnpm test
|
|
|
120
151
|
pnpm build
|
|
121
152
|
```
|
|
122
153
|
|
|
123
|
-
## 架构文档
|
|
124
|
-
|
|
125
|
-
详细的架构说明请参阅 [docs/ARCHITECTURE.md](./docs/ARCHITECTURE.md)
|
|
126
|
-
|
|
127
154
|
## 许可证
|
|
128
155
|
|
|
129
156
|
MIT
|
package/dist/commands/create.js
CHANGED
|
@@ -37,7 +37,6 @@ export async function createProject(projectName) {
|
|
|
37
37
|
console.log(chalk.gray(` UI 组件库: ${chalk.white(config.uiLibrary)}`));
|
|
38
38
|
console.log(chalk.gray(` 路由模式: ${chalk.white(config.routeMode)}`));
|
|
39
39
|
console.log(chalk.gray(` 国际化: ${chalk.white(config.i18n ? '是' : '否')}`));
|
|
40
|
-
console.log(chalk.gray(` 微前端: ${chalk.white(config.qiankun ? '是' : '否')}`));
|
|
41
40
|
console.log(chalk.gray(` 错误监控: ${chalk.white(config.sentry ? '是' : '否')}`));
|
|
42
41
|
console.log(chalk.gray(` 包管理器: ${chalk.white(config.packageManager)}`));
|
|
43
42
|
console.log('');
|
|
@@ -51,6 +50,15 @@ export async function createProject(projectName) {
|
|
|
51
50
|
spinner.fail('项目创建失败');
|
|
52
51
|
throw error;
|
|
53
52
|
}
|
|
53
|
+
// 初始化 Git
|
|
54
|
+
const gitSpinner = ora('正在初始化 Git...').start();
|
|
55
|
+
try {
|
|
56
|
+
await initGit(config.targetDir, config.projectName);
|
|
57
|
+
gitSpinner.succeed('Git 初始化成功!');
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
gitSpinner.warn('Git 初始化跳过');
|
|
61
|
+
}
|
|
54
62
|
// 安装依赖
|
|
55
63
|
const installSpinner = ora('正在安装依赖...').start();
|
|
56
64
|
try {
|
|
@@ -65,15 +73,6 @@ export async function createProject(projectName) {
|
|
|
65
73
|
console.log(chalk.gray(` 错误详情: ${error.message}`));
|
|
66
74
|
}
|
|
67
75
|
}
|
|
68
|
-
// 初始化 Git
|
|
69
|
-
const gitSpinner = ora('正在初始化 Git...').start();
|
|
70
|
-
try {
|
|
71
|
-
await initGit(config.targetDir);
|
|
72
|
-
gitSpinner.succeed('Git 初始化成功!');
|
|
73
|
-
}
|
|
74
|
-
catch {
|
|
75
|
-
gitSpinner.warn('Git 初始化跳过');
|
|
76
|
-
}
|
|
77
76
|
// 显示成功信息
|
|
78
77
|
console.log(chalk.green.bold('\n✅ 项目创建成功!\n'));
|
|
79
78
|
console.log(chalk.blue('下一步:'));
|
package/dist/generators/react.js
CHANGED
package/dist/generators/vue.js
CHANGED
package/dist/test.js
CHANGED
|
@@ -170,6 +170,7 @@ function createTestConfig(framework, uiLibrary, suffix, overrides) {
|
|
|
170
170
|
/**
|
|
171
171
|
* 生成测试项目
|
|
172
172
|
* @param minimalOnly 是否只生成全量和最小配置
|
|
173
|
+
* @returns Promise<void>
|
|
173
174
|
*/
|
|
174
175
|
async function generateTestProjects(minimalOnly = false) {
|
|
175
176
|
const mode = minimalOnly ? '(仅全量和最小配置)' : '(全部组合)';
|
|
@@ -220,6 +221,8 @@ async function generateTestProjects(minimalOnly = false) {
|
|
|
220
221
|
}
|
|
221
222
|
/**
|
|
222
223
|
* 检查 package.json 中是否有 catalog 引用(应该已经全部替换为实际版本号)
|
|
224
|
+
* @param projectDir 项目目录路径
|
|
225
|
+
* @returns 检查是否通过(true 表示通过,false 表示失败)
|
|
223
226
|
*/
|
|
224
227
|
function checkPackageJsonVersions(projectDir) {
|
|
225
228
|
const packageJsonPath = path.join(projectDir, FILE_CONSTANTS.PACKAGE_JSON);
|
|
@@ -371,6 +374,9 @@ async function showFileTrees() {
|
|
|
371
374
|
}
|
|
372
375
|
/**
|
|
373
376
|
* 打印文件树
|
|
377
|
+
* @param dir 目录路径
|
|
378
|
+
* @param indent 缩进字符串
|
|
379
|
+
* @returns Promise<void>
|
|
374
380
|
*/
|
|
375
381
|
async function printFileTree(dir, indent) {
|
|
376
382
|
const items = fs.readdirSync(dir).sort();
|
|
@@ -390,6 +396,8 @@ async function printFileTree(dir, indent) {
|
|
|
390
396
|
}
|
|
391
397
|
/**
|
|
392
398
|
* 主函数
|
|
399
|
+
* 执行测试项目生成、依赖审计和文件树显示
|
|
400
|
+
* @returns Promise<void>
|
|
393
401
|
*/
|
|
394
402
|
async function main() {
|
|
395
403
|
const { minimalOnly } = parseArgs();
|
package/dist/utils/deepMerge.js
CHANGED
|
@@ -11,10 +11,10 @@ import type { FrameworkType } from '../types/index.ts';
|
|
|
11
11
|
export declare function scanAllFeatures(framework: FrameworkType): string[];
|
|
12
12
|
/**
|
|
13
13
|
* 配置项到 feature 目录的映射(从 renderFeatures 提取)
|
|
14
|
-
* @param
|
|
14
|
+
* @param _framework 框架类型(已不再使用,保留以保持接口兼容性)
|
|
15
15
|
* @returns 配置键到 feature 名称的映射对象
|
|
16
16
|
*/
|
|
17
|
-
export declare function getConfigToFeatureMap(
|
|
17
|
+
export declare function getConfigToFeatureMap(_framework: FrameworkType): Record<string, string>;
|
|
18
18
|
/**
|
|
19
19
|
* 公共 features 映射
|
|
20
20
|
* @returns 公共配置键到 feature 名称的映射对象
|
|
@@ -41,17 +41,15 @@ export function scanAllFeatures(framework) {
|
|
|
41
41
|
}
|
|
42
42
|
/**
|
|
43
43
|
* 配置项到 feature 目录的映射(从 renderFeatures 提取)
|
|
44
|
-
* @param
|
|
44
|
+
* @param _framework 框架类型(已不再使用,保留以保持接口兼容性)
|
|
45
45
|
* @returns 配置键到 feature 名称的映射对象
|
|
46
46
|
*/
|
|
47
|
-
export function getConfigToFeatureMap(
|
|
47
|
+
export function getConfigToFeatureMap(_framework) {
|
|
48
48
|
return {
|
|
49
|
-
router
|
|
50
|
-
stateManagement: framework === 'vue' ? 'pinia' : 'zustand',
|
|
49
|
+
// router、stateManagement、qiankun 已内置到 base,不再作为 feature
|
|
51
50
|
eslint: 'eslint',
|
|
52
51
|
i18n: 'i18n',
|
|
53
52
|
sentry: 'sentry',
|
|
54
|
-
qiankun: 'qiankun',
|
|
55
53
|
};
|
|
56
54
|
}
|
|
57
55
|
/**
|
|
@@ -36,7 +36,7 @@ export function generateFrameworkProject(config, ejsConfig) {
|
|
|
36
36
|
};
|
|
37
37
|
const frameworkBasePath = path.join(templatesDir, framework, 'base');
|
|
38
38
|
renderEjsToFile(path.join(frameworkBasePath, ejsConfig.mainTemplate), path.join(targetDir, ejsConfig.mainOutput), ejsData);
|
|
39
|
-
|
|
39
|
+
// Router 已通过 feature 覆盖实现(manualRoutes/pageRoutes),不再使用 EJS
|
|
40
40
|
// 6. 数据驱动生成 vite.config.ts(使用 EJS 模板)
|
|
41
41
|
const viteConfigEjsData = getViteConfigEjsData(config);
|
|
42
42
|
const commonBasePath = path.join(templatesDir, 'common', 'base');
|
package/dist/utils/install.d.ts
CHANGED
|
@@ -15,6 +15,7 @@ export declare function installDependencies(packageManager: PackageManagerType,
|
|
|
15
15
|
/**
|
|
16
16
|
* 初始化 Git 仓库
|
|
17
17
|
* @param cwd 工作目录
|
|
18
|
+
* @param projectName 项目名称,用于生成提交信息
|
|
18
19
|
* @returns Promise<void>
|
|
19
20
|
*/
|
|
20
|
-
export declare function initGit(cwd: string): Promise<void>;
|
|
21
|
+
export declare function initGit(cwd: string, projectName: string): Promise<void>;
|
package/dist/utils/install.js
CHANGED
|
@@ -12,7 +12,7 @@ const RETRY_DELAY_BASE_MS = 1000;
|
|
|
12
12
|
* 验证命令参数安全性
|
|
13
13
|
* @param packageManager 包管理器类型
|
|
14
14
|
* @param cwd 工作目录
|
|
15
|
-
* @throws {Error}
|
|
15
|
+
* @throws {Error} 如果包管理器类型不支持或路径不安全
|
|
16
16
|
*/
|
|
17
17
|
function validateInstallParams(packageManager, cwd) {
|
|
18
18
|
// 验证包管理器类型
|
|
@@ -64,15 +64,16 @@ export async function installDependencies(packageManager, cwd, retries = 0) {
|
|
|
64
64
|
/**
|
|
65
65
|
* 初始化 Git 仓库
|
|
66
66
|
* @param cwd 工作目录
|
|
67
|
+
* @param projectName 项目名称,用于生成提交信息
|
|
67
68
|
* @returns Promise<void>
|
|
68
69
|
*/
|
|
69
|
-
export async function initGit(cwd) {
|
|
70
|
+
export async function initGit(cwd, projectName) {
|
|
70
71
|
try {
|
|
71
72
|
// 验证路径安全性
|
|
72
73
|
validatePath(cwd);
|
|
73
74
|
await execAsync('git init', { cwd });
|
|
74
75
|
await execAsync('git add .', { cwd });
|
|
75
|
-
await execAsync(
|
|
76
|
+
await execAsync(`git commit -m "feat: initialize ${projectName}"`, { cwd });
|
|
76
77
|
}
|
|
77
78
|
catch {
|
|
78
79
|
// Git 初始化失败不影响项目创建,静默失败
|
package/dist/utils/prompts.js
CHANGED
|
@@ -113,14 +113,7 @@ export async function collectProjectConfig(projectName) {
|
|
|
113
113
|
}
|
|
114
114
|
},
|
|
115
115
|
},
|
|
116
|
-
//
|
|
117
|
-
{
|
|
118
|
-
type: 'confirm',
|
|
119
|
-
name: 'router',
|
|
120
|
-
message: '是否启用路由 (vue-router/react-router-dom)?',
|
|
121
|
-
default: true,
|
|
122
|
-
},
|
|
123
|
-
// 路由模式(仅在启用路由时询问)
|
|
116
|
+
// 路由模式(路由已内置,只需选择模式)
|
|
124
117
|
{
|
|
125
118
|
type: 'list',
|
|
126
119
|
name: 'routeMode',
|
|
@@ -129,18 +122,6 @@ export async function collectProjectConfig(projectName) {
|
|
|
129
122
|
{ name: '文件系统路由 (vite-plugin-pages)', value: 'file-system' },
|
|
130
123
|
{ name: '手动配置路由', value: 'manual' },
|
|
131
124
|
],
|
|
132
|
-
when: (answers) => answers.router === true,
|
|
133
|
-
},
|
|
134
|
-
// 是否启用状态管理
|
|
135
|
-
{
|
|
136
|
-
type: 'confirm',
|
|
137
|
-
name: 'stateManagement',
|
|
138
|
-
message: (answers) => {
|
|
139
|
-
return answers.framework === 'vue'
|
|
140
|
-
? '是否启用状态管理 (Pinia)?'
|
|
141
|
-
: '是否启用状态管理 (Zustand)?';
|
|
142
|
-
},
|
|
143
|
-
default: true,
|
|
144
125
|
},
|
|
145
126
|
// 是否启用国际化
|
|
146
127
|
{
|
|
@@ -149,13 +130,6 @@ export async function collectProjectConfig(projectName) {
|
|
|
149
130
|
message: '是否启用国际化 (i18n)?',
|
|
150
131
|
default: true,
|
|
151
132
|
},
|
|
152
|
-
// 是否启用微前端
|
|
153
|
-
{
|
|
154
|
-
type: 'confirm',
|
|
155
|
-
name: 'qiankun',
|
|
156
|
-
message: '是否启用微前端 (qiankun)?',
|
|
157
|
-
default: false,
|
|
158
|
-
},
|
|
159
133
|
// 是否启用错误监控
|
|
160
134
|
{
|
|
161
135
|
type: 'confirm',
|
|
@@ -198,10 +172,10 @@ export async function collectProjectConfig(projectName) {
|
|
|
198
172
|
framework: answers.framework,
|
|
199
173
|
uiLibrary: answers.uiLibrary,
|
|
200
174
|
routeMode: answers.routeMode || 'manual',
|
|
201
|
-
router:
|
|
202
|
-
stateManagement:
|
|
175
|
+
router: true, // 路由已内置
|
|
176
|
+
stateManagement: true, // 状态管理已内置
|
|
203
177
|
i18n: answers.i18n,
|
|
204
|
-
qiankun:
|
|
178
|
+
qiankun: true, // 微前端已内置
|
|
205
179
|
sentry: answers.sentry,
|
|
206
180
|
eslint: answers.eslint,
|
|
207
181
|
gitHooks: answers.gitHooks,
|
|
@@ -23,13 +23,15 @@ export function renderTemplate(src, dest) {
|
|
|
23
23
|
if (path.basename(src) === FILE_CONSTANTS.NODE_MODULES) {
|
|
24
24
|
return;
|
|
25
25
|
}
|
|
26
|
-
|
|
26
|
+
// 统一使用绝对路径,确保目录创建和文件复制使用相同的路径格式
|
|
27
|
+
const resolvedDest = path.resolve(dest);
|
|
28
|
+
fs.mkdirSync(resolvedDest, { recursive: true });
|
|
27
29
|
for (const file of fs.readdirSync(src)) {
|
|
28
30
|
// 验证文件名安全性
|
|
29
31
|
if (file.includes('..') || file.includes('~')) {
|
|
30
32
|
throw new Error(`不安全的文件名: ${file}`);
|
|
31
33
|
}
|
|
32
|
-
renderTemplate(path.resolve(src, file), path.resolve(
|
|
34
|
+
renderTemplate(path.resolve(src, file), path.resolve(resolvedDest, file));
|
|
33
35
|
}
|
|
34
36
|
return;
|
|
35
37
|
}
|
|
@@ -51,6 +53,9 @@ export function renderTemplate(src, dest) {
|
|
|
51
53
|
// 处理特殊文件名转换(如 _gitignore -> .gitignore)
|
|
52
54
|
const targetFilename = renameFile(filename);
|
|
53
55
|
const targetPath = path.resolve(path.dirname(dest), targetFilename);
|
|
56
|
+
// 确保目标文件的父目录存在
|
|
57
|
+
// 虽然目录处理时已创建,但文件名重命名时路径可能不同,需要确保父目录存在
|
|
58
|
+
fs.mkdirSync(path.dirname(targetPath), { recursive: true });
|
|
54
59
|
// 普通文件直接复制(后面的会覆盖前面的)
|
|
55
60
|
fs.copyFileSync(src, targetPath);
|
|
56
61
|
}
|
|
@@ -106,7 +111,7 @@ function renderPackageJson(src, dest) {
|
|
|
106
111
|
/**
|
|
107
112
|
* 获取包管理器的默认版本号
|
|
108
113
|
* @param packageManager 包管理器类型
|
|
109
|
-
* @returns
|
|
114
|
+
* @returns 包管理器版本字符串,如果未找到则返回 pnpm 的默认版本
|
|
110
115
|
*/
|
|
111
116
|
function getPackageManagerVersion(packageManager) {
|
|
112
117
|
const versions = {
|
|
@@ -158,7 +163,7 @@ export function updatePackageJsonMetadata(packageJsonPath, projectName, descript
|
|
|
158
163
|
* 重命名特殊文件
|
|
159
164
|
* 某些文件不能以 . 开头存在于模板中,需要特殊处理
|
|
160
165
|
* @param name 原始文件名
|
|
161
|
-
* @returns
|
|
166
|
+
* @returns 转换后的文件名,_ 开头的文件会转换为 . 开头
|
|
162
167
|
*/
|
|
163
168
|
function renameFile(name) {
|
|
164
169
|
// _开头的文件转换为.开头
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@moluoxixi/create-app",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.407",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Create Vue/React projects with atomic layered architecture",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -77,6 +77,7 @@
|
|
|
77
77
|
"test:all": "tsx src/test.ts",
|
|
78
78
|
"type-check": "tsc --noEmit",
|
|
79
79
|
"lint:eslint": "eslint . --fix",
|
|
80
|
+
"submodule:update": "git submodule init && git submodule update --init --recursive",
|
|
80
81
|
"lint-staged": "lint-staged",
|
|
81
82
|
"commit": "git add . && git-cz",
|
|
82
83
|
"version:patch": "pnpm version patch --no-git-tag-version",
|
|
@@ -9,6 +9,8 @@
|
|
|
9
9
|
"packageManager": "pnpm@10.8.0",
|
|
10
10
|
"scripts": {
|
|
11
11
|
"dev": "vite",
|
|
12
|
+
"submodule:update": "git submodule init && git submodule update --init --recursive",
|
|
13
|
+
"prepare": "pnpm submodule:update",
|
|
12
14
|
"build": "vite build --mode production",
|
|
13
15
|
"build:zip": "vite build --mode production && tsx scripts/build.mts",
|
|
14
16
|
"preview": "vite preview",
|
|
@@ -60,12 +60,23 @@ export default ViteConfig(
|
|
|
60
60
|
scss: {
|
|
61
61
|
silenceDeprecations: ['legacy-js-api'],
|
|
62
62
|
api: 'modern-compiler',
|
|
63
|
+
<% if (uiLibrary === 'element-plus') { -%>
|
|
64
|
+
additionalData: (source: string, filename: string) => {
|
|
65
|
+
if (filename.includes('assets/styles/element/index.scss')) {
|
|
66
|
+
return `$namespace : ${appCode || 'el'};
|
|
67
|
+
${source}`
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
return source
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
<% } -%>
|
|
63
74
|
},
|
|
64
75
|
postcss: {
|
|
65
76
|
plugins: [
|
|
66
77
|
cssModuleGlobalRootPlugin() as any,
|
|
67
|
-
]
|
|
68
|
-
}
|
|
78
|
+
],
|
|
79
|
+
},
|
|
69
80
|
},
|
|
70
81
|
},
|
|
71
82
|
},
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"scripts": {
|
|
3
|
-
"prepare": "node .husky/install.mjs",
|
|
3
|
+
"prepare": "pnpm submodule:update && node .husky/install.mjs",
|
|
4
4
|
"lint-staged": "lint-staged",
|
|
5
5
|
"commit": "git add . && git-cz"
|
|
6
6
|
},
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
"devDependencies": {
|
|
21
21
|
"@commitlint/cli": "^19.8.0",
|
|
22
22
|
"@commitlint/config-conventional": "^19.8.0",
|
|
23
|
+
"@commitlint/types": "^19.8.0",
|
|
23
24
|
"commitizen": "^4.3.1",
|
|
24
25
|
"cz-customizable": "^7.4.0",
|
|
25
26
|
"husky": "^9.1.7",
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 用户状态管理
|
|
3
|
+
* 基于 Zustand
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { create } from 'zustand'
|
|
7
|
+
import { persist } from 'zustand/middleware'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* 用户信息接口
|
|
11
|
+
*/
|
|
12
|
+
interface UserInfo {
|
|
13
|
+
/** 用户 ID */
|
|
14
|
+
id: string
|
|
15
|
+
/** 用户名 */
|
|
16
|
+
username: string
|
|
17
|
+
/** 邮箱 */
|
|
18
|
+
email: string
|
|
19
|
+
/** 头像 URL(可选) */
|
|
20
|
+
avatar?: string
|
|
21
|
+
/** 角色列表 */
|
|
22
|
+
roles: string[]
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* 用户状态接口
|
|
27
|
+
*/
|
|
28
|
+
interface UserState {
|
|
29
|
+
/** 用户信息 */
|
|
30
|
+
userInfo: UserInfo | null
|
|
31
|
+
/** 认证 token */
|
|
32
|
+
token: string
|
|
33
|
+
/** 设置用户信息 */
|
|
34
|
+
setUserInfo: (info: UserInfo | null) => void
|
|
35
|
+
/** 设置 token */
|
|
36
|
+
setToken: (token: string) => void
|
|
37
|
+
/** 清除用户信息 */
|
|
38
|
+
clearUser: () => void
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export const useUserStore = create<UserState>()(
|
|
42
|
+
persist(
|
|
43
|
+
set => ({
|
|
44
|
+
userInfo: null,
|
|
45
|
+
token: '',
|
|
46
|
+
setUserInfo: info => set({ userInfo: info }),
|
|
47
|
+
setToken: token => set({ token }),
|
|
48
|
+
clearUser: () => set({ userInfo: null, token: '' }),
|
|
49
|
+
}),
|
|
50
|
+
{
|
|
51
|
+
name: 'user-storage',
|
|
52
|
+
partialize: state => ({ token: state.token }),
|
|
53
|
+
},
|
|
54
|
+
),
|
|
55
|
+
)
|
package/templates/react/{base/src/router/index.tsx.ejs → features/manualRoutes/src/router/index.tsx}
RENAMED
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* 路由配置
|
|
3
|
+
* 手动配置路由模式
|
|
3
4
|
*/
|
|
4
5
|
|
|
5
6
|
import { createBrowserRouter, createHashRouter } from 'react-router-dom'
|
|
6
|
-
<% if (routeMode === 'file-system') { -%>
|
|
7
|
-
import routes from '~react-pages'
|
|
8
|
-
<% } else { -%>
|
|
9
7
|
import { routes } from './routes'
|
|
10
|
-
<% } -%>
|
|
11
8
|
|
|
12
9
|
interface RouterConfig {
|
|
13
10
|
historyMode?: 'hash' | 'history'
|
|
14
11
|
basename?: string
|
|
15
12
|
}
|
|
16
13
|
|
|
14
|
+
/**
|
|
15
|
+
* 创建路由实例
|
|
16
|
+
* @param config 路由配置
|
|
17
|
+
* @returns 路由实例
|
|
18
|
+
*/
|
|
17
19
|
export function createRouter(config: RouterConfig = {}) {
|
|
18
20
|
const { historyMode = 'history', basename } = config
|
|
19
21
|
|
|
@@ -25,4 +27,3 @@ export function createRouter(config: RouterConfig = {}) {
|
|
|
25
27
|
}
|
|
26
28
|
|
|
27
29
|
export { routes }
|
|
28
|
-
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 路由配置
|
|
3
|
+
* 文件系统路由模式(基于 vite-plugin-pages)
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { createBrowserRouter, createHashRouter } from 'react-router-dom'
|
|
7
|
+
// @ts-expect-error - vite-plugin-pages 自动生成
|
|
8
|
+
import routes from '~react-pages'
|
|
9
|
+
|
|
10
|
+
interface RouterConfig {
|
|
11
|
+
historyMode?: 'hash' | 'history'
|
|
12
|
+
basename?: string
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* 创建路由实例
|
|
17
|
+
* @param config 路由配置
|
|
18
|
+
* @returns 路由实例
|
|
19
|
+
*/
|
|
20
|
+
export function createRouter(config: RouterConfig = {}) {
|
|
21
|
+
const { historyMode = 'history', basename } = config
|
|
22
|
+
|
|
23
|
+
if (historyMode === 'hash') {
|
|
24
|
+
return createHashRouter(routes, { basename })
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return createBrowserRouter(routes, { basename })
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export { routes }
|
|
@@ -1,15 +1,19 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "vue-project",
|
|
3
|
-
"scripts": {
|
|
4
|
-
"type-check": "vue-tsc --noEmit"
|
|
5
|
-
},
|
|
6
|
-
"dependencies": {
|
|
7
|
-
"vue": "^3.5.13"
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
"
|
|
11
|
-
"
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "vue-project",
|
|
3
|
+
"scripts": {
|
|
4
|
+
"type-check": "vue-tsc --noEmit"
|
|
5
|
+
},
|
|
6
|
+
"dependencies": {
|
|
7
|
+
"vue": "^3.5.13",
|
|
8
|
+
"vite-plugin-qiankun": "^1.0.15",
|
|
9
|
+
"pinia": "^2.2.7",
|
|
10
|
+
"pinia-plugin-persistedstate": "^3.2.1",
|
|
11
|
+
"vue-router": "^4.4.5"
|
|
12
|
+
},
|
|
13
|
+
"devDependencies": {
|
|
14
|
+
"@moluoxixi/css-module-global-root-plugin": "latest",
|
|
15
|
+
"@moluoxixi/vite-config": "latest",
|
|
16
|
+
"@vue-macros/volar": "^3.0.0-beta.15",
|
|
17
|
+
"vue-tsc": "^2.1.30"
|
|
18
|
+
}
|
|
19
|
+
}
|