@sokeai/cli 1.0.39 → 1.0.53

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 (34) hide show
  1. package/README.md +1 -24
  2. package/package.json +2 -2
  3. package/scripts/build-binaries.sh +1 -30
  4. package/scripts/e2e-test.sh +63 -3
  5. package/scripts/install.js +52 -110
  6. package/scripts/local-test.js +10 -85
  7. package/scripts/local-test.sh +52 -7
  8. package/scripts/push.sh +12 -4
  9. package/scripts/release.sh +45 -8
  10. package/scripts/test-auto-detect.js +71 -48
  11. package/skills/README.md +0 -1
  12. package/skills/oss-upload/skill.md +50 -0
  13. package/skills/oss-upload/upload.py +355 -0
  14. package/skills/soke-assign/README.md +310 -0
  15. package/skills/soke-assign/SKILL.md +383 -0
  16. package/skills/soke-course/README.md +168 -92
  17. package/skills/soke-course/SKILL.md +372 -460
  18. package/skills/soke-exam/SKILL.md +565 -0
  19. package/skills/soke-exam/references/exam-get-exam-user.md +212 -0
  20. package/skills/soke-learning-map/SKILL.md +544 -0
  21. package/skills/soke-learning-profile/SKILL.md +0 -1
  22. package/skills/soke-lesson/README.md +53 -0
  23. package/skills/soke-lesson/SKILL.md +510 -0
  24. package/skills/soke-material/README.md +49 -0
  25. package/skills/soke-material/SKILL.md +390 -0
  26. package/scripts/ci/check-legacy-constants.sh +0 -27
  27. package/scripts/ci/check-yaml-env-whitelist.sh +0 -33
  28. package/scripts/mcp-stdout-scan.sh +0 -46
  29. package/scripts/regress-auth.sh +0 -56
  30. package/scripts/regress-baseline.md +0 -84
  31. package/scripts/test-local-reconcile.js +0 -55
  32. package/skills/soke-business-training-report/SKILL.md +0 -58
  33. package/skills/soke-course/SUMMARY.md +0 -236
  34. package/skills/soke-course/templates/batch-create-from-excel.md +0 -75
@@ -1,595 +1,507 @@
1
1
  ---
2
2
  name: soke-course
3
- summary: 授客课程管理(课程列表/分类/课程详情/学习记录),通过 soke-cli 查询
4
- version: 1.0.0
5
- description: "授客课程管理:查询课程、课程分类、课程详情、学习记录。查询课程列表、课程分类、课程用户学习记录、课件列表、人脸识别记录。当用户需要查询课程信息、查看课程列表、查询学习记录、查看课程分类时使用。"
6
- requiredAuthorizations: [{"platformId":"soke-ai"}]
3
+ summary: 授客学堂课程管理(课程创建/更新/发布/查询),集成素材库和课件管理子 skills,完整管理课程生命周期
4
+ version: 4.0.0
5
+ description: "授客学堂课程管理:完整的课程生命周期管理,包括创建课程分类、上传文件(素材)、创建课件、创建课程、指派部门/学员、查询学员学习状态的全链路流程。集成 soke-material(素材库管理)、soke-lesson(课件管理)、soke-assign(指派管理)子 skills。当用户需要创建课程、上传课件、指派学员、查询学习进度时使用。"
7
6
  metadata:
8
7
  requires:
9
8
  bins: ["soke-cli"]
9
+ skills: ["soke-material", "soke-lesson", "soke-assign"]
10
10
  cliHelp: "soke-cli course --help"
11
11
  ---
12
12
 
13
- # 课程管理 (course)
13
+ # 课程管理 (soke-course)
14
14
 
15
15
  **CRITICAL — 开始前 MUST 先用 Read 工具读取 [`../soke-shared/SKILL.md`](../soke-shared/SKILL.md),其中包含认证、配置、权限处理**
16
16
 
17
- ## 核心概念
17
+ ## 使用前提
18
18
 
19
- - **Course(课程)**: 课程实体,包含标题、分类、讲师、学时等信息,通过 `uuid` 标识
20
- - **CourseUser(课程用户)**: 用户的课程学习记录,包含学习进度、完成状态、学习时长等,通过 `target_id` 标识
21
- - **Category(课程分类)**: 课程分类,支持层级结构,通过 `uuid` 标识
22
- - **Lesson(课件)**: 课程下的课件,包含视频、音频、文章、文档等类型
23
- - **LessonLearn(课件学习记录)**: 用户的课件学习记录
24
- - **LessonFace(人脸识别记录)**: 课件学习过程中的人脸识别记录
19
+ 1. 已安装 `soke-cli`
20
+ 2. 已登录授权: `soke-cli auth login`
25
21
 
26
- ## 资源关系
27
-
28
- ```
29
- Course (课程)
30
- ├── Category (课程分类)
31
- ├── Lesson (课件)
32
- │ ├── LessonLearn (课件学习记录)
33
- │ └── LessonFace (人脸识别记录)
34
- └── CourseUser (课程用户学习记录)
35
- ├── dept_user_id (用户ID)
36
- ├── study_progress (学习进度)
37
- ├── finish_status (完成状态)
38
- └── study_duration (学习时长)
22
+ ```bash
23
+ soke-cli auth login
24
+ soke-cli config show # 验证登录状态
39
25
  ```
40
26
 
41
- ## Shortcuts(推荐优先使用)
27
+ ## 端到端工作流
42
28
 
43
- Shortcut 是对常用操作的高级封装(`soke-cli course +<verb> [flags]`)。有 Shortcut 的操作优先使用。
29
+ 完整创建一门可学习的课程需要以下步骤:
44
30
 
45
- | Shortcut | 说明 |
46
- |----------|------|
47
- | [`+list-courses`](#list-courses) | 列出课程列表,支持时间范围、分类和状态筛选 |
48
- | [`+get-course`](#get-course) | 获取单个课程的详细信息 |
49
- | [`+list-categories`](#list-categories) | 列出课程分类 |
50
- | [`+list-lessons`](#list-lessons) | 列出课程下的课件列表 |
51
- | [`+list-course-users`](#list-course-users) | 列出课程用户学习记录列表 |
52
- | [`+get-course-user`](#get-course-user) | 获取单个用户的课程学习详情 |
53
- | [`+list-lesson-learns`](#list-lesson-learns) | 列出课件学习记录 |
54
- | [`+list-lesson-faces`](#list-lesson-faces) | 列出课件人脸识别记录 |
55
- | [`+batch-create-from-excel`](#batch-create-from-excel) | 通过 Excel 批量创建课程并上传课件(原 createcourse 工具能力,已合入) |
56
-
57
- ## 命令详解
58
-
59
- ### +list-courses
31
+ ```
32
+ ┌──────────────────────────────────────────────────────────────────┐
33
+ 1. 查询课程分类 → 获取 category-id │
34
+ 2. 创建课程 → 获取 course-id │
35
+ 3. 上传素材 → 获取 media-id + 所有文件信息 │
36
+ 4. 创建课件 → 关联素材到课程 (至少 1 个) │
37
+ 5. (可选)更新课程 补充描述等 │
38
+ 6. 发布课程 → 学员可见 │
39
+ 7. (可选)指派 → 分配给部门/学员 学员开始学习 │
40
+ 8. 查询学习状态 → 查看学员进度/完成率 │
41
+ └──────────────────────────────────────────────────────────────────┘
42
+ ```
60
43
 
61
- 列出课程列表,支持按时间范围、分类和状态筛选。
44
+ ### 数据流转图
62
45
 
63
- **命令格式**:
64
- ```bash
65
- soke-cli course +list-courses \
66
- --start-time <timestamp> \
67
- --end-time <timestamp> \
68
- [--category-id <category_id>] \
69
- [--is-in <0|1>] \
70
- [--status <0|1|2>] \
71
- [--page <page>] \
72
- [--page-size <size>]
73
46
  ```
74
-
75
- **参数说明**:
76
- - `--start-time`: 课程创建开始时间(Unix时间戳,毫秒)**必需**
77
- - `--end-time`: 课程创建结束时间(Unix时间戳,毫秒)**必需**(起始与结束时间差不超365天)
78
- - `--category-id`: 课程分类ID(可选)
79
- - `--is-in`: 课程来源(可选)
80
- - `0`: 采购课
81
- - `1`: 自建课
82
- - `--status`: 课程状态(可选)
83
- - `0`: 未发布
84
- - `1`: 已发布
85
- - `2`: 已关闭
86
- - `--page`: 页码,从1开始(默认: 1)
87
- - `--page-size`: 每页数量,最大100(默认: 100)
88
-
89
- **返回字段**:
90
- - `uuid`: 课程ID
91
- - `title`: 课程标题
92
- - `category_id`: 课程分类ID
93
- - `certificate_id`: 关联证书ID
94
- - `lector_id`: 关联讲师ID
95
- - `study_type`: 学习模式(1=自由式, 2=解锁式)
96
- - `credit`: 学分数量
97
- - `point`: 积分数量
98
- - `status`: 课程发布状态(-1=删除, 0=未发布, 1=已发布, 2=关闭)
99
- - `lesson_num`: 课件数量
100
- - `total_length`: 学时长度(单位:秒)
101
- - `description`: 课程描述
102
- - `pc_url`: PC端跳转链接
103
- - `mobile_url`: 移动端跳转链接
104
- - `create_time`: 创建时间
105
- - `update_time`: 更新时间
106
- - `create_dept_user_id`: 创建人ID
107
- - `create_dept_user_name`: 创建人姓名
108
-
109
- **示例**:
110
- ```bash
111
- # 查询2024年的所有课程
112
- soke-cli course +list-courses \
113
- --start-time 1704038400000 \
114
- --end-time 1735660799000
115
-
116
- # 查询已发布的自建课
117
- soke-cli course +list-courses \
118
- --start-time 1704038400000 \
119
- --end-time 1735660799000 \
120
- --is-in 1 \
121
- --status 1
122
-
123
- # 查询特定分类的课程
124
- soke-cli course +list-courses \
125
- --start-time 1704038400000 \
126
- --end-time 1735660799000 \
127
- --category-id "category123"
47
+ 分类查询 素材上传 (file +upload)
48
+ │ │
49
+ ▼ ▼
50
+ category-id media-id, filename, filesize, object, ext, type
51
+ │ │
52
+ ▼ ▼
53
+ 创建课程 ──→ course-id ──→ 创建课件 (course +lesson-create) ──→ lesson-id
54
+
55
+
56
+ 发布课程 ◄── 课件数量 ≥ 1
57
+
58
+
59
+ 指派给学员 ◄── assign +create (可选)
60
+
61
+
62
+ 学员可开始学习
63
+
64
+
65
+ 查询学习记录/进度
128
66
  ```
129
67
 
130
- **权限要求**: `course:course:readonly`
131
-
132
68
  ---
133
69
 
134
- ### +get-course
70
+ ## 步骤1: 查询课程分类
135
71
 
136
- 获取单个课程的详细信息。
72
+ 创建课程前必须先获取分类 ID。
137
73
 
138
- **命令格式**:
139
74
  ```bash
140
- soke-cli course +get-course --uuid <course_id>
141
- ```
142
-
143
- **参数说明**:
144
- - `--uuid`: 课程ID **必需**
145
-
146
- **返回字段**:
147
- 与 `+list-courses` 返回字段相同,但返回单个课程的完整详情。
75
+ soke-cli course +list-categories --page 1 --page-size 100
148
76
 
149
- **示例**:
150
- ```bash
151
- # 查询指定课程详情
152
- soke-cli course +get-course --uuid "course123"
77
+ # JSON 输出供解析:
78
+ soke-cli course +list-categories --format json
153
79
  ```
154
80
 
155
- **权限要求**: `course:course:readonly`
81
+ **响应关键字段**:
82
+ - `data.list[].uuid` → 分类 ID(创建课程时传入 `--category-id`)
83
+ - `data.list[].title` → 分类名称
84
+ - `data.list[].parent_id` → 父分类 ID
156
85
 
157
86
  ---
158
87
 
159
- ### +list-categories
160
-
161
- 列出课程分类,支持分页。
162
-
163
- **命令格式**:
164
- ```bash
165
- soke-cli course +list-categories \
166
- [--page <page>] \
167
- [--page-size <size>]
168
- ```
169
-
170
- **参数说明**:
171
- - `--page`: 页码,从1开始(默认: 1)
172
- - `--page-size`: 每页数量,最大100(默认: 100)
173
-
174
- **返回字段**:
175
- - `uuid`: 分类ID
176
- - `title`: 分类标题
177
- - `parent_id`: 分类父ID
178
- - `create_time`: 创建时间
88
+ ## 步骤2: 创建课程
179
89
 
180
- **示例**:
181
90
  ```bash
182
- # 查询所有课程分类
183
- soke-cli course +list-categories
91
+ soke-cli course +create \
92
+ --title "课程标题" \
93
+ --category-id "CATEGORY-UUID" \
94
+ --description "课程描述(可选)"
184
95
 
185
- # 分页查询
186
- soke-cli course +list-categories --page 1 --page-size 50
96
+ # JSON 输出:
97
+ soke-cli course +create --title "标题" --category-id "CATEGORY-UUID" --format json
187
98
  ```
188
99
 
189
- **权限要求**: `course:category:readonly`
100
+ **参数**:
101
+ | 参数 | 必填 | 说明 |
102
+ |------|------|------|
103
+ | `--title` | 是 | 课程标题 |
104
+ | `--category-id` | 是 | 分类 ID(从步骤1获取) |
105
+ | `--description` | 否 | 课程描述 |
106
+
107
+ **响应提取**: `data.uuid` → 课程 ID (`course-id`)
190
108
 
191
109
  ---
192
110
 
193
- ### +list-lessons
111
+ ## 步骤3: 上传素材文件
194
112
 
195
- 列出课程下的课件列表。
113
+ > 详见 [`../soke-material/SKILL.md`](../soke-material/SKILL.md)
196
114
 
197
- **命令格式**:
198
115
  ```bash
199
- soke-cli course +list-lessons \
200
- --course-id <course_id> \
201
- [--page <page>] \
202
- [--page-size <size>]
203
- ```
116
+ # 自动检测文件类型和时长
117
+ soke-cli file +upload --file "./video.mp4"
204
118
 
205
- **参数说明**:
206
- - `--course-id`: 课程ID **必需**
207
- - `--page`: 页码,从1开始(默认: 1)
208
- - `--page-size`: 每页数量,最大100(默认: 100)
209
-
210
- **返回字段**:
211
- - `uuid`: 课件ID
212
- - `title`: 课件标题
213
- - `type`: 课件类型(video=视频, audio=音频, article=文章, document=文档)
214
- - `media_id`: 关联素材库ID
215
- - `duration`: 课件时长(单位:秒)
216
- - `sort`: 排序号
217
- - `status`: 状态(-1=删除, 0=未发布, 1=发布)
218
- - `create_time`: 创建时间
219
-
220
- **示例**:
221
- ```bash
222
- # 查询课程的所有课件
223
- soke-cli course +list-lessons --course-id "course123"
119
+ # 指定类型和时长
120
+ soke-cli file +upload --file "./audio.mp3" --type audio --length 236
121
+
122
+ # JSON 输出
123
+ soke-cli file +upload --file "./video.mp4" --format json
224
124
  ```
225
125
 
226
- **权限要求**: `course:lesson:readonly`
126
+ **响应关键字段(全部用于步骤4创建课件)**:
127
+ | 字段 | 用途 | 说明 |
128
+ |------|------|------|
129
+ | `data.uuid` | `--media-id` | 素材 UUID |
130
+ | `data.filename` | `--filename` | 文件名 |
131
+ | `data.filesize` | `--filesize` | 文件大小(字节) |
132
+ | `data.object` | `--object` | OSS 对象路径 |
133
+ | `data.ext` | `--ext` | 文件扩展名 |
134
+ | `data.type` | `--type` | 文件类型 |
135
+
136
+ **时长默认值**: video→600s, audio→300s, 其他→0s
227
137
 
228
138
  ---
229
139
 
230
- ### +list-course-users
140
+ ## 步骤4: 创建课件
231
141
 
232
- 列出课程用户学习记录列表,支持按用户ID和完成时间筛选。
142
+ > 详见 [`../soke-lesson/SKILL.md`](../soke-lesson/SKILL.md)
233
143
 
234
- **命令格式**:
235
144
  ```bash
236
- soke-cli course +list-course-users \
237
- --course-id <course_id> \
238
- [--userid-list <user_ids>] \
239
- [--finish-start-time <timestamp>] \
240
- [--finish-end-time <timestamp>] \
241
- [--page <page>] \
242
- [--page-size <size>]
145
+ soke-cli course +lesson-create \
146
+ --course-id "COURSE-UUID" \
147
+ --title "第一课" \
148
+ --media-id "MATERIAL-UUID" \
149
+ --type "video" \
150
+ --length 600 \
151
+ --object "uploads/20260601/video.mp4" \
152
+ --filename "video.mp4" \
153
+ --ext "mp4" \
154
+ --filesize 10485760 \
155
+ --sort 0
243
156
  ```
244
157
 
245
- **参数说明**:
246
- - `--course-id`: 课程ID **必需**
247
- - `--userid-list`: 用户ID列表,逗号分隔,最多100个(可选)
248
- - `--finish-start-time`: 完成开始时间(Unix时间戳,毫秒)(可选)
249
- - `--finish-end-time`: 完成结束时间(Unix时间戳,毫秒)(可选)
250
- - `--page`: 页码,从1开始(默认: 1)
251
- - `--page-size`: 每页数量,最大100(默认: 100)
252
-
253
- **返回字段**:
254
- - `target_id`: 课程用户记录ID
255
- - `dept_user_id`: 部门用户ID
256
- - `dept_user_name`: 用户姓名
257
- - `study_progress`: 学习进度(百分比)
258
- - `finish_status`: 完成状态(0=未完成, 1=已完成)
259
- - `study_duration`: 学习时长(单位:秒)
260
- - `create_time`: 创建时间
261
- - `update_time`: 更新时间
262
-
263
- **示例**:
264
- ```bash
265
- # 查询某个课程的所有用户学习记录
266
- soke-cli course +list-course-users --course-id "course123"
267
-
268
- # 查询特定用户的学习记录
269
- soke-cli course +list-course-users \
270
- --course-id "course123" \
271
- --userid-list "user1,user2,user3"
158
+ **参数来源映射**:
159
+ | 参数 | 必填 | 来源 |
160
+ |------|------|------|
161
+ | `--course-id` | 是 | 步骤2 `data.uuid` |
162
+ | `--title` | 是 | 自定义标题 |
163
+ | `--media-id` | 是 | 步骤3 `data.uuid` |
164
+ | `--type` | 是 | 步骤3 `data.type` |
165
+ | `--length` | 否 | 媒体时长(秒) |
166
+ | `--object` | 否 | 步骤3 `data.object` |
167
+ | `--filename` | 否 | 步骤3 `data.filename` |
168
+ | `--ext` | 否 | 步骤3 `data.ext` |
169
+ | `--filesize` | 否 | 步骤3 `data.filesize` |
170
+ | `--sort` | 否 | 排序值(默认 0) |
272
171
 
273
- # 查询某个时间段内完成的学习记录
274
- soke-cli course +list-course-users \
275
- --course-id "course123" \
276
- --finish-start-time 1704038400000 \
277
- --finish-end-time 1735660799000
278
- ```
172
+ **关键原则**: 课件参数全部从 `file +upload` 响应提取,无需手动填写。
279
173
 
280
- **权限要求**: `course:courseUser:readonly`
174
+ ### 批量上传文件
281
175
 
282
- ---
283
-
284
- ### +get-course-user
285
-
286
- 获取单个用户的课程学习详情。
287
-
288
- **命令格式**:
289
176
  ```bash
290
- soke-cli course +get-course-user \
291
- --course-id <course_id> \
292
- --dept-user-id <dept_user_id>
177
+ FILES=("lesson1.mp4" "lesson2.mp4" "handout.pdf")
178
+
179
+ for file in "${FILES[@]}"; do
180
+ RESULT=$(soke-cli file +upload --file "$file" --format json)
181
+ MEDIA_ID=$(echo "$RESULT" | jq -r '.data.uuid')
182
+ FILE_TYPE=$(echo "$RESULT" | jq -r '.data.type')
183
+ FILE_NAME=$(echo "$RESULT" | jq -r '.data.filename')
184
+ FILE_SIZE=$(echo "$RESULT" | jq -r '.data.filesize')
185
+ OBJECT=$(echo "$RESULT" | jq -r '.data.object')
186
+ EXT=$(echo "$RESULT" | jq -r '.data.ext')
187
+
188
+ LENGTH=0
189
+ [[ "$FILE_TYPE" == "video" ]] && LENGTH=600
190
+ [[ "$FILE_TYPE" == "audio" ]] && LENGTH=300
191
+
192
+ TITLE=$(basename "$file" | sed 's/\.[^.]*$//')
193
+
194
+ soke-cli course +lesson-create \
195
+ --course-id "$COURSE_ID" --title "$TITLE" \
196
+ --media-id "$MEDIA_ID" --type "$FILE_TYPE" --length "$LENGTH" \
197
+ --object "$OBJECT" --filename "$FILE_NAME" --ext "$EXT" --filesize "$FILE_SIZE"
198
+ done
293
199
  ```
294
200
 
295
- **参数说明**:
296
- - `--course-id`: 课程ID **必需**
297
- - `--dept-user-id`: 部门用户ID **必需**
201
+ ---
298
202
 
299
- **返回字段**:
300
- 与 `+list-course-users` 返回字段相同,但返回单个用户的完整学习详情。
203
+ ## 步骤5: 更新课程(可选)
301
204
 
302
- **示例**:
303
205
  ```bash
304
- # 查询张三的课程学习记录
305
- soke-cli course +get-course-user \
306
- --course-id "course123" \
307
- --dept-user-id "user456"
206
+ soke-cli course +update \
207
+ --course-id "COURSE-UUID" \
208
+ --title "新标题" \
209
+ --description "课程描述"
308
210
  ```
309
211
 
310
- **权限要求**: `course:courseUser:readonly`
311
-
312
- **使用场景**:
313
- - 当用户询问"查询某人的课程学习情况"时使用
314
- - 需要同时提供课程ID和用户ID
315
- - 如果只知道用户名,需要先通过 `soke-cli contact +search-user` 查询用户ID
316
-
317
212
  ---
318
213
 
319
- ### +list-lesson-learns
214
+ ## 步骤6: 发布课程
320
215
 
321
- 列出课件学习记录,支持按用户ID和时间范围筛选。
216
+ **前提**: 课程至少包含 1 个课件。
322
217
 
323
- **命令格式**:
324
218
  ```bash
325
- soke-cli course +list-lesson-learns \
326
- --lesson-id <lesson_id> \
327
- [--userid-list <user_ids>] \
328
- [--start-time <timestamp>] \
329
- [--end-time <timestamp>] \
330
- [--page <page>] \
331
- [--page-size <size>]
219
+ soke-cli course +publish --course-id "COURSE-UUID"
332
220
  ```
333
221
 
334
- **参数说明**:
335
- - `--lesson-id`: 课件ID **必需**
336
- - `--userid-list`: 用户ID列表,逗号分隔,最多100个(可选)
337
- - `--start-time`: 学习开始时间(Unix时间戳,毫秒)(可选)
338
- - `--end-time`: 学习结束时间(Unix时间戳,毫秒)(可选)
339
- - `--page`: 页码,从1开始(默认: 1)
340
- - `--page-size`: 每页数量,最大100(默认: 100)
341
-
342
- **返回字段**:
343
- - `uuid`: 学习记录ID
344
- - `dept_user_id`: 部门用户ID
345
- - `dept_user_name`: 用户姓名
346
- - `study_duration`: 学习时长(单位:秒)
347
- - `finish_status`: 完成状态(0=未完成, 1=已完成)
348
- - `create_time`: 创建时间
349
- - `update_time`: 更新时间
350
-
351
- **示例**:
352
- ```bash
353
- # 查询某个课件的所有学习记录
354
- soke-cli course +list-lesson-learns --lesson-id "lesson123"
355
-
356
- # 查询特定用户的课件学习记录
357
- soke-cli course +list-lesson-learns \
358
- --lesson-id "lesson123" \
359
- --userid-list "user1,user2"
360
- ```
222
+ ---
361
223
 
362
- **权限要求**: `course:lessonLearn:readonly`
224
+ ## 步骤7: 指派课程(可选)
363
225
 
364
- ---
226
+ > 详见 [`../soke-assign/SKILL.md`](../soke-assign/SKILL.md)
365
227
 
366
- ### +list-lesson-faces
228
+ 发布后指派给部门或学员,学员才能看到并学习。
367
229
 
368
- 列出课件人脸识别记录,支持按用户ID和时间范围筛选。
230
+ ### 7.1 查询可用部门/用户
369
231
 
370
- **命令格式**:
371
232
  ```bash
372
- soke-cli course +list-lesson-faces \
373
- --lesson-id <lesson_id> \
374
- [--userid-list <user_ids>] \
375
- [--start-time <timestamp>] \
376
- [--end-time <timestamp>] \
377
- [--page <page>] \
378
- [--page-size <size>]
233
+ soke-cli assign +list-departments --keyword "关键词"
234
+ soke-cli assign +list-users --dept-id "DEPT-ID" --keyword "关键词"
379
235
  ```
380
236
 
381
- **参数说明**:
382
- - `--lesson-id`: 课件ID **必需**
383
- - `--userid-list`: 用户ID列表,逗号分隔,最多100个(可选)
384
- - `--start-time`: 识别开始时间(Unix时间戳,毫秒)(可选)
385
- - `--end-time`: 识别结束时间(Unix时间戳,毫秒)(可选)
386
- - `--page`: 页码,从1开始(默认: 1)
387
- - `--page-size`: 每页数量,最大100(默认: 100)
388
-
389
- **返回字段**:
390
- - `uuid`: 识别记录ID
391
- - `dept_user_id`: 部门用户ID
392
- - `dept_user_name`: 用户姓名
393
- - `face_status`: 识别状态(0=未识别, 1=识别成功, 2=识别失败)
394
- - `face_time`: 识别时间
395
- - `create_time`: 创建时间
396
-
397
- **示例**:
398
- ```bash
399
- # 查询某个课件的所有人脸识别记录
400
- soke-cli course +list-lesson-faces --lesson-id "lesson123"
237
+ ### 7.2 创建指派
401
238
 
402
- # 查询特定用户的人脸识别记录
403
- soke-cli course +list-lesson-faces \
404
- --lesson-id "lesson123" \
405
- --userid-list "user1,user2"
239
+ ```bash
240
+ # 指派给部门
241
+ soke-cli assign +create \
242
+ --module "course" \
243
+ --target-id "COURSE-UUID" \
244
+ --dept-ids "DEPT-ID" \
245
+ --dept-names "部门名称" \
246
+ --learn-type "required"
247
+
248
+ # 指派给用户
249
+ soke-cli assign +create \
250
+ --module "course" \
251
+ --target-id "COURSE-UUID" \
252
+ --user-ids "USER-ID" \
253
+ --user-names "学员姓名" \
254
+ --learn-type "required"
255
+
256
+ # 同时指派给多个部门和用户
257
+ soke-cli assign +create \
258
+ --module "course" --target-id "COURSE-UUID" \
259
+ --dept-ids "DEPT1,DEPT2" --dept-names "部门1,部门2" \
260
+ --user-ids "USER1,USER2" --user-names "学员1,学员2" \
261
+ --learn-type "required"
406
262
  ```
407
263
 
408
- **权限要求**: `course:lessonFace:readonly`
264
+ **指派参数**:
265
+ | 参数 | 必填 | 说明 |
266
+ |------|------|------|
267
+ | `--module` | 是 | 固定 `course` |
268
+ | `--target-id` | 是 | 课程 ID |
269
+ | `--learn-type` | 是 | `required`(必修) / `optional`(选修) |
270
+ | `--dept-ids` | 否 | 部门 ID,逗号分隔 |
271
+ | `--dept-names` | 否 | 部门名(与 ids 一一对应) |
272
+ | `--user-ids` | 否 | 用户 ID,逗号分隔 |
273
+ | `--user-names` | 否 | 用户名(与 ids 一一对应) |
409
274
 
410
275
  ---
411
276
 
412
- ## 常见工作流
413
-
414
- ### 工作流1: 查询用户的课程学习情况
277
+ ## 步骤8: 查询学习状态
415
278
 
416
- 当用户询问"查询张三的课程学习情况"时:
279
+ ### 课程学习记录
417
280
 
418
- **步骤1**: 如果只知道用户名,先查询用户ID
419
281
  ```bash
420
- soke-cli contact +search-user --name "张三"
421
- ```
282
+ soke-cli course +list-course-users --course-id "COURSE-UUID"
422
283
 
423
- **步骤2**: 获取课程列表,找到目标课程ID
424
- ```bash
425
- soke-cli course +list-courses \
426
- --start-time 1704038400000 \
427
- --end-time 1735660799000
284
+ # 按用户筛选
285
+ soke-cli course +list-course-users \
286
+ --course-id "COURSE-UUID" --userid-list "USER1,USER2"
287
+
288
+ # 按完成时间筛选
289
+ soke-cli course +list-course-users \
290
+ --course-id "COURSE-UUID" \
291
+ --finish-start-time 1700000000000 --finish-end-time 1700100000000
428
292
  ```
429
293
 
430
- **步骤3**: 查询该用户的课程学习记录
294
+ ### 学员学习详情
295
+
431
296
  ```bash
432
297
  soke-cli course +get-course-user \
433
- --course-id <course_id> \
434
- --dept-user-id <dept_user_id>
298
+ --course-id "COURSE-UUID" --dept-user-id "DEPT-USER-ID"
435
299
  ```
436
300
 
437
- ### 工作流2: 统计课程学习完成情况
301
+ 返回: `lesson_finish_num`(已完成)、`lesson_num`(总数)、`progress`(进度%)、`learn_status`
438
302
 
439
- 当用户询问"统计某个课程的学习完成情况"时:
303
+ ### 课件学习记录
440
304
 
441
- **步骤1**: 获取课程用户学习记录列表
442
305
  ```bash
443
- soke-cli course +list-course-users --course-id <course_id>
306
+ soke-cli course +list-lesson-learns \
307
+ --course-id "COURSE-UUID" --lesson-id "LESSON-UUID"
444
308
  ```
445
309
 
446
- **步骤2**: 分析返回的数据
447
- - 统计 `finish_status` 字段的分布
448
- - 计算平均学习进度(`study_progress` 字段)
449
- - 统计完成人数和未完成人数
450
- - 计算平均学习时长(`study_duration` 字段)
310
+ ### 课件列表
451
311
 
452
- ### 工作流3: 查询某个时间段的课程
453
-
454
- 当用户询问"查询本月的课程"时:
455
-
456
- **步骤1**: 计算时间范围(Unix时间戳,毫秒)
457
312
  ```bash
458
- # 例如:2024年1月1日 00:00:00 = 1704038400000
459
- # 2024年1月31日 23:59:59 = 1706716799000
460
- ```
313
+ # +list-lessons: 支持时间范围
314
+ soke-cli course +list-lessons --course-id "ID" --start-time 1700000000000 --end-time 1700100000000
461
315
 
462
- **步骤2**: 查询课程列表
463
- ```bash
464
- soke-cli course +list-courses \
465
- --start-time 1704038400000 \
466
- --end-time 1706716799000
316
+ # +lesson-list: 支持类型/关键词筛选
317
+ soke-cli course +lesson-list --course-id "ID" --type "video" --keyword "关键词"
467
318
  ```
468
319
 
469
- ### 工作流4: 查询课程的课件学习详情
320
+ ---
470
321
 
471
- 当用户询问"查询某个课程的课件学习情况"时:
322
+ ## 可用命令全览
323
+
324
+ ### 课程管理
325
+
326
+ | 命令 | 说明 | 风险 |
327
+ |------|------|------|
328
+ | `+list-categories` | 查询课程分类列表 | read |
329
+ | `+list-courses` | 查询课程列表 | read |
330
+ | `+get-course` | 查询课程详情 | read |
331
+ | `+create` | 创建课程 | write |
332
+ | `+update` | 更新课程 | write |
333
+ | `+publish` | 发布课程 | write |
334
+
335
+ ### 课件管理
336
+
337
+ | 命令 | 说明 | 风险 |
338
+ |------|------|------|
339
+ | `+lesson-create` | 创建课件 | write |
340
+ | `+lesson-get` | 查询课件详情 | read |
341
+ | `+lesson-list` | 查询课件列表(type/keyword) | read |
342
+ | `+list-lessons` | 查询课件列表(时间范围) | read |
343
+
344
+ ### 素材管理 (soke-material)
345
+
346
+ | 命令 | 说明 |
347
+ |------|------|
348
+ | `file +upload` | 上传文件到素材库 |
349
+ | `file +create` | 手动创建素材记录 |
350
+ | `file +list-files` | 查询素材列表 |
351
+ | `file +get-info` | 查询素材详情 |
352
+ | `file +download` | 获取下载链接 |
353
+ | `file +list-categories` | 查询素材分类 |
354
+
355
+ ### 学习记录查询
356
+
357
+ | 命令 | 说明 |
358
+ |------|------|
359
+ | `+list-course-users` | 课程学员学习记录 |
360
+ | `+get-course-user` | 学员个人详情 |
361
+ | `+list-lesson-learns` | 课件学习记录 |
362
+ | `+list-lesson-faces` | 人脸识别记录 |
363
+
364
+ ### 指派管理 (soke-assign)
365
+
366
+ | 命令 | 说明 |
367
+ |------|------|
368
+ | `assign +list-departments` | 查询可用部门 |
369
+ | `assign +list-users` | 查询可用用户 |
370
+ | `assign +create` | 创建指派 |
371
+ | `assign +list` | 查询指派记录 |
472
372
 
473
- **步骤1**: 获取课程的课件列表
474
- ```bash
475
- soke-cli course +list-lessons --course-id <course_id>
476
- ```
373
+ ---
477
374
 
478
- **步骤2**: 查询每个课件的学习记录
479
- ```bash
480
- soke-cli course +list-lesson-learns --lesson-id <lesson_id>
481
- ```
375
+ ## 调试与故障排除
482
376
 
483
- **步骤3**: (可选)查询课件的人脸识别记录
484
- ```bash
485
- soke-cli course +list-lesson-faces --lesson-id <lesson_id>
486
- ```
377
+ ### 常见错误速查
487
378
 
488
- ### +batch-create-from-excel
379
+ | 错误 | 原因 | 解决 |
380
+ |------|------|------|
381
+ | `未登录授权` | Token 过期 | `soke-cli auth login` |
382
+ | `参数错误` | 必填参数缺失 | `soke-cli course <cmd> --help` |
383
+ | `文件不存在` | 上传路径错误 | 使用绝对路径 |
384
+ | `课程发布失败` | 无课件 | 先创建至少 1 个课件 |
385
+ | `分类不存在` | category-id 无效 | 查询 `+list-categories` |
386
+ | `素材不存在` | media-id 无效 | 确认上传成功 |
387
+ | `指派失败` | 资源未发布 | 先发布课程 |
489
388
 
490
- 通过 Excel 文件批量创建课程并上传课件素材。能力来自原独立工具 createcourse,已物理合入本 CLI(`internal/courseimport`)。
389
+ ### 调试检查清单
491
390
 
492
- **命令格式**:
493
391
  ```bash
494
- soke-cli course +batch-create-from-excel \
495
- --file <课程信息.xlsx> \
496
- [--material-dir <素材目录>] \
497
- [--separator <分隔符>] \
498
- [--mode default|hg] \
499
- [--picture-time 6] \
500
- [--material-category-id <分类ID>] \
501
- [--json-events]
502
- ```
503
-
504
- **Flags**:
392
+ # 1. 认证状态
393
+ soke-cli config show # 确认用户凭证不为空
505
394
 
506
- | 名称 | 必填 | 默认 | 说明 |
507
- | --- | --- | --- | --- |
508
- | `--file` | 是 | - | Excel 文件路径,必须 `.xlsx` |
509
- | `--material-dir` | 否 | Excel 同目录 | 素材文件相对路径解析的根目录 |
510
- | `--separator` | 否 | `-` | Excel `分类` / `标签` 列的分隔符,同时影响两列 |
511
- | `--mode` | 否 | `default` | `default` 普通课程 / `hg` 海关学时模式 |
512
- | `--picture-time` | 否 | `6` | 视频抽帧秒数;仅当系统已装 ffmpeg 时生效 |
513
- | `--material-category-id` | 否 | 空 | 素材库默认分类 ID,空则交由后端兜底 |
514
- | `--json-events` | 否 | false | stdout 输出 JSON-lines 进度事件,供 sokeclaw 等 IPC 调用方解析 |
395
+ # 2. 课程存在
396
+ soke-cli course +get-course --course-id "ID" --format json | jq '.data.uuid'
515
397
 
516
- **Excel 模板**: 详见 [`templates/batch-create-from-excel.md`](./templates/batch-create-from-excel.md)。
398
+ # 3. 课件数量
399
+ soke-cli course +lesson-list --course-id "ID" --format json | jq '.data.list | length'
517
400
 
518
- **进度事件协议**(`--json-events` 模式):
401
+ # 4. 发布状态
402
+ soke-cli course +get-course --course-id "ID" --format json | jq '.data.status'
403
+ # status=1 表示已发布
519
404
 
520
- | `type` | 含义 |
521
- | --- | --- |
522
- | `env` | 启动时报告 ffmpeg 是否可用 |
523
- | `course_start` | 开始处理某门课程 |
524
- | `course_done` | 某门课程全流程成功 |
525
- | `course_failed` | 某门课程失败(单门失败不中断整批) |
526
- | `episode_uploaded` | 单节课件上传完成 |
527
- | `cover_fallback` | 封面降级为默认封面 |
528
- | `run_done` | 整批结束,带 `ok` / `failed` 计数 |
405
+ # 5. 指派状态
406
+ soke-cli assign +list --module course --target-id "ID" --format json | jq '.data.list | length'
529
407
 
530
- **示例**:
531
-
532
- ```bash
533
- # 默认模式,Excel 与素材同目录
534
- soke-cli course +batch-create-from-excel --file ./courses.xlsx
535
-
536
- # HG 学时模式,显式指定素材目录,机器可读输出
537
- soke-cli course +batch-create-from-excel \
538
- --file ./hg-courses.xlsx \
539
- --material-dir ./materials \
540
- --mode hg \
541
- --json-events
408
+ # 始终用 --format json 获取结构化输出
542
409
  ```
543
410
 
544
- **注意**:
545
-
546
- - ffmpeg 是可选依赖:已装则启用视频抽帧封面;未装则封面策略自动降级到默认封面,不影响主流程。如需启用抽帧,把 ffmpeg 装到 `PATH`,或设置环境变量 `SOKE_CLI_FFMPEG_PATH` 指向可执行文件。
547
- - HG 模式下"所属单位标签"的 tag id 通过环境变量 `SOKE_CLI_HG_ORG_TAG_ID` 注入(原 createcourse 写死在 token 配置表里,合入 soke-cli 后改为外部注入)。
548
- - 单门课程失败不会中断整批运行,失败统计会在 `run_done` 事件汇总。
411
+ ---
549
412
 
550
- ## 注意事项
413
+ ## 完整示例
551
414
 
552
- 1. **时间格式**: 所有时间参数使用Unix时间戳(毫秒),不是秒
553
- 2. **时间范围限制**: `+list-courses` 的起始与结束时间差不能超过365天
554
- 3. **分页**: 默认每页100条,最大100条,超过需要分页查询
555
- 4. **用户ID**: `dept_user_id` 是企业内的用户ID,不是用户名
556
- 5. **课程ID**: `course-id` 和 `uuid` 是同一个字段,都表示课程ID
557
- 6. **权限**: 所有操作都需要先完成认证(`soke-cli auth login`)
558
- 7. **课程状态**:
559
- - `-1`: 删除
560
- - `0`: 未发布
561
- - `1`: 已发布
562
- - `2`: 关闭
563
- 8. **学习模式**:
564
- - `1`: 自由式(可以任意顺序学习)
565
- - `2`: 解锁式(必须按顺序学习)
566
-
567
- ## 错误处理
568
-
569
- ### 权限不足
570
- 如果遇到权限错误,参考 [`../soke-shared/SKILL.md`](../soke-shared/SKILL.md) 中的权限处理章节。
571
-
572
- ### 参数错误
573
- 使用 `--help` 查看命令参数说明:
574
415
  ```bash
575
- soke-cli course +list-courses --help
416
+ # === 1. 查询分类 ===
417
+ CATEGORY_ID=$(soke-cli course +list-categories --format json | jq -r '.data.list[0].uuid')
418
+
419
+ # === 2. 创建课程 ===
420
+ COURSE_ID=$(soke-cli course +create \
421
+ --title "Python 数据分析实战" \
422
+ --category-id "$CATEGORY_ID" \
423
+ --format json | jq -r '.data.uuid')
424
+
425
+ # === 3. 上传素材 ===
426
+ UPLOAD=$(soke-cli file +upload --file "./lesson1.mp4" --format json)
427
+ MEDIA_ID=$(echo "$UPLOAD" | jq -r '.data.uuid')
428
+ FILE_TYPE=$(echo "$UPLOAD" | jq -r '.data.type')
429
+ FILENAME=$(echo "$UPLOAD" | jq -r '.data.filename')
430
+ FILESIZE=$(echo "$UPLOAD" | jq -r '.data.filesize')
431
+ OBJECT=$(echo "$UPLOAD" | jq -r '.data.object')
432
+ EXT=$(echo "$UPLOAD" | jq -r '.data.ext')
433
+
434
+ # === 4. 创建课件 ===
435
+ soke-cli course +lesson-create \
436
+ --course-id "$COURSE_ID" --title "第一课:环境搭建" \
437
+ --media-id "$MEDIA_ID" --type "$FILE_TYPE" --length 600 \
438
+ --object "$OBJECT" --filename "$FILENAME" --ext "$EXT" --filesize "$FILESIZE"
439
+
440
+ # === 5. 发布课程 ===
441
+ soke-cli course +publish --course-id "$COURSE_ID"
442
+
443
+ # === 6. 指派学员 ===
444
+ DEPT_ID=$(soke-cli assign +list-departments --keyword "研发" --format json | jq -r '.data.list[0].uuid')
445
+ soke-cli assign +create \
446
+ --module "course" --target-id "$COURSE_ID" \
447
+ --dept-ids "$DEPT_ID" --dept-names "研发部" \
448
+ --learn-type "required"
449
+
450
+ # === 7. 验证 ===
451
+ soke-cli course +get-course --course-id "$COURSE_ID" --format json | jq .
452
+ soke-cli course +lesson-list --course-id "$COURSE_ID" --format json | jq '.data.list'
576
453
  ```
577
454
 
578
- ### 数据不存在
579
- 如果查询的课程或用户不存在,API会返回空数据或错误提示。
580
-
581
- ### 时间范围超限
582
- 如果 `+list-courses` 的时间范围超过365天,API会返回错误,需要缩小时间范围。
455
+ ---
583
456
 
584
457
  ## API 接口映射
585
458
 
586
- | Shortcut | API 路径 | HTTP 方法 |
587
- |----------|----------|-----------|
459
+ | CLI 命令 | API 路径 | 方法 |
460
+ |----------|----------|------|
461
+ | `+list-categories` | `/course/category/list` | GET |
588
462
  | `+list-courses` | `/course/course/list` | GET |
589
463
  | `+get-course` | `/course/course/info` | GET |
590
- | `+list-categories` | `/course/category/list` | GET |
464
+ | `+create` | `/skills/course/create` | POST |
465
+ | `+update` | `/skills/course/update/{id}` | PUT |
466
+ | `+publish` | `/skills/course/update/{id}` | PUT |
467
+ | `+lesson-create` | `/skills/course/lesson/create` | POST |
468
+ | `+lesson-get` | `/skills/courseware/get/{id}` | GET |
469
+ | `+lesson-list` | `/skills/course/lesson/list` | GET |
591
470
  | `+list-lessons` | `/course/lesson/list` | GET |
592
- | `+list-course-users` | `/course/courseUser/list` | GET |
593
- | `+get-course-user` | `/course/courseUser/info` | GET |
471
+ | `+list-course-users` | `/course/user/list` | GET |
472
+ | `+get-course-user` | `/course/user/info` | GET |
594
473
  | `+list-lesson-learns` | `/course/lessonLearn/list` | GET |
595
474
  | `+list-lesson-faces` | `/course/lessonFace/list` | GET |
475
+ | `file +upload` | `/skills/uploadFile/signature` + `/skills/uploadFile/create` | POST |
476
+ | `assign +list-departments` | `/skills/department/list` | GET |
477
+ | `assign +list-users` | `/skills/user/list` | GET |
478
+ | `assign +create` | `/skills/assignLog/create` | POST |
479
+ | `assign +list` | `/skills/assignLog/list` | GET |
480
+
481
+ ## 权限要求
482
+
483
+ | 操作 | 权限范围 |
484
+ |------|----------|
485
+ | 课程读写 | `course:course:write` / `course:course:readonly` |
486
+ | 课件读写 | `course:courseware:write` / `course:courseware:readonly` |
487
+ | 素材读写 | `file:file:write` / `file:file:readonly` |
488
+ | 指派读写 | `assign:write` / `assign:read` |
489
+ | 学习记录 | `course:courseUser:readonly` / `course:lessonLearn:readonly` |
490
+
491
+ ## 注意事项
492
+
493
+ 1. **课程至少需要 1 个课件才能发布**
494
+ 2. **课件参数全部从素材上传响应提取**,不手动构造
495
+ 3. **时长根据文件类型自动设置**: video=600s, audio=300s, 其他=0
496
+ 4. **课程发布后学员才可见**
497
+ 5. **指派是可选的**,未指派时学员看不到课程
498
+ 6. **所有时间参数使用毫秒级 Unix 时间戳**
499
+
500
+ ## 相关文档
501
+
502
+ - [`../soke-shared/SKILL.md`](../soke-shared/SKILL.md) — 认证、配置、权限
503
+ - [`../soke-material/SKILL.md`](../soke-material/SKILL.md) — 文件上传和素材管理
504
+ - [`../soke-lesson/SKILL.md`](../soke-lesson/SKILL.md) — 课件创建和管理
505
+ - [`../soke-assign/SKILL.md`](../soke-assign/SKILL.md) — 指派管理
506
+ - [`references/examples.md`](./references/examples.md) — 更多使用示例
507
+ - [`references/course-list-courses.md`](./references/course-list-courses.md) — 课程查询参考