# course create 一句话:创建课程(基本信息 + 可选章节 JSON),仅机构管理员;创建的课程固定为下架状态。传入 `--id` 时变为更新模式,但编辑已有课程请优先用 [`course edit`](zeyiji-course-edit.md)。 向用户汇报前 MUST 遵循 [课程对外表达](zeyiji-course-presentation.md)。 ## 命令 ```bash # 最小必填创建 zeyiji-cli course create \ --name "Go 语言入门" --category-id-resource 1 --category-id 5 \ --teacher "张老师" --validate-day 365 --current-price 9900 \ --rebate-flag 2 --show-flag 1 --cover-image ./cover.jpg # 带返佣(固定比例):rebate-flag=1 时必须同时传 rebate-way / rebate-count zeyiji-cli course create \ --name "前端开发进阶" --category-id-resource 2 --category-id 8 \ --teacher "王老师" --validate-day 365 --current-price 9900 \ --rebate-flag 1 --rebate-way 2 --rebate-count 30 \ --show-flag 1 --cover-image ./cover.jpg # 带单层章节(默认) zeyiji-cli course create \ --name "Go 语言入门" --category-id-resource 1 --category-id 5 \ --teacher "张老师" --validate-day 365 --current-price 9900 \ --rebate-flag 2 --show-flag 1 --cover-image ./cover.jpg \ --sections '[{"name":"第1节 Go基础","videoUrl":"./v1.mp4","freeFlag":1}]' # 带双层章节目录 zeyiji-cli course create \ --name "Go 语言入门" --category-id-resource 1 --category-id 5 \ --teacher "张老师" --validate-day 365 --current-price 9900 \ --rebate-flag 2 --show-flag 1 --cover-image ./cover.jpg --deep 2 \ --chapters '[{"name":"第一章 入门","sections":[{"name":"1.1 环境搭建","videoUrl":"./v1.mp4"}]}]' # 预览请求(不实际执行) zeyiji-cli course create --name "测试课程" --dry-run ``` ## 参数要点 ### 必填(创建模式,共 9 个) | 参数 | 说明 | |---|---| | `--name` | 课程名称 | | `--category-id-resource` | 资源领域 ID(下方级联查询 Step 1) | | `--category-id` | 课程类型 ID(Step 2,必须选叶子节点) | | `--teacher` | 课程讲师,多个用逗号分隔 | | `--validate-day` | 365(1年) / 546(1年半) / 730(2年) / 1095(3年) | | `--current-price` | 现价,单位分,≥0 | | `--rebate-flag` | 1 参与返佣 / 2 不参与 | | `--show-flag` | 1 全平台 / 2 仅机构平台 / 3 仅平台 | | `--cover-image` | 封面图片本地路径(jpg/jpeg/png,≤10MB) | ### 条件必填 | 参数 | 条件 | 说明 | |---|---|---| | `--rebate-way` | rebate-flag=1 时必填 | 1 固定金额 / 2 固定比例 | | `--rebate-count` | rebate-flag=1 时必填且 >0 | 固定金额单位分;固定比例传百分比 | ### 其余不明显参数 | 参数 | 说明 | |---|---| | `--deep` | 1 单层(只有节)/ 2 双层(章+节),默认 1 | | `--sections` / `--chapters` | 章节 JSON,二者互斥且必须与目录类型匹配:单层目录用 `--sections`,双层目录用 `--chapters` | | `--introduce-url` | 图文介绍本地文件:.html/.htm/.txt 直接上传;图片自动包装为 HTML | | `--introduce` | 课程简介,最多 200 字 | | `--video` | 宣传视频本地路径(mp4/mov,≤1GB) | | `--original-price` | 原价,单位分,≥0;不传则前台不显示原价 | | `--profession-id` / `--profession-level-id` | 关联职业 / 职业等级,资源领域 code=1/2 时使用(见 Step 3) | | `--category-id-standard` | 课程类别 ID(国标),可选 | | `--sort` | 排序 [0-100] | | `--id` | 传入则为更新模式(仅 `--name` 必填),推荐改用 `course edit` | | `--data` | 直接传完整 JSON 请求体(`{"course":{...},"courseChapterDetails":[],"courseSections":[]}`),覆盖其他 flags | ## 对外结果 - 创建成功:说「已创建课程《课程名称》,当前为下架状态」,再按用户关注点补充展示平台、目录类型、价格等业务信息。 - 不要把请求 JSON、`--jq` 结果、字段名或数字枚举作为最终答复;目录类型说「单层目录 / 双层目录」,展示平台说「全平台 / 仅机构平台 / 仅平台」。 - 创建后不要主动播报未填写的可选字段、空值或内部状态。 ## 章节 JSON ### 单层目录 `--sections` ```json [{"name":"第1节 Go基础","videoUrl":"./v1.mp4","freeFlag":1,"lecturerName":"张老师"}] ``` | 字段 | 必填 | 说明 | |---|---|---| | name | 是 | 节名称 | | videoUrl | 否 | 视频文件本地路径(≤4GB),CLI 自动上传换取 URL | | videoCoverImageUrl | 否 | 视频封面本地路径(≤10MB) | | coursewareUrl | 否 | 课件文件本地路径(名称自动取文件名) | | lecturerName / lecturerUnit | 否 | 讲师名称 / 讲师单位 | | freeFlag | 否 | 是否免费试看:1 否(收费)/ 2 是(免费试看) | > 视频时长由 CLI 自动识别(仅 MP4/MOV),无需也不能传 videoTime。 ### 双层目录 `--chapters` ```json [{"name":"第一章 入门","sections":[{"name":"1.1 环境搭建","videoUrl":"./v1.mp4","freeFlag":1}]}] ``` 章字段:`name`(必填)、`sections`(节数组,结构同上)。 ## 关联数据级联查询 ID 不能凭空填写,必须查询后让用户按名称选择。查询一律用 `--jq` 在进程内过滤(不要用管道 grep,Windows 下中文会乱码)。 Step 1 资源领域: ```bash zeyiji-cli api GET /back/category/page -p type=1 -p parentId=0 -p size=100 --jq ".records[] | {id, name, code}" ``` Step 2 课程类型树(依赖 Step 1 选中的 id): ```bash zeyiji-cli api GET /back/category/tree -p type=1 -p parentId=<资源领域ID> --jq "def t: {id, name, sons: [(.sons // [])[] | t]}; .[] | t" ``` 必须选到叶子节点(无 `sons`);同名节点选最深层。 Step 3 按 Step 1 的 `code` 分流是否还要职业/等级: | code | 资源领域 | 额外字段 | |---|---|---| | 1 | 职业技能 | 关联职业 + 职业等级 | | 2 | 职业资格 | 关联职业(不同接口,无职业等级) | | 3 / 4 | 兴趣技能 / 公益生活 | 无 | ```bash # code=1:关联职业 → 职业等级 zeyiji-cli api GET /back/profession/page -p categoryId=<课程类型ID> --jq ".records[] | {id, name}" zeyiji-cli api GET /back/profession/level/page -p professionId=<职业ID> --jq ".records[] | {id, name}" # code=2:关联职业(无等级) zeyiji-cli api GET /back/profession/qualify/page -p categoryId=<课程类型ID> --jq ".records[] | {id, name}" ``` Step 4(可选)课程类别(国标,type=2;与 Step 2 的「课程类型」不是一回事): ```bash zeyiji-cli api GET /back/category/tree -p type=2 --jq "def t: {id, name, sons: [(.sons // [])[] | t]}; .[] | t" ``` Step 5(可选)返佣比例字典(rebate-flag=1 且 rebate-way=2 时): ```bash zeyiji-cli api GET /back/sys/dict/page -p dictType=course_rebate_ratio --jq ".records[] | {dictName, dictValue}" ``` ## 常见错误 | 现象 | 处理 | |---|---| | 课程名称不能为空 | 补 `--name` | | 资源领域不能为空 / 课程类型不能为空 | 按级联查询补 `--category-id-resource` / `--category-id` | | 有效期天数不合法 | 仅允许 365/546/730/1095 | | 参与返佣时,返佣方式不能为空 / 返佣数量必须大于0 | 补 `--rebate-way` / `--rebate-count` | | 单层目录不支持 `--chapters`(双层目录也不支持 `--sections`) | 单层目录用 `--sections`,双层目录用 `--chapters` | | 封面图片大小超出限制 / 宣传视频大小超出限制 / 第 N 节视频大小超出限制 | 压缩到 10MB / 1GB / 4GB 以内 | | 封面图片文件不存在 / 宣传视频文件不存在 | 检查本地路径 |