@qcplay/cli 1.0.10 → 1.0.12

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qcplay/cli",
3
- "version": "1.0.10",
3
+ "version": "1.0.12",
4
4
  "description": "QCPlay CLI",
5
5
  "type": "module",
6
6
  "bin": {
@@ -5,24 +5,25 @@ description: "QCPlay 官网文章上传:Use when user mentions 发布文章、
5
5
  metadata:
6
6
  requires:
7
7
  bins: ["qcplay", "qcplay-cli"]
8
- native_bins: ["publish-article.exe", "qcplay-auth.exe"]
9
8
  cliHelp: "qcplay article --help"
10
9
  authFile: "~/.qcplay/auth.json"
11
10
  templateCommand: "qcplay article"
12
11
  initCommand: "qcplay article init"
13
12
  importCommand: "qcplay article import <wechat-url> [file]"
14
13
  publishCommand: "qcplay www-article-list.store article.md"
14
+ updateCommand: "qcplay article update [id]"
15
+ deleteCommand: "qcplay article delete [id]"
15
16
  ---
16
17
 
17
18
  # qcplay www-article-list.store
18
19
 
19
20
  ## CRITICAL — 文章上传工作流,必须遵循
20
21
 
21
- 本 Skill 用于通过 QCPlay CLI 上传 / 发布官网文章。
22
+ 本 Skill 用于通过 QCPlay CLI 保存、预览、上线和删除官网文章。
22
23
 
23
24
  文章参数必须写在 Markdown 文件顶部的 Front Matter 中,正文写在 Front Matter 之后。
24
25
 
25
- 用户发布文章时,默认只需要执行:
26
+ 用户提交文章时,先执行:
26
27
 
27
28
  ```bash
28
29
  qcplay www-article-list.store article.md
@@ -42,7 +43,21 @@ qcplay-cli www-article-list.store article.md
42
43
  qcplay article import "https://mp.weixin.qq.com/s/..." article.md
43
44
  ```
44
45
 
45
- 该命令只生成未发布的官网文章草稿,不会直接发布。确认草稿正文和 Front Matter 后,再执行发布命令。
46
+ 该命令只生成本地官网文章草稿,不会提交到官网。确认草稿正文和 Front Matter 后,再执行保存命令。
47
+
48
+ 保存命令始终以 `status: "0"` 创建未上线文章,并输出文章 ID 和可点击预览地址。必须先让用户检查 PC、移动端排版;只有用户明确确认上线后,才能执行:
49
+
50
+ ```bash
51
+ qcplay article update [id]
52
+ ```
53
+
54
+ 用户要求删除时执行软删除,将状态更新为 `2`:
55
+
56
+ ```bash
57
+ qcplay article delete [id]
58
+ ```
59
+
60
+ `id` 省略时,只能使用当前账号最近一次保存的未上线文章;找不到时必须要求手动输入 ID。
46
61
 
47
62
  正确方式是:
48
63
 
@@ -53,7 +68,7 @@ Front Matter 解析文章参数
53
68
 
54
69
  Markdown 正文作为 article_content
55
70
 
56
- publish-article.exe 执行上传
71
+ QCPlay CLI 调用认证后端保存文章
57
72
  ```
58
73
 
59
74
  ---
@@ -63,9 +78,7 @@ publish-article.exe 执行上传
63
78
  - **文章文件(Article File)**:一个 Markdown 文件,例如 `article.md`,顶部包含 YAML Front Matter,下面是正文内容。
64
79
  - **Front Matter**:`---` 包裹的 YAML 参数区,用来填写文章标题、缩略图、分类、标签、发布时间等。
65
80
  - **文章正文(article_content)**:Front Matter 后面的 Markdown 正文内容,程序自动作为 `article_content` 上传。
66
- - **发布程序(publish-article.exe)**:Go 编译的本地文章上传程序,负责读取文章文件、解析参数、读取登录凭证并调用发布接口。
67
- - **登录程序(qcplay-auth.exe)**:Go 编译的本地登录程序,负责浏览器登录并生成 `~/.qcplay/auth.json`。
68
- - **统一 CLI(qcplay / qcplay-cli)**:npm 包提供的统一入口,根据子命令调用不同 exe。
81
+ - **统一 CLI(qcplay / qcplay-cli)**:npm 包提供的统一入口,负责解析文章、读取登录凭证并调用认证后端。
69
82
  - **认证文件(auth.json)**:登录成功后保存的本地认证文件,路径为 `~/.qcplay/auth.json`。
70
83
  - **文章模板**:通过 `qcplay article` 查看模板说明,或通过 `qcplay article init` 生成 `article.md`。
71
84
  - **微信文章导入**:通过 `qcplay article import <wechat-url> [file]` 提取推文正文,将图片转存到官网图片服务并生成 Markdown 草稿。
@@ -109,12 +122,12 @@ publish-article.exe 执行上传
109
122
  6. **文章正文不能为空**
110
123
  Front Matter 后面的 Markdown 正文为空时不得上传。
111
124
 
112
- 7. **正式发布需要用户明确设置**
113
- `status: "1"` 表示发布,`status: "0"` 表示未发布。
114
- 如果用户没有明确要求上线,建议使用:
125
+ 7. **首次保存固定为未上线**
126
+ `www-article-list.store` 必须忽略 Front Matter 中的上线值并强制使用:
115
127
  ```yaml
116
128
  status: "0"
117
129
  ```
130
+ 用户检查预览并明确确认后,使用 `article update [id]` 将状态更新为 `1`。不得通过首次保存直接上线。
118
131
 
119
132
  8. **不得伪造发布结果**
120
133
  如果接口返回失败,必须原样提示失败原因,不得编造文章 URL 或成功状态。
@@ -302,10 +315,13 @@ qcplay article import "https://mp.weixin.qq.com/s/..." article.md
302
315
  该命令会:
303
316
 
304
317
  ```txt
305
- 读取微信文章标题、作者、发布日期和正文
306
- 逐张下载正文与封面图片
318
+ 读取微信文章标题、作者、发布日期和完整正文
319
+ 逐张下载正文图片、CSS 背景图与封面图片
307
320
  上传图片到官网图片服务并替换链接
308
- 清理微信脚本、表单和交互节点
321
+ 清理脚本和危险属性,同时保留原文 HTML 层级、内联样式及特殊节点里的可读内容
322
+ 背景图片保留在原容器中,不得重复生成为普通图片
323
+ 生成保持微信 677px 阅读宽度并兼容窄屏的富 HTML 正文
324
+ 独占一行的图片使用块级布局,避免 PC 端标题行盒造成相邻图片重叠
309
325
  生成 status: "0" 的官网 Markdown 草稿
310
326
  ```
311
327
 
@@ -315,22 +331,41 @@ qcplay article import "https://mp.weixin.qq.com/s/..." article.md
315
331
 
316
332
  用户在 `article.md` 顶部 Front Matter 填写文章参数,在下方填写正文。
317
333
 
318
- 6. **发布文章**
334
+ 6. **保存为未上线文章**
319
335
 
320
336
  ```bash
321
337
  qcplay www-article-list.store article.md
322
338
  ```
323
339
 
324
- 7. **查看发布结果**
340
+ 7. **检查预览**
325
341
 
326
- 发布成功后应输出:
342
+ 保存成功后必须输出:
327
343
 
328
344
  ```txt
329
- 官网文章发布成功
345
+ 文章已保存为未上线状态
346
+ 文章 ID: 123
347
+ 文章状态: 未上线
348
+ 预览地址: https://snail.qingcigame.com/official/news-details.html?id=123
349
+ ```
350
+
351
+ 让用户打开预览地址检查 PC 和移动端排版。用户明确确认上线后执行:
330
352
 
331
- 标题: xxx
332
- 状态: 已发布 / 未发布
333
- 文章链接: xxx
353
+ ```bash
354
+ qcplay article update 123
355
+ ```
356
+
357
+ 也可以省略 ID,使用当前账号最近一次保存的未上线文章:
358
+
359
+ ```bash
360
+ qcplay article update
361
+ ```
362
+
363
+ 8. **删除文章**
364
+
365
+ 用户明确要求删除时,将文章状态软删除为 `2`:
366
+
367
+ ```bash
368
+ qcplay article delete 123
334
369
  ```
335
370
 
336
371
  ---
@@ -392,50 +427,54 @@ qcplay article init --force
392
427
 
393
428
  ---
394
429
 
395
- ### 发布文章
430
+ ### 保存未上线文章
396
431
 
397
432
  ```bash
398
433
  qcplay www-article-list.store article.md
399
434
  ```
400
435
 
401
- 内部应调用:
436
+ 首次保存始终将 `status` 强制为 `0`。成功后记录最近文章 ID,并输出预览地址。
437
+
438
+ ### 确认上线
402
439
 
403
440
  ```bash
404
- publish-article.exe --content-file <article.md绝对路径>
441
+ qcplay article update [id]
405
442
  ```
406
443
 
407
- 例如:
444
+ 等价命令:
408
445
 
409
446
  ```bash
410
- publish-article.exe --content-file E:\go-admin\article.md
447
+ qcplay www-article-list.update [id]
411
448
  ```
412
449
 
413
- ---
450
+ 该命令通过更新操作将 `status` 修改为 `1`。
414
451
 
415
- ### Dry Run,可选
452
+ ### 删除文章
416
453
 
417
- 如果支持:
454
+ ```bash
455
+ qcplay article delete [id]
456
+ ```
457
+
458
+ 等价命令:
418
459
 
419
460
  ```bash
420
- qcplay www-article-list.store article.md --dry-run
461
+ qcplay www-article-list.delete [id]
421
462
  ```
422
463
 
423
- 则只解析、校验并展示 payload,不真正调用发布接口。
464
+ 该命令通过更新操作将 `status` 修改为 `2`,不得执行物理删除。
424
465
 
425
466
  ---
426
467
 
427
- ### 指定环境,可选
428
-
429
- ```bash
430
- qcplay www-article-list.store article.md --env prod
431
- ```
468
+ ### Dry Run,可选
432
469
 
433
- 内部传给 Go 程序:
470
+ 如果支持:
434
471
 
435
472
  ```bash
436
- publish-article.exe --content-file E:\go-admin\article.md --env prod
473
+ qcplay www-article-list.store article.md --dry-run
437
474
  ```
438
475
 
476
+ 则只解析、校验并展示 payload,不真正调用发布接口。
477
+
439
478
  ---
440
479
 
441
480
  ## article.md 文件格式
@@ -452,7 +491,7 @@ move_thumbnail: https://example.com/mobile-thumbnail.png
452
491
  article_excerpt: 文章描述,可以为空
453
492
  article_url: article-url-slug
454
493
  origin: QCPlay
455
- status: "1"
494
+ status: "0"
456
495
  cate_id: "2"
457
496
  video_link: ""
458
497
  is_hot: "0"
@@ -494,7 +533,7 @@ index_move_img: ""
494
533
  | `article_excerpt` | 否 | 文章描述,可以为空 |
495
534
  | `article_url` | 建议 | 文章链接,建议使用英文 slug |
496
535
  | `origin` | 否 | 作者来源 |
497
- | `status` | 是 | `1` 发布,`0` 未发布 |
536
+ | `status` | 是 | 模板填写 `0`;首次保存会强制为 `0` |
498
537
  | `cate_id` | 是 | 分类 ID |
499
538
  | `video_link` | 否 | 视频链接 |
500
539
  | `is_hot` | 是 | `1` 热门,`0` 非热门 |
@@ -583,20 +622,17 @@ Front Matter.index_move_img -> index_move_img
583
622
 
584
623
  | 状态 | status |
585
624
  |---|---:|
586
- | 未发布 | 0 |
587
- | 发布 | 1 |
625
+ | 未上线 | 0 |
626
+ | 已上线 | 1 |
627
+ | 已删除(软删除) | 2 |
588
628
 
589
- 默认建议:
629
+ 首次保存固定使用:
590
630
 
591
631
  ```yaml
592
632
  status: "0"
593
633
  ```
594
634
 
595
- 用户明确要求立即发布时:
596
-
597
- ```yaml
598
- status: "1"
599
- ```
635
+ 用户明确确认预览排版无误后,不修改 Front Matter,执行 `qcplay article update [id]` 上线。
600
636
 
601
637
  ---
602
638
 
@@ -815,7 +851,7 @@ index_move_img: ""
815
851
  1. `article_title` 不能为空;
816
852
  2. `thumbnail` 不能为空;
817
853
  3. `cate_id` 不能为空;
818
- 4. `status` 只能是 `"0"` 或 `"1"`;
854
+ 4. Front Matter 的 `status` 只能是 `"0"` 或 `"1"`,首次保存请求固定覆盖为 `"0"`;
819
855
  5. `is_hot` 只能是 `"0"` 或 `"1"`;
820
856
  6. `is_index` 只能是 `"0"` 或 `"1"`;
821
857
  7. `release_time` 格式必须是 `YYYY-MM-DD`,例如:
@@ -877,7 +913,7 @@ qcplay article import "https://mp.weixin.qq.com/s/..." article.md
877
913
  - 输出状态固定为未发布,发布前必须检查分类、缩略图、发布日期和正文;
878
914
  - 不允许覆盖已经存在的文件。
879
915
 
880
- ### 发布文章
916
+ ### 保存未上线文章
881
917
 
882
918
  ```bash
883
919
  qcplay www-article-list.store article.md
@@ -891,88 +927,21 @@ qcplay www-article-list.store ./articles/news.md
891
927
 
892
928
  ---
893
929
 
894
- ## npm 调用到 Go 程序的约定
895
-
896
- Node CLI 只负责路由,不负责发布逻辑。
897
-
898
- 当用户执行:
930
+ ## CLI 与后端约定
899
931
 
900
- ```bash
901
- qcplay www-article-list.store article.md
902
- ```
903
-
904
- Node CLI 内部应调用:
905
-
906
- ```bash
907
- publish-article.exe --content-file <article.md绝对路径>
908
- ```
932
+ Node CLI 负责解析 Markdown、构建请求、读取本地认证状态和输出结果;Go 后端负责认证、权限校验和数据库更新。
909
933
 
910
- 不要把 Front Matter 中的字段拆成命令行参数传递。
911
-
912
- 正确:
913
-
914
- ```bash
915
- publish-article.exe --content-file E:\go-admin\article.md
916
- ```
917
-
918
- 不推荐:
919
-
920
- ```bash
921
- publish-article.exe --article-title "标题" --cate-id 2 --thumbnail xxx
922
- ```
923
-
924
- ---
925
-
926
- ## Go 程序实现要求
927
-
928
- `publish-article.exe` 必须完成:
929
-
930
- 1. 读取 `--content-file`;
931
- 2. 解析 Markdown Front Matter;
932
- 3. 将正文作为 `article_content`;
933
- 4. 从 `~/.qcplay/auth.json` 读取 `access_token`;
934
- 5. 校验 token 是否存在;
935
- 6. 校验 token 是否过期;
936
- 7. 补充默认参数:
937
- ```txt
938
- is_index2 = 0
939
- type = 1
940
- ```
941
- 8. 构建发布请求;
942
- 9. 调用官网文章发布接口;
943
- 10. 输出发布结果。
944
-
945
- ---
946
-
947
- ## Go 字段结构参考
948
-
949
- ```go
950
- type ArticleMeta struct {
951
- ArticleTitle string `yaml:"article_title"`
952
- Thumbnail string `yaml:"thumbnail"`
953
- MoveThumbnail string `yaml:"move_thumbnail"`
954
- ArticleExcerpt string `yaml:"article_excerpt"`
955
- ArticleURL string `yaml:"article_url"`
956
- Origin string `yaml:"origin"`
957
- Status string `yaml:"status"`
958
- CateID string `yaml:"cate_id"`
959
- VideoLink string `yaml:"video_link"`
960
- IsHot string `yaml:"is_hot"`
961
- IsIndex string `yaml:"is_index"`
962
- ReleaseTime string `yaml:"release_time"`
963
- Area string `yaml:"area"`
964
- Sort string `yaml:"sort"`
965
- GameID string `yaml:"game_id"`
966
- IndexPCImg string `yaml:"index_pc_img"`
967
- IndexMoveImg string `yaml:"index_move_img"`
968
- }
969
- ```
934
+ - 首次保存:`POST /api/articles/publish`,后端再次强制 `status=0`;
935
+ - 确认上线:`PATCH /api/articles/status`,请求 `{ "id": 123, "status": "1" }`;
936
+ - 删除文章:`PATCH /api/articles/status`,请求 `{ "id": 123, "status": "2" }`;
937
+ - 上线和删除都要求 `www-article-list.update` 权限;
938
+ - 删除是状态更新,不得执行物理删除。
970
939
 
971
940
  ---
972
941
 
973
942
  ## Front Matter 解析要求
974
943
 
975
- Go 程序必须兼容:
944
+ CLI 必须兼容:
976
945
 
977
946
  1. UTF-8 BOM;
978
947
  2. Windows 换行 `\r\n`;
@@ -997,9 +966,9 @@ Go 程序必须兼容:
997
966
 
998
967
  ---
999
968
 
1000
- ## 发布请求字段
969
+ ## 首次保存请求字段
1001
970
 
1002
- 发布接口最终应收到:
971
+ 首次保存接口最终应收到:
1003
972
 
1004
973
  ```json
1005
974
  {
@@ -1010,7 +979,7 @@ Go 程序必须兼容:
1010
979
  "article_excerpt": "文章描述,可以为空",
1011
980
  "article_url": "article-url-slug",
1012
981
  "origin": "QCPlay",
1013
- "status": "1",
982
+ "status": "0",
1014
983
  "cate_id": "2",
1015
984
  "video_link": "",
1016
985
  "is_hot": "0",
@@ -1030,23 +999,30 @@ Go 程序必须兼容:
1030
999
 
1031
1000
  ## 成功输出
1032
1001
 
1033
- 发布成功后输出:
1002
+ 首次保存成功后输出:
1034
1003
 
1035
1004
  ```txt
1036
- 官网文章发布成功
1037
-
1038
- 标题: 文章标题
1039
- 状态: 已发布
1040
- 文章链接: xxx
1005
+ 文章已保存为未上线状态
1006
+ 文章 ID: 123
1007
+ 文章状态: 未上线
1008
+ 预览地址: https://snail.qingcigame.com/official/news-details.html?id=123
1041
1009
  ```
1042
1010
 
1043
- 如果 `status` 是 `"0"`:
1011
+ 确认上线成功后输出:
1044
1012
 
1045
1013
  ```txt
1046
- 官网文章已保存为未发布状态
1014
+ 文章已上线
1015
+ 文章 ID: 123
1016
+ 文章状态: 已上线
1017
+ 文章地址: https://snail.qingcigame.com/official/news-details.html?id=123
1018
+ ```
1019
+
1020
+ 删除成功后输出:
1047
1021
 
1048
- 标题: 文章标题
1049
- 状态: 未发布
1022
+ ```txt
1023
+ 文章已删除
1024
+ 文章 ID: 123
1025
+ 文章状态: 已删除
1050
1026
  ```
1051
1027
 
1052
1028
  ---
@@ -1139,13 +1115,12 @@ release_time 格式错误,请使用 YYYY-MM-DD,例如 2026-07-09
1139
1115
  4. 不要在命令中拼接全部文章字段;
1140
1116
  5. 文章字段从 `article.md` Front Matter 读取;
1141
1117
  6. Markdown 正文作为 `article_content`;
1142
- 7. Node CLI 只负责调用:
1143
- ```bash
1144
- publish-article.exe --content-file <file>
1145
- ```
1146
- 8. Go 程序负责解析、校验、读取 auth、调用接口;
1147
- 9. 发布成功或失败都在当前终端输出;
1148
- 10. 不得打印完整 token。
1118
+ 7. Node CLI 负责解析、校验、读取 auth 并调用后端接口;
1119
+ 8. Go 后端负责权限校验、强制草稿状态和数据库更新;
1120
+ 9. 保存、上线或删除的成功和失败都在当前终端输出;
1121
+ 10. 不得打印完整 token;
1122
+ 11. 未得到用户确认,不得执行上线;
1123
+ 12. 删除只能更新 `status=2`,不得物理删除数据。
1149
1124
 
1150
1125
  ---
1151
1126
 
@@ -1186,14 +1161,21 @@ qcplay article init
1186
1161
  qcplay www-article-list.store article.md
1187
1162
  ```
1188
1163
 
1189
- 读取 `article.md` 并发布文章。
1164
+ 读取 `article.md` 并保存为未上线文章。
1165
+
1166
+ ```bash
1167
+ qcplay article update [id]
1168
+ qcplay article delete [id]
1169
+ ```
1170
+
1171
+ 分别将文章状态更新为已上线和已删除。
1190
1172
 
1191
1173
  并满足:
1192
1174
 
1193
1175
  - 能解析 Front Matter;
1194
1176
  - 能读取 Markdown 正文;
1195
1177
  - 能读取 `~/.qcplay/auth.json`;
1196
- - 能调用 `publish-article.exe`;
1178
+ - 能调用认证后端并处理接口错误;
1197
1179
  - 能处理无权限错误;
1198
1180
  - 能处理字段缺失错误;
1199
1181
  - 不要求用户在命令行传标题;
@@ -1208,8 +1190,11 @@ qcplay www-article-list.store article.md
1208
1190
  命令只传文章文件。
1209
1191
  正文自动作为 article_content。
1210
1192
  登录状态读取 auth.json。
1211
- Node 只做路由。
1212
- Go 负责发布。
1193
+ Node 解析文章并调用后端。
1194
+ Go 后端负责权限和数据库更新。
1213
1195
  默认参数程序内部补齐。
1196
+ 首次保存固定 status=0。
1197
+ 确认后更新 status=1。
1198
+ 删除更新 status=2。
1214
1199
  发布失败不得伪造成成功。
1215
1200
  ```