openyida 2026.3.28-2 → 2026.4.2-beta.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 (60) hide show
  1. package/README.md +1 -1
  2. package/bin/yida.js +4 -3
  3. package/lib/app/create-app.js +8 -4
  4. package/lib/app/create-form.js +1 -0
  5. package/lib/app/get-schema.js +8 -6
  6. package/lib/app/publish.js +10 -4
  7. package/lib/core/check-update.js +5 -2
  8. package/lib/core/doctor.js +119 -72
  9. package/lib/core/locales/ar.js +3 -0
  10. package/lib/core/locales/de.js +3 -0
  11. package/lib/core/locales/en.js +1 -1
  12. package/lib/core/locales/es.js +3 -0
  13. package/lib/core/locales/fr.js +3 -0
  14. package/lib/core/locales/hi.js +3 -0
  15. package/lib/core/locales/ja.js +1 -1
  16. package/lib/core/locales/ko.js +3 -0
  17. package/lib/core/locales/pt.js +3 -0
  18. package/lib/core/locales/vi.js +3 -0
  19. package/lib/core/locales/zh-TW.js +1 -1
  20. package/lib/core/locales/zh.js +1 -1
  21. package/lib/core/utils.js +1 -1
  22. package/lib/flash-note/flash-to-prd.js +26 -15
  23. package/lib/report/chart-builder.js +134 -956
  24. package/lib/report/data-model.js +380 -0
  25. package/lib/report/field-utils.js +208 -0
  26. package/lib/report/filter-builder.js +376 -0
  27. package/lib/report/index.js +17 -6
  28. package/package.json +4 -3
  29. package/scripts/postinstall.js +33 -1
  30. package/yida-skills/SKILL.md +87 -91
  31. package/yida-skills/references/edition-features-guide.md +382 -0
  32. package/yida-skills/skills/yida-app/SKILL.md +20 -8
  33. package/yida-skills/skills/yida-chart/SKILL.md +26 -21
  34. package/yida-skills/skills/yida-connector/SKILL.md +22 -0
  35. package/yida-skills/skills/yida-create-app/SKILL.md +44 -2
  36. package/yida-skills/skills/yida-create-form-page/SKILL.md +22 -0
  37. package/yida-skills/skills/yida-create-page/SKILL.md +21 -0
  38. package/yida-skills/skills/yida-create-process/SKILL.md +22 -0
  39. package/yida-skills/skills/yida-custom-page/SKILL.md +31 -0
  40. package/yida-skills/skills/yida-custom-page/references/assets-guide.md +2 -2
  41. package/yida-skills/skills/yida-data-management/SKILL.md +34 -0
  42. package/yida-skills/skills/yida-density/SKILL.md +27 -14
  43. package/yida-skills/skills/yida-export-conversation/SKILL.md +16 -0
  44. package/yida-skills/skills/yida-flash-note-to-prd/SKILL.md +25 -28
  45. package/yida-skills/skills/yida-form-permission/SKILL.md +25 -0
  46. package/yida-skills/skills/yida-formula/SKILL.md +24 -7
  47. package/yida-skills/skills/yida-get-schema/SKILL.md +24 -0
  48. package/yida-skills/skills/yida-integration/SKILL.md +22 -16
  49. package/yida-skills/skills/yida-login/SKILL.md +25 -17
  50. package/yida-skills/skills/yida-logout/SKILL.md +19 -0
  51. package/yida-skills/skills/yida-page-config/SKILL.md +23 -0
  52. package/yida-skills/skills/yida-ppt-slider/SKILL.md +28 -16
  53. package/yida-skills/skills/yida-process-rule/SKILL.md +22 -16
  54. package/yida-skills/skills/yida-publish-page/SKILL.md +20 -0
  55. package/yida-skills/skills/yida-report/SKILL.md +25 -16
  56. package/yida-skills/skills/yida-table-form/SKILL.md +26 -14
  57. package/yida-skills/skills/yida-chatbot/SKILL.md +0 -237
  58. package/yida-skills/skills/yida-create-report/SKILL.md +0 -738
  59. /package/{yida-skills/skills/yida-flash-note-to-prd → lib/flash-note}/build-flash-note-prompt.js +0 -0
  60. /package/{yida-skills/skills/yida-create-report/build-yida-report-schema.js → lib/report/schema-template.js} +0 -0
package/README.md CHANGED
@@ -8,7 +8,7 @@
8
8
 
9
9
  **Build Yida low-code apps with AI — zero config, instant deploy.**
10
10
 
11
- [Get Started](#get-started) · [CLI Commands](#cli-commands) · [Demo](#demo) · [Contributing](./CONTRIBUTING.md) · [Changelog](./CHANGELOG.md)
11
+ [Get Started](#get-started) · [CLI Commands](#cli-commands) · [Demo](https://www.aliwork.com/o/OpenYidaAppShowcase) · [Contributing](./CONTRIBUTING.md) · [Changelog](./CHANGELOG.md)
12
12
 
13
13
  [![npm version](https://img.shields.io/npm/v/openyida?color=brightgreen&label=npm)](https://www.npmjs.com/package/openyida)
14
14
  [![npm downloads](https://img.shields.io/npm/dm/openyida?color=blue)](https://www.npmjs.com/package/openyida)
package/bin/yida.js CHANGED
@@ -16,7 +16,7 @@
16
16
  * openyida auth logout 退出登录
17
17
  * openyida org list 列出可访问的组织
18
18
  * openyida org switch --corp-id <corpId> 切换组织(无需重新登录)
19
- * openyida create-app "<名称>" [desc] [icon] [color] [themeColor] 创建应用
19
+ * openyida create-app "<名称>" [desc] [icon] [color] [colour] [navTheme] [layout] 创建应用
20
20
  * openyida create-page <appType> "<页面名>" 创建自定义页面
21
21
  * openyida create-form create <appType> "<表单名>" <字段JSON> [--layout <布局>] [--theme <主题>] [--label-align <对齐>] 创建表单页面
22
22
  * openyida create-form update <appType> <formUuid> <修改JSON> 更新表单页面
@@ -76,7 +76,7 @@ openyida - 宜搭命令行工具
76
76
  copy [--force] 复制 project 工作目录到当前 AI 工具环境
77
77
  login 登录态管理(优先缓存,否则扫码)
78
78
  logout 退出登录 / 切换账号
79
- create-app "<名称>" [描述] [图标] [颜色] [主题色] 创建应用,输出 appType
79
+ create-app "<名称>" [描述] [图标] [颜色] [主题色] [导航风格] [布局] 创建应用,输出 appType
80
80
  create-page <appType> "<页面名>" 创建自定义页面,输出 pageId
81
81
  create-form create <appType> "<表单名>" <字段JSON> [--layout <布局>] [--theme <主题>] [--label-align <对齐>] 创建表单页面
82
82
  create-form update <appType> <formUuid> <修改JSON> 更新表单页面
@@ -132,7 +132,8 @@ openyida - 宜搭命令行工具
132
132
  openyida login
133
133
  openyida logout
134
134
  openyida create-app "考勤管理"
135
- openyida create-app "考勤管理" "员工考勤系统" "xian-daka" "#00B853" "red"
135
+ openyida create-app "考勤管理" "员工考勤系统" "xian-daka" "#00B853" "deepBlue" "dark" "slide"
136
+ openyida create-app "党建管理" "党员管理系统" "xian-zhengfu" "#FF4D4F" "red" "light" "ver"
136
137
  openyida create-page APP_XXX "游戏主页"
137
138
  openyida create-form create APP_XXX "员工信息" fields.json
138
139
  openyida create-form update APP_XXX FORM-XXX '[{"action":"add","field":{"type":"TextField","label":"备注"}}]'
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * create-app.js - 宜搭应用创建命令
3
3
  *
4
- * 用法:yidacli create-app "<appName>" [description] [icon] [iconColor]
4
+ * 用法:yidacli create-app "<appName>" [description] [icon] [iconColor] [colour] [navTheme] [layoutDirection]
5
5
  */
6
6
 
7
7
  'use strict';
@@ -93,7 +93,9 @@ async function run(args) {
93
93
  const description = args[1] || appName;
94
94
  const icon = args[2] || 'xian-yingyong';
95
95
  const iconColor = args[3] || '#0089FF';
96
- const themeColor = args[4] || 'blue';
96
+ const colour = args[4] || 'deepBlue';
97
+ const navTheme = args[5] || 'dark';
98
+ const layoutDirection = args[6] || 'slide';
97
99
 
98
100
  const SEP = '='.repeat(50);
99
101
  console.error(SEP);
@@ -102,7 +104,7 @@ async function run(args) {
102
104
  console.error(t('create_app.app_name', appName));
103
105
  console.error(t('create_app.app_desc', description));
104
106
  console.error(t('create_app.app_icon', icon, iconColor));
105
- console.error(t('create_app.app_theme', themeColor));
107
+ console.error(t('create_app.app_theme', colour, navTheme, layoutDirection));
106
108
 
107
109
  // Step 1: 读取登录态
108
110
  console.error(t('common.step_login', 1));
@@ -150,7 +152,9 @@ async function run(args) {
150
152
  description: JSON.stringify({ zh_CN: description, en_US: description, type: 'i18n' }),
151
153
  icon: iconValue,
152
154
  iconUrl: iconValue,
153
- colour: themeColor,
155
+ colour,
156
+ navTheme,
157
+ layoutDirection,
154
158
  defaultLanguage: 'zh_CN',
155
159
  openExclusive: openExclusive,
156
160
  openPhysicColumn: openPhysicColumn,
@@ -1337,6 +1337,7 @@ function buildFormSchema(formTitle, fields, formUuid, corpId, appType, layout, t
1337
1337
  compiled: constructorCode,
1338
1338
  source: constructorCode,
1339
1339
  },
1340
+ componentDidMount: { name: 'didMount', id: 'didMount', params: {}, type: 'actionRef' },
1340
1341
  },
1341
1342
  hidden: false,
1342
1343
  title: '',
@@ -35,11 +35,6 @@ function extractFieldSummary(schemaResult) {
35
35
  return fields;
36
36
  }
37
37
 
38
- const tree = pages[0].componentsTree && pages[0].componentsTree[0];
39
- if (!tree) {
40
- return fields;
41
- }
42
-
43
38
  const FIELD_COMPONENT_NAMES = new Set([
44
39
  'TextField', 'TextareaField', 'SelectField', 'DateField', 'NumberField',
45
40
  'RadioField', 'CheckboxField', 'EmployeeField', 'PhoneField', 'EmailField',
@@ -69,7 +64,14 @@ function extractFieldSummary(schemaResult) {
69
64
  }
70
65
  }
71
66
 
72
- traverse(tree);
67
+ // 遍历所有页面,避免多页面表单遗漏字段
68
+ for (const page of pages) {
69
+ const tree = page.componentsTree && page.componentsTree[0];
70
+ if (tree) {
71
+ traverse(tree);
72
+ }
73
+ }
74
+
73
75
  return fields;
74
76
  }
75
77
 
@@ -205,10 +205,15 @@ function compileSource(sourcePath) {
205
205
 
206
206
  // ── ID 生成工具 ──────────────────────────────────────
207
207
 
208
- let nodeIdCounter = 1;
209
-
210
- function nextNodeId() {
211
- return 'node_oc' + Date.now().toString(36) + (nodeIdCounter++).toString(36);
208
+ /**
209
+ * 创建一个独立的 nodeId 生成器,每次调用 buildSchemaContent 时应创建新实例,
210
+ * 避免模块级全局计数器在多次调用时累加导致 ID 不可预期。
211
+ */
212
+ function createNodeIdGenerator() {
213
+ let counter = 1;
214
+ return function nextNodeId() {
215
+ return 'node_oc' + Date.now().toString(36) + (counter++).toString(36);
216
+ };
212
217
  }
213
218
 
214
219
  function generateSuffix() {
@@ -219,6 +224,7 @@ function generateSuffix() {
219
224
 
220
225
  function buildSchemaContent(sourceCode, compiledCode, formUuid) {
221
226
  console.error(t('publish.building_schema'));
227
+ const nextNodeId = createNodeIdGenerator();
222
228
 
223
229
  // 构造函数代码(固定模板)
224
230
  const constructorCode = "function constructor() {\nvar module = { exports: {} };\nvar _this = this;\nthis.__initMethods__(module.exports, module);\nObject.keys(module.exports).forEach(function(item) {\n if(typeof module.exports[item] === 'function'){\n _this[item] = module.exports[item];\n }\n});\n\n}";
@@ -37,10 +37,13 @@ function fetchLatestVersion() {
37
37
 
38
38
  /**
39
39
  * 比较版本号,返回 latestVersion 是否比 currentVersion 更新。
40
- * 仅支持 semver 格式(major.minor.patch)。
40
+ * 支持 semver 格式(major.minor.patch),pre-release 标签(如 -beta.1)会被忽略,
41
+ * 仅比较数字部分。
41
42
  */
42
43
  function isNewer(currentVersion, latestVersion) {
43
- const parseParts = (v) => (v || '').split('.').map((n) => parseInt(n, 10) || 0);
44
+ // 截取 '-' 前的纯数字版本部分,兼容 pre-release 格式(如 1.2.3-beta.1)
45
+ const parseStableVersion = (v) => (v || '').split('-')[0];
46
+ const parseParts = (v) => parseStableVersion(v).split('.').map((n) => parseInt(n, 10) || 0);
44
47
  const [cMajor, cMinor, cPatch] = parseParts(currentVersion);
45
48
  const [lMajor, lMinor, lPatch] = parseParts(latestVersion);
46
49
 
@@ -148,10 +148,7 @@ class EnvironmentChecker {
148
148
  this.checkNodeVersion(),
149
149
  this.checkNpmVersion(),
150
150
  this.checkPlaywrightInstalled(),
151
- this.checkGhCli(),
152
- this.checkGhAuth(),
153
151
  this.checkConfig(),
154
- this.checkSkills(),
155
152
  this.checkLoginStatus(),
156
153
  await this.checkNetwork(),
157
154
  ];
@@ -220,51 +217,6 @@ class EnvironmentChecker {
220
217
  }
221
218
  }
222
219
 
223
- checkGhCli() {
224
- try {
225
- const ghVersion = execSync('gh --version 2>&1', { encoding: 'utf-8' }).split('\n')[0].trim();
226
- return {
227
- id: 'env-gh',
228
- label: ghVersion,
229
- passed: true,
230
- severity: Severity.INFO,
231
- fixType: null,
232
- };
233
- } catch {
234
- return {
235
- id: 'env-gh',
236
- label: 'gh CLI 安装检测',
237
- passed: false,
238
- severity: Severity.ERROR,
239
- message: 'gh CLI 未安装,请安装:https://cli.github.com/',
240
- fixType: null,
241
- };
242
- }
243
- }
244
-
245
- checkGhAuth() {
246
- try {
247
- execSync('gh auth status 2>&1', { encoding: 'utf-8', stdio: 'pipe' });
248
- return {
249
- id: 'env-gh-auth',
250
- label: 'gh CLI 已登录',
251
- passed: true,
252
- severity: Severity.INFO,
253
- fixType: null,
254
- };
255
- } catch {
256
- return {
257
- id: 'env-gh-auth',
258
- label: 'gh CLI 登录状态',
259
- passed: false,
260
- severity: Severity.WARNING,
261
- message: 'gh CLI 未登录',
262
- fixType: FixType.COMMAND,
263
- fixCommand: 'gh auth login',
264
- };
265
- }
266
- }
267
-
268
220
  checkConfig() {
269
221
  const configPath = path.join(this.projectRoot, 'config.json');
270
222
  if (!fs.existsSync(configPath)) {
@@ -301,30 +253,6 @@ class EnvironmentChecker {
301
253
  }
302
254
  }
303
255
 
304
- checkSkills() {
305
- const skillsPath = path.join(this.projectRoot, '.claude', 'skills', 'skills');
306
- if (fs.existsSync(skillsPath)) {
307
- const skills = fs.readdirSync(skillsPath).filter((name) =>
308
- fs.statSync(path.join(skillsPath, name)).isDirectory()
309
- );
310
- return {
311
- id: 'env-skills',
312
- label: `Skills 已安装(${skills.length} 个)`,
313
- passed: true,
314
- severity: Severity.INFO,
315
- fixType: null,
316
- };
317
- }
318
- return {
319
- id: 'env-skills',
320
- label: 'Skills 安装检测',
321
- passed: false,
322
- severity: Severity.WARNING,
323
- message: 'Skills 未安装,运行 bash install-skills.sh 安装',
324
- fixType: FixType.MANUAL,
325
- };
326
- }
327
-
328
256
  checkLoginStatus() {
329
257
  const cookiePath = path.join(this.projectRoot, '.cache', 'cookies.json');
330
258
  if (!fs.existsSync(cookiePath)) {
@@ -399,6 +327,121 @@ class EnvironmentChecker {
399
327
  }
400
328
  }
401
329
 
330
+ // ── VersionChecker ───────────────────────────────────
331
+
332
+ /**
333
+ * openyida 版本检查器。
334
+ * 检测当前安装版本是否与 SKILL.md 中的 metadata.version 一致,
335
+ * 不一致时在 --fix 模式下自动升级到最新版。
336
+ */
337
+ class VersionChecker {
338
+ constructor({ projectRoot } = {}) {
339
+ this.projectRoot = projectRoot || findProjectRoot();
340
+ }
341
+
342
+ /**
343
+ * 读取 SKILL.md 中 metadata.version 字段。
344
+ * @returns {string|null}
345
+ */
346
+ readSkillVersion() {
347
+ const skillPaths = [
348
+ path.join(this.projectRoot, 'yida-skills', 'SKILL.md'),
349
+ path.join(require('os').homedir(), '.claude', 'yida-skills', 'SKILL.md'),
350
+ path.join(require('os').homedir(), '.aone_copilot', 'yida-skills', 'SKILL.md'),
351
+ ];
352
+ for (const skillPath of skillPaths) {
353
+ if (!fs.existsSync(skillPath)) {continue;}
354
+ const content = fs.readFileSync(skillPath, 'utf-8');
355
+ const match = content.match(/^metadata:\s*\n\s*version:\s*(.+)$/m);
356
+ if (match) {return match[1].trim();}
357
+ }
358
+ return null;
359
+ }
360
+
361
+ /**
362
+ * 获取当前安装的 openyida 版本。
363
+ * @returns {string|null}
364
+ */
365
+ getInstalledVersion() {
366
+ try {
367
+ return execSync('openyida -v 2>/dev/null', { encoding: 'utf-8' }).trim();
368
+ } catch {
369
+ return null;
370
+ }
371
+ }
372
+
373
+ async check() {
374
+ const skillVersion = this.readSkillVersion();
375
+ const installedVersion = this.getInstalledVersion();
376
+
377
+ if (!skillVersion) {
378
+ return [{
379
+ id: 'version-skill',
380
+ label: 'openyida 版本检测',
381
+ passed: true,
382
+ severity: Severity.INFO,
383
+ message: '无法读取 SKILL.md 版本,跳过版本比对',
384
+ fixType: null,
385
+ }];
386
+ }
387
+
388
+ if (!installedVersion) {
389
+ return [{
390
+ id: 'version-installed',
391
+ label: 'openyida 版本检测',
392
+ passed: false,
393
+ severity: Severity.ERROR,
394
+ message: 'openyida 未安装,请运行:npm install -g openyida',
395
+ fixType: FixType.COMMAND,
396
+ fixCommand: 'npm install -g openyida@latest',
397
+ }];
398
+ }
399
+
400
+ // 比较主版本号(忽略 -beta.x 等预发布后缀)
401
+ const installedMain = installedVersion.replace(/-.+$/, '');
402
+ const skillMain = skillVersion.replace(/-.+$/, '');
403
+ const passed = installedMain === skillMain;
404
+
405
+ return [{
406
+ id: 'version-match',
407
+ label: `openyida 版本:${installedVersion}(SKILL 期望:${skillVersion})`,
408
+ passed,
409
+ severity: passed ? Severity.INFO : Severity.WARNING,
410
+ message: passed ? null : `版本不匹配,建议升级到最新版`,
411
+ fixType: passed ? null : FixType.COMMAND,
412
+ fixCommand: passed ? null : 'npm install -g openyida@latest',
413
+ }];
414
+ }
415
+ }
416
+
417
+ // ── ProjectInitChecker ────────────────────────────────
418
+
419
+ /**
420
+ * project 工作目录初始化检查器。
421
+ * 检测 project/ 目录是否存在,不存在时在 --fix 模式下自动执行 openyida copy。
422
+ */
423
+ class ProjectInitChecker {
424
+ constructor({ projectRoot } = {}) {
425
+ this.projectRoot = projectRoot || findProjectRoot();
426
+ }
427
+
428
+ async check() {
429
+ const projectDir = path.join(this.projectRoot, 'project');
430
+ const configPath = path.join(projectDir, 'config.json');
431
+ const passed = fs.existsSync(projectDir) && fs.existsSync(configPath);
432
+
433
+ return [{
434
+ id: 'project-init',
435
+ label: passed ? 'project/ 工作目录已初始化' : 'project/ 工作目录检测',
436
+ passed,
437
+ severity: passed ? Severity.INFO : Severity.WARNING,
438
+ message: passed ? null : 'project/ 目录未初始化,将自动执行 openyida copy',
439
+ fixType: passed ? null : FixType.COMMAND,
440
+ fixCommand: passed ? null : 'openyida copy',
441
+ }];
442
+ }
443
+ }
444
+
402
445
  // ── ApplicationChecker ────────────────────────────────
403
446
 
404
447
  /**
@@ -1410,6 +1453,8 @@ async function run(args) {
1410
1453
 
1411
1454
  // ── 主诊断流程 ──
1412
1455
  const engine = new DiagnosticEngine({ projectRoot });
1456
+ engine.registerChecker(new VersionChecker({ projectRoot }));
1457
+ engine.registerChecker(new ProjectInitChecker({ projectRoot }));
1413
1458
  engine.registerChecker(new EnvironmentChecker({ projectRoot }));
1414
1459
  engine.registerChecker(new ApplicationChecker({ projectRoot, appId: options.app }));
1415
1460
 
@@ -1451,6 +1496,8 @@ async function run(args) {
1451
1496
 
1452
1497
  module.exports = {
1453
1498
  DiagnosticEngine,
1499
+ VersionChecker,
1500
+ ProjectInitChecker,
1454
1501
  EnvironmentChecker,
1455
1502
  ApplicationChecker,
1456
1503
  FixEngine,
@@ -42,6 +42,9 @@ module.exports = {
42
42
  example: 'مثال: openyida create-app "تطبيقي"',
43
43
  title: ' create-app - أداة إنشاء تطبيق Yida',
44
44
  app_name: '\n اسم التطبيق: {0}',
45
+ app_desc: ' الوصف: {0}',
46
+ app_icon: ' الأيقونة: {0} ({1})',
47
+ app_theme: ' السمة: colour={0} navTheme={1} layout={2}',
45
48
  step_create: '\n🚀 جارٍ إنشاء التطبيق...',
46
49
  sending_request: ' جارٍ إرسال طلب createApp...',
47
50
  success: ' ✅ تم إنشاء التطبيق بنجاح!',
@@ -42,6 +42,9 @@ module.exports = {
42
42
  example: 'Beispiel: openyida create-app "Meine App"',
43
43
  title: ' create-app - Yida-App-Erstellungstool',
44
44
  app_name: '\n App-Name: {0}',
45
+ app_desc: ' Beschreibung: {0}',
46
+ app_icon: ' Symbol: {0} ({1})',
47
+ app_theme: ' Thema: colour={0} navTheme={1} layout={2}',
45
48
  step_create: '\n🚀 App wird erstellt...',
46
49
  sending_request: ' createApp-Anfrage wird gesendet...',
47
50
  success: ' ✅ App erfolgreich erstellt!',
@@ -230,7 +230,7 @@ Examples:
230
230
  app_name: ' App name: {0}',
231
231
  app_desc: ' Description: {0}',
232
232
  app_icon: ' Icon: {0} ({1})',
233
- app_theme: ' Theme: {0}',
233
+ app_theme: ' Theme: colour={0} navTheme={1} layout={2}',
234
234
  step_create: '\n📦 Step 2: Create App\n',
235
235
  success: ' ✅ App created successfully!',
236
236
  app_type_label: ' appType: {0}',
@@ -42,6 +42,9 @@ module.exports = {
42
42
  example: 'Ejemplo: openyida create-app "Mi App"',
43
43
  title: ' create-app - Herramienta de creación de aplicaciones Yida',
44
44
  app_name: '\n Nombre de la app: {0}',
45
+ app_desc: ' Descripción: {0}',
46
+ app_icon: ' Icono: {0} ({1})',
47
+ app_theme: ' Tema: colour={0} navTheme={1} layout={2}',
45
48
  step_create: '\n🚀 Creando la aplicación...',
46
49
  sending_request: ' Enviando solicitud createApp...',
47
50
  success: ' ✅ ¡Aplicación creada exitosamente!',
@@ -42,6 +42,9 @@ module.exports = {
42
42
  example: 'Exemple : openyida create-app "Mon App"',
43
43
  title: " create-app - Outil de création d'application Yida",
44
44
  app_name: "\n Nom de l'app : {0}",
45
+ app_desc: ' Description : {0}',
46
+ app_icon: ' Icône : {0} ({1})',
47
+ app_theme: ' Thème : colour={0} navTheme={1} layout={2}',
45
48
  step_create: "\n🚀 Création de l'application...",
46
49
  sending_request: ' Envoi de la requête createApp...',
47
50
  success: ' ✅ Application créée avec succès !',
@@ -42,6 +42,9 @@ module.exports = {
42
42
  example: 'उदाहरण: openyida create-app "मेरा ऐप"',
43
43
  title: ' create-app - Yida ऐप निर्माण टूल',
44
44
  app_name: '\n ऐप नाम: {0}',
45
+ app_desc: ' विवरण: {0}',
46
+ app_icon: ' आइकॉन: {0} ({1})',
47
+ app_theme: ' थीम: colour={0} navTheme={1} layout={2}',
45
48
  step_create: '\n🚀 ऐप बनाया जा रहा है...',
46
49
  sending_request: ' createApp अनुरोध भेजा जा रहा है...',
47
50
  success: ' ✅ ऐप सफलतापूर्वक बनाया गया!',
@@ -215,7 +215,7 @@ openyida - Yida CLI ツール
215
215
  app_name: ' アプリ名: {0}',
216
216
  app_desc: ' 説明: {0}',
217
217
  app_icon: ' アイコン: {0} ({1})',
218
- app_theme: ' テーマカラー: {0}',
218
+ app_theme: ' テーマ: colour={0} navTheme={1} layout={2}',
219
219
  step_create: '\n📦 Step 2: アプリを作成\n',
220
220
  success: ' ✅ アプリが正常に作成されました!',
221
221
  app_type_label: ' appType: {0}',
@@ -42,6 +42,9 @@ module.exports = {
42
42
  example: '예시: openyida create-app "내 앱"',
43
43
  title: ' create-app - Yida 앱 생성 도구',
44
44
  app_name: '\n 앱 이름: {0}',
45
+ app_desc: ' 설명: {0}',
46
+ app_icon: ' 아이콘: {0} ({1})',
47
+ app_theme: ' 테마: colour={0} navTheme={1} layout={2}',
45
48
  step_create: '\n🚀 앱 생성 중...',
46
49
  sending_request: ' createApp 요청 전송 중...',
47
50
  success: ' ✅ 앱 생성 성공!',
@@ -42,6 +42,9 @@ module.exports = {
42
42
  example: 'Exemplo: openyida create-app "Meu App"',
43
43
  title: ' create-app - Ferramenta de criação de aplicativos Yida',
44
44
  app_name: '\n Nome do app: {0}',
45
+ app_desc: ' Descrição: {0}',
46
+ app_icon: ' Ícone: {0} ({1})',
47
+ app_theme: ' Tema: colour={0} navTheme={1} layout={2}',
45
48
  step_create: '\n🚀 Criando o aplicativo...',
46
49
  sending_request: ' Enviando requisição createApp...',
47
50
  success: ' ✅ Aplicativo criado com sucesso!',
@@ -42,6 +42,9 @@ module.exports = {
42
42
  example: 'Ví dụ: openyida create-app "Ứng dụng của tôi"',
43
43
  title: ' create-app - Công cụ tạo ứng dụng Yida',
44
44
  app_name: '\n Tên ứng dụng: {0}',
45
+ app_desc: ' Mô tả: {0}',
46
+ app_icon: ' Biểu tượng: {0} ({1})',
47
+ app_theme: ' Chủ đề: colour={0} navTheme={1} layout={2}',
45
48
  step_create: '\n🚀 Đang tạo ứng dụng...',
46
49
  sending_request: ' Đang gửi yêu cầu createApp...',
47
50
  success: ' ✅ Tạo ứng dụng thành công!',
@@ -222,7 +222,7 @@ openyida - 宜搭命令列工具
222
222
  app_name: ' 應用名稱:{0}',
223
223
  app_desc: ' 應用描述:{0}',
224
224
  app_icon: ' 圖示: {0} ({1})',
225
- app_theme: ' 主題色: {0}',
225
+ app_theme: ' 主題: colour={0} navTheme={1} layout={2}',
226
226
  step_create: '\n📦 Step 2:建立應用\n',
227
227
  success: ' ✅ 應用建立成功!',
228
228
  app_type_label: ' appType:{0}',
@@ -222,7 +222,7 @@ openyida - 宜搭命令行工具
222
222
  app_name: ' 应用名称: {0}',
223
223
  app_desc: ' 应用描述: {0}',
224
224
  app_icon: ' 图标: {0} ({1})',
225
- app_theme: ' 主题色: {0}',
225
+ app_theme: ' 主题: colour={0} navTheme={1} layout={2}',
226
226
  step_create: '\n📦 Step 2: 创建应用\n',
227
227
  success: ' ✅ 应用创建成功!',
228
228
  app_type_label: ' appType: {0}',
package/lib/core/utils.js CHANGED
@@ -5,7 +5,7 @@
5
5
  * findProjectRoot() - 查找项目根目录(兼容悟空环境)
6
6
  * extractInfoFromCookies() - 从 Cookie 列表中提取 csrf_token / corp_id / user_id
7
7
  * loadCookieData() - 读取 .cache/cookies.json 登录态缓存
8
- * triggerLogin() - 触发登录(自动区分标准/悟空环境)
8
+ * triggerLogin() - 触发登录
9
9
  * refreshCsrfToken() - 刷新 csrf_token
10
10
  * resolveBaseUrl() - 从 cookieData 中解析 base_url
11
11
  * isLoginExpired() - 检测响应体是否表示登录过期
@@ -24,6 +24,19 @@ const {
24
24
  } = require('../core/utils');
25
25
  const { t } = require('../core/i18n');
26
26
 
27
+ // ── 路径常量 ──────────────────────────────────────────
28
+
29
+ /** Prompt 构建模块文件名(与本文件同目录) */
30
+ const PROMPT_BUILDER_FILE = 'build-flash-note-prompt.js';
31
+
32
+ /** 闪记转 PRD 技能在工作目录软链中的相对路径(用户自定义覆盖场景) */
33
+ const FLASH_NOTE_SKILL_RELATIVE_PATH = path.join(
34
+ 'yida-skills', 'skills', 'yida-flash-note-to-prd', PROMPT_BUILDER_FILE
35
+ );
36
+
37
+ /** PRD 输出目录名(相对于项目工作目录) */
38
+ const PRD_OUTPUT_DIR = 'prd';
39
+
27
40
  // ── 参数解析 ──────────────────────────────────────────
28
41
 
29
42
  function parseArgs(args) {
@@ -117,28 +130,26 @@ function extractProjectNameFromPrd(prdContent) {
117
130
  // ── Prompt 构建模块加载 ───────────────────────────────
118
131
 
119
132
  function loadPromptBuilder() {
133
+ // 优先:与本文件同目录的内置模块(npm 包安装后的标准路径)
134
+ const builtinModulePath = path.join(__dirname, PROMPT_BUILDER_FILE);
135
+
136
+ // 备用:用户工作目录下的 yida-skills 软链(openyida copy -skills 创建的软链)
120
137
  const projectRoot = findProjectRoot();
121
- const skillsModulePath = path.join(
122
- __dirname, '..', '..', 'yida-skills', 'skills',
123
- 'yida-flash-note-to-prd', 'build-flash-note-prompt.js'
124
- );
125
- const localModulePath = path.join(
126
- projectRoot, 'skills', 'yida-flash-note-to-prd', 'build-flash-note-prompt.js'
127
- );
138
+ const linkedModulePath = path.join(projectRoot, FLASH_NOTE_SKILL_RELATIVE_PATH);
128
139
 
129
- if (fs.existsSync(skillsModulePath)) {
140
+ if (fs.existsSync(builtinModulePath)) {
130
141
  console.error(t('flashNote.toPrd.module_loaded_builtin'));
131
- return require(skillsModulePath);
142
+ return require(builtinModulePath);
132
143
  }
133
144
 
134
- if (fs.existsSync(localModulePath)) {
135
- console.error(t('flashNote.toPrd.module_loaded_local', localModulePath));
136
- return require(localModulePath);
145
+ if (fs.existsSync(linkedModulePath)) {
146
+ console.error(t('flashNote.toPrd.module_loaded_local', linkedModulePath));
147
+ return require(linkedModulePath);
137
148
  }
138
149
 
139
150
  console.error(t('flashNote.toPrd.module_not_found'));
140
- console.error(t('flashNote.toPrd.module_path_tried', '1', skillsModulePath));
141
- console.error(t('flashNote.toPrd.module_path_tried', '2', localModulePath));
151
+ console.error(t('flashNote.toPrd.module_path_tried', '1', builtinModulePath));
152
+ console.error(t('flashNote.toPrd.module_path_tried', '2', linkedModulePath));
142
153
  process.exit(1);
143
154
  }
144
155
 
@@ -268,7 +279,7 @@ async function run(args) {
268
279
  const projectName = parsed.name || extractProjectNameFromPrd(prdContent);
269
280
  const safeFileName = projectName.replace(/[<>:"/\\|?*\s]/g, '-').replace(/-+/g, '-');
270
281
  const projectRoot = findProjectRoot();
271
- const prdDir = path.join(projectRoot, 'prd');
282
+ const prdDir = path.join(projectRoot, PRD_OUTPUT_DIR);
272
283
 
273
284
  if (!fs.existsSync(prdDir)) {
274
285
  fs.mkdirSync(prdDir, { recursive: true });