foco-cli 0.1.5 → 0.1.9

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 (79) hide show
  1. package/dist/commands/activation-codes.d.ts +14 -0
  2. package/dist/commands/activation-codes.d.ts.map +1 -0
  3. package/dist/commands/activation-codes.js +29 -0
  4. package/dist/commands/activation-codes.js.map +1 -0
  5. package/dist/commands/admins.d.ts +12 -0
  6. package/dist/commands/admins.d.ts.map +1 -0
  7. package/dist/commands/admins.js +35 -0
  8. package/dist/commands/admins.js.map +1 -0
  9. package/dist/commands/changelogs.d.ts +12 -0
  10. package/dist/commands/changelogs.d.ts.map +1 -0
  11. package/dist/commands/changelogs.js +31 -0
  12. package/dist/commands/changelogs.js.map +1 -0
  13. package/dist/commands/dashboard.d.ts +11 -0
  14. package/dist/commands/dashboard.d.ts.map +1 -0
  15. package/dist/commands/dashboard.js +27 -0
  16. package/dist/commands/dashboard.js.map +1 -0
  17. package/dist/commands/exams.d.ts +22 -0
  18. package/dist/commands/exams.d.ts.map +1 -0
  19. package/dist/commands/exams.js +58 -0
  20. package/dist/commands/exams.js.map +1 -0
  21. package/dist/commands/feedback.d.ts +17 -0
  22. package/dist/commands/feedback.d.ts.map +1 -0
  23. package/dist/commands/feedback.js +43 -0
  24. package/dist/commands/feedback.js.map +1 -0
  25. package/dist/commands/help-articles.d.ts +28 -0
  26. package/dist/commands/help-articles.d.ts.map +1 -0
  27. package/dist/commands/help-articles.js +67 -0
  28. package/dist/commands/help-articles.js.map +1 -0
  29. package/dist/commands/knowledge-base.d.ts +28 -0
  30. package/dist/commands/knowledge-base.d.ts.map +1 -0
  31. package/dist/commands/knowledge-base.js +67 -0
  32. package/dist/commands/knowledge-base.js.map +1 -0
  33. package/dist/commands/knowledge-points.d.ts +29 -0
  34. package/dist/commands/knowledge-points.d.ts.map +1 -0
  35. package/dist/commands/knowledge-points.js +64 -0
  36. package/dist/commands/knowledge-points.js.map +1 -0
  37. package/dist/commands/login.d.ts +1 -6
  38. package/dist/commands/login.d.ts.map +1 -1
  39. package/dist/commands/login.js +13 -13
  40. package/dist/commands/login.js.map +1 -1
  41. package/dist/commands/orders.d.ts +9 -0
  42. package/dist/commands/orders.d.ts.map +1 -0
  43. package/dist/commands/orders.js +15 -0
  44. package/dist/commands/orders.js.map +1 -0
  45. package/dist/commands/products.d.ts +22 -0
  46. package/dist/commands/products.d.ts.map +1 -0
  47. package/dist/commands/products.js +54 -0
  48. package/dist/commands/products.js.map +1 -0
  49. package/dist/commands/projects.d.ts +24 -0
  50. package/dist/commands/projects.d.ts.map +1 -0
  51. package/dist/commands/projects.js +61 -0
  52. package/dist/commands/projects.js.map +1 -0
  53. package/dist/commands/resource-packs.d.ts +26 -0
  54. package/dist/commands/resource-packs.d.ts.map +1 -0
  55. package/dist/commands/resource-packs.js +64 -0
  56. package/dist/commands/resource-packs.js.map +1 -0
  57. package/dist/commands/stats.d.ts +2 -0
  58. package/dist/commands/stats.d.ts.map +1 -0
  59. package/dist/commands/stats.js +6 -0
  60. package/dist/commands/stats.js.map +1 -0
  61. package/dist/commands/syllabi.d.ts +26 -0
  62. package/dist/commands/syllabi.d.ts.map +1 -0
  63. package/dist/commands/syllabi.js +65 -0
  64. package/dist/commands/syllabi.js.map +1 -0
  65. package/dist/commands/threads.d.ts +13 -0
  66. package/dist/commands/threads.d.ts.map +1 -0
  67. package/dist/commands/threads.js +33 -0
  68. package/dist/commands/threads.js.map +1 -0
  69. package/dist/commands/users.d.ts +7 -0
  70. package/dist/commands/users.d.ts.map +1 -0
  71. package/dist/commands/users.js +13 -0
  72. package/dist/commands/users.js.map +1 -0
  73. package/dist/index.js +385 -71
  74. package/dist/index.js.map +1 -1
  75. package/dist/lib/auth.d.ts +7 -8
  76. package/dist/lib/auth.d.ts.map +1 -1
  77. package/dist/lib/auth.js +26 -80
  78. package/dist/lib/auth.js.map +1 -1
  79. package/package.json +1 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"threads.js","sourceRoot":"","sources":["../../src/commands/threads.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAGpD,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,OAIvC;IACC,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,OAAO,CAAyC,uBAAuB,EAAE;QAC9F,MAAM,EAAE;YACN,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,QAAQ,EAAE,OAAO,CAAC,QAAQ;SAC3B;KACF,CAAC,CAAC;IAEH,UAAU,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;AACrC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,EAAU;IAC/C,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,OAAO,CAA0B,yBAAyB,EAAE,EAAE,CAAC,CAAC;IACvF,UAAU,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;AACrC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,EAAU,EACV,OAEC;IAED,MAAM,IAAI,GAA4B,EAAE,CAAC;IAEzC,IAAI,OAAO,CAAC,MAAM;QAAE,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAEjD,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,OAAO,CAA0B,yBAAyB,EAAE,EAAE,EAAE;QACrF,MAAM,EAAE,OAAO;QACf,IAAI;KACL,CAAC,CAAC;IAEH,UAAU,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;AACrC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,EAAU,EACV,OAEC;IAED,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,OAAO,CAA0B,yBAAyB,EAAE,QAAQ,EAAE;QAC3F,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE;KACnC,CAAC,CAAC;IAEH,UAAU,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;AACrC,CAAC"}
@@ -0,0 +1,7 @@
1
+ export declare function handleUsersList(options: {
2
+ status?: string;
3
+ keyword?: string;
4
+ page?: string;
5
+ pageSize?: string;
6
+ }): Promise<void>;
7
+ //# sourceMappingURL=users.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"users.d.ts","sourceRoot":"","sources":["../../src/commands/users.ts"],"names":[],"mappings":"AAcA,wBAAsB,eAAe,CAAC,OAAO,EAAE;IAC7C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,GAAG,OAAO,CAAC,IAAI,CAAC,CAWhB"}
@@ -0,0 +1,13 @@
1
+ import { apiCall, outputJSON } from "../lib/api.js";
2
+ export async function handleUsersList(options) {
3
+ const { data } = await apiCall("/api/admin/v1/users", {
4
+ params: {
5
+ status: options.status,
6
+ keyword: options.keyword,
7
+ page: options.page,
8
+ pageSize: options.pageSize,
9
+ },
10
+ });
11
+ outputJSON({ status: "ok", data });
12
+ }
13
+ //# sourceMappingURL=users.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"users.js","sourceRoot":"","sources":["../../src/commands/users.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAcpD,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,OAKrC;IACC,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,OAAO,CAAsB,qBAAqB,EAAE;QACzE,MAAM,EAAE;YACN,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,QAAQ,EAAE,OAAO,CAAC,QAAQ;SAC3B;KACF,CAAC,CAAC;IAEH,UAAU,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;AACrC,CAAC"}
package/dist/index.js CHANGED
@@ -7,6 +7,23 @@ import { handleLogin, handleStatus, handleLogout } from "./commands/login.js";
7
7
  import { handleBanksList, handleBankShow } from "./commands/banks.js";
8
8
  import { handleQuestionsList, handleQuestionShow } from "./commands/questions.js";
9
9
  import { handleIssuesList, handleIssueShow, handleIssueCreate, handleIssueUpdate, handleIssueComment } from "./commands/issues.js";
10
+ import { handleChangelogsList, handleChangelogCreate, handleChangelogUpdate } from "./commands/changelogs.js";
11
+ import { handleExamsList, handleExamShow, handleExamCreate, handleExamUpdate, handleExamDelete } from "./commands/exams.js";
12
+ import { handleSyllabiList, handleSyllabusShow, handleSyllabusCreate, handleSyllabusUpdate, handleSyllabusDelete } from "./commands/syllabi.js";
13
+ import { handleUsersList } from "./commands/users.js";
14
+ import { handleOrdersList } from "./commands/orders.js";
15
+ import { handleProductsList, handleProductShow, handleProductCreate, handleProductUpdate, handleProductDelete } from "./commands/products.js";
16
+ import { handleProjectsList, handleProjectShow, handleProjectCreate, handleProjectUpdate, handleProjectDelete } from "./commands/projects.js";
17
+ import { handleThreadsList, handleThreadShow, handleThreadUpdate, handleThreadReply } from "./commands/threads.js";
18
+ import { handleFeedbackList, handleFeedbackShow, handleFeedbackCreate, handleFeedbackUpdate } from "./commands/feedback.js";
19
+ import { handleStats } from "./commands/stats.js";
20
+ import { handleDashboardOverview, handleDashboardLearning, handleDashboardProducts } from "./commands/dashboard.js";
21
+ import { handleKnowledgePointsList, handleKnowledgePointCreate, handleKnowledgePointUpdate, handleKnowledgePointDelete } from "./commands/knowledge-points.js";
22
+ import { handleHelpArticlesList, handleHelpArticleShow, handleHelpArticleCreate, handleHelpArticleUpdate, handleHelpArticleDelete } from "./commands/help-articles.js";
23
+ import { handleKnowledgeBaseList, handleKnowledgeBaseShow, handleKnowledgeBaseCreate, handleKnowledgeBaseUpdate, handleKnowledgeBaseDelete } from "./commands/knowledge-base.js";
24
+ import { handleActivationCodesList, handleActivationCodeBatchCreate } from "./commands/activation-codes.js";
25
+ import { handleResourcePacksList, handleResourcePackShow, handleResourcePackCreate, handleResourcePackUpdate, handleResourcePackDelete } from "./commands/resource-packs.js";
26
+ import { handleAdminsList, handleAdminShow, handleAdminCreate, handleAdminUpdate } from "./commands/admins.js";
10
27
  const __dirname = dirname(fileURLToPath(import.meta.url));
11
28
  const pkg = JSON.parse(readFileSync(join(__dirname, "..", "package.json"), "utf-8"));
12
29
  const program = new Command();
@@ -18,12 +35,11 @@ program
18
35
  const auth = program.command("auth").description("认证管理");
19
36
  auth
20
37
  .command("login")
21
- .description("登录到 FOCO 服务器(浏览器授权)")
38
+ .description("登录到 FOCO 服务器")
22
39
  .argument("[apiUrl]", "API 服务器地址")
23
- .option("-t, --token <token>", "使用已有的 API token(跳过浏览器)")
24
40
  .option("-d, --dev", "使用本地开发服务器 (http://localhost:3001)")
25
41
  .action(async (apiUrl, options) => {
26
- await handleLogin(apiUrl, options?.token, options?.dev);
42
+ await handleLogin(apiUrl, options?.dev);
27
43
  });
28
44
  auth
29
45
  .command("status")
@@ -40,14 +56,12 @@ auth
40
56
  // Alias: foco login = foco auth login
41
57
  program
42
58
  .command("login")
43
- .description("登录到 FOCO 服务器(浏览器授权)")
59
+ .description("登录到 FOCO 服务器")
44
60
  .argument("[apiUrl]", "API 服务器地址")
45
- .option("-t, --token <token>", "使用已有的 API token")
46
61
  .option("-d, --dev", "使用本地开发服务器 (http://localhost:3001)")
47
62
  .action(async (apiUrl, options) => {
48
- await handleLogin(apiUrl, options?.token, options?.dev);
63
+ await handleLogin(apiUrl, options?.dev);
49
64
  });
50
- // Top-level status (AI tools often look for this)
51
65
  program
52
66
  .command("status")
53
67
  .description("查看当前登录状态")
@@ -56,102 +70,402 @@ program
56
70
  });
57
71
  // ── Banks (题库) ──────────────────────────────────────────────
58
72
  const banks = program.command("banks").description("题库管理");
59
- banks
60
- .command("list")
61
- .description("查看题库列表")
73
+ banks.command("list").description("查看题库列表")
62
74
  .option("--status <status>", "按状态筛选 (draft|published|archived)")
63
75
  .option("--exam-id <id>", "按考试筛选")
64
76
  .option("--keyword <keyword>", "按名称关键词搜索")
65
77
  .option("--page <page>", "页码", "1")
66
78
  .option("--page-size <size>", "每页数量", "20")
67
- .action(async (options) => {
68
- await handleBanksList(options);
69
- });
70
- banks
71
- .command("show <bankId>")
72
- .description("查看题库详情")
73
- .action(async (bankId) => {
74
- await handleBankShow(bankId);
75
- });
79
+ .action(async (o) => { await handleBanksList(o); });
80
+ banks.command("show <bankId>").description("查看题库详情")
81
+ .action(async (id) => { await handleBankShow(id); });
76
82
  // ── Questions (题目) ──────────────────────────────────────────
77
83
  const questions = program.command("questions").description("题目管理");
78
- questions
79
- .command("list")
80
- .description("查看题目列表")
84
+ questions.command("list").description("查看题目列表")
81
85
  .option("--bank-id <id>", "按题库筛选")
82
86
  .option("--type <type>", "按题型筛选")
83
87
  .option("--difficulty <level>", "按难度筛选 (1-5)")
84
88
  .option("--keyword <keyword>", "按题干关键词搜索")
85
89
  .option("--page <page>", "页码", "1")
86
90
  .option("--page-size <size>", "每页数量", "20")
87
- .action(async (options) => {
88
- await handleQuestionsList(options);
89
- });
90
- questions
91
- .command("show <questionId>")
92
- .description("查看题目详情")
93
- .action(async (questionId) => {
94
- await handleQuestionShow(questionId);
95
- });
91
+ .action(async (o) => { await handleQuestionsList(o); });
92
+ questions.command("show <questionId>").description("查看题目详情")
93
+ .action(async (id) => { await handleQuestionShow(id); });
96
94
  // ── Issues (工单) ─────────────────────────────────────────────
97
95
  const issues = program.command("issues").description("工单管理");
98
- issues
99
- .command("list")
100
- .description("查看工单列表")
101
- .option("--status <status>", "按状态筛选 (backlog|todo|in_progress|done|cancelled)")
102
- .option("--priority <priority>", "按优先级筛选 (none|urgent|high|medium|low)")
103
- .option("--assignee-id <id>", "按指派人筛选 (使用 me 表示当前用户)")
96
+ issues.command("list").description("查看工单列表")
97
+ .option("--status <status>", "按状态筛选")
98
+ .option("--priority <priority>", "按优先级筛选")
99
+ .option("--assignee-id <id>", "按指派人筛选")
104
100
  .option("--project-id <id>", "按项目筛选")
105
101
  .option("--labels <labels>", "按标签筛选(逗号分隔)")
106
- .option("--source <source>", "按来源筛选")
107
102
  .option("--search <keyword>", "搜索标题和描述")
108
103
  .option("--page <page>", "页码", "1")
109
104
  .option("--page-size <size>", "每页数量", "20")
110
- .action(async (options) => {
111
- await handleIssuesList(options);
112
- });
113
- issues
114
- .command("show <id>")
115
- .description("查看工单详情")
116
- .action(async (id) => {
117
- await handleIssueShow(id);
118
- });
119
- issues
120
- .command("create")
121
- .description("创建工单")
105
+ .action(async (o) => { await handleIssuesList(o); });
106
+ issues.command("show <id>").description("查看工单详情")
107
+ .action(async (id) => { await handleIssueShow(id); });
108
+ issues.command("create").description("创建工单")
122
109
  .requiredOption("--title <title>", "工单标题")
123
110
  .option("--description <desc>", "工单描述")
124
- .option("--priority <priority>", "优先级 (none|urgent|high|medium|low)")
111
+ .option("--priority <priority>", "优先级")
125
112
  .option("--labels <labels>", "标签(逗号分隔)")
126
113
  .option("--project-id <id>", "所属项目 ID")
127
114
  .option("--assignee-id <id>", "指派人 ID")
128
115
  .option("--parent-id <id>", "父工单 ID")
129
116
  .option("--due-date <date>", "截止日期 (ISO 8601)")
130
- .action(async (options) => {
131
- await handleIssueCreate(options);
132
- });
133
- issues
134
- .command("update <id>")
135
- .description("更新工单")
136
- .option("--status <status>", "状态 (backlog|todo|in_progress|done|cancelled)")
137
- .option("--priority <priority>", "优先级 (none|urgent|high|medium|low)")
138
- .option("--assignee-id <id>", "指派人 ID(空字符串取消指派)")
139
- .option("--project-id <id>", "所属项目 ID(空字符串取消关联)")
117
+ .action(async (o) => { await handleIssueCreate(o); });
118
+ issues.command("update <id>").description("更新工单")
119
+ .option("--status <status>", "状态")
120
+ .option("--priority <priority>", "优先级")
121
+ .option("--assignee-id <id>", "指派人 ID")
122
+ .option("--project-id <id>", "所属项目 ID")
140
123
  .option("--labels <labels>", "标签(逗号分隔)")
141
124
  .option("--title <title>", "标题")
142
125
  .option("--description <desc>", "描述")
143
- .option("--due-date <date>", "截止日期(空字符串清除)")
126
+ .option("--due-date <date>", "截止日期")
144
127
  .option("--sort-order <n>", "排序序号")
145
- .action(async (id, options) => {
146
- await handleIssueUpdate(id, options);
147
- });
148
- issues
149
- .command("comment <id>")
150
- .description("添加评论")
128
+ .action(async (id, o) => { await handleIssueUpdate(id, o); });
129
+ issues.command("comment <id>").description("添加评论")
151
130
  .requiredOption("-m, --message <text>", "评论内容")
152
- .action(async (id, options) => {
153
- await handleIssueComment(id, options.message);
154
- });
131
+ .action(async (id, o) => { await handleIssueComment(id, o.message); });
132
+ // ── Changelogs (开发日志) ─────────────────────────────────────
133
+ const changelogs = program.command("changelogs").description("开发日志管理");
134
+ changelogs.command("list").description("查看开发日志列表")
135
+ .option("--page <page>", "页码", "1")
136
+ .option("--page-size <size>", "每页数量", "20")
137
+ .action(async (o) => { await handleChangelogsList(o); });
138
+ changelogs.command("create").description("创建开发日志")
139
+ .requiredOption("--date <date>", "日期 (YYYY-MM-DD)")
140
+ .option("--content <markdown>", "日志内容(Markdown)")
141
+ .action(async (o) => { await handleChangelogCreate(o); });
142
+ changelogs.command("update <id>").description("更新开发日志")
143
+ .requiredOption("--content <markdown>", "日志内容(Markdown)")
144
+ .action(async (id, o) => { await handleChangelogUpdate(id, o); });
145
+ // ── Exams (考试) ──────────────────────────────────────────────
146
+ const exams = program.command("exams").description("考试管理");
147
+ exams.command("list").description("查看考试列表")
148
+ .option("--page <page>", "页码", "1")
149
+ .option("--page-size <size>", "每页数量", "20")
150
+ .action(async (o) => { await handleExamsList(o); });
151
+ exams.command("show <id>").description("查看考试详情")
152
+ .action(async (id) => { await handleExamShow(id); });
153
+ exams.command("create").description("创建考试")
154
+ .requiredOption("--code <code>", "考试编码")
155
+ .requiredOption("--name <name>", "考试名称")
156
+ .option("--short-name <name>", "简称")
157
+ .option("--description <desc>", "描述")
158
+ .option("--sort-order <n>", "排序")
159
+ .option("--is-visible <bool>", "是否可见 (true/false)")
160
+ .action(async (o) => { await handleExamCreate(o); });
161
+ exams.command("update <id>").description("更新考试")
162
+ .option("--name <name>", "考试名称")
163
+ .option("--short-name <name>", "简称")
164
+ .option("--description <desc>", "描述")
165
+ .option("--sort-order <n>", "排序")
166
+ .option("--is-visible <bool>", "是否可见 (true/false)")
167
+ .action(async (id, o) => { await handleExamUpdate(id, o); });
168
+ exams.command("delete <id>").description("删除考试")
169
+ .action(async (id) => { await handleExamDelete(id); });
170
+ // ── Syllabi (大纲) ────────────────────────────────────────────
171
+ const syllabi = program.command("syllabi").description("大纲管理");
172
+ syllabi.command("list").description("查看大纲列表")
173
+ .option("--exam-id <id>", "按考试筛选")
174
+ .option("--page <page>", "页码", "1")
175
+ .option("--page-size <size>", "每页数量", "20")
176
+ .action(async (o) => { await handleSyllabiList(o); });
177
+ syllabi.command("show <id>").description("查看大纲详情")
178
+ .action(async (id) => { await handleSyllabusShow(id); });
179
+ syllabi.command("create").description("创建大纲")
180
+ .requiredOption("--exam-id <id>", "考试 ID")
181
+ .requiredOption("--name <name>", "大纲名称")
182
+ .option("--version-label <label>", "版本标签")
183
+ .option("--description <desc>", "描述")
184
+ .option("--sort-order <n>", "排序")
185
+ .option("--is-trial <bool>", "是否试用 (true/false)")
186
+ .option("--is-active <bool>", "是否启用 (true/false)")
187
+ .action(async (o) => { await handleSyllabusCreate(o); });
188
+ syllabi.command("update <id>").description("更新大纲")
189
+ .option("--exam-id <id>", "考试 ID")
190
+ .option("--name <name>", "大纲名称")
191
+ .option("--version-label <label>", "版本标签")
192
+ .option("--description <desc>", "描述")
193
+ .option("--sort-order <n>", "排序")
194
+ .option("--is-trial <bool>", "是否试用")
195
+ .option("--is-active <bool>", "是否启用")
196
+ .action(async (id, o) => { await handleSyllabusUpdate(id, o); });
197
+ syllabi.command("delete <id>").description("删除大纲")
198
+ .action(async (id) => { await handleSyllabusDelete(id); });
199
+ // ── Users (用户) ──────────────────────────────────────────────
200
+ program.command("users").description("用户管理")
201
+ .command("list").description("查看用户列表")
202
+ .option("--status <status>", "按状态筛选")
203
+ .option("--keyword <keyword>", "搜索昵称/手机号/openid")
204
+ .option("--page <page>", "页码", "1")
205
+ .option("--page-size <size>", "每页数量", "20")
206
+ .action(async (o) => { await handleUsersList(o); });
207
+ // ── Orders (订单) ─────────────────────────────────────────────
208
+ program.command("orders").description("订单管理")
209
+ .command("list").description("查看订单列表")
210
+ .option("--status <status>", "按状态筛选")
211
+ .option("--order-type <type>", "按订单类型筛选")
212
+ .option("--user-id <id>", "按用户筛选")
213
+ .option("--keyword <keyword>", "搜索订单号")
214
+ .option("--page <page>", "页码", "1")
215
+ .option("--page-size <size>", "每页数量", "20")
216
+ .action(async (o) => { await handleOrdersList(o); });
217
+ // ── Products (商品) ───────────────────────────────────────────
218
+ const products = program.command("products").description("商品管理");
219
+ products.command("list").description("查看商品列表")
220
+ .option("--product-type <type>", "按类型筛选 (bank|material)")
221
+ .option("--status <status>", "按状态筛选")
222
+ .option("--keyword <keyword>", "搜索标题")
223
+ .option("--page <page>", "页码", "1")
224
+ .option("--page-size <size>", "每页数量", "20")
225
+ .action(async (o) => { await handleProductsList(o); });
226
+ products.command("show <id>").description("查看商品详情")
227
+ .action(async (id) => { await handleProductShow(id); });
228
+ products.command("create").description("创建商品")
229
+ .requiredOption("--product-type <type>", "类型 (bank|material)")
230
+ .requiredOption("--ref-id <id>", "关联 ID")
231
+ .requiredOption("--title <title>", "商品标题")
232
+ .option("--cover-url <url>", "封面 URL")
233
+ .option("--status <status>", "状态 (active|inactive)")
234
+ .action(async (o) => { await handleProductCreate(o); });
235
+ products.command("update <id>").description("更新商品")
236
+ .option("--title <title>", "商品标题")
237
+ .option("--cover-url <url>", "封面 URL")
238
+ .option("--status <status>", "状态")
239
+ .action(async (id, o) => { await handleProductUpdate(id, o); });
240
+ products.command("delete <id>").description("删除商品")
241
+ .action(async (id) => { await handleProductDelete(id); });
242
+ // ── Projects (项目) ───────────────────────────────────────────
243
+ const projects = program.command("projects").description("项目管理");
244
+ projects.command("list").description("查看项目列表")
245
+ .option("--page <page>", "页码", "1")
246
+ .option("--page-size <size>", "每页数量", "20")
247
+ .action(async (o) => { await handleProjectsList(o); });
248
+ projects.command("show <id>").description("查看项目详情")
249
+ .action(async (id) => { await handleProjectShow(id); });
250
+ projects.command("create").description("创建项目")
251
+ .requiredOption("--name <name>", "项目名称")
252
+ .requiredOption("--slug <slug>", "项目标识 (a-z0-9-)")
253
+ .option("--description <desc>", "描述")
254
+ .option("--icon <icon>", "图标")
255
+ .option("--color <color>", "颜色")
256
+ .option("--lead-id <id>", "负责人 ID")
257
+ .action(async (o) => { await handleProjectCreate(o); });
258
+ projects.command("update <id>").description("更新项目")
259
+ .option("--name <name>", "项目名称")
260
+ .option("--slug <slug>", "项目标识")
261
+ .option("--description <desc>", "描述")
262
+ .option("--icon <icon>", "图标")
263
+ .option("--color <color>", "颜色")
264
+ .option("--lead-id <id>", "负责人 ID")
265
+ .action(async (id, o) => { await handleProjectUpdate(id, o); });
266
+ projects.command("delete <id>").description("删除项目")
267
+ .action(async (id) => { await handleProjectDelete(id); });
268
+ // ── Threads (讨论) ────────────────────────────────────────────
269
+ const threads = program.command("threads").description("讨论管理");
270
+ threads.command("list").description("查看讨论列表")
271
+ .option("--status <status>", "按状态筛选")
272
+ .option("--page <page>", "页码", "1")
273
+ .option("--page-size <size>", "每页数量", "20")
274
+ .action(async (o) => { await handleThreadsList(o); });
275
+ threads.command("show <id>").description("查看讨论详情")
276
+ .action(async (id) => { await handleThreadShow(id); });
277
+ threads.command("update <id>").description("更新讨论状态")
278
+ .requiredOption("--status <status>", "状态 (resolved|closed)")
279
+ .action(async (id, o) => { await handleThreadUpdate(id, o); });
280
+ threads.command("reply <id>").description("回复讨论")
281
+ .requiredOption("-m, --message <text>", "回复内容")
282
+ .action(async (id, o) => { await handleThreadReply(id, { content: o.message }); });
283
+ // ── Feedback (反馈) ───────────────────────────────────────────
284
+ const feedback = program.command("feedback").description("反馈管理");
285
+ feedback.command("list").description("查看反馈列表")
286
+ .option("--state <state>", "按状态筛选 (open|closed|all)")
287
+ .option("--labels <labels>", "按标签筛选(逗号分隔)")
288
+ .option("--page <page>", "页码", "1")
289
+ .option("--per-page <n>", "每页数量", "20")
290
+ .action(async (o) => { await handleFeedbackList(o); });
291
+ feedback.command("show <number>").description("查看反馈详情")
292
+ .action(async (num) => { await handleFeedbackShow(num); });
293
+ feedback.command("create").description("创建反馈")
294
+ .requiredOption("--title <title>", "标题")
295
+ .option("--description <desc>", "描述")
296
+ .option("--labels <labels>", "标签(逗号分隔)")
297
+ .action(async (o) => { await handleFeedbackCreate(o); });
298
+ feedback.command("update <number>").description("更新反馈")
299
+ .option("--state <state>", "状态 (open|closed)")
300
+ .option("--labels <labels>", "标签(逗号分隔)")
301
+ .action(async (num, o) => { await handleFeedbackUpdate(num, o); });
302
+ // ── Knowledge Points (知识点) ─────────────────────────────────
303
+ const kps = program.command("knowledge-points").description("知识点管理");
304
+ kps.command("list").description("查看知识点列表")
305
+ .option("--bank-id <id>", "按题库筛选")
306
+ .option("--type <type>", "按类型筛选")
307
+ .option("--status <status>", "按状态筛选")
308
+ .option("--keyword <keyword>", "搜索标题")
309
+ .option("--page <page>", "页码", "1")
310
+ .option("--page-size <size>", "每页数量", "20")
311
+ .action(async (o) => { await handleKnowledgePointsList(o); });
312
+ kps.command("create").description("创建知识点")
313
+ .requiredOption("--bank-id <id>", "题库 ID")
314
+ .requiredOption("--type <type>", "类型 (qa|knowledge|summary_note)")
315
+ .requiredOption("--title <title>", "标题")
316
+ .requiredOption("--content <content>", "内容")
317
+ .option("--syllabus-id <id>", "大纲 ID")
318
+ .option("--section-id <id>", "章节 ID")
319
+ .option("--sort-order <n>", "排序")
320
+ .option("--status <status>", "状态")
321
+ .action(async (o) => { await handleKnowledgePointCreate(o); });
322
+ kps.command("update <id>").description("更新知识点")
323
+ .option("--syllabus-id <id>", "大纲 ID")
324
+ .option("--section-id <id>", "章节 ID")
325
+ .option("--type <type>", "类型")
326
+ .option("--title <title>", "标题")
327
+ .option("--content <content>", "内容")
328
+ .option("--sort-order <n>", "排序")
329
+ .option("--status <status>", "状态")
330
+ .action(async (id, o) => { await handleKnowledgePointUpdate(id, o); });
331
+ kps.command("delete <id>").description("删除知识点")
332
+ .action(async (id) => { await handleKnowledgePointDelete(id); });
333
+ // ── Help Articles (帮助文章) ──────────────────────────────────
334
+ const helpArticles = program.command("help-articles").description("帮助文章管理");
335
+ helpArticles.command("list").description("查看文章列表")
336
+ .option("--category <cat>", "按分类筛选")
337
+ .option("--is-published <bool>", "按发布状态筛选")
338
+ .option("--keyword <keyword>", "搜索标题")
339
+ .option("--page <page>", "页码", "1")
340
+ .option("--page-size <size>", "每页数量", "20")
341
+ .action(async (o) => { await handleHelpArticlesList(o); });
342
+ helpArticles.command("show <id>").description("查看文章详情")
343
+ .action(async (id) => { await handleHelpArticleShow(id); });
344
+ helpArticles.command("create").description("创建文章")
345
+ .requiredOption("--title <title>", "标题")
346
+ .requiredOption("--slug <slug>", "URL 标识")
347
+ .option("--content <content>", "内容")
348
+ .option("--summary <summary>", "摘要")
349
+ .option("--category <cat>", "分类")
350
+ .option("--sort-order <n>", "排序")
351
+ .option("--is-published <bool>", "是否发布")
352
+ .action(async (o) => { await handleHelpArticleCreate(o); });
353
+ helpArticles.command("update <id>").description("更新文章")
354
+ .option("--title <title>", "标题")
355
+ .option("--slug <slug>", "URL 标识")
356
+ .option("--content <content>", "内容")
357
+ .option("--summary <summary>", "摘要")
358
+ .option("--category <cat>", "分类")
359
+ .option("--sort-order <n>", "排序")
360
+ .option("--is-published <bool>", "是否发布")
361
+ .action(async (id, o) => { await handleHelpArticleUpdate(id, o); });
362
+ helpArticles.command("delete <id>").description("删除文章")
363
+ .action(async (id) => { await handleHelpArticleDelete(id); });
364
+ // ── Knowledge Base (知识库) ──────────────────────────────────
365
+ const knowledgeBase = program.command("knowledge-base").description("知识库管理");
366
+ knowledgeBase.command("list").description("查看知识库文档列表")
367
+ .option("--category <cat>", "按分类筛选 (culture|product|tech|ops|management|general)")
368
+ .option("--is-published <bool>", "按发布状态筛选")
369
+ .option("--keyword <keyword>", "搜索标题")
370
+ .option("--page <page>", "页码", "1")
371
+ .option("--page-size <size>", "每页数量", "20")
372
+ .action(async (o) => { await handleKnowledgeBaseList(o); });
373
+ knowledgeBase.command("show <id>").description("查看文档详情")
374
+ .action(async (id) => { await handleKnowledgeBaseShow(id); });
375
+ knowledgeBase.command("create").description("创建文档")
376
+ .requiredOption("--title <title>", "标题")
377
+ .requiredOption("--slug <slug>", "URL 标识")
378
+ .option("--category <cat>", "分类 (culture|product|tech|ops|management|general)")
379
+ .option("--content <content>", "内容")
380
+ .option("--tags <tags>", "标签(逗号分隔)")
381
+ .option("--sort-order <n>", "排序")
382
+ .option("--is-published <bool>", "是否发布")
383
+ .action(async (o) => { await handleKnowledgeBaseCreate(o); });
384
+ knowledgeBase.command("update <id>").description("更新文档")
385
+ .option("--title <title>", "标题")
386
+ .option("--slug <slug>", "URL 标识")
387
+ .option("--category <cat>", "分类")
388
+ .option("--content <content>", "内容")
389
+ .option("--tags <tags>", "标签(逗号分隔)")
390
+ .option("--sort-order <n>", "排序")
391
+ .option("--is-published <bool>", "是否发布")
392
+ .action(async (id, o) => { await handleKnowledgeBaseUpdate(id, o); });
393
+ knowledgeBase.command("delete <id>").description("删除文档")
394
+ .action(async (id) => { await handleKnowledgeBaseDelete(id); });
395
+ // ── Activation Codes (激活码) ─────────────────────────────────
396
+ const activationCodes = program.command("activation-codes").description("激活码管理");
397
+ activationCodes.command("list").description("查看激活码列表")
398
+ .option("--batch-no <no>", "按批次筛选")
399
+ .option("--status <status>", "按状态筛选")
400
+ .option("--code <code>", "搜索激活码")
401
+ .option("--page <page>", "页码", "1")
402
+ .option("--page-size <size>", "每页数量", "20")
403
+ .action(async (o) => { await handleActivationCodesList(o); });
404
+ activationCodes.command("create-batch").description("批量生成激活码")
405
+ .requiredOption("--sku-id <id>", "SKU ID")
406
+ .requiredOption("--count <n>", "数量 (1-1000)")
407
+ .option("--batch-no <no>", "批次号")
408
+ .option("--expires-at <date>", "过期时间 (ISO 日期)")
409
+ .action(async (o) => { await handleActivationCodeBatchCreate(o); });
410
+ // ── Resource Packs (资源包) ───────────────────────────────────
411
+ const resourcePacks = program.command("resource-packs").description("资源包管理");
412
+ resourcePacks.command("list").description("查看资源包列表")
413
+ .option("--status <status>", "按状态筛选")
414
+ .option("--bank-id <id>", "按题库筛选")
415
+ .option("--keyword <keyword>", "搜索标题")
416
+ .option("--page <page>", "页码", "1")
417
+ .option("--page-size <size>", "每页数量", "20")
418
+ .action(async (o) => { await handleResourcePacksList(o); });
419
+ resourcePacks.command("show <id>").description("查看资源包详情")
420
+ .action(async (id) => { await handleResourcePackShow(id); });
421
+ resourcePacks.command("create").description("创建资源包")
422
+ .requiredOption("--title <title>", "标题")
423
+ .option("--bank-id <id>", "题库 ID")
424
+ .option("--cover-url <url>", "封面 URL")
425
+ .option("--description <desc>", "描述")
426
+ .option("--status <status>", "状态")
427
+ .option("--sort-order <n>", "排序")
428
+ .action(async (o) => { await handleResourcePackCreate(o); });
429
+ resourcePacks.command("update <id>").description("更新资源包")
430
+ .option("--title <title>", "标题")
431
+ .option("--bank-id <id>", "题库 ID")
432
+ .option("--cover-url <url>", "封面 URL")
433
+ .option("--description <desc>", "描述")
434
+ .option("--status <status>", "状态")
435
+ .option("--sort-order <n>", "排序")
436
+ .action(async (id, o) => { await handleResourcePackUpdate(id, o); });
437
+ resourcePacks.command("delete <id>").description("删除资源包")
438
+ .action(async (id) => { await handleResourcePackDelete(id); });
439
+ // ── Admins (管理员) ───────────────────────────────────────────
440
+ const admins = program.command("admins").description("管理员管理");
441
+ admins.command("list").description("查看管理员列表")
442
+ .action(async () => { await handleAdminsList(); });
443
+ admins.command("show <id>").description("查看管理员详情")
444
+ .action(async (id) => { await handleAdminShow(id); });
445
+ admins.command("create").description("创建管理员")
446
+ .requiredOption("--username <username>", "用户名")
447
+ .requiredOption("--password <password>", "密码")
448
+ .option("--display-name <name>", "展示名称")
449
+ .action(async (o) => { await handleAdminCreate(o); });
450
+ admins.command("update <id>").description("更新管理员")
451
+ .option("--display-name <name>", "展示名称")
452
+ .option("--password <password>", "新密码")
453
+ .action(async (id, o) => { await handleAdminUpdate(id, o); });
454
+ // ── Stats (统计) ──────────────────────────────────────────────
455
+ program.command("stats").description("查看统计数据")
456
+ .action(async () => { await handleStats(); });
457
+ // ── Dashboard (仪表盘) ───────────────────────────────────────
458
+ const dashboard = program.command("dashboard").description("仪表盘数据");
459
+ dashboard.command("overview").description("总览数据")
460
+ .option("--range <range>", "时间范围 (7d|30d)", "7d")
461
+ .action(async (o) => { await handleDashboardOverview(o); });
462
+ dashboard.command("learning").description("学习数据")
463
+ .option("--range <range>", "时间范围 (7d|30d)", "7d")
464
+ .action(async (o) => { await handleDashboardLearning(o); });
465
+ dashboard.command("products").description("商品数据")
466
+ .option("--range <range>", "时间范围 (7d|30d)", "7d")
467
+ .option("--product-type <type>", "商品类型 (bank|material)")
468
+ .action(async (o) => { await handleDashboardProducts(o); });
155
469
  // ── Parse ─────────────────────────────────────────────────────
156
470
  program.parse(process.argv);
157
471
  //# sourceMappingURL=index.js.map