flu-cli 0.0.5 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/CLI.md +349 -0
  2. package/README.md +59 -276
  3. package/config/dev.config.js +56 -0
  4. package/config/templates.js +147 -0
  5. package/index.js +128 -81
  6. package/lib/commands/add.js +472 -0
  7. package/lib/commands/cache.js +99 -0
  8. package/lib/commands/completion.js +94 -0
  9. package/lib/commands/generate.js +26 -0
  10. package/lib/commands/newClack.js +396 -0
  11. package/lib/commands/snippets.js +39 -0
  12. package/lib/commands/templates.js +84 -0
  13. package/lib/generators/component_generator.js +93 -0
  14. package/lib/generators/model_generator.js +303 -0
  15. package/lib/generators/module_generator.js +141 -0
  16. package/lib/generators/page_generator.js +322 -0
  17. package/lib/generators/project_generator.js +96 -0
  18. package/lib/generators/service_generator.js +408 -0
  19. package/lib/generators/state_manager_generator.js +402 -0
  20. package/lib/generators/viewmodel_generator.js +115 -0
  21. package/lib/generators/widget_generator.js +104 -0
  22. package/lib/templates/templateCopier.js +296 -0
  23. package/lib/templates/templateManager.js +191 -0
  24. package/lib/utils/config.js +99 -0
  25. package/lib/utils/flutterHelper.js +85 -0
  26. package/lib/utils/index_updater.js +69 -0
  27. package/lib/utils/logger.js +57 -0
  28. package/lib/utils/project_detector.js +227 -0
  29. package/lib/utils/snippet_loader.js +32 -0
  30. package/lib/utils/string_helper.js +56 -0
  31. package/lib/utils/templateSelectorEnquirer.js +200 -0
  32. package/package.json +31 -6
  33. package/release.sh +107 -0
  34. package/scripts/e2e-state-tests.js +116 -0
  35. package/scripts/sync-base-to-templates.js +108 -0
  36. package/scripts/workspace-clone-all.sh +101 -0
  37. package/scripts/workspace-status-all.sh +112 -0
  38. package/templates/README.md +138 -0
  39. package/templates/base_files/base_list_page.dart.template +174 -0
  40. package/templates/base_files/base_list_viewmodel.dart.template +134 -0
  41. package/templates/base_files/base_page.dart.template +251 -0
  42. package/templates/base_files/base_viewmodel.dart.template +77 -0
  43. package/templates/base_files/theme/status_views_theme.dart.template +46 -0
  44. package/templates/snippets/dart.code-snippets +487 -0
  45. package/lib/createProject.js +0 -220
  46. package/lib/flutterProjectCreator.js +0 -80
  47. package/lib/libCopier.js +0 -368
  48. package/lib/userInteraction.js +0 -274
  49. package/lib/utils.js +0 -200
  50. package/publish.sh +0 -29
@@ -1,220 +0,0 @@
1
- /**
2
- * 项目创建模块
3
- *
4
- * 负责协调整个Flutter项目的创建流程,包括用户交互、项目初始化、模板复制和环境配置
5
- * 支持通过命令行参数或交互式方式创建不同类型和模板的Flutter项目
6
- */
7
-
8
- import { execSync } from 'child_process';
9
- import ora from 'ora';
10
- import { dirname, join } from 'path';
11
- import { fileURLToPath } from 'url';
12
- import fsExtra from 'fs-extra';
13
- const { existsSync, mkdirSync, accessSync, constants, removeSync } = fsExtra;
14
- import { getUserInteraction } from './userInteraction.js';
15
- import { copyLibDirectory, copyVscode } from './libCopier.js';
16
- import { runFlutterCreate } from './flutterProjectCreator.js';
17
- import { printColored, updateReadme, openProjectInIde, getTemplateBranch } from './utils.js';
18
-
19
- /**
20
- * 生成默认项目名称
21
- *
22
- * 根据项目类型和当前日期生成唯一的默认项目名称,避免命名冲突
23
- * 应用类型项目以'flutter_app_'为前缀,模块类型以'flutter_module_'为前缀
24
- *
25
- * @param {string} projectType - 项目类型 ('app' 或 'module')
26
- * @returns {string} 带时间戳的默认项目名称
27
- */
28
- function getDefaultProjectName (projectType) {
29
- const date = new Date();
30
- const timestamp = `${date.getFullYear()}${String(date.getMonth() + 1).padStart(2, '0')}${String(date.getDate()).padStart(2, '0')}`;
31
- return projectType === 'app' ? `flutter_app_${timestamp}` : `flutter_module_${timestamp}`;
32
- }
33
-
34
- /**
35
- * 创建项目的主函数
36
- *
37
- * 协调整个项目创建流程,包括获取用户输入、验证环境、创建Flutter项目、复制模板文件、
38
- * 生成README和自动打开IDE等步骤。支持命令行参数和交互式两种模式
39
- *
40
- * @param {Object} [options={}] - 命令行参数选项
41
- * @param {boolean} [options.useCommandLineArgs=false] - 是否使用命令行参数
42
- * @param {string} [options.projectType] - 项目类型 ('app','module','package','plugin')
43
- * @param {string} [options.templateType] - 模板类型 ('only', 'min', 'normal', 'pro')
44
- * @param {string} [options.stateManager] - 状态管理 ('state', 'GetX', 'Provider', etc.)
45
- * @param {string} [options.projectName] - 项目名称
46
- * @param {string} [options.packageName] - 包名
47
- * @param {string} [options.parentDir] - 项目存放路径
48
- * @param {string} [options.ideChoice] - IDE选择 ('vscode', 'android_studio', etc.)
49
- * @param {string} [options.flutterSdk] - Flutter SDK路径
50
- * @example
51
- * // 交互式创建项目
52
- * createProject();
53
- * // 命令行模式创建项目
54
- * createProject({
55
- * useCommandLineArgs: true,
56
- * projectType: 'app',
57
- * templateType: 'pro',
58
- * projectName: 'my_app',
59
- * packageName: 'com.example.myapp',
60
- * parentDir: '/path/to/projects'
61
- * });
62
- */
63
- async function createProject (options = {}) {
64
- try {
65
- // 获取项目类型 - 从命令行参数或交互式输入
66
- const projectType = options.useCommandLineArgs ? options.projectType : await getUserInteraction.getProjectType();
67
- let templateType = '';
68
- // 项目类型为app或module时,获取模板类型
69
- if (projectType == "app" || projectType == "module") {
70
- // 获取模板类型 - 从命令行参数或交互式输入
71
- templateType = options.useCommandLineArgs ? options.templateType : await getUserInteraction.getTemplateType();
72
- } else {
73
- // 项目类型为package或plugin时,模板类型固定为only
74
- templateType = 'only';
75
- }
76
-
77
-
78
- // 获取状态管理 - 仅在非基础模板时需要
79
- let stateManager = '';
80
- if (templateType != 'only' && templateType != 'min') {
81
- stateManager = options.useCommandLineArgs ? options.stateManager : await getUserInteraction.getStateManager();
82
- }
83
-
84
- // 获取当前脚本所在目录作为源目录
85
- const sourceDir = dirname(fileURLToPath(import.meta.url));
86
-
87
- // 获取项目信息 - 从命令行参数或交互式输入
88
- let projectName, packageName, parentDir, targetDir, flutterSdkPath;
89
-
90
- if (options.useCommandLineArgs && options.projectName && options.packageName && options.parentDir && options.flutterSdk) {
91
- // 使用命令行参数
92
- projectName = options.projectName;
93
- packageName = options.packageName;
94
- parentDir = options.parentDir;
95
- targetDir = join(parentDir, projectName);
96
- flutterSdkPath = options.flutterSdk;
97
- } else if (options.useCommandLineArgs) {
98
- // 命令行参数不完整,使用交互式输入,但预填充已提供的参数
99
- const defaultName = getDefaultProjectName(projectType);
100
- const projectInfo = await getUserInteraction.getProjectInfo(
101
- projectType,
102
- options.projectName || defaultName,
103
- options.packageName || `com.example.${options.projectName || defaultName}`,
104
- options.parentDir
105
- );
106
- projectName = projectInfo.projectName;
107
- packageName = projectInfo.packageName;
108
- parentDir = projectInfo.parentDir;
109
- targetDir = projectInfo.targetDir;
110
- flutterSdkPath = projectInfo.flutterSdkPath;
111
- } else {
112
- // 完全使用交互式输入
113
- const projectInfo = await getUserInteraction.getProjectInfo(projectType);
114
- // 项目名字
115
- projectName = projectInfo.projectName;
116
- // 包名
117
- packageName = projectInfo.packageName;
118
- // 项目存放地址
119
- parentDir = projectInfo.parentDir;
120
- targetDir = projectInfo.targetDir;
121
- flutterSdkPath = projectInfo.flutterSdkPath;
122
- }
123
-
124
- console.log('flutterSdkPath:', flutterSdkPath);
125
- // 验证目标目录是否存在并具有写权限
126
- if (!existsSync(parentDir)) {
127
- try {
128
- mkdirSync(parentDir, { recursive: true });
129
- } catch (e) {
130
- printColored(`错误: 无法创建目录 ${parentDir}: ${e.message}`, 'red');
131
- return;
132
- }
133
- }
134
-
135
- // 检查目标目录是否具有写权限
136
- try {
137
- accessSync(parentDir, constants.W_OK);
138
- } catch (e) {
139
- printColored(`错误: 目录 ${parentDir} 没有写权限`, 'red');
140
- return;
141
- }
142
-
143
- // 检查目标目录是否已存在
144
- if (existsSync(targetDir)) {
145
- const overwrite = await getUserInteraction.confirmOverwrite(targetDir);
146
- if (!overwrite) {
147
- printColored("操作已取消", 'yellow');
148
- return;
149
- }
150
-
151
- // 删除已存在的目录
152
- removeSync(targetDir);
153
- }
154
-
155
- // 使用flutter create创建新项目
156
- const flutterCreateSpinner = ora('正在创建Flutter项目...').start();
157
- const flutterCreateResult = await runFlutterCreate(targetDir, projectName, packageName, projectType, flutterSdkPath);
158
- if (!flutterCreateResult) {
159
- flutterCreateSpinner.fail('Flutter项目创建失败');
160
- return;
161
- }
162
- flutterCreateSpinner.succeed('Flutter项目创建成功');
163
-
164
-
165
-
166
- if (templateType != 'only') {
167
- // 获取模板分支名称
168
- const templateBranch = getTemplateBranch(templateType, stateManager);
169
- // 复制项目文件
170
- const copySpinner = ora('正在复制项目模板...').start();
171
- const copyResult = await copyLibDirectory(sourceDir, targetDir, projectName, projectType, templateType, packageName, templateBranch);
172
- if (!copyResult) {
173
- copySpinner.fail('项目模板复制失败');
174
- return;
175
- }
176
- copySpinner.succeed('项目模板复制成功');
177
- // 更新README.md
178
- updateReadme(targetDir, projectName, packageName);
179
- }
180
-
181
-
182
-
183
-
184
- // 打印完成信息
185
- printColored("\n新项目已创建成功!", 'green');
186
- printColored(`项目路径: ${targetDir}`, 'green');
187
- printColored("\n执行以下命令开始开发:\n", 'blue');
188
- printColored(`cd ${targetDir}`, 'yellow');
189
- printColored(`flutter pub get`, 'yellow');
190
- printColored(`flutter run`, 'yellow');
191
-
192
- // 获取用户选择的IDE类型 - 从命令行参数或交互式输入
193
- const ideChoice = options.useCommandLineArgs ? options.ideChoice : await getUserInteraction.getIdeChoice();
194
- if (ideChoice == 'vscode' && templateType != 'only') {
195
- await copyVscode(targetDir);
196
- }
197
- if ((ideChoice == 'vscode' || ideChoice == 'android_studio') && flutterSdkPath === 'flutter') {
198
- const pubGetSpinner = ora('正在获取Flutter依赖...').start();
199
- try {
200
- // 执行flutter pub get命令
201
- execSync(`cd ${targetDir} && flutter pub get`, { stdio: 'inherit' });
202
- pubGetSpinner.succeed('依赖获取成功');
203
- } catch (e) {
204
- pubGetSpinner.fail('依赖获取失败');
205
- printColored(`错误信息: ${e.message}`, 'red');
206
- }
207
- }
208
- // 自动打开项目
209
- openProjectInIde(targetDir, ideChoice);
210
-
211
- } catch (error) {
212
- if (error.isTtyError) {
213
- printColored("\n当前环境不支持交互式提示", 'red');
214
- } else {
215
- printColored(`\n错误: ${error.message}`, 'red');
216
- }
217
- }
218
- }
219
-
220
- export { createProject };
@@ -1,80 +0,0 @@
1
- /**
2
- * Flutter项目创建器模块
3
- *
4
- * 负责执行Flutter官方命令行工具创建新项目,处理不同项目类型的创建参数
5
- * 支持应用、模块、包和插件等多种项目类型,并处理Flutter SDK路径配置
6
- */
7
-
8
- import { exec } from 'child_process';
9
- import { printColored } from './utils.js';
10
-
11
- /**
12
- * 执行flutter create命令创建新项目
13
- *
14
- * 根据提供的参数调用Flutter SDK的create命令,创建指定类型的Flutter项目
15
- * 支持自定义Flutter SDK路径,处理不同操作系统下的命令格式差异
16
- *
17
- * @param {string} targetDir - 项目创建目标目录绝对路径
18
- * @param {string} projectName - 项目名称
19
- * @param {string} packageName - 应用包名(Android)或Bundle ID(iOS)
20
- * @param {string} projectType - 项目类型,可选值:'app', 'module', 'package', 'plugin'
21
- * @param {string} [flutterSdkPath='flutter'] - Flutter SDK路径,默认为系统环境变量中的'flutter'
22
- * @returns {Promise<boolean>} 创建成功返回true,失败返回false
23
- */
24
- async function runFlutterCreate (targetDir, projectName, packageName, projectType, flutterSdkPath = 'flutter') {
25
- return new Promise((resolve) => {
26
- // 构建flutter create命令参数
27
- let command = `${flutterSdkPath} create`;
28
-
29
- // 根据项目类型添加参数
30
- switch (projectType) {
31
- case 'module':
32
- command += ' --template=module';
33
- break;
34
- case 'package':
35
- command += ' --template=package';
36
- break;
37
- case 'plugin':
38
- command += ' --template=plugin';
39
- break;
40
- case 'app':
41
- default:
42
- // 默认创建应用项目
43
- break;
44
- }
45
-
46
- // 添加包名参数
47
- command += ` --org ${packageName}`;
48
-
49
- // 添加项目名称和目标路径
50
- command += ` --project-name ${projectName} ${targetDir}`;
51
-
52
- printColored(`执行命令: ${command}`, 'blue');
53
-
54
- // 执行命令
55
- exec(command, (error, stdout, stderr) => {
56
- // 输出命令执行过程信息
57
- if (stdout) printColored(stdout, 'gray');
58
- if (stderr) printColored(stderr, 'yellow');
59
-
60
- // 处理错误
61
- if (error) {
62
- printColored(`Flutter项目创建失败: ${error.message}`, 'red');
63
- resolve(false);
64
- return;
65
- }
66
-
67
- // 验证是否包含成功信息
68
- if (stdout.includes('All done!') || stdout.includes('Created project')) {
69
- printColored(`Flutter ${projectType}项目创建成功`, 'green');
70
- resolve(true);
71
- } else {
72
- printColored('Flutter项目创建未检测到成功标志', 'yellow');
73
- resolve(false);
74
- }
75
- });
76
- });
77
- }
78
-
79
- export { runFlutterCreate };
80
-
package/lib/libCopier.js DELETED
@@ -1,368 +0,0 @@
1
- /**
2
- * 项目模板复制模块
3
- *
4
- * 用于复制和处理 Flutter 项目的 lib 目录文件
5
- * 支持从Git仓库获取代码
6
- * 支持创建packages目录并克隆常用库
7
- */
8
-
9
- import fsExtra from 'fs-extra'
10
- const { mkdtempSync, existsSync, removeSync, readFileSync, writeFileSync, ensureDirSync, copySync, readdirSync, statSync } = fsExtra;
11
- import { join } from 'path';
12
- import { tmpdir } from 'os';
13
- import { exec } from 'child_process';
14
- import { printColored } from './utils.js';
15
-
16
-
17
- /**
18
- * 从Git仓库克隆代码到临时目录
19
- *
20
- * @param {string} gitUrl - Git仓库URL
21
- * @param {string} branch - 分支名称
22
- * @returns {Promise<string|null>} 临时目录路径或null
23
- */
24
- async function cloneGitRepo (gitUrl, branch = 'master') {
25
- return new Promise((resolve) => {
26
- try {
27
- // 创建临时目录
28
- const tempDir = mkdtempSync(join(tmpdir(), 'flutter-cli-'));
29
- printColored(`正在从Git仓库克隆代码到临时目录: ${tempDir}`, 'blue');
30
-
31
- // 克隆指定分支的代码
32
- const command = `git clone -b ${branch} --single-branch ${gitUrl} "${tempDir}"`;
33
-
34
- exec(command, (error, stdout, stderr) => {
35
- if (error) {
36
- printColored(`Git仓库克隆失败: ${error.message}`, 'red');
37
- if (existsSync(tempDir)) {
38
- removeSync(tempDir);
39
- }
40
- resolve(null);
41
- return;
42
- }
43
-
44
- printColored("Git仓库克隆成功!", 'green');
45
- resolve(tempDir);
46
- });
47
- } catch (e) {
48
- printColored(`创建临时目录失败: ${e.message}`, 'red');
49
- resolve(null);
50
- }
51
- });
52
- }
53
-
54
- /**
55
- * 复制并处理lib目录文件和pubspec.yaml
56
- * 支持从本地目录或Git仓库复制
57
- *
58
- * @param {string} sourceDir - 源目录路径
59
- * @param {string} targetDir - 目标目录路径
60
- * @param {string} projectName - 项目名称
61
- * @param {string} projectType - 项目类型 ('app'或'module')
62
- * @param {string} templateType - 模板类型 ('only','min','normal','pro')
63
- * @param {string} packageName - 包名
64
- * @param {string} branch - Git分支
65
- * @param {string} gitUrl - Git仓库URL
66
- * @returns {Promise<boolean>} 是否复制成功
67
- */
68
- export async function copyLibDirectory (
69
- sourceDir,
70
- targetDir,
71
- projectName,
72
- projectType,
73
- templateType,
74
- packageName,
75
- branch = 'master',
76
- gitUrl = 'https://gitee.com/tengteng_fan/hzy_basic_project.git',
77
- ) {
78
- try {
79
- // 如果提供了gitUrl,从Git仓库获取代码
80
- let tempDir = null;
81
- if (gitUrl) {
82
- tempDir = await cloneGitRepo(gitUrl, branch);
83
- if (!tempDir) {
84
- return false;
85
- }
86
- sourceDir = tempDir;
87
- }
88
- try {
89
- // 复制pubspec.yaml
90
- // 源目录路径拼接pubspec.yaml文件名
91
- const pubspecSource = join(sourceDir, 'pubspec.yaml');
92
- // 目标目录路径拼接pubspec.yaml文件名
93
- const pubspecTarget = join(targetDir, 'pubspec.yaml');
94
- // 确保目标目录存在
95
- if (existsSync(pubspecSource)) {
96
- printColored("正在复制并处理pubspec.yaml...", 'blue');
97
-
98
- // 读取源文件内容
99
- let sourceContent = readFileSync(pubspecSource, 'utf8');
100
-
101
- // 提取dependencies部分
102
- let dependenciesContent = 'dependencies:\n';
103
- const dependenciesRegex = /dependencies:[\s\S]*?(?=\n\s*dev_dependencies:)/;
104
- const dependenciesMatch = sourceContent.match(dependenciesRegex);
105
- if (dependenciesMatch) {
106
- dependenciesContent = dependenciesMatch[0];
107
- }
108
-
109
- // 提取assets部分
110
- let assetsContent = '';
111
- let assetsRegex = '';
112
- if (projectType == 'app') {
113
- assetsRegex = / uses-material-design: true[\s\S]*/;
114
- } else if (projectType == 'module') {
115
- assetsRegex = / uses-material-design: true[\s\S]*?(?=\n\s*module:)/;
116
- }
117
- const assetsMatch = sourceContent.match(/ uses-material-design: true[\s\S]*/);
118
- if (assetsMatch) {
119
- printColored("正在提取assets部分...", 'blue');
120
- printColored("assetsMatch[0]: " + assetsMatch, 'blue');
121
- assetsContent = assetsMatch[0];
122
- }
123
-
124
- // 读取目标文件内容
125
- let targetContent = '';
126
- if (existsSync(pubspecTarget)) {
127
- targetContent = readFileSync(pubspecTarget, 'utf8');
128
- }
129
-
130
- // 替换项目名称和描述
131
- targetContent = targetContent.replace(
132
- /description:\s*["'].*?["']/g,
133
- 'description: "火之夜工作室 Flutter 脚手架"'
134
- );
135
-
136
- // 添加publish_to配置防止意外发布
137
- if (!targetContent.includes('publish_to:')) {
138
- targetContent = targetContent.replace(
139
- `name: ${projectName}\n`,
140
- `name: ${projectName}\npublish_to: none\n`
141
- );
142
- }
143
-
144
- // 替换dependencies部分
145
- if (targetContent.match(dependenciesRegex)) {
146
- targetContent = targetContent.replace(dependenciesRegex, dependenciesContent);
147
- } else {
148
- // 如果没有找到dependencies部分,添加到文件末尾
149
- targetContent += '\n' + dependenciesContent;
150
- }
151
- if (targetContent.match(assetsRegex)) {
152
- targetContent = targetContent.replace(assetsRegex, assetsContent);
153
- } else {
154
- // 如果没有找到assets部分,添加到文件末尾
155
- targetContent += '\n' + assetsContent;
156
- }
157
-
158
- // 写入目标文件
159
- writeFileSync(pubspecTarget, targetContent, 'utf8');
160
- }
161
-
162
- // 复制lib目录
163
- const libSource = join(sourceDir, 'lib');
164
- const libTarget = join(targetDir, 'lib');
165
-
166
- if (existsSync(libSource)) {
167
- printColored("正在复制lib目录...", 'blue');
168
-
169
- // 确保目标lib目录存在
170
- ensureDirSync(libTarget);
171
-
172
- // 复制lib目录内容
173
- copySync(libSource, libTarget, {
174
- overwrite: true,
175
- filter: (src) => {
176
- // 可以在这里添加过滤逻辑,例如排除某些文件
177
- return true;
178
- }
179
- });
180
- }
181
-
182
- // 复制assets目录(如果存在)
183
- const assetsSource = join(sourceDir, 'assets');
184
- const assetsTarget = join(targetDir, 'assets');
185
- if (existsSync(assetsSource)) {
186
- printColored("正在复制assets目录...", 'blue');
187
- copySync(assetsSource, assetsTarget, { overwrite: true });
188
- }
189
- // 复制test目录 (如果存在)
190
- const testSource = join(sourceDir, 'test');
191
- const testTarget = join(targetDir, 'test');
192
- if (existsSync(testSource)) {
193
- printColored("正在复制test目录...", 'blue');
194
- copySync(testSource, testTarget, { overwrite: true });
195
- }
196
- // 全局替换包名和项目名称
197
- processLibFiles(libTarget, packageName, projectName);
198
- printColored("正在处理替换lib文件项目名称...", 'blue');
199
- processLibFiles(testTarget, packageName, projectName);
200
- printColored("正在处理test目录文件项目名称...", 'blue');
201
- printColored("项目模板复制完成!", 'green');
202
- return true;
203
- } finally {
204
- // 清理临时目录
205
- if (tempDir && existsSync(tempDir)) {
206
- removeSync(tempDir);
207
- }
208
- }
209
- } catch (e) {
210
- printColored(`复制项目模板时发生错误: ${e.message}`, 'red');
211
- return false;
212
- }
213
- }
214
-
215
-
216
- /**
217
- * 复制vscode配置文件
218
- *
219
- * @param {string} targetDir - 目标目录路径
220
- */
221
- export async function copyVscode (targetDir) {
222
-
223
- /**
224
- * 第一步:创建.vscode 文件夹.
225
- * - 配置.vscode 文件夹的路径.
226
- *
227
- * - 如果.vscode 目录存在,先删除
228
- * - 重新创建 .vscode 目录
229
- * 第二步: 克隆 vscode_config 仓库代码到.vscode 目录
230
- * - 从https://gitee.com/tengteng_fan/vscode_config.git仓库克隆代码到临时目录,
231
- * - 获取临时文件夹中的flutter_vscode文件夹里面的文件
232
- * - 复制到 .vscode 目录中.
233
- */
234
-
235
- // 定义.vscode 目录路径
236
- const vscodeDir = join(targetDir, '.vscode')
237
-
238
- if (existsSync(vscodeDir)) {
239
- printColored("删除已存在的.vscode目录...", 'blue');
240
- removeSync(vscodeDir);
241
- }
242
- printColored("创建.vscode目录...", 'blue');
243
- ensureDirSync(vscodeDir);
244
- printColored("克隆vscode_config仓库代码到.vscode目录...", 'blue');
245
-
246
- const vscodeConfigRepoUrl = 'https://gitee.com/tengteng_fan/vscode_config.git';
247
- // 配置 vscode_config 临时文件夹
248
- const tempDir = await cloneGitRepo(vscodeConfigRepoUrl);
249
- printColored("vscode_config 仓库代码克隆完成...", 'blue');
250
- // 打印临时目录路径
251
- printColored(`临时目录路径: ${tempDir}`, 'blue');
252
- // 定义 vscode_config 目录路径
253
- const vscodeConfigDir = join(tempDir, 'flutter_vscode');
254
- // 打印 vscode_config 目录路径
255
- printColored(`vscode_config 目录路径: ${vscodeConfigDir}`, 'blue');
256
- // 复制 vscode_config 目录内容到 .vscode 目录
257
- copySync(vscodeConfigDir, vscodeDir, { overwrite: true });
258
-
259
- // 清理临时目录
260
- if (tempDir && existsSync(tempDir)) {
261
- removeSync(tempDir);
262
- }
263
- }
264
-
265
- export async function copyPackages (targetDir) {
266
- /**
267
- * 待定: 暂时使用本地packages目录,里面的内容通过git clone 下载在package文件里.
268
- * 后续会增加功能选项.根据用户选择使用本地packages目录,
269
- * 还是直接在pubspec.yaml中添加依赖.
270
- */
271
-
272
- // 创建packages目录
273
- const packagesDir = join(targetDir, 'packages');
274
-
275
- // 如果packages目录存在,先删除
276
- if (existsSync(packagesDir)) {
277
- printColored("删除已存在的packages目录...", 'blue');
278
- removeSync(packagesDir);
279
- }
280
-
281
- // 重新创建packages目录
282
- printColored("创建packages目录...", 'blue');
283
- ensureDirSync(packagesDir);
284
-
285
- // 克隆常用库到packages目录
286
- printColored("正在克隆常用库到packages目录...", 'blue');
287
-
288
-
289
-
290
- // 并行克隆两个仓库
291
- const toolRepoUrl = 'https://gitee.com/hot_night/hzy_normal_tool.git';
292
- const networkRepoUrl = 'https://gitee.com/hot_night/hzy_normal_network.git';
293
- let proArr = [];
294
- if (templateType === '0') {
295
- proArr = [
296
- cloneRepo(toolRepoUrl, join(packagesDir, 'hzy_normal_tool'), 'hzy_normal_tool'),
297
- ];
298
- } else {
299
- proArr = [
300
- cloneRepo(toolRepoUrl, join(packagesDir, 'hzy_normal_tool'), 'hzy_normal_tool'),
301
- cloneRepo(networkRepoUrl, join(packagesDir, 'hzy_normal_network'), 'hzy_normal_network')
302
- ];
303
- }
304
- // 等待两个仓库克隆完成
305
- await Promise.all(proArr);
306
-
307
-
308
-
309
- printColored("packages目录克隆完成!", 'green');
310
- }
311
-
312
- // 定义克隆仓库的Promise函数
313
- const cloneRepo = (repoUrl, targetDir, repoName) => {
314
- return new Promise((resolve) => {
315
- const command = `git clone ${repoUrl} "${targetDir}"`;
316
- exec(command, (error, stdout, stderr) => {
317
- if (error) {
318
- printColored(`克隆${repoName}库失败: ${error.message}`, 'yellow');
319
- resolve(false);
320
- } else {
321
- printColored(`克隆${repoName}库成功!`, 'green');
322
- resolve(true);
323
- }
324
- });
325
- });
326
- };
327
-
328
-
329
- /**
330
- * 处理lib目录中的文件,替换包名等
331
- *
332
- * @param {string} libDir - lib目录路径
333
- * @param {string} packageName - 包名
334
- */
335
- function processLibFiles (targetDir, packageName, projectName) {
336
- try {
337
- // 递归处理目录中的所有文件
338
- const processDir = (dir) => {
339
- const files = readdirSync(dir);
340
-
341
- for (const file of files) {
342
- const filePath = join(dir, file);
343
- const stat = statSync(filePath);
344
-
345
- if (stat.isDirectory()) {
346
- // 递归处理子目录
347
- processDir(filePath);
348
- } else if (stat.isFile() && (file.endsWith('.dart') || file.endsWith('.yaml'))) {
349
- // 处理dart和yaml文件
350
- let content = readFileSync(filePath, 'utf8');
351
-
352
- // 替换packageName和projectName
353
- content = content.replace(/hzy_basic_project/g, projectName);
354
- // 替换包名
355
- content = content.replace(/com\.example\.hzy_basic_project/g, packageName);
356
-
357
- // 写回文件
358
- writeFileSync(filePath, content, 'utf8');
359
- }
360
- }
361
- };
362
-
363
- processDir(targetDir);
364
- } catch (e) {
365
- printColored(`处理lib文件时发生错误: ${e.message}`, 'yellow');
366
- }
367
- }
368
-