@agile-team/robot-cli 1.1.12 → 2.1.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.
- package/CHANGELOG.md +77 -0
- package/README.md +355 -438
- package/bin/robot.js +3 -0
- package/dist/index.js +1720 -0
- package/package.json +77 -81
- package/bin/index.js +0 -405
- package/lib/create.js +0 -1201
- package/lib/download.js +0 -205
- package/lib/templates.js +0 -353
- package/lib/utils.js +0 -334
package/lib/download.js
DELETED
|
@@ -1,205 +0,0 @@
|
|
|
1
|
-
// lib/download.js - 简化版,移除缓存功能
|
|
2
|
-
import fs from 'fs-extra';
|
|
3
|
-
import path from 'path';
|
|
4
|
-
import os from 'os';
|
|
5
|
-
import fetch from 'node-fetch';
|
|
6
|
-
import extract from 'extract-zip';
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* 解析仓库URL,构建下载链接
|
|
10
|
-
*/
|
|
11
|
-
function buildDownloadUrl(repoUrl) {
|
|
12
|
-
try {
|
|
13
|
-
const url = new URL(repoUrl);
|
|
14
|
-
const hostname = url.hostname;
|
|
15
|
-
|
|
16
|
-
if (hostname === 'github.com') {
|
|
17
|
-
return `${repoUrl}/archive/refs/heads/main.zip`;
|
|
18
|
-
} else if (hostname === 'gitee.com') {
|
|
19
|
-
return `${repoUrl}/repository/archive/master.zip`;
|
|
20
|
-
} else if (hostname === 'gitlab.com') {
|
|
21
|
-
const repoName = repoUrl.split('/').pop();
|
|
22
|
-
return `${repoUrl}/-/archive/main/${repoName}-main.zip`;
|
|
23
|
-
} else {
|
|
24
|
-
return `${repoUrl}/archive/refs/heads/main.zip`;
|
|
25
|
-
}
|
|
26
|
-
} catch (error) {
|
|
27
|
-
return `${repoUrl}/archive/refs/heads/main.zip`;
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* 尝试从多个源下载
|
|
33
|
-
*/
|
|
34
|
-
async function tryDownload(repoUrl, spinner) {
|
|
35
|
-
const url = new URL(repoUrl);
|
|
36
|
-
const hostname = url.hostname;
|
|
37
|
-
|
|
38
|
-
// 根据平台选择镜像源
|
|
39
|
-
let mirrors = [];
|
|
40
|
-
|
|
41
|
-
if (hostname === 'github.com') {
|
|
42
|
-
mirrors = [
|
|
43
|
-
repoUrl, // 官方源
|
|
44
|
-
`https://ghproxy.com/${repoUrl}` // GitHub 代理
|
|
45
|
-
];
|
|
46
|
-
} else {
|
|
47
|
-
mirrors = [repoUrl];
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
for (let i = 0; i < mirrors.length; i++) {
|
|
51
|
-
const currentUrl = mirrors[i];
|
|
52
|
-
const isOriginal = currentUrl === repoUrl;
|
|
53
|
-
const sourceName = isOriginal ? `${hostname} 官方` : `${hostname} 镜像`;
|
|
54
|
-
|
|
55
|
-
try {
|
|
56
|
-
if (spinner) {
|
|
57
|
-
spinner.text = `🔍 连接到 ${sourceName}...`;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
const downloadUrl = buildDownloadUrl(currentUrl);
|
|
61
|
-
|
|
62
|
-
if (spinner) {
|
|
63
|
-
spinner.text = `📦 从 ${sourceName} 下载模板...`;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
const response = await fetch(downloadUrl, {
|
|
67
|
-
timeout: isOriginal ? 15000 : 10000,
|
|
68
|
-
headers: {
|
|
69
|
-
'User-Agent': 'Robot-CLI/1.0.0'
|
|
70
|
-
}
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
if (!response.ok) {
|
|
74
|
-
if (response.status === 404) {
|
|
75
|
-
throw new Error(`仓库不存在: ${repoUrl}`);
|
|
76
|
-
}
|
|
77
|
-
throw new Error(`HTTP ${response.status}`);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
if (spinner) {
|
|
81
|
-
const contentLength = response.headers.get('content-length');
|
|
82
|
-
if (contentLength) {
|
|
83
|
-
const sizeInMB = (parseInt(contentLength) / 1024 / 1024).toFixed(1);
|
|
84
|
-
spinner.text = `📦 下载中... (${sizeInMB}MB from ${sourceName})`;
|
|
85
|
-
} else {
|
|
86
|
-
spinner.text = `📦 下载中... (from ${sourceName})`;
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
return { response, sourceName };
|
|
91
|
-
|
|
92
|
-
} catch (error) {
|
|
93
|
-
if (i === mirrors.length - 1) {
|
|
94
|
-
throw error;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
if (spinner) {
|
|
98
|
-
spinner.text = `⚠️ ${sourceName} 访问失败,尝试其他源...`;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
/**
|
|
107
|
-
* 下载模板 - 简化版,总是下载最新版本
|
|
108
|
-
*/
|
|
109
|
-
export async function downloadTemplate(template, options = {}) {
|
|
110
|
-
const { spinner } = options;
|
|
111
|
-
|
|
112
|
-
// 验证模板参数
|
|
113
|
-
if (!template || !template.repoUrl) {
|
|
114
|
-
throw new Error(`模板配置无效: ${JSON.stringify(template)}`);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
try {
|
|
118
|
-
if (spinner) {
|
|
119
|
-
spinner.text = '🌐 开始下载最新模板...';
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
// 尝试从不同源下载
|
|
123
|
-
const { response, sourceName } = await tryDownload(template.repoUrl, spinner);
|
|
124
|
-
|
|
125
|
-
if (spinner) {
|
|
126
|
-
spinner.text = '💾 保存下载文件...';
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
// 创建临时目录和文件
|
|
130
|
-
const timestamp = Date.now();
|
|
131
|
-
const tempZipPath = path.join(os.tmpdir(), `robot-template-${timestamp}.zip`);
|
|
132
|
-
const tempExtractPath = path.join(os.tmpdir(), `robot-extract-${timestamp}`);
|
|
133
|
-
|
|
134
|
-
// 保存下载的文件
|
|
135
|
-
const buffer = await response.buffer();
|
|
136
|
-
await fs.writeFile(tempZipPath, buffer);
|
|
137
|
-
|
|
138
|
-
if (spinner) {
|
|
139
|
-
spinner.text = '📂 解压模板文件...';
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
// 解压文件
|
|
143
|
-
await extract(tempZipPath, { dir: tempExtractPath });
|
|
144
|
-
|
|
145
|
-
if (spinner) {
|
|
146
|
-
spinner.text = '🔍 查找项目结构...';
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
// 查找项目目录
|
|
150
|
-
const extractedItems = await fs.readdir(tempExtractPath);
|
|
151
|
-
const projectDir = extractedItems.find(item =>
|
|
152
|
-
item.endsWith('-main') ||
|
|
153
|
-
item.endsWith('-master') ||
|
|
154
|
-
item === template.repoUrl.split('/').pop()
|
|
155
|
-
);
|
|
156
|
-
|
|
157
|
-
if (!projectDir) {
|
|
158
|
-
throw new Error(`解压后找不到项目目录,可用目录: ${extractedItems.join(', ')}`);
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
const sourcePath = path.join(tempExtractPath, projectDir);
|
|
162
|
-
|
|
163
|
-
// 验证模板完整性
|
|
164
|
-
if (spinner) {
|
|
165
|
-
spinner.text = '✅ 验证模板完整性...';
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
const packageJsonPath = path.join(sourcePath, 'package.json');
|
|
169
|
-
if (!fs.existsSync(packageJsonPath)) {
|
|
170
|
-
throw new Error(`模板缺少 package.json 文件`);
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
if (spinner) {
|
|
174
|
-
spinner.text = `🎉 模板下载完成 (via ${sourceName})`;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
// 清理zip文件,但保留解压的源码目录供后续使用
|
|
178
|
-
await fs.remove(tempZipPath).catch(() => {});
|
|
179
|
-
|
|
180
|
-
return sourcePath;
|
|
181
|
-
|
|
182
|
-
} catch (error) {
|
|
183
|
-
// 清理临时文件
|
|
184
|
-
try {
|
|
185
|
-
const tempFiles = await fs.readdir(os.tmpdir());
|
|
186
|
-
const robotTempFiles = tempFiles.filter(file =>
|
|
187
|
-
file.includes('robot-template-') || file.includes('robot-extract-')
|
|
188
|
-
);
|
|
189
|
-
|
|
190
|
-
for (const file of robotTempFiles) {
|
|
191
|
-
await fs.remove(path.join(os.tmpdir(), file)).catch(() => {});
|
|
192
|
-
}
|
|
193
|
-
} catch (cleanupError) {
|
|
194
|
-
// 忽略清理错误
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
let errorMessage = `模板下载失败: ${error.message}`;
|
|
198
|
-
|
|
199
|
-
if (error.code === 'ENOTFOUND' || error.message.includes('网络')) {
|
|
200
|
-
errorMessage += '\n\n💡 建议:\n1. 检查网络连接\n2. 如果在国内,尝试使用科学上网\n3. 稍后重试';
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
throw new Error(errorMessage);
|
|
204
|
-
}
|
|
205
|
-
}
|
package/lib/templates.js
DELETED
|
@@ -1,353 +0,0 @@
|
|
|
1
|
-
// lib/templates.js - 使用 repoUrl 配置
|
|
2
|
-
export const TEMPLATE_CATEGORIES = {
|
|
3
|
-
frontend: {
|
|
4
|
-
name: '🎨 前端项目',
|
|
5
|
-
stacks: {
|
|
6
|
-
vue: {
|
|
7
|
-
name: 'Vue.js',
|
|
8
|
-
patterns: {
|
|
9
|
-
monolith: {
|
|
10
|
-
name: '单体应用',
|
|
11
|
-
templates: {
|
|
12
|
-
'robot-admin': {
|
|
13
|
-
name: 'Robot Admin 完整版',
|
|
14
|
-
description: '包含30+完整示例、权限管理、图表组件、最佳实践等等',
|
|
15
|
-
repoUrl: 'https://github.com/ChenyCHENYU/Robot_Admin',
|
|
16
|
-
features: ['Naive UI', 'Vue Router', 'Pinia', '权限管理', '动态路由', '图表组件', '性能优化等等'],
|
|
17
|
-
version: 'full'
|
|
18
|
-
},
|
|
19
|
-
'robot-admin-base': {
|
|
20
|
-
name: 'Robot Admin 精简版',
|
|
21
|
-
description: '基础架构、核心功能、快速启动',
|
|
22
|
-
repoUrl: 'https://github.com/ChenyCHENYU/Robot_Admin_Base',
|
|
23
|
-
features: ['Naive UI', 'Vue Router', 'Pinia', '基础布局'],
|
|
24
|
-
version: 'base'
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
},
|
|
28
|
-
monorepo: {
|
|
29
|
-
name: 'Monorepo 架构',
|
|
30
|
-
templates: {
|
|
31
|
-
'robot-monorepo': {
|
|
32
|
-
name: 'Robot Monorepo 完整版',
|
|
33
|
-
description: 'bun workspace + 多包管理 + 共享组件库',
|
|
34
|
-
repoUrl: 'https://github.com/ChenyCHENYU/Robot_Monorepo',
|
|
35
|
-
features: ['bun workspace', 'shared components', 'build tools', 'CI/CD'],
|
|
36
|
-
version: 'full'
|
|
37
|
-
},
|
|
38
|
-
'robot-monorepo-base': {
|
|
39
|
-
name: 'Robot Monorepo 精简版',
|
|
40
|
-
description: '基础 monorepo 结构 + 核心配置',
|
|
41
|
-
repoUrl: 'https://github.com/ChenyCHENYU/Robot_Monorepo_Base',
|
|
42
|
-
features: ['bun workspace', 'basic structure'],
|
|
43
|
-
version: 'base'
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
},
|
|
47
|
-
microfrontend: {
|
|
48
|
-
name: '微前端架构',
|
|
49
|
-
templates: {
|
|
50
|
-
'robot-micro': {
|
|
51
|
-
name: 'Robot微前端 完整版',
|
|
52
|
-
description: 'MicroApp + Vite插件模块联邦 + 多应用示例',
|
|
53
|
-
repoUrl: 'https://github.com/ChenyCHENYU/Robot_Micro',
|
|
54
|
-
features: ['MicroApp', 'Vite模块联邦', '多应用', '路由共享'],
|
|
55
|
-
version: 'full'
|
|
56
|
-
},
|
|
57
|
-
'robot-micro-base': {
|
|
58
|
-
name: 'Robot微前端 精简版',
|
|
59
|
-
description: '基础 MicroApp 架构 + 主子应用',
|
|
60
|
-
repoUrl: 'https://github.com/ChenyCHENYU/Robot_Micro_Base',
|
|
61
|
-
features: ['MicroApp', '基础配置'],
|
|
62
|
-
version: 'base'
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
},
|
|
68
|
-
react: {
|
|
69
|
-
name: 'React.js',
|
|
70
|
-
patterns: {
|
|
71
|
-
monolith: {
|
|
72
|
-
name: '单体应用',
|
|
73
|
-
templates: {
|
|
74
|
-
'robot-react': {
|
|
75
|
-
name: 'Robot React 完整版',
|
|
76
|
-
description: 'Ant Design + 完整功能演示',
|
|
77
|
-
repoUrl: 'https://github.com/ChenyCHENYU/Robot_React',
|
|
78
|
-
features: ['Ant Design', 'React Router', 'Redux Toolkit'],
|
|
79
|
-
version: 'full'
|
|
80
|
-
},
|
|
81
|
-
'robot-react-base': {
|
|
82
|
-
name: 'Robot React 精简版',
|
|
83
|
-
description: '基础React + 核心功能',
|
|
84
|
-
repoUrl: 'https://github.com/ChenyCHENYU/Robot_React_Base',
|
|
85
|
-
features: ['React', 'React Router', '基础组件'],
|
|
86
|
-
version: 'base'
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
},
|
|
94
|
-
mobile: {
|
|
95
|
-
name: '📱 移动端项目',
|
|
96
|
-
stacks: {
|
|
97
|
-
uniapp: {
|
|
98
|
-
name: 'uni-app',
|
|
99
|
-
patterns: {
|
|
100
|
-
multiplatform: {
|
|
101
|
-
name: '多端应用',
|
|
102
|
-
templates: {
|
|
103
|
-
'robot-uniapp': {
|
|
104
|
-
name: 'Robot uni-app 完整版',
|
|
105
|
-
description: '多端适配 + 插件市场 + 完整示例',
|
|
106
|
-
repoUrl: 'https://github.com/ChenyCHENYU/Robot_Uniapp',
|
|
107
|
-
features: ['多端发布', 'uView UI', '插件集成'],
|
|
108
|
-
version: 'full'
|
|
109
|
-
},
|
|
110
|
-
'robot-uniapp-base': {
|
|
111
|
-
name: 'Robot uni-app 精简版',
|
|
112
|
-
description: '基础框架 + 核心功能',
|
|
113
|
-
repoUrl: 'https://github.com/ChenyCHENYU/Robot_Uniapp_Base',
|
|
114
|
-
features: ['基础框架', '路由配置'],
|
|
115
|
-
version: 'base'
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
},
|
|
121
|
-
tarao: {
|
|
122
|
-
name: 'Tarao',
|
|
123
|
-
patterns: {
|
|
124
|
-
native: {
|
|
125
|
-
name: '原生应用',
|
|
126
|
-
templates: {
|
|
127
|
-
'robot-tarao': {
|
|
128
|
-
name: 'Robot Tarao 完整版',
|
|
129
|
-
description: '原生性能 + 跨平台 + 完整功能(暂无,后续完善)',
|
|
130
|
-
repoUrl: 'https://github.com/ChenyCHENYU/Robot_Tarao',
|
|
131
|
-
features: ['原生性能', '跨平台', '完整功能'],
|
|
132
|
-
version: 'full',
|
|
133
|
-
status: 'coming-soon'
|
|
134
|
-
},
|
|
135
|
-
'robot-tarao-base': {
|
|
136
|
-
name: 'Robot Tarao 精简版',
|
|
137
|
-
description: '基础 Tarao 框架(暂无,后续完善)',
|
|
138
|
-
repoUrl: 'https://github.com/ChenyCHENYU/Robot_Tarao_Base',
|
|
139
|
-
features: ['基础框架', '核心功能'],
|
|
140
|
-
version: 'base',
|
|
141
|
-
status: 'coming-soon'
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
},
|
|
149
|
-
backend: {
|
|
150
|
-
name: '🚀 后端项目',
|
|
151
|
-
stacks: {
|
|
152
|
-
nestjs: {
|
|
153
|
-
name: 'NestJS',
|
|
154
|
-
patterns: {
|
|
155
|
-
api: {
|
|
156
|
-
name: 'API服务',
|
|
157
|
-
templates: {
|
|
158
|
-
'robot-nest': {
|
|
159
|
-
name: 'Robot NestJS 完整版',
|
|
160
|
-
description: 'NestJS + TypeORM + JWT + Swagger + Redis + 完整生态',
|
|
161
|
-
repoUrl: 'https://github.com/ChenyCHENYU/Robot_Nest',
|
|
162
|
-
features: ['NestJS', 'TypeORM', 'JWT认证', 'ApiFox文档', 'Redis', '微服务'],
|
|
163
|
-
version: 'full'
|
|
164
|
-
},
|
|
165
|
-
'robot-nest-base': {
|
|
166
|
-
name: 'Robot NestJS 精简版',
|
|
167
|
-
description: '基础 NestJS + 核心模块',
|
|
168
|
-
repoUrl: 'https://github.com/ChenyCHENYU/Robot_Nest_Base',
|
|
169
|
-
features: ['NestJS', '基础路由', '错误处理'],
|
|
170
|
-
version: 'base'
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
},
|
|
174
|
-
microservice: {
|
|
175
|
-
name: '微服务架构',
|
|
176
|
-
templates: {
|
|
177
|
-
'robot-nest-micro': {
|
|
178
|
-
name: 'Robot NestJS微服务版',
|
|
179
|
-
description: 'NestJS + 微服务架构 + gRPC + 服务发现',
|
|
180
|
-
repoUrl: 'https://github.com/ChenyCHENYU/Robot_Nest_Micro',
|
|
181
|
-
features: ['NestJS', '微服务', 'gRPC', 'Redis', '服务发现'],
|
|
182
|
-
version: 'micro'
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
},
|
|
188
|
-
koa: {
|
|
189
|
-
name: 'Koa3',
|
|
190
|
-
patterns: {
|
|
191
|
-
api: {
|
|
192
|
-
name: 'API服务',
|
|
193
|
-
templates: {
|
|
194
|
-
'robot-koa': {
|
|
195
|
-
name: 'Robot Koa3 完整版',
|
|
196
|
-
description: 'Koa3 + TypeScript + JWT + 数据库 + 中间件',
|
|
197
|
-
repoUrl: 'https://github.com/ChenyCHENYU/Robot_Koa',
|
|
198
|
-
features: ['Koa3', 'TypeScript', 'JWT认证', 'MySQL', '中间件'],
|
|
199
|
-
version: 'full'
|
|
200
|
-
},
|
|
201
|
-
'robot-koa-base': {
|
|
202
|
-
name: 'Robot Koa3 精简版',
|
|
203
|
-
description: '基础Koa3 + 核心中间件',
|
|
204
|
-
repoUrl: 'https://github.com/ChenyCHENYU/Robot_Koa_Base',
|
|
205
|
-
features: ['Koa3', '基础路由', '错误处理'],
|
|
206
|
-
version: 'base'
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
},
|
|
214
|
-
desktop: {
|
|
215
|
-
name: '💻 桌面端项目',
|
|
216
|
-
stacks: {
|
|
217
|
-
electron: {
|
|
218
|
-
name: 'Electron',
|
|
219
|
-
patterns: {
|
|
220
|
-
desktop: {
|
|
221
|
-
name: '桌面应用',
|
|
222
|
-
templates: {
|
|
223
|
-
'robot-electron': {
|
|
224
|
-
name: 'Robot Electron 完整版',
|
|
225
|
-
description: 'Vue3 + Electron + 自动更新 + 原生能力',
|
|
226
|
-
repoUrl: 'https://github.com/ChenyCHENYU/Robot_Electron',
|
|
227
|
-
features: ['Vue3', 'Electron', '自动更新', '原生API'],
|
|
228
|
-
version: 'full'
|
|
229
|
-
},
|
|
230
|
-
'robot-electron-base': {
|
|
231
|
-
name: 'Robot Electron 精简版',
|
|
232
|
-
description: '基础Electron + Vue框架',
|
|
233
|
-
repoUrl: 'https://github.com/ChenyCHENYU/Robot_Electron_Base',
|
|
234
|
-
features: ['Vue3', 'Electron', '基础功能'],
|
|
235
|
-
version: 'base'
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
},
|
|
241
|
-
tauri: {
|
|
242
|
-
name: 'Tauri',
|
|
243
|
-
patterns: {
|
|
244
|
-
desktop: {
|
|
245
|
-
name: '桌面应用',
|
|
246
|
-
templates: {
|
|
247
|
-
'robot-tauri': {
|
|
248
|
-
name: 'Robot Tauri 完整版',
|
|
249
|
-
description: 'Rust后端 + Vue前端 + 原生性能',
|
|
250
|
-
repoUrl: 'https://github.com/ChenyCHENYU/Robot_Tauri',
|
|
251
|
-
features: ['Tauri', 'Vue3', 'Rust backend', '原生性能'],
|
|
252
|
-
version: 'full'
|
|
253
|
-
},
|
|
254
|
-
'robot-tauri-base': {
|
|
255
|
-
name: 'Robot Tauri 精简版',
|
|
256
|
-
description: '基础Tauri + Vue框架',
|
|
257
|
-
repoUrl: 'https://github.com/ChenyCHENYU/Robot_Tauri_Base',
|
|
258
|
-
features: ['Tauri', 'Vue3', '基础功能'],
|
|
259
|
-
version: 'base'
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
};
|
|
268
|
-
|
|
269
|
-
/**
|
|
270
|
-
* 获取所有模板的扁平化列表
|
|
271
|
-
*/
|
|
272
|
-
export function getAllTemplates() {
|
|
273
|
-
const templates = {};
|
|
274
|
-
|
|
275
|
-
Object.values(TEMPLATE_CATEGORIES).forEach(category => {
|
|
276
|
-
Object.values(category.stacks).forEach(stack => {
|
|
277
|
-
Object.values(stack.patterns).forEach(pattern => {
|
|
278
|
-
Object.assign(templates, pattern.templates);
|
|
279
|
-
});
|
|
280
|
-
});
|
|
281
|
-
});
|
|
282
|
-
|
|
283
|
-
return templates;
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
/**
|
|
287
|
-
* 根据分类获取模板
|
|
288
|
-
*/
|
|
289
|
-
export function getTemplatesByCategory(categoryKey, stackKey, patternKey) {
|
|
290
|
-
const category = TEMPLATE_CATEGORIES[categoryKey];
|
|
291
|
-
if (!category) return {};
|
|
292
|
-
|
|
293
|
-
const stack = category.stacks[stackKey];
|
|
294
|
-
if (!stack) return {};
|
|
295
|
-
|
|
296
|
-
const pattern = stack.patterns[patternKey];
|
|
297
|
-
if (!pattern) return {};
|
|
298
|
-
|
|
299
|
-
return pattern.templates;
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
/**
|
|
303
|
-
* 搜索模板
|
|
304
|
-
*/
|
|
305
|
-
export function searchTemplates(keyword) {
|
|
306
|
-
const allTemplates = getAllTemplates();
|
|
307
|
-
const results = {};
|
|
308
|
-
|
|
309
|
-
Object.entries(allTemplates).forEach(([key, template]) => {
|
|
310
|
-
const searchText = `${template.name} ${template.description} ${template.features.join(' ')}`.toLowerCase();
|
|
311
|
-
if (searchText.includes(keyword.toLowerCase())) {
|
|
312
|
-
results[key] = template;
|
|
313
|
-
}
|
|
314
|
-
});
|
|
315
|
-
|
|
316
|
-
return results;
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
/**
|
|
320
|
-
* 获取推荐模板(基于使用频率或团队偏好)- 统一Robot命名
|
|
321
|
-
*/
|
|
322
|
-
export function getRecommendedTemplates() {
|
|
323
|
-
const allTemplates = getAllTemplates();
|
|
324
|
-
const recommended = {};
|
|
325
|
-
|
|
326
|
-
// 使用统一的Robot命名风格
|
|
327
|
-
const recommendedKeys = [
|
|
328
|
-
'robot-admin', // Vue后台管理 - 最常用
|
|
329
|
-
'robot-uniapp', // 移动端开发 - 跨平台
|
|
330
|
-
'robot-nest', // 后端API - 企业级
|
|
331
|
-
'robot-electron', // 桌面应用 - 全栈
|
|
332
|
-
'robot-react', // React项目 - 前端选择
|
|
333
|
-
'robot-koa' // 轻量后端 - 快速开发
|
|
334
|
-
];
|
|
335
|
-
|
|
336
|
-
recommendedKeys.forEach(key => {
|
|
337
|
-
if (allTemplates[key]) {
|
|
338
|
-
recommended[key] = allTemplates[key];
|
|
339
|
-
}
|
|
340
|
-
});
|
|
341
|
-
|
|
342
|
-
// 如果没有找到足够的推荐模板,补充一些
|
|
343
|
-
if (Object.keys(recommended).length < 4) {
|
|
344
|
-
const availableKeys = Object.keys(allTemplates);
|
|
345
|
-
for (const key of availableKeys) {
|
|
346
|
-
if (!recommended[key] && Object.keys(recommended).length < 6) {
|
|
347
|
-
recommended[key] = allTemplates[key];
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
return recommended;
|
|
353
|
-
}
|