foco-cli 0.10.0 → 0.11.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.
Files changed (74) hide show
  1. package/README.md +200 -130
  2. package/dist/commands/cfa-knowledge-points.d.ts +25 -0
  3. package/dist/commands/cfa-knowledge-points.d.ts.map +1 -0
  4. package/dist/commands/{knowledge-points.js → cfa-knowledge-points.js} +11 -19
  5. package/dist/commands/cfa-knowledge-points.js.map +1 -0
  6. package/dist/commands/cfa-levels.d.ts +20 -0
  7. package/dist/commands/cfa-levels.d.ts.map +1 -0
  8. package/dist/commands/{exam-subjects.js → cfa-levels.js} +11 -11
  9. package/dist/commands/cfa-levels.js.map +1 -0
  10. package/dist/commands/cfa-modules.d.ts +20 -0
  11. package/dist/commands/cfa-modules.d.ts.map +1 -0
  12. package/dist/commands/{exam-levels.js → cfa-modules.js} +11 -11
  13. package/dist/commands/cfa-modules.js.map +1 -0
  14. package/dist/commands/cfa-subjects.d.ts +20 -0
  15. package/dist/commands/{exam-modules.d.ts.map → cfa-subjects.d.ts.map} +1 -1
  16. package/dist/commands/{exam-modules.js → cfa-subjects.js} +11 -11
  17. package/dist/commands/{exam-modules.js.map → cfa-subjects.js.map} +1 -1
  18. package/dist/commands/iiqe-sections.d.ts +13 -0
  19. package/dist/commands/iiqe-sections.d.ts.map +1 -0
  20. package/dist/commands/iiqe-sections.js +46 -0
  21. package/dist/commands/iiqe-sections.js.map +1 -0
  22. package/dist/commands/iiqe-syllabi.d.ts +14 -0
  23. package/dist/commands/iiqe-syllabi.d.ts.map +1 -0
  24. package/dist/commands/iiqe-syllabi.js +33 -0
  25. package/dist/commands/iiqe-syllabi.js.map +1 -0
  26. package/dist/commands/iiqe-units.d.ts +21 -0
  27. package/dist/commands/iiqe-units.d.ts.map +1 -0
  28. package/dist/commands/iiqe-units.js +49 -0
  29. package/dist/commands/iiqe-units.js.map +1 -0
  30. package/dist/commands/issues.js +3 -3
  31. package/dist/commands/issues.js.map +1 -1
  32. package/dist/commands/questions.d.ts +1 -1
  33. package/dist/commands/questions.d.ts.map +1 -1
  34. package/dist/commands/questions.js +1 -1
  35. package/dist/commands/questions.js.map +1 -1
  36. package/dist/index.js +137 -185
  37. package/dist/index.js.map +1 -1
  38. package/dist/types.d.ts +72 -18
  39. package/dist/types.d.ts.map +1 -1
  40. package/package.json +1 -1
  41. package/dist/app/admin/questions/[questionId]/edit/page.d.ts +0 -1
  42. package/dist/app/admin/questions/[questionId]/edit/page.d.ts.map +0 -1
  43. package/dist/app/admin/questions/[questionId]/edit/page.js +0 -2
  44. package/dist/app/admin/questions/[questionId]/edit/page.js.map +0 -1
  45. package/dist/commands/banks.d.ts +0 -9
  46. package/dist/commands/banks.d.ts.map +0 -1
  47. package/dist/commands/banks.js +0 -18
  48. package/dist/commands/banks.js.map +0 -1
  49. package/dist/commands/cc-connect.d.ts +0 -8
  50. package/dist/commands/cc-connect.d.ts.map +0 -1
  51. package/dist/commands/cc-connect.js +0 -27
  52. package/dist/commands/cc-connect.js.map +0 -1
  53. package/dist/commands/exam-levels.d.ts +0 -20
  54. package/dist/commands/exam-levels.d.ts.map +0 -1
  55. package/dist/commands/exam-levels.js.map +0 -1
  56. package/dist/commands/exam-modules.d.ts +0 -20
  57. package/dist/commands/exam-subjects.d.ts +0 -20
  58. package/dist/commands/exam-subjects.d.ts.map +0 -1
  59. package/dist/commands/exam-subjects.js.map +0 -1
  60. package/dist/commands/exams.d.ts +0 -25
  61. package/dist/commands/exams.d.ts.map +0 -1
  62. package/dist/commands/exams.js +0 -82
  63. package/dist/commands/exams.js.map +0 -1
  64. package/dist/commands/knowledge-points.d.ts +0 -29
  65. package/dist/commands/knowledge-points.d.ts.map +0 -1
  66. package/dist/commands/knowledge-points.js.map +0 -1
  67. package/dist/commands/resource-packs.d.ts +0 -26
  68. package/dist/commands/resource-packs.d.ts.map +0 -1
  69. package/dist/commands/resource-packs.js +0 -64
  70. package/dist/commands/resource-packs.js.map +0 -1
  71. package/dist/commands/syllabi.d.ts +0 -26
  72. package/dist/commands/syllabi.d.ts.map +0 -1
  73. package/dist/commands/syllabi.js +0 -65
  74. package/dist/commands/syllabi.js.map +0 -1
package/dist/index.js CHANGED
@@ -11,17 +11,14 @@ function mergeBody(opts) {
11
11
  return opts;
12
12
  }
13
13
  import { handleLogin, handleStatus, handleLogout } from "./commands/login.js";
14
- import { handleBanksList, handleBankShow } from "./commands/banks.js";
15
14
  import { handleQuestionsList, handleQuestionShow, handleQuestionUpdateTitle } from "./commands/questions.js";
16
15
  import { handleQuestionsFormat } from "./commands/questions-format.js";
17
16
  import { handleIssuesList, handleIssueShow, handleIssueCreate, handleIssueUpdate, handleIssueComment, handleIssueComments, handleIssueCommentUpdate, handleIssueCommentDelete } from "./commands/issues.js";
18
17
  import { handleEpicsList, handleEpicShow, handleEpicCreate, handleEpicUpdate } from "./commands/epics.js";
19
18
  import { handleChangelogsList, handleChangelogCreate, handleChangelogUpdate } from "./commands/changelogs.js";
20
- import { handleExamsList, handleExamShow, handleExamCreate, handleExamUpdate, handleExamDelete } from "./commands/exams.js";
21
- import { handleExamLevelsList, handleExamLevelShow, handleExamLevelCreate, handleExamLevelUpdate, handleExamLevelDelete } from "./commands/exam-levels.js";
22
- import { handleExamSubjectsList, handleExamSubjectShow, handleExamSubjectCreate, handleExamSubjectUpdate, handleExamSubjectDelete } from "./commands/exam-subjects.js";
23
- import { handleExamModulesList, handleExamModuleShow, handleExamModuleCreate, handleExamModuleUpdate, handleExamModuleDelete } from "./commands/exam-modules.js";
24
- import { handleSyllabiList, handleSyllabusShow, handleSyllabusCreate, handleSyllabusUpdate, handleSyllabusDelete } from "./commands/syllabi.js";
19
+ import { handleCfaLevelsList, handleCfaLevelShow, handleCfaLevelCreate, handleCfaLevelUpdate, handleCfaLevelDelete } from "./commands/cfa-levels.js";
20
+ import { handleCfaSubjectsList, handleCfaSubjectShow, handleCfaSubjectCreate, handleCfaSubjectUpdate, handleCfaSubjectDelete } from "./commands/cfa-subjects.js";
21
+ import { handleCfaModulesList, handleCfaModuleShow, handleCfaModuleCreate, handleCfaModuleUpdate, handleCfaModuleDelete } from "./commands/cfa-modules.js";
25
22
  import { handleUsersList } from "./commands/users.js";
26
23
  import { handleOrdersList } from "./commands/orders.js";
27
24
  import { handleProductsList, handleProductShow, handleProductCreate, handleProductUpdate, handleProductDelete } from "./commands/products.js";
@@ -30,16 +27,18 @@ import { handleThreadsList, handleThreadShow, handleThreadUpdate, handleThreadRe
30
27
  import { handleFeedbackList, handleFeedbackShow, handleFeedbackCreate, handleFeedbackUpdate } from "./commands/feedback.js";
31
28
  import { handleStats } from "./commands/stats.js";
32
29
  import { handleDashboardOverview, handleDashboardLearning, handleDashboardProducts } from "./commands/dashboard.js";
33
- import { handleKnowledgePointsList, handleKnowledgePointCreate, handleKnowledgePointUpdate, handleKnowledgePointDelete } from "./commands/knowledge-points.js";
30
+ import { handleCfaKnowledgePointsList, handleCfaKnowledgePointCreate, handleCfaKnowledgePointUpdate, handleCfaKnowledgePointDelete } from "./commands/cfa-knowledge-points.js";
34
31
  import { handleHelpArticlesList, handleHelpArticleShow, handleHelpArticleCreate, handleHelpArticleUpdate, handleHelpArticleDelete } from "./commands/help-articles.js";
35
32
  import { handleKnowledgeBaseList, handleKnowledgeBaseShow, handleKnowledgeBaseCreate, handleKnowledgeBaseUpdate, handleKnowledgeBaseDelete } from "./commands/knowledge-base.js";
36
33
  import { handleActivationCodesList, handleActivationCodeBatchCreate } from "./commands/activation-codes.js";
37
- import { handleResourcePacksList, handleResourcePackShow, handleResourcePackCreate, handleResourcePackUpdate, handleResourcePackDelete } from "./commands/resource-packs.js";
38
34
  import { handleAdminsList, handleAdminShow, handleAdminCreate, handleAdminUpdate, handleAdminDisable, handleAdminEnable } from "./commands/admins.js";
39
35
  import { handleHuddlesList, handleHuddleShow, handleHuddleCreate, handleHuddleUpdate, handleHuddleDelete } from "./commands/huddles.js";
40
36
  import { handleOpenCodeServerGet, handleOpenCodeServerSet } from "./commands/opencode-server.js";
41
37
  import { handleAiConfigGet, handleAiConfigSet } from "./commands/ai-config.js";
42
38
  import { handlePromptGroupsList, handlePromptGroupShow, handlePromptGroupCreate, handlePromptGroupUpdate, handlePromptGroupDelete, handlePromptTemplatesList, handlePromptTemplateShow, handlePromptTemplateCreate, handlePromptTemplateUpdate, handlePromptTemplateDelete, } from "./commands/prompt-templates.js";
39
+ import { handleIiqeUnitsList, handleIiqeUnitShow, handleIiqeUnitCreate, handleIiqeUnitUpdate, handleIiqeUnitDelete } from "./commands/iiqe-units.js";
40
+ import { handleIiqeSyllabiList, handleIiqeSyllabusShow, handleIiqeSyllabusUpdate, handleIiqeSyllabusDelete } from "./commands/iiqe-syllabi.js";
41
+ import { handleIiqeSectionsList, handleIiqeSectionShow, handleIiqeSectionUpdate, handleIiqeSectionDelete } from "./commands/iiqe-sections.js";
43
42
  import { checkForUpdate, fetchLatestVersion, upgradeCli } from "./lib/version-check.js";
44
43
  const __dirname = dirname(fileURLToPath(import.meta.url));
45
44
  const pkg = JSON.parse(readFileSync(join(__dirname, "..", "package.json"), "utf-8"));
@@ -90,23 +89,10 @@ program
90
89
  .action(async () => {
91
90
  await handleStatus();
92
91
  });
93
- // ── Banks (题库) ──────────────────────────────────────────────
94
- const banks = program.command("banks").description("题库管理");
95
- banks.command("list").description("查看题库列表")
96
- .option("--status <status>", "按状态筛选 (draft|published|archived)")
97
- .option("--exam-id <id>", "按考试筛选 (用 exams list 查看 ID)")
98
- .option("--keyword <keyword>", "按名称关键词搜索")
99
- .option("--page <page>", "页码", "1")
100
- .option("--page-size <size>", "每页数量", "20")
101
- .alias("ls")
102
- .action(async (o) => { await handleBanksList(o); });
103
- banks.command("show <bankId>").description("查看题库详情")
104
- .alias("get")
105
- .action(async (id) => { await handleBankShow(id); });
106
92
  // ── Questions (题目) ──────────────────────────────────────────
107
93
  const questions = program.command("questions").description("题目管理");
108
94
  questions.command("list").description("查看题目列表")
109
- .option("--bank-id <id>", "按题库筛选 (用 banks list 查看 ID)")
95
+ .option("--exam-code <code>", "按考试筛选 (cfa|iiqe)")
110
96
  .option("--type <type>", "按题型筛选 (single_choice|multiple_choice|true_false|fill_blank|short_answer)")
111
97
  .option("--difficulty <level>", "按难度筛选 (1-5)")
112
98
  .option("--keyword <keyword>", "按题干关键词搜索")
@@ -252,156 +238,90 @@ changelogs.command("update <id>").description("更新开发日志")
252
238
  .option("--file <path>", "从文件读取日志内容(Markdown)")
253
239
  .alias("edit")
254
240
  .action(async (id, o) => { await handleChangelogUpdate(id, mergeBody(o)); });
255
- // ── Exams (考试) ──────────────────────────────────────────────
256
- const exams = program.command("exams").description("考试管理");
257
- exams.command("list").description("查看考试列表")
258
- .option("--page <page>", "页码", "1")
259
- .option("--page-size <size>", "每页数量", "20")
260
- .alias("ls")
261
- .action(async (o) => { await handleExamsList(o); });
262
- exams.command("show <id>").description("查看考试详情")
263
- .alias("get")
264
- .action(async (id) => { await handleExamShow(id); });
265
- exams.command("create").description("创建考试")
266
- .requiredOption("--code <code>", "考试编码")
267
- .requiredOption("--name <name>", "考试名称")
268
- .option("--short-name <name>", "简称")
269
- .option("--description <desc>", "描述")
270
- .option("--sort-order <n>", "排序")
271
- .option("--is-visible <bool>", "是否可见 (true/false)")
272
- .alias("new")
273
- .action(async (o) => { await handleExamCreate(o); });
274
- exams.command("update <id>").description("更新考试")
275
- .option("--name <name>", "考试名称")
276
- .option("--short-name <name>", "简称")
277
- .option("--description <desc>", "描述")
278
- .option("--sort-order <n>", "排序")
279
- .option("--is-visible <bool>", "是否可见 (true/false)")
280
- .alias("edit")
281
- .action(async (id, o) => { await handleExamUpdate(id, o); });
282
- exams.command("delete <id>").description("删除考试")
283
- .option("--cascade", "级联删除关联数据(题库、题目、练习记录等)")
284
- .option("-f, --force", "跳过确认提示")
285
- .alias("rm")
286
- .action(async (id, o) => { await handleExamDelete(id, o); });
287
- // ── Exam Levels (考试等级) ──────────────────────────────────────
288
- const examLevels = program.command("exam-levels").description("考试等级管理");
289
- examLevels.command("list").description("查看考试等级列表")
290
- .requiredOption("--exam-id <id>", "考试 ID 或编码 (用 exams list 查看)")
241
+ // ── CFA Levels (CFA 等级) ──────────────────────────────────────
242
+ const cfaLevels = program.command("cfa-levels").description("CFA 等级管理");
243
+ cfaLevels.command("list").description("查看 CFA 等级列表")
244
+ .requiredOption("--exam-code <code>", "考试编码 (cfa)", "cfa")
291
245
  .alias("ls")
292
- .action(async (o) => { await handleExamLevelsList(o); });
293
- examLevels.command("show <id>").description("查看考试等级详情")
246
+ .action(async (o) => { await handleCfaLevelsList(o); });
247
+ cfaLevels.command("show <id>").description("查看等级详情")
294
248
  .alias("get")
295
- .action(async (id) => { await handleExamLevelShow(id); });
296
- examLevels.command("create").description("创建考试等级")
297
- .requiredOption("--exam-id <id>", "考试 ID 或编码")
249
+ .action(async (id) => { await handleCfaLevelShow(id); });
250
+ cfaLevels.command("create").description("创建等级")
251
+ .requiredOption("--exam-code <code>", "考试编码 (cfa)", "cfa")
298
252
  .requiredOption("--code <code>", "等级编码")
299
253
  .requiredOption("--name <name>", "等级名称")
300
254
  .option("--description <desc>", "描述")
301
255
  .option("--sort-order <n>", "排序")
302
256
  .option("--is-visible <bool>", "是否可见 (true/false)")
303
257
  .alias("new")
304
- .action(async (o) => { await handleExamLevelCreate(o); });
305
- examLevels.command("update <id>").description("更新考试等级")
258
+ .action(async (o) => { await handleCfaLevelCreate(o); });
259
+ cfaLevels.command("update <id>").description("更新等级")
306
260
  .option("--name <name>", "等级名称")
307
261
  .option("--description <desc>", "描述")
308
262
  .option("--sort-order <n>", "排序")
309
263
  .option("--is-visible <bool>", "是否可见 (true/false)")
310
264
  .alias("edit")
311
- .action(async (id, o) => { await handleExamLevelUpdate(id, o); });
312
- examLevels.command("delete <id>").description("删除考试等级")
265
+ .action(async (id, o) => { await handleCfaLevelUpdate(id, o); });
266
+ cfaLevels.command("delete <id>").description("删除等级")
313
267
  .alias("rm")
314
- .action(async (id) => { await handleExamLevelDelete(id); });
315
- // ── Exam Subjects (科目) ───────────────────────────────────────
316
- const examSubjects = program.command("exam-subjects").description("科目管理");
317
- examSubjects.command("list").description("查看科目列表")
318
- .requiredOption("--level-id <id>", "考试等级 ID 或编码 (用 exam-levels list 查看)")
268
+ .action(async (id) => { await handleCfaLevelDelete(id); });
269
+ // ── CFA Subjects (CFA 科目) ───────────────────────────────────────
270
+ const cfaSubjects = program.command("cfa-subjects").description("CFA 科目管理");
271
+ cfaSubjects.command("list").description("查看科目列表")
272
+ .requiredOption("--level-id <id>", "等级 ID (用 cfa-levels list 查看)")
319
273
  .alias("ls")
320
- .action(async (o) => { await handleExamSubjectsList(o); });
321
- examSubjects.command("show <id>").description("查看科目详情")
274
+ .action(async (o) => { await handleCfaSubjectsList(o); });
275
+ cfaSubjects.command("show <id>").description("查看科目详情")
322
276
  .alias("get")
323
- .action(async (id) => { await handleExamSubjectShow(id); });
324
- examSubjects.command("create").description("创建科目")
325
- .requiredOption("--level-id <id>", "考试等级 ID 或编码")
277
+ .action(async (id) => { await handleCfaSubjectShow(id); });
278
+ cfaSubjects.command("create").description("创建科目")
279
+ .requiredOption("--level-id <id>", "等级 ID")
326
280
  .requiredOption("--code <code>", "科目编码")
327
281
  .requiredOption("--name <name>", "科目名称")
328
282
  .option("--description <desc>", "描述")
329
283
  .option("--sort-order <n>", "排序")
330
284
  .option("--is-visible <bool>", "是否可见 (true/false)")
331
285
  .alias("new")
332
- .action(async (o) => { await handleExamSubjectCreate(o); });
333
- examSubjects.command("update <id>").description("更新科目")
286
+ .action(async (o) => { await handleCfaSubjectCreate(o); });
287
+ cfaSubjects.command("update <id>").description("更新科目")
334
288
  .option("--name <name>", "科目名称")
335
289
  .option("--description <desc>", "描述")
336
290
  .option("--sort-order <n>", "排序")
337
291
  .option("--is-visible <bool>", "是否可见 (true/false)")
338
292
  .alias("edit")
339
- .action(async (id, o) => { await handleExamSubjectUpdate(id, o); });
340
- examSubjects.command("delete <id>").description("删除科目")
293
+ .action(async (id, o) => { await handleCfaSubjectUpdate(id, o); });
294
+ cfaSubjects.command("delete <id>").description("删除科目")
341
295
  .alias("rm")
342
- .action(async (id) => { await handleExamSubjectDelete(id); });
343
- // ── Exam Modules (Module) ──────────────────────────────────────
344
- const examModules = program.command("exam-modules").description("Module 管理");
345
- examModules.command("list").description("查看 Module 列表")
346
- .requiredOption("--subject-id <id>", "科目 ID 或编码 (用 exam-subjects list 查看)")
296
+ .action(async (id) => { await handleCfaSubjectDelete(id); });
297
+ // ── CFA Modules (CFA 学习模块) ──────────────────────────────────────
298
+ const cfaModules = program.command("cfa-modules").description("CFA 学习模块管理");
299
+ cfaModules.command("list").description("查看 Module 列表")
300
+ .requiredOption("--subject-id <id>", "科目 ID (用 cfa-subjects list 查看)")
347
301
  .alias("ls")
348
- .action(async (o) => { await handleExamModulesList(o); });
349
- examModules.command("show <id>").description("查看 Module 详情")
302
+ .action(async (o) => { await handleCfaModulesList(o); });
303
+ cfaModules.command("show <id>").description("查看 Module 详情")
350
304
  .alias("get")
351
- .action(async (id) => { await handleExamModuleShow(id); });
352
- examModules.command("create").description("创建 Module")
353
- .requiredOption("--subject-id <id>", "科目 ID 或编码")
305
+ .action(async (id) => { await handleCfaModuleShow(id); });
306
+ cfaModules.command("create").description("创建 Module")
307
+ .requiredOption("--subject-id <id>", "科目 ID")
354
308
  .requiredOption("--code <code>", "Module 编码")
355
309
  .requiredOption("--name <name>", "Module 名称")
356
310
  .option("--description <desc>", "描述")
357
311
  .option("--sort-order <n>", "排序")
358
312
  .option("--is-visible <bool>", "是否可见 (true/false)")
359
313
  .alias("new")
360
- .action(async (o) => { await handleExamModuleCreate(o); });
361
- examModules.command("update <id>").description("更新 Module")
314
+ .action(async (o) => { await handleCfaModuleCreate(o); });
315
+ cfaModules.command("update <id>").description("更新 Module")
362
316
  .option("--name <name>", "Module 名称")
363
317
  .option("--description <desc>", "描述")
364
318
  .option("--sort-order <n>", "排序")
365
319
  .option("--is-visible <bool>", "是否可见 (true/false)")
366
320
  .alias("edit")
367
- .action(async (id, o) => { await handleExamModuleUpdate(id, o); });
368
- examModules.command("delete <id>").description("删除 Module")
321
+ .action(async (id, o) => { await handleCfaModuleUpdate(id, o); });
322
+ cfaModules.command("delete <id>").description("删除 Module")
369
323
  .alias("rm")
370
- .action(async (id) => { await handleExamModuleDelete(id); });
371
- // ── Syllabi (大纲) ────────────────────────────────────────────
372
- const syllabi = program.command("syllabi").description("大纲管理");
373
- syllabi.command("list").description("查看大纲列表")
374
- .option("--exam-id <id>", "按考试筛选")
375
- .option("--page <page>", "页码", "1")
376
- .option("--page-size <size>", "每页数量", "20")
377
- .alias("ls")
378
- .action(async (o) => { await handleSyllabiList(o); });
379
- syllabi.command("show <id>").description("查看大纲详情")
380
- .alias("get")
381
- .action(async (id) => { await handleSyllabusShow(id); });
382
- syllabi.command("create").description("创建大纲")
383
- .requiredOption("--exam-id <id>", "考试 ID")
384
- .requiredOption("--name <name>", "大纲名称")
385
- .option("--version-label <label>", "版本标签")
386
- .option("--description <desc>", "描述")
387
- .option("--sort-order <n>", "排序")
388
- .option("--is-trial <bool>", "是否试用 (true/false)")
389
- .option("--is-active <bool>", "是否启用 (true/false)")
390
- .alias("new")
391
- .action(async (o) => { await handleSyllabusCreate(o); });
392
- syllabi.command("update <id>").description("更新大纲")
393
- .option("--exam-id <id>", "考试 ID")
394
- .option("--name <name>", "大纲名称")
395
- .option("--version-label <label>", "版本标签")
396
- .option("--description <desc>", "描述")
397
- .option("--sort-order <n>", "排序")
398
- .option("--is-trial <bool>", "是否试用")
399
- .option("--is-active <bool>", "是否启用")
400
- .alias("edit")
401
- .action(async (id, o) => { await handleSyllabusUpdate(id, o); });
402
- syllabi.command("delete <id>").description("删除大纲")
403
- .alias("rm")
404
- .action(async (id) => { await handleSyllabusDelete(id); });
324
+ .action(async (id) => { await handleCfaModuleDelete(id); });
405
325
  // ── Users (用户) ──────────────────────────────────────────────
406
326
  program.command("users").description("用户管理")
407
327
  .command("list").description("查看用户列表")
@@ -425,7 +345,7 @@ program.command("orders").description("订单管理")
425
345
  // ── Products (商品) ───────────────────────────────────────────
426
346
  const products = program.command("products").description("商品管理");
427
347
  products.command("list").description("查看商品列表")
428
- .option("--product-type <type>", "按类型筛选 (bank|material)")
348
+ .option("--product-type <type>", "按类型筛选 (exam_level|iiqe_unit)")
429
349
  .option("--status <status>", "按状态筛选")
430
350
  .option("--keyword <keyword>", "搜索标题")
431
351
  .option("--page <page>", "页码", "1")
@@ -436,8 +356,8 @@ products.command("show <id>").description("查看商品详情")
436
356
  .alias("get")
437
357
  .action(async (id) => { await handleProductShow(id); });
438
358
  products.command("create").description("创建商品")
439
- .requiredOption("--product-type <type>", "类型 (bank|material)")
440
- .requiredOption("--ref-id <id>", "关联资源 ID (题库 ID 或资料包 ID)")
359
+ .requiredOption("--product-type <type>", "类型 (exam_level|iiqe_unit)")
360
+ .requiredOption("--ref-id <id>", "关联资源 ID (等级 ID 或单元 ID)")
441
361
  .requiredOption("--title <title>", "商品标题")
442
362
  .option("--cover-url <url>", "封面 URL")
443
363
  .option("--status <status>", "状态 (active|inactive)")
@@ -526,32 +446,28 @@ feedback.command("update <number>").description("更新反馈")
526
446
  .option("--labels <labels>", "标签(逗号分隔)")
527
447
  .alias("edit")
528
448
  .action(async (num, o) => { await handleFeedbackUpdate(num, o); });
529
- // ── Knowledge Points (知识点) ─────────────────────────────────
530
- const kps = program.command("knowledge-points").description("知识点管理");
531
- kps.command("list").description("查看知识点列表")
532
- .option("--bank-id <id>", "按题库筛选")
449
+ // ── CFA Knowledge Points (CFA 考点) ─────────────────────────────────
450
+ const cfaKps = program.command("cfa-knowledge-points").description("CFA 考点管理");
451
+ cfaKps.command("list").description("查看考点列表")
452
+ .option("--exam-code <code>", "按考试筛选 (cfa)")
533
453
  .option("--type <type>", "按类型筛选")
534
454
  .option("--status <status>", "按状态筛选")
535
455
  .option("--keyword <keyword>", "搜索标题")
536
456
  .option("--page <page>", "页码", "1")
537
457
  .option("--page-size <size>", "每页数量", "20")
538
458
  .alias("ls")
539
- .action(async (o) => { await handleKnowledgePointsList(o); });
540
- kps.command("create").description("创建知识点")
541
- .requiredOption("--bank-id <id>", "题库 ID (用 banks list 查看)")
459
+ .action(async (o) => { await handleCfaKnowledgePointsList(o); });
460
+ cfaKps.command("create").description("创建考点")
461
+ .requiredOption("--exam-code <code>", "考试编码 (cfa)", "cfa")
542
462
  .requiredOption("--type <type>", "类型 (qa|knowledge|summary_note)")
543
463
  .requiredOption("--title <title>", "标题")
544
464
  .requiredOption("--content <content>", "内容")
545
465
  .option("--body <content>", "内容(--content 的别名)")
546
- .option("--syllabus-id <id>", "大纲 ID")
547
- .option("--section-id <id>", "章节 ID")
548
466
  .option("--sort-order <n>", "排序")
549
467
  .option("--status <status>", "状态 (draft|published|archived)")
550
468
  .alias("new")
551
- .action(async (o) => { await handleKnowledgePointCreate(mergeBody(o)); });
552
- kps.command("update <id>").description("更新知识点")
553
- .option("--syllabus-id <id>", "大纲 ID")
554
- .option("--section-id <id>", "章节 ID")
469
+ .action(async (o) => { await handleCfaKnowledgePointCreate(mergeBody(o)); });
470
+ cfaKps.command("update <id>").description("更新考点")
555
471
  .option("--type <type>", "类型 (qa|knowledge|summary_note)")
556
472
  .option("--title <title>", "标题")
557
473
  .option("--content <content>", "内容")
@@ -559,10 +475,10 @@ kps.command("update <id>").description("更新知识点")
559
475
  .option("--sort-order <n>", "排序")
560
476
  .option("--status <status>", "状态 (draft|published|archived)")
561
477
  .alias("edit")
562
- .action(async (id, o) => { await handleKnowledgePointUpdate(id, mergeBody(o)); });
563
- kps.command("delete <id>").description("删除知识点")
478
+ .action(async (id, o) => { await handleCfaKnowledgePointUpdate(id, mergeBody(o)); });
479
+ cfaKps.command("delete <id>").description("删除考点")
564
480
  .alias("rm")
565
- .action(async (id) => { await handleKnowledgePointDelete(id); });
481
+ .action(async (id) => { await handleCfaKnowledgePointDelete(id); });
566
482
  // ── Help Articles (帮助文章) ──────────────────────────────────
567
483
  const helpArticles = program.command("help-articles").description("帮助文章管理");
568
484
  helpArticles.command("list").description("查看文章列表")
@@ -656,40 +572,6 @@ activationCodes.command("create-batch").description("批量生成激活码")
656
572
  .option("--expires-at <date>", "过期时间 (ISO 日期)")
657
573
  .alias("new")
658
574
  .action(async (o) => { await handleActivationCodeBatchCreate(o); });
659
- // ── Resource Packs (资源包) ───────────────────────────────────
660
- const resourcePacks = program.command("resource-packs").description("资源包管理");
661
- resourcePacks.command("list").description("查看资源包列表")
662
- .option("--status <status>", "按状态筛选")
663
- .option("--bank-id <id>", "按题库筛选")
664
- .option("--keyword <keyword>", "搜索标题")
665
- .option("--page <page>", "页码", "1")
666
- .option("--page-size <size>", "每页数量", "20")
667
- .alias("ls")
668
- .action(async (o) => { await handleResourcePacksList(o); });
669
- resourcePacks.command("show <id>").description("查看资源包详情")
670
- .alias("get")
671
- .action(async (id) => { await handleResourcePackShow(id); });
672
- resourcePacks.command("create").description("创建资源包")
673
- .requiredOption("--title <title>", "标题")
674
- .option("--bank-id <id>", "题库 ID")
675
- .option("--cover-url <url>", "封面 URL")
676
- .option("--description <desc>", "描述")
677
- .option("--status <status>", "状态")
678
- .option("--sort-order <n>", "排序")
679
- .alias("new")
680
- .action(async (o) => { await handleResourcePackCreate(o); });
681
- resourcePacks.command("update <id>").description("更新资源包")
682
- .option("--title <title>", "标题")
683
- .option("--bank-id <id>", "题库 ID")
684
- .option("--cover-url <url>", "封面 URL")
685
- .option("--description <desc>", "描述")
686
- .option("--status <status>", "状态")
687
- .option("--sort-order <n>", "排序")
688
- .alias("edit")
689
- .action(async (id, o) => { await handleResourcePackUpdate(id, o); });
690
- resourcePacks.command("delete <id>").description("删除资源包")
691
- .alias("rm")
692
- .action(async (id) => { await handleResourcePackDelete(id); });
693
575
  // ── Admins (管理员) ───────────────────────────────────────────
694
576
  const admins = program.command("admins").description("管理员管理");
695
577
  admins.command("list").description("查看管理员列表")
@@ -713,6 +595,76 @@ admins.command("disable <id>").description("禁用管理员")
713
595
  .action(async (id) => { await handleAdminDisable(id); });
714
596
  admins.command("enable <id>").description("启用管理员")
715
597
  .action(async (id) => { await handleAdminEnable(id); });
598
+ // ── IIQE Units (IIQE 卷) ───────────────────────────────────────
599
+ const iiqeUnits = program.command("iiqe-units").description("IIQE 卷管理");
600
+ iiqeUnits.command("list").description("查看卷列表")
601
+ .requiredOption("--exam-code <code>", "考试编码 (iiqe)", "iiqe")
602
+ .alias("ls")
603
+ .action(async (o) => { await handleIiqeUnitsList(o); });
604
+ iiqeUnits.command("show <id>").description("查看卷详情")
605
+ .alias("get")
606
+ .action(async (id) => { await handleIiqeUnitShow(id); });
607
+ iiqeUnits.command("create").description("创建卷")
608
+ .requiredOption("--exam-code <code>", "考试编码 (iiqe)", "iiqe")
609
+ .requiredOption("--code <code>", "卷编码")
610
+ .requiredOption("--name <name>", "卷名称")
611
+ .option("--description <desc>", "描述")
612
+ .option("--sort-order <n>", "排序")
613
+ .option("--is-visible <bool>", "是否可见 (true/false)")
614
+ .alias("new")
615
+ .action(async (o) => { await handleIiqeUnitCreate(o); });
616
+ iiqeUnits.command("update <id>").description("更新卷")
617
+ .option("--name <name>", "卷名称")
618
+ .option("--description <desc>", "描述")
619
+ .option("--sort-order <n>", "排序")
620
+ .option("--is-visible <bool>", "是否可见 (true/false)")
621
+ .option("--required-product-id <id>", "关联产品 ID")
622
+ .alias("edit")
623
+ .action(async (id, o) => { await handleIiqeUnitUpdate(id, o); });
624
+ iiqeUnits.command("delete <id>").description("删除卷")
625
+ .alias("rm")
626
+ .action(async (id) => { await handleIiqeUnitDelete(id); });
627
+ // ── IIQE Syllabi (IIQE 大纲) ───────────────────────────────────
628
+ const iiqeSyllabi = program.command("iiqe-syllabi").description("IIQE 大纲管理");
629
+ iiqeSyllabi.command("list").description("查看大纲列表")
630
+ .requiredOption("--unit-id <id>", "卷 ID (用 iiqe-units list 查看)")
631
+ .alias("ls")
632
+ .action(async (o) => { await handleIiqeSyllabiList(o); });
633
+ iiqeSyllabi.command("show <id>").description("查看大纲详情")
634
+ .alias("get")
635
+ .action(async (id) => { await handleIiqeSyllabusShow(id); });
636
+ iiqeSyllabi.command("update <id>").description("更新大纲")
637
+ .option("--name <name>", "大纲名称")
638
+ .option("--version-label <label>", "版本标签")
639
+ .option("--description <desc>", "描述")
640
+ .option("--sort-order <n>", "排序")
641
+ .option("--is-trial <bool>", "是否试用")
642
+ .option("--is-active <bool>", "是否激活")
643
+ .alias("edit")
644
+ .action(async (id, o) => { await handleIiqeSyllabusUpdate(id, o); });
645
+ iiqeSyllabi.command("delete <id>").description("删除大纲")
646
+ .alias("rm")
647
+ .action(async (id) => { await handleIiqeSyllabusDelete(id); });
648
+ // ── IIQE Sections (IIQE 章节) ──────────────────────────────────
649
+ const iiqeSections = program.command("iiqe-sections").description("IIQE 章节管理");
650
+ iiqeSections.command("list").description("查看章节列表")
651
+ .requiredOption("--syllabus-id <id>", "大纲 ID (用 iiqe-syllabi list 查看)")
652
+ .alias("ls")
653
+ .action(async (o) => { await handleIiqeSectionsList(o); });
654
+ iiqeSections.command("show <id>").description("查看章节详情")
655
+ .alias("get")
656
+ .action(async (id) => { await handleIiqeSectionShow(id); });
657
+ iiqeSections.command("update <id>").description("更新章节")
658
+ .option("--title <title>", "章节标题")
659
+ .option("--section-type <type>", "章节类型")
660
+ .option("--parent-id <id>", "父章节 ID")
661
+ .option("--sort-order <n>", "排序")
662
+ .option("--is-trial <bool>", "是否试用")
663
+ .alias("edit")
664
+ .action(async (id, o) => { await handleIiqeSectionUpdate(id, o); });
665
+ iiqeSections.command("delete <id>").description("删除章节")
666
+ .alias("rm")
667
+ .action(async (id) => { await handleIiqeSectionDelete(id); });
716
668
  // ── Stats (统计) ──────────────────────────────────────────────
717
669
  program.command("stats").description("查看统计数据")
718
670
  .action(async () => { await handleStats(); });
@@ -752,7 +704,7 @@ dashboard.command("learning").description("学习数据")
752
704
  .action(async (o) => { await handleDashboardLearning(o); });
753
705
  dashboard.command("products").description("商品数据")
754
706
  .option("--range <range>", "时间范围 (7d|30d)", "7d")
755
- .option("--product-type <type>", "商品类型 (bank|material)")
707
+ .option("--product-type <type>", "商品类型 (exam_level|iiqe_unit)")
756
708
  .action(async (o) => { await handleDashboardProducts(o); });
757
709
  // ── OpenCode Server (集成配置) ──────────────────────────────────
758
710
  const opencodeServer = program.command("opencode-server").description("OpenCode Server 集成配置");
@@ -816,7 +768,7 @@ promptTemplates.command("show <id>").description("查看模板详情")
816
768
  .action(async (id) => { await handlePromptTemplateShow(id); });
817
769
  promptTemplates.command("create <groupId>").description("创建模板")
818
770
  .requiredOption("--name <name>", "名称")
819
- .option("--scope <scope>", "范围 (global|bank|module)", "global")
771
+ .option("--scope <scope>", "范围 (global|module)", "global")
820
772
  .option("--scope-id <id>", "范围 ID")
821
773
  .option("--field-type <type>", "字段类型")
822
774
  .option("--system-prompt <prompt>", "提示词内容")