zant-admin 1.0.4 → 2.0.1
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.en.md +414 -25
- package/README.md +460 -285
- package/bin/cli.js +3 -3
- package/bin/generator.js +502 -502
- package/bin/prompts.js +158 -158
- package/bin/utils.js +133 -133
- package/package.json +2 -2
- package/public/logo.png +0 -0
- package/src/App.vue +16 -16
- package/src/api/methods/department.js +36 -0
- package/src/api/methods/employee.js +22 -0
- package/src/api/methods/logError.js +8 -8
- package/src/api/methods/logOperation.js +8 -8
- package/src/api/methods/login.js +6 -6
- package/src/api/methods/position.js +26 -0
- package/src/api/methods/quartz.js +36 -36
- package/src/api/methods/region.js +16 -16
- package/src/api/methods/sysAccount.js +29 -29
- package/src/api/methods/sysDict.js +29 -29
- package/src/api/methods/sysDictItem.js +26 -26
- package/src/api/methods/sysMenu.js +42 -42
- package/src/api/methods/sysRole.js +35 -35
- package/src/api/methods/sysUser.js +25 -25
- package/src/api/methods/system.js +15 -15
- package/src/api/request.js +225 -225
- package/src/assets/css/style.css +2 -2
- package/src/assets/css/zcui.css +1023 -1023
- package/src/assets/imgs/logo.png +0 -0
- package/src/assets/imgs/md/console.png +0 -0
- package/src/assets/imgs/md/login.png +0 -0
- package/src/assets/imgs/md/menu.png +0 -0
- package/src/assets/imgs/md/serviceMonitoring.png +0 -0
- package/src/assets/imgs/md/statistics.png +0 -0
- package/src/components/FormTable.vue +5 -19
- package/src/components/IconPicker.vue +351 -351
- package/src/components/MainPage.vue +838 -838
- package/src/components/details/logErrorDetails.vue +58 -58
- package/src/components/details/logOperationDetails.vue +76 -76
- package/src/components/edit/QuartzEdit.vue +221 -221
- package/src/components/edit/SysAccountEdit.vue +185 -185
- package/src/components/edit/SysDictEdit.vue +116 -116
- package/src/components/edit/SysDictItemEdit.vue +136 -136
- package/src/components/edit/SysRoleEdit.vue +111 -111
- package/src/components/edit/organizationalStructure/DepartmentEdit.vue +162 -0
- package/src/components/edit/organizationalStructure/EmployeeEdit.vue +295 -0
- package/src/components/edit/organizationalStructure/PositionEdit.vue +166 -0
- package/src/components/edit/sysMenuEdit.vue +2 -1
- package/src/config/index.js +74 -74
- package/src/directives/permission.js +49 -49
- package/src/main.js +37 -37
- package/src/router/index.js +4 -6
- package/src/stores/config.js +43 -43
- package/src/stores/dict.js +33 -33
- package/src/stores/menu.js +81 -81
- package/src/stores/user.js +21 -21
- package/src/utils/baseEcharts.js +661 -661
- package/src/utils/dictTemplate.js +26 -26
- package/src/utils/regionUtils.js +173 -173
- package/src/utils/useFormCRUD.js +59 -59
- package/src/views/baiscstatis/center.vue +474 -474
- package/src/views/baiscstatis/iframePage.vue +29 -29
- package/src/views/baiscstatis/notFound.vue +192 -192
- package/src/views/console.vue +821 -821
- package/src/views/demo/button.vue +269 -269
- package/src/views/demo/importexport.vue +119 -119
- package/src/views/demo/region.vue +322 -322
- package/src/views/demo/statistics.vue +214 -214
- package/src/views/home.vue +6 -6
- package/src/views/login.vue +264 -149
- package/src/views/operations/log/logError.vue +78 -78
- package/src/views/operations/log/logLogin.vue +66 -66
- package/src/views/operations/log/logOperation.vue +103 -103
- package/src/views/operations/log/logQuartz.vue +56 -56
- package/src/views/operations/quartz.vue +179 -179
- package/src/views/operations/serviceMonitoring.vue +134 -134
- package/src/views/organizationalStructure/department.vue +194 -0
- package/src/views/organizationalStructure/employee.vue +234 -0
- package/src/views/organizationalStructure/position.vue +196 -0
- package/src/views/system/sysAccount.vue +128 -128
- package/src/views/system/sysDict.vue +159 -159
- package/src/views/system/sysDictItem.vue +118 -118
- package/src/views/system/sysMenu.vue +225 -225
- package/src/views/system/sysRole.vue +207 -207
- package/src/assets/imgs/md/1.png +0 -0
- package/src/assets/imgs/md/10.png +0 -0
- package/src/assets/imgs/md/11.png +0 -0
- package/src/assets/imgs/md/2.png +0 -0
- package/src/assets/imgs/md/3.png +0 -0
- package/src/assets/imgs/md/4.png +0 -0
- package/src/assets/imgs/md/5.png +0 -0
- package/src/assets/imgs/md/6.png +0 -0
- package/src/assets/imgs/md/7.png +0 -0
- package/src/assets/imgs/md/8.png +0 -0
- package/src/assets/imgs/md/9.png +0 -0
package/bin/generator.js
CHANGED
|
@@ -1,503 +1,503 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 项目生成器
|
|
3
|
-
* 负责创建和管理项目模板
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import fs from 'fs';
|
|
7
|
-
import path from 'path';
|
|
8
|
-
import {
|
|
9
|
-
createDirectory,
|
|
10
|
-
copyDirectory,
|
|
11
|
-
writeFile,
|
|
12
|
-
renderTemplate,
|
|
13
|
-
executeCommand,
|
|
14
|
-
getProjectRoot,
|
|
15
|
-
validateProjectName
|
|
16
|
-
} from './utils.js';
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* 创建新项目
|
|
20
|
-
*/
|
|
21
|
-
export async function createProject(projectName, options) {
|
|
22
|
-
// 验证项目名称
|
|
23
|
-
validateProjectName(projectName);
|
|
24
|
-
|
|
25
|
-
const projectPath = path.resolve(process.cwd(), projectName);
|
|
26
|
-
|
|
27
|
-
// 检查目录是否已存在
|
|
28
|
-
if (fs.existsSync(projectPath)) {
|
|
29
|
-
throw new Error(`目录 "${projectName}" 已存在,请选择其他名称`);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
// 创建项目目录
|
|
33
|
-
createDirectory(projectPath);
|
|
34
|
-
|
|
35
|
-
// 根据模板类型生成项目
|
|
36
|
-
await generateProjectStructure(projectPath, options);
|
|
37
|
-
|
|
38
|
-
// 生成配置文件
|
|
39
|
-
await generateConfigFiles(projectPath, projectName, options);
|
|
40
|
-
|
|
41
|
-
// 安装依赖(如果未跳过)
|
|
42
|
-
if (!options.skipInstall) {
|
|
43
|
-
await installDependencies(projectPath);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* 生成项目结构
|
|
49
|
-
*/
|
|
50
|
-
async function generateProjectStructure(projectPath, options) {
|
|
51
|
-
const templateType = options.template || 'default';
|
|
52
|
-
const sourceRoot = getProjectRoot();
|
|
53
|
-
|
|
54
|
-
console.log('📁 生成项目结构...');
|
|
55
|
-
|
|
56
|
-
// 复制基础文件
|
|
57
|
-
const baseFiles = [
|
|
58
|
-
'package.json',
|
|
59
|
-
'vite.config.js',
|
|
60
|
-
'index.html',
|
|
61
|
-
'eslint.config.js',
|
|
62
|
-
'.prettierrc.json',
|
|
63
|
-
'.gitignore',
|
|
64
|
-
'.editorconfig',
|
|
65
|
-
'jsconfig.json'
|
|
66
|
-
];
|
|
67
|
-
|
|
68
|
-
baseFiles.forEach(file => {
|
|
69
|
-
const sourceFile = path.join(sourceRoot, file);
|
|
70
|
-
const targetFile = path.join(projectPath, file);
|
|
71
|
-
|
|
72
|
-
if (fs.existsSync(sourceFile)) {
|
|
73
|
-
fs.copyFileSync(sourceFile, targetFile);
|
|
74
|
-
}
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
// 复制环境配置文件
|
|
78
|
-
const envFiles = ['.env.development', '.env.test'];
|
|
79
|
-
envFiles.forEach(file => {
|
|
80
|
-
const sourceFile = path.join(sourceRoot, file);
|
|
81
|
-
const targetFile = path.join(projectPath, file);
|
|
82
|
-
|
|
83
|
-
if (fs.existsSync(sourceFile)) {
|
|
84
|
-
fs.copyFileSync(sourceFile, targetFile);
|
|
85
|
-
}
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
// 使用模板生成生产环境配置文件
|
|
89
|
-
await generateProductionEnv(projectPath);
|
|
90
|
-
|
|
91
|
-
// 复制 public 目录
|
|
92
|
-
copyDirectory(path.join(sourceRoot, 'public'), path.join(projectPath, 'public'));
|
|
93
|
-
|
|
94
|
-
// 复制 src 目录(根据模板类型)
|
|
95
|
-
await copySourceDirectory(sourceRoot, projectPath, templateType);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* 复制源代码目录
|
|
100
|
-
*/
|
|
101
|
-
async function copySourceDirectory(sourceRoot, projectPath, templateType) {
|
|
102
|
-
const srcPath = path.join(sourceRoot, 'src');
|
|
103
|
-
const targetSrcPath = path.join(projectPath, 'src');
|
|
104
|
-
|
|
105
|
-
// 创建 src 目录结构
|
|
106
|
-
createDirectory(targetSrcPath);
|
|
107
|
-
|
|
108
|
-
// 复制核心文件
|
|
109
|
-
const coreFiles = ['main.js', 'App.vue'];
|
|
110
|
-
coreFiles.forEach(file => {
|
|
111
|
-
const sourceFile = path.join(srcPath, file);
|
|
112
|
-
const targetFile = path.join(targetSrcPath, file);
|
|
113
|
-
|
|
114
|
-
if (fs.existsSync(sourceFile)) {
|
|
115
|
-
fs.copyFileSync(sourceFile, targetFile);
|
|
116
|
-
}
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
// 复制核心目录
|
|
120
|
-
const coreDirs = ['api', 'assets', 'config', 'directives', 'router', 'stores', 'utils'];
|
|
121
|
-
coreDirs.forEach(dir => {
|
|
122
|
-
const sourceDir = path.join(srcPath, dir);
|
|
123
|
-
const targetDir = path.join(targetSrcPath, dir);
|
|
124
|
-
|
|
125
|
-
if (fs.existsSync(sourceDir)) {
|
|
126
|
-
copyDirectory(sourceDir, targetDir);
|
|
127
|
-
}
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
// 根据模板类型处理 components 和 views
|
|
131
|
-
await handleTemplateSpecificFiles(srcPath, targetSrcPath, templateType);
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
* 处理模板特定的文件
|
|
136
|
-
*/
|
|
137
|
-
async function handleTemplateSpecificFiles(srcPath, targetSrcPath, templateType) {
|
|
138
|
-
// 复制 components 目录
|
|
139
|
-
const componentsSource = path.join(srcPath, 'components');
|
|
140
|
-
const componentsTarget = path.join(targetSrcPath, 'components');
|
|
141
|
-
|
|
142
|
-
if (fs.existsSync(componentsSource)) {
|
|
143
|
-
copyDirectory(componentsSource, componentsTarget);
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
// 处理 views 目录
|
|
147
|
-
const viewsSource = path.join(srcPath, 'views');
|
|
148
|
-
const viewsTarget = path.join(targetSrcPath, 'views');
|
|
149
|
-
|
|
150
|
-
if (fs.existsSync(viewsSource)) {
|
|
151
|
-
if (templateType === 'basic') {
|
|
152
|
-
// 基础模板:只保留核心页面
|
|
153
|
-
createDirectory(viewsTarget);
|
|
154
|
-
const basicViews = ['console.vue', 'home.vue', 'login.vue'];
|
|
155
|
-
|
|
156
|
-
basicViews.forEach(view => {
|
|
157
|
-
const sourceFile = path.join(viewsSource, view);
|
|
158
|
-
const targetFile = path.join(viewsTarget, view);
|
|
159
|
-
|
|
160
|
-
if (fs.existsSync(sourceFile)) {
|
|
161
|
-
fs.copyFileSync(sourceFile, targetFile);
|
|
162
|
-
}
|
|
163
|
-
});
|
|
164
|
-
} else {
|
|
165
|
-
// 默认和完整模板:复制所有页面
|
|
166
|
-
copyDirectory(viewsSource, viewsTarget);
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
/**
|
|
172
|
-
* 生成配置文件
|
|
173
|
-
*/
|
|
174
|
-
async function generateConfigFiles(projectPath, projectName, options) {
|
|
175
|
-
console.log('⚙️ 生成配置文件...');
|
|
176
|
-
|
|
177
|
-
// 读取并更新 package.json
|
|
178
|
-
const packageJsonPath = path.join(projectPath, 'package.json');
|
|
179
|
-
if (fs.existsSync(packageJsonPath)) {
|
|
180
|
-
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
181
|
-
|
|
182
|
-
// 更新项目信息
|
|
183
|
-
packageJson.name = projectName;
|
|
184
|
-
packageJson.description = options.description;
|
|
185
|
-
|
|
186
|
-
if (options.author) {
|
|
187
|
-
packageJson.author = options.author;
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
// 根据功能特性调整依赖
|
|
191
|
-
if (options.features && options.features.length > 0) {
|
|
192
|
-
await adjustDependencies(packageJson, options.features);
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
// 移除脚手架特定的配置
|
|
196
|
-
delete packageJson.bin;
|
|
197
|
-
delete packageJson.main;
|
|
198
|
-
|
|
199
|
-
// 写入更新后的 package.json
|
|
200
|
-
writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2));
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
// 生成 README.md
|
|
204
|
-
await generateReadme(projectPath, projectName, options);
|
|
205
|
-
|
|
206
|
-
// 根据功能特性生成额外文件
|
|
207
|
-
if (options.features && options.features.length > 0) {
|
|
208
|
-
await generateFeatureFiles(projectPath, options.features);
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
/**
|
|
213
|
-
* 根据功能特性调整依赖
|
|
214
|
-
*/
|
|
215
|
-
async function adjustDependencies(packageJson, features) {
|
|
216
|
-
const featureDependencies = {
|
|
217
|
-
'i18n-support': {
|
|
218
|
-
dependencies: {
|
|
219
|
-
'vue-i18n': '^9.0.0'
|
|
220
|
-
}
|
|
221
|
-
},
|
|
222
|
-
'file-upload': {
|
|
223
|
-
dependencies: {
|
|
224
|
-
'ant-design-vue': '^4.2.6' // 已包含,确保版本
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
};
|
|
228
|
-
|
|
229
|
-
features.forEach(feature => {
|
|
230
|
-
const deps = featureDependencies[feature];
|
|
231
|
-
if (deps && deps.dependencies) {
|
|
232
|
-
Object.assign(packageJson.dependencies, deps.dependencies);
|
|
233
|
-
}
|
|
234
|
-
});
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
/**
|
|
238
|
-
* 根据功能特性生成额外文件
|
|
239
|
-
*/
|
|
240
|
-
async function generateFeatureFiles(projectPath, features) {
|
|
241
|
-
const featureGenerators = {
|
|
242
|
-
'i18n-support': generateI18nFiles,
|
|
243
|
-
'user-management': generateUserManagementFiles,
|
|
244
|
-
'permission-management': generatePermissionFiles
|
|
245
|
-
};
|
|
246
|
-
|
|
247
|
-
for (const feature of features) {
|
|
248
|
-
const generator = featureGenerators[feature];
|
|
249
|
-
if (generator) {
|
|
250
|
-
await generator(projectPath);
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
/**
|
|
256
|
-
* 生成国际化支持文件
|
|
257
|
-
*/
|
|
258
|
-
async function generateI18nFiles(projectPath) {
|
|
259
|
-
console.log('🌐 生成国际化支持文件...');
|
|
260
|
-
|
|
261
|
-
// 创建 locales 目录
|
|
262
|
-
const localesDir = path.join(projectPath, 'src/locales');
|
|
263
|
-
createDirectory(localesDir);
|
|
264
|
-
|
|
265
|
-
// 生成中文语言包
|
|
266
|
-
const zhCNContent = `{
|
|
267
|
-
"common": {
|
|
268
|
-
"save": "保存",
|
|
269
|
-
"cancel": "取消",
|
|
270
|
-
"delete": "删除",
|
|
271
|
-
"edit": "编辑",
|
|
272
|
-
"add": "添加"
|
|
273
|
-
},
|
|
274
|
-
"menu": {
|
|
275
|
-
"dashboard": "仪表盘",
|
|
276
|
-
"user": "用户管理",
|
|
277
|
-
"system": "系统管理"
|
|
278
|
-
}
|
|
279
|
-
}`;
|
|
280
|
-
|
|
281
|
-
writeFile(path.join(localesDir, 'zh-CN.json'), zhCNContent);
|
|
282
|
-
|
|
283
|
-
// 生成英文语言包
|
|
284
|
-
const enUSContent = `{
|
|
285
|
-
"common": {
|
|
286
|
-
"save": "Save",
|
|
287
|
-
"cancel": "Cancel",
|
|
288
|
-
"delete": "Delete",
|
|
289
|
-
"edit": "Edit",
|
|
290
|
-
"add": "Add"
|
|
291
|
-
},
|
|
292
|
-
"menu": {
|
|
293
|
-
"dashboard": "Dashboard",
|
|
294
|
-
"user": "User Management",
|
|
295
|
-
"system": "System Management"
|
|
296
|
-
}
|
|
297
|
-
}`;
|
|
298
|
-
|
|
299
|
-
writeFile(path.join(localesDir, 'en-US.json'), enUSContent);
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
/**
|
|
303
|
-
* 生成用户管理相关文件
|
|
304
|
-
*/
|
|
305
|
-
async function generateUserManagementFiles(projectPath) {
|
|
306
|
-
console.log('👥 生成用户管理文件...');
|
|
307
|
-
|
|
308
|
-
// 创建用户管理相关目录
|
|
309
|
-
const userViewsDir = path.join(projectPath, 'src/views/system/user');
|
|
310
|
-
createDirectory(userViewsDir);
|
|
311
|
-
|
|
312
|
-
// 生成用户列表页面
|
|
313
|
-
const userListContent = `<template>
|
|
314
|
-
<div class="user-management">
|
|
315
|
-
<a-card title="用户管理">
|
|
316
|
-
<a-table :columns="columns" :data-source="userList">
|
|
317
|
-
<template #action="{ record }">
|
|
318
|
-
<a-space>
|
|
319
|
-
<a-button type="link" @click="handleEdit(record)">编辑</a-button>
|
|
320
|
-
<a-button type="link" danger @click="handleDelete(record)">删除</a-button>
|
|
321
|
-
</a-space>
|
|
322
|
-
</template>
|
|
323
|
-
</a-table>
|
|
324
|
-
</a-card>
|
|
325
|
-
</div>
|
|
326
|
-
</template>
|
|
327
|
-
|
|
328
|
-
<script setup>
|
|
329
|
-
import { ref, onMounted } from 'vue';
|
|
330
|
-
|
|
331
|
-
const columns = [
|
|
332
|
-
{ title: '用户名', dataIndex: 'username' },
|
|
333
|
-
{ title: '邮箱', dataIndex: 'email' },
|
|
334
|
-
{ title: '角色', dataIndex: 'role' },
|
|
335
|
-
{ title: '状态', dataIndex: 'status' },
|
|
336
|
-
{ title: '操作', slots: { customRender: 'action' } }
|
|
337
|
-
];
|
|
338
|
-
|
|
339
|
-
const userList = ref([]);
|
|
340
|
-
|
|
341
|
-
onMounted(() => {
|
|
342
|
-
// 加载用户数据
|
|
343
|
-
loadUserData();
|
|
344
|
-
});
|
|
345
|
-
|
|
346
|
-
const loadUserData = async () => {
|
|
347
|
-
// 模拟数据
|
|
348
|
-
userList.value = [
|
|
349
|
-
{ id: 1, username: 'admin', email: 'admin@example.com', role: '管理员', status: '正常' }
|
|
350
|
-
];
|
|
351
|
-
};
|
|
352
|
-
|
|
353
|
-
const handleEdit = (record) => {
|
|
354
|
-
console.log('编辑用户:', record);
|
|
355
|
-
};
|
|
356
|
-
|
|
357
|
-
const handleDelete = (record) => {
|
|
358
|
-
console.log('删除用户:', record);
|
|
359
|
-
};
|
|
360
|
-
</script>
|
|
361
|
-
|
|
362
|
-
<style scoped>
|
|
363
|
-
.user-management {
|
|
364
|
-
padding: 20px;
|
|
365
|
-
}
|
|
366
|
-
</style>`;
|
|
367
|
-
|
|
368
|
-
writeFile(path.join(userViewsDir, 'index.vue'), userListContent);
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
/**
|
|
372
|
-
* 生成权限管理相关文件
|
|
373
|
-
*/
|
|
374
|
-
async function generatePermissionFiles(projectPath) {
|
|
375
|
-
console.log('🔐 生成权限管理文件...');
|
|
376
|
-
|
|
377
|
-
// 创建权限管理相关目录
|
|
378
|
-
const permissionViewsDir = path.join(projectPath, 'src/views/system/permission');
|
|
379
|
-
createDirectory(permissionViewsDir);
|
|
380
|
-
|
|
381
|
-
// 生成权限管理页面
|
|
382
|
-
const permissionContent = `<template>
|
|
383
|
-
<div class="permission-management">
|
|
384
|
-
<a-card title="权限管理">
|
|
385
|
-
<p>权限管理功能已生成,请根据业务需求进行开发。</p>
|
|
386
|
-
</a-card>
|
|
387
|
-
</div>
|
|
388
|
-
</template>
|
|
389
|
-
|
|
390
|
-
<script setup>
|
|
391
|
-
// 权限管理页面逻辑
|
|
392
|
-
</script>
|
|
393
|
-
|
|
394
|
-
<style scoped>
|
|
395
|
-
.permission-management {
|
|
396
|
-
padding: 20px;
|
|
397
|
-
}
|
|
398
|
-
</style>`;
|
|
399
|
-
|
|
400
|
-
writeFile(path.join(permissionViewsDir, 'index.vue'), permissionContent);
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
/**
|
|
404
|
-
* 生成生产环境配置文件
|
|
405
|
-
*/
|
|
406
|
-
async function generateProductionEnv(projectPath) {
|
|
407
|
-
console.log('🔧 生成生产环境配置文件...');
|
|
408
|
-
|
|
409
|
-
const templatePath = path.join(getProjectRoot(), 'templates/env.production');
|
|
410
|
-
const targetPath = path.join(projectPath, '.env.production');
|
|
411
|
-
|
|
412
|
-
if (fs.existsSync(templatePath)) {
|
|
413
|
-
// 使用模板文件
|
|
414
|
-
fs.copyFileSync(templatePath, targetPath);
|
|
415
|
-
} else {
|
|
416
|
-
// 如果模板不存在,创建默认的生产环境配置
|
|
417
|
-
const defaultProdConfig = `# 生产环境配置
|
|
418
|
-
VITE_BASE_API=http://your-production-server.com/api/
|
|
419
|
-
|
|
420
|
-
# 其他生产环境变量
|
|
421
|
-
NODE_ENV=production
|
|
422
|
-
VITE_APP_TITLE=ZAnt Admin`;
|
|
423
|
-
|
|
424
|
-
writeFile(targetPath, defaultProdConfig);
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
/**
|
|
429
|
-
* 生成 README.md 文件
|
|
430
|
-
*/
|
|
431
|
-
async function generateReadme(projectPath, projectName, options) {
|
|
432
|
-
const readmeContent = `# ${projectName}
|
|
433
|
-
|
|
434
|
-
${options.description}
|
|
435
|
-
|
|
436
|
-
## 技术栈
|
|
437
|
-
|
|
438
|
-
- Vue 3 (Composition API)
|
|
439
|
-
- Vite 构建工具
|
|
440
|
-
- Ant Design Vue UI 组件库
|
|
441
|
-
- Pinia 状态管理
|
|
442
|
-
- Vue Router 路由管理
|
|
443
|
-
|
|
444
|
-
## 快速开始
|
|
445
|
-
|
|
446
|
-
### 安装依赖
|
|
447
|
-
\`\`\`bash
|
|
448
|
-
npm install
|
|
449
|
-
\`\`\`
|
|
450
|
-
|
|
451
|
-
### 启动开发服务器
|
|
452
|
-
\`\`\`bash
|
|
453
|
-
npm run dev
|
|
454
|
-
\`\`\`
|
|
455
|
-
|
|
456
|
-
### 构建生产版本
|
|
457
|
-
\`\`\`bash
|
|
458
|
-
npm run build
|
|
459
|
-
\`\`\`
|
|
460
|
-
|
|
461
|
-
## 项目结构
|
|
462
|
-
|
|
463
|
-
\`\`\`
|
|
464
|
-
src/
|
|
465
|
-
├── api/ # 接口请求相关
|
|
466
|
-
├── assets/ # 静态资源文件
|
|
467
|
-
├── components/ # 公共组件
|
|
468
|
-
├── router/ # 路由配置
|
|
469
|
-
├── stores/ # 状态管理
|
|
470
|
-
├── utils/ # 工具函数
|
|
471
|
-
├── views/ # 页面视图
|
|
472
|
-
├── App.vue # 根组件
|
|
473
|
-
└── main.js # 入口文件
|
|
474
|
-
\`\`\`
|
|
475
|
-
|
|
476
|
-
## 命令说明
|
|
477
|
-
|
|
478
|
-
- \`npm run dev\` - 启动开发服务器
|
|
479
|
-
- \`npm run build\` - 构建生产版本
|
|
480
|
-
- \`npm run preview\` - 预览生产构建
|
|
481
|
-
- \`npm run lint\` - 代码检查
|
|
482
|
-
- \`npm run format\` - 代码格式化
|
|
483
|
-
|
|
484
|
-
## 许可证
|
|
485
|
-
|
|
486
|
-
MIT License
|
|
487
|
-
`;
|
|
488
|
-
|
|
489
|
-
writeFile(path.join(projectPath, 'README.md'), readmeContent);
|
|
490
|
-
}
|
|
491
|
-
|
|
492
|
-
/**
|
|
493
|
-
* 安装依赖
|
|
494
|
-
*/
|
|
495
|
-
async function installDependencies(projectPath) {
|
|
496
|
-
console.log('📦 安装依赖包...');
|
|
497
|
-
|
|
498
|
-
const success = executeCommand('npm install', projectPath);
|
|
499
|
-
|
|
500
|
-
if (!success) {
|
|
501
|
-
console.warn('⚠️ 依赖安装失败,请手动运行: npm install');
|
|
502
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* 项目生成器
|
|
3
|
+
* 负责创建和管理项目模板
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import fs from 'fs';
|
|
7
|
+
import path from 'path';
|
|
8
|
+
import {
|
|
9
|
+
createDirectory,
|
|
10
|
+
copyDirectory,
|
|
11
|
+
writeFile,
|
|
12
|
+
renderTemplate,
|
|
13
|
+
executeCommand,
|
|
14
|
+
getProjectRoot,
|
|
15
|
+
validateProjectName
|
|
16
|
+
} from './utils.js';
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* 创建新项目
|
|
20
|
+
*/
|
|
21
|
+
export async function createProject(projectName, options) {
|
|
22
|
+
// 验证项目名称
|
|
23
|
+
validateProjectName(projectName);
|
|
24
|
+
|
|
25
|
+
const projectPath = path.resolve(process.cwd(), projectName);
|
|
26
|
+
|
|
27
|
+
// 检查目录是否已存在
|
|
28
|
+
if (fs.existsSync(projectPath)) {
|
|
29
|
+
throw new Error(`目录 "${projectName}" 已存在,请选择其他名称`);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// 创建项目目录
|
|
33
|
+
createDirectory(projectPath);
|
|
34
|
+
|
|
35
|
+
// 根据模板类型生成项目
|
|
36
|
+
await generateProjectStructure(projectPath, options);
|
|
37
|
+
|
|
38
|
+
// 生成配置文件
|
|
39
|
+
await generateConfigFiles(projectPath, projectName, options);
|
|
40
|
+
|
|
41
|
+
// 安装依赖(如果未跳过)
|
|
42
|
+
if (!options.skipInstall) {
|
|
43
|
+
await installDependencies(projectPath);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* 生成项目结构
|
|
49
|
+
*/
|
|
50
|
+
async function generateProjectStructure(projectPath, options) {
|
|
51
|
+
const templateType = options.template || 'default';
|
|
52
|
+
const sourceRoot = getProjectRoot();
|
|
53
|
+
|
|
54
|
+
console.log('📁 生成项目结构...');
|
|
55
|
+
|
|
56
|
+
// 复制基础文件
|
|
57
|
+
const baseFiles = [
|
|
58
|
+
'package.json',
|
|
59
|
+
'vite.config.js',
|
|
60
|
+
'index.html',
|
|
61
|
+
'eslint.config.js',
|
|
62
|
+
'.prettierrc.json',
|
|
63
|
+
'.gitignore',
|
|
64
|
+
'.editorconfig',
|
|
65
|
+
'jsconfig.json'
|
|
66
|
+
];
|
|
67
|
+
|
|
68
|
+
baseFiles.forEach(file => {
|
|
69
|
+
const sourceFile = path.join(sourceRoot, file);
|
|
70
|
+
const targetFile = path.join(projectPath, file);
|
|
71
|
+
|
|
72
|
+
if (fs.existsSync(sourceFile)) {
|
|
73
|
+
fs.copyFileSync(sourceFile, targetFile);
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
// 复制环境配置文件
|
|
78
|
+
const envFiles = ['.env.development', '.env.test'];
|
|
79
|
+
envFiles.forEach(file => {
|
|
80
|
+
const sourceFile = path.join(sourceRoot, file);
|
|
81
|
+
const targetFile = path.join(projectPath, file);
|
|
82
|
+
|
|
83
|
+
if (fs.existsSync(sourceFile)) {
|
|
84
|
+
fs.copyFileSync(sourceFile, targetFile);
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
// 使用模板生成生产环境配置文件
|
|
89
|
+
await generateProductionEnv(projectPath);
|
|
90
|
+
|
|
91
|
+
// 复制 public 目录
|
|
92
|
+
copyDirectory(path.join(sourceRoot, 'public'), path.join(projectPath, 'public'));
|
|
93
|
+
|
|
94
|
+
// 复制 src 目录(根据模板类型)
|
|
95
|
+
await copySourceDirectory(sourceRoot, projectPath, templateType);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* 复制源代码目录
|
|
100
|
+
*/
|
|
101
|
+
async function copySourceDirectory(sourceRoot, projectPath, templateType) {
|
|
102
|
+
const srcPath = path.join(sourceRoot, 'src');
|
|
103
|
+
const targetSrcPath = path.join(projectPath, 'src');
|
|
104
|
+
|
|
105
|
+
// 创建 src 目录结构
|
|
106
|
+
createDirectory(targetSrcPath);
|
|
107
|
+
|
|
108
|
+
// 复制核心文件
|
|
109
|
+
const coreFiles = ['main.js', 'App.vue'];
|
|
110
|
+
coreFiles.forEach(file => {
|
|
111
|
+
const sourceFile = path.join(srcPath, file);
|
|
112
|
+
const targetFile = path.join(targetSrcPath, file);
|
|
113
|
+
|
|
114
|
+
if (fs.existsSync(sourceFile)) {
|
|
115
|
+
fs.copyFileSync(sourceFile, targetFile);
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
// 复制核心目录
|
|
120
|
+
const coreDirs = ['api', 'assets', 'config', 'directives', 'router', 'stores', 'utils'];
|
|
121
|
+
coreDirs.forEach(dir => {
|
|
122
|
+
const sourceDir = path.join(srcPath, dir);
|
|
123
|
+
const targetDir = path.join(targetSrcPath, dir);
|
|
124
|
+
|
|
125
|
+
if (fs.existsSync(sourceDir)) {
|
|
126
|
+
copyDirectory(sourceDir, targetDir);
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
// 根据模板类型处理 components 和 views
|
|
131
|
+
await handleTemplateSpecificFiles(srcPath, targetSrcPath, templateType);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* 处理模板特定的文件
|
|
136
|
+
*/
|
|
137
|
+
async function handleTemplateSpecificFiles(srcPath, targetSrcPath, templateType) {
|
|
138
|
+
// 复制 components 目录
|
|
139
|
+
const componentsSource = path.join(srcPath, 'components');
|
|
140
|
+
const componentsTarget = path.join(targetSrcPath, 'components');
|
|
141
|
+
|
|
142
|
+
if (fs.existsSync(componentsSource)) {
|
|
143
|
+
copyDirectory(componentsSource, componentsTarget);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// 处理 views 目录
|
|
147
|
+
const viewsSource = path.join(srcPath, 'views');
|
|
148
|
+
const viewsTarget = path.join(targetSrcPath, 'views');
|
|
149
|
+
|
|
150
|
+
if (fs.existsSync(viewsSource)) {
|
|
151
|
+
if (templateType === 'basic') {
|
|
152
|
+
// 基础模板:只保留核心页面
|
|
153
|
+
createDirectory(viewsTarget);
|
|
154
|
+
const basicViews = ['console.vue', 'home.vue', 'login.vue'];
|
|
155
|
+
|
|
156
|
+
basicViews.forEach(view => {
|
|
157
|
+
const sourceFile = path.join(viewsSource, view);
|
|
158
|
+
const targetFile = path.join(viewsTarget, view);
|
|
159
|
+
|
|
160
|
+
if (fs.existsSync(sourceFile)) {
|
|
161
|
+
fs.copyFileSync(sourceFile, targetFile);
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
} else {
|
|
165
|
+
// 默认和完整模板:复制所有页面
|
|
166
|
+
copyDirectory(viewsSource, viewsTarget);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* 生成配置文件
|
|
173
|
+
*/
|
|
174
|
+
async function generateConfigFiles(projectPath, projectName, options) {
|
|
175
|
+
console.log('⚙️ 生成配置文件...');
|
|
176
|
+
|
|
177
|
+
// 读取并更新 package.json
|
|
178
|
+
const packageJsonPath = path.join(projectPath, 'package.json');
|
|
179
|
+
if (fs.existsSync(packageJsonPath)) {
|
|
180
|
+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
181
|
+
|
|
182
|
+
// 更新项目信息
|
|
183
|
+
packageJson.name = projectName;
|
|
184
|
+
packageJson.description = options.description;
|
|
185
|
+
|
|
186
|
+
if (options.author) {
|
|
187
|
+
packageJson.author = options.author;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// 根据功能特性调整依赖
|
|
191
|
+
if (options.features && options.features.length > 0) {
|
|
192
|
+
await adjustDependencies(packageJson, options.features);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// 移除脚手架特定的配置
|
|
196
|
+
delete packageJson.bin;
|
|
197
|
+
delete packageJson.main;
|
|
198
|
+
|
|
199
|
+
// 写入更新后的 package.json
|
|
200
|
+
writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2));
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// 生成 README.md
|
|
204
|
+
await generateReadme(projectPath, projectName, options);
|
|
205
|
+
|
|
206
|
+
// 根据功能特性生成额外文件
|
|
207
|
+
if (options.features && options.features.length > 0) {
|
|
208
|
+
await generateFeatureFiles(projectPath, options.features);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* 根据功能特性调整依赖
|
|
214
|
+
*/
|
|
215
|
+
async function adjustDependencies(packageJson, features) {
|
|
216
|
+
const featureDependencies = {
|
|
217
|
+
'i18n-support': {
|
|
218
|
+
dependencies: {
|
|
219
|
+
'vue-i18n': '^9.0.0'
|
|
220
|
+
}
|
|
221
|
+
},
|
|
222
|
+
'file-upload': {
|
|
223
|
+
dependencies: {
|
|
224
|
+
'ant-design-vue': '^4.2.6' // 已包含,确保版本
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
features.forEach(feature => {
|
|
230
|
+
const deps = featureDependencies[feature];
|
|
231
|
+
if (deps && deps.dependencies) {
|
|
232
|
+
Object.assign(packageJson.dependencies, deps.dependencies);
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* 根据功能特性生成额外文件
|
|
239
|
+
*/
|
|
240
|
+
async function generateFeatureFiles(projectPath, features) {
|
|
241
|
+
const featureGenerators = {
|
|
242
|
+
'i18n-support': generateI18nFiles,
|
|
243
|
+
'user-management': generateUserManagementFiles,
|
|
244
|
+
'permission-management': generatePermissionFiles
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
for (const feature of features) {
|
|
248
|
+
const generator = featureGenerators[feature];
|
|
249
|
+
if (generator) {
|
|
250
|
+
await generator(projectPath);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* 生成国际化支持文件
|
|
257
|
+
*/
|
|
258
|
+
async function generateI18nFiles(projectPath) {
|
|
259
|
+
console.log('🌐 生成国际化支持文件...');
|
|
260
|
+
|
|
261
|
+
// 创建 locales 目录
|
|
262
|
+
const localesDir = path.join(projectPath, 'src/locales');
|
|
263
|
+
createDirectory(localesDir);
|
|
264
|
+
|
|
265
|
+
// 生成中文语言包
|
|
266
|
+
const zhCNContent = `{
|
|
267
|
+
"common": {
|
|
268
|
+
"save": "保存",
|
|
269
|
+
"cancel": "取消",
|
|
270
|
+
"delete": "删除",
|
|
271
|
+
"edit": "编辑",
|
|
272
|
+
"add": "添加"
|
|
273
|
+
},
|
|
274
|
+
"menu": {
|
|
275
|
+
"dashboard": "仪表盘",
|
|
276
|
+
"user": "用户管理",
|
|
277
|
+
"system": "系统管理"
|
|
278
|
+
}
|
|
279
|
+
}`;
|
|
280
|
+
|
|
281
|
+
writeFile(path.join(localesDir, 'zh-CN.json'), zhCNContent);
|
|
282
|
+
|
|
283
|
+
// 生成英文语言包
|
|
284
|
+
const enUSContent = `{
|
|
285
|
+
"common": {
|
|
286
|
+
"save": "Save",
|
|
287
|
+
"cancel": "Cancel",
|
|
288
|
+
"delete": "Delete",
|
|
289
|
+
"edit": "Edit",
|
|
290
|
+
"add": "Add"
|
|
291
|
+
},
|
|
292
|
+
"menu": {
|
|
293
|
+
"dashboard": "Dashboard",
|
|
294
|
+
"user": "User Management",
|
|
295
|
+
"system": "System Management"
|
|
296
|
+
}
|
|
297
|
+
}`;
|
|
298
|
+
|
|
299
|
+
writeFile(path.join(localesDir, 'en-US.json'), enUSContent);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* 生成用户管理相关文件
|
|
304
|
+
*/
|
|
305
|
+
async function generateUserManagementFiles(projectPath) {
|
|
306
|
+
console.log('👥 生成用户管理文件...');
|
|
307
|
+
|
|
308
|
+
// 创建用户管理相关目录
|
|
309
|
+
const userViewsDir = path.join(projectPath, 'src/views/system/user');
|
|
310
|
+
createDirectory(userViewsDir);
|
|
311
|
+
|
|
312
|
+
// 生成用户列表页面
|
|
313
|
+
const userListContent = `<template>
|
|
314
|
+
<div class="user-management">
|
|
315
|
+
<a-card title="用户管理">
|
|
316
|
+
<a-table :columns="columns" :data-source="userList">
|
|
317
|
+
<template #action="{ record }">
|
|
318
|
+
<a-space>
|
|
319
|
+
<a-button type="link" @click="handleEdit(record)">编辑</a-button>
|
|
320
|
+
<a-button type="link" danger @click="handleDelete(record)">删除</a-button>
|
|
321
|
+
</a-space>
|
|
322
|
+
</template>
|
|
323
|
+
</a-table>
|
|
324
|
+
</a-card>
|
|
325
|
+
</div>
|
|
326
|
+
</template>
|
|
327
|
+
|
|
328
|
+
<script setup>
|
|
329
|
+
import { ref, onMounted } from 'vue';
|
|
330
|
+
|
|
331
|
+
const columns = [
|
|
332
|
+
{ title: '用户名', dataIndex: 'username' },
|
|
333
|
+
{ title: '邮箱', dataIndex: 'email' },
|
|
334
|
+
{ title: '角色', dataIndex: 'role' },
|
|
335
|
+
{ title: '状态', dataIndex: 'status' },
|
|
336
|
+
{ title: '操作', slots: { customRender: 'action' } }
|
|
337
|
+
];
|
|
338
|
+
|
|
339
|
+
const userList = ref([]);
|
|
340
|
+
|
|
341
|
+
onMounted(() => {
|
|
342
|
+
// 加载用户数据
|
|
343
|
+
loadUserData();
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
const loadUserData = async () => {
|
|
347
|
+
// 模拟数据
|
|
348
|
+
userList.value = [
|
|
349
|
+
{ id: 1, username: 'admin', email: 'admin@example.com', role: '管理员', status: '正常' }
|
|
350
|
+
];
|
|
351
|
+
};
|
|
352
|
+
|
|
353
|
+
const handleEdit = (record) => {
|
|
354
|
+
console.log('编辑用户:', record);
|
|
355
|
+
};
|
|
356
|
+
|
|
357
|
+
const handleDelete = (record) => {
|
|
358
|
+
console.log('删除用户:', record);
|
|
359
|
+
};
|
|
360
|
+
</script>
|
|
361
|
+
|
|
362
|
+
<style scoped>
|
|
363
|
+
.user-management {
|
|
364
|
+
padding: 20px;
|
|
365
|
+
}
|
|
366
|
+
</style>`;
|
|
367
|
+
|
|
368
|
+
writeFile(path.join(userViewsDir, 'index.vue'), userListContent);
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
/**
|
|
372
|
+
* 生成权限管理相关文件
|
|
373
|
+
*/
|
|
374
|
+
async function generatePermissionFiles(projectPath) {
|
|
375
|
+
console.log('🔐 生成权限管理文件...');
|
|
376
|
+
|
|
377
|
+
// 创建权限管理相关目录
|
|
378
|
+
const permissionViewsDir = path.join(projectPath, 'src/views/system/permission');
|
|
379
|
+
createDirectory(permissionViewsDir);
|
|
380
|
+
|
|
381
|
+
// 生成权限管理页面
|
|
382
|
+
const permissionContent = `<template>
|
|
383
|
+
<div class="permission-management">
|
|
384
|
+
<a-card title="权限管理">
|
|
385
|
+
<p>权限管理功能已生成,请根据业务需求进行开发。</p>
|
|
386
|
+
</a-card>
|
|
387
|
+
</div>
|
|
388
|
+
</template>
|
|
389
|
+
|
|
390
|
+
<script setup>
|
|
391
|
+
// 权限管理页面逻辑
|
|
392
|
+
</script>
|
|
393
|
+
|
|
394
|
+
<style scoped>
|
|
395
|
+
.permission-management {
|
|
396
|
+
padding: 20px;
|
|
397
|
+
}
|
|
398
|
+
</style>`;
|
|
399
|
+
|
|
400
|
+
writeFile(path.join(permissionViewsDir, 'index.vue'), permissionContent);
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
/**
|
|
404
|
+
* 生成生产环境配置文件
|
|
405
|
+
*/
|
|
406
|
+
async function generateProductionEnv(projectPath) {
|
|
407
|
+
console.log('🔧 生成生产环境配置文件...');
|
|
408
|
+
|
|
409
|
+
const templatePath = path.join(getProjectRoot(), 'templates/env.production');
|
|
410
|
+
const targetPath = path.join(projectPath, '.env.production');
|
|
411
|
+
|
|
412
|
+
if (fs.existsSync(templatePath)) {
|
|
413
|
+
// 使用模板文件
|
|
414
|
+
fs.copyFileSync(templatePath, targetPath);
|
|
415
|
+
} else {
|
|
416
|
+
// 如果模板不存在,创建默认的生产环境配置
|
|
417
|
+
const defaultProdConfig = `# 生产环境配置
|
|
418
|
+
VITE_BASE_API=http://your-production-server.com/api/
|
|
419
|
+
|
|
420
|
+
# 其他生产环境变量
|
|
421
|
+
NODE_ENV=production
|
|
422
|
+
VITE_APP_TITLE=ZAnt Admin`;
|
|
423
|
+
|
|
424
|
+
writeFile(targetPath, defaultProdConfig);
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
/**
|
|
429
|
+
* 生成 README.md 文件
|
|
430
|
+
*/
|
|
431
|
+
async function generateReadme(projectPath, projectName, options) {
|
|
432
|
+
const readmeContent = `# ${projectName}
|
|
433
|
+
|
|
434
|
+
${options.description}
|
|
435
|
+
|
|
436
|
+
## 技术栈
|
|
437
|
+
|
|
438
|
+
- Vue 3 (Composition API)
|
|
439
|
+
- Vite 构建工具
|
|
440
|
+
- Ant Design Vue UI 组件库
|
|
441
|
+
- Pinia 状态管理
|
|
442
|
+
- Vue Router 路由管理
|
|
443
|
+
|
|
444
|
+
## 快速开始
|
|
445
|
+
|
|
446
|
+
### 安装依赖
|
|
447
|
+
\`\`\`bash
|
|
448
|
+
npm install
|
|
449
|
+
\`\`\`
|
|
450
|
+
|
|
451
|
+
### 启动开发服务器
|
|
452
|
+
\`\`\`bash
|
|
453
|
+
npm run dev
|
|
454
|
+
\`\`\`
|
|
455
|
+
|
|
456
|
+
### 构建生产版本
|
|
457
|
+
\`\`\`bash
|
|
458
|
+
npm run build
|
|
459
|
+
\`\`\`
|
|
460
|
+
|
|
461
|
+
## 项目结构
|
|
462
|
+
|
|
463
|
+
\`\`\`
|
|
464
|
+
src/
|
|
465
|
+
├── api/ # 接口请求相关
|
|
466
|
+
├── assets/ # 静态资源文件
|
|
467
|
+
├── components/ # 公共组件
|
|
468
|
+
├── router/ # 路由配置
|
|
469
|
+
├── stores/ # 状态管理
|
|
470
|
+
├── utils/ # 工具函数
|
|
471
|
+
├── views/ # 页面视图
|
|
472
|
+
├── App.vue # 根组件
|
|
473
|
+
└── main.js # 入口文件
|
|
474
|
+
\`\`\`
|
|
475
|
+
|
|
476
|
+
## 命令说明
|
|
477
|
+
|
|
478
|
+
- \`npm run dev\` - 启动开发服务器
|
|
479
|
+
- \`npm run build\` - 构建生产版本
|
|
480
|
+
- \`npm run preview\` - 预览生产构建
|
|
481
|
+
- \`npm run lint\` - 代码检查
|
|
482
|
+
- \`npm run format\` - 代码格式化
|
|
483
|
+
|
|
484
|
+
## 许可证
|
|
485
|
+
|
|
486
|
+
MIT License
|
|
487
|
+
`;
|
|
488
|
+
|
|
489
|
+
writeFile(path.join(projectPath, 'README.md'), readmeContent);
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
/**
|
|
493
|
+
* 安装依赖
|
|
494
|
+
*/
|
|
495
|
+
async function installDependencies(projectPath) {
|
|
496
|
+
console.log('📦 安装依赖包...');
|
|
497
|
+
|
|
498
|
+
const success = executeCommand('npm install', projectPath);
|
|
499
|
+
|
|
500
|
+
if (!success) {
|
|
501
|
+
console.warn('⚠️ 依赖安装失败,请手动运行: npm install');
|
|
502
|
+
}
|
|
503
503
|
}
|