wjx-cli 0.1.10 → 0.1.11

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 +887 -889
  2. package/bundled/wjx-cli-expert.md +102 -0
  3. package/bundled/wjx-cli-use/SKILL.md +111 -0
  4. package/bundled/wjx-cli-use/references/analytics-commands.md +159 -0
  5. package/bundled/wjx-cli-use/references/contacts-commands.md +330 -0
  6. package/bundled/wjx-cli-use/references/dsl-syntax.md +160 -0
  7. package/bundled/wjx-cli-use/references/question-types.md +102 -0
  8. package/bundled/wjx-cli-use/references/response-commands.md +164 -0
  9. package/bundled/wjx-cli-use/references/survey-commands.md +194 -0
  10. package/dist/commands/init.js +10 -0
  11. package/dist/commands/init.js.map +1 -1
  12. package/dist/commands/reference.js +332 -328
  13. package/dist/commands/reference.js.map +1 -1
  14. package/dist/commands/response.js +17 -50
  15. package/dist/commands/response.js.map +1 -1
  16. package/dist/commands/skill.d.ts +2 -0
  17. package/dist/commands/skill.js +46 -0
  18. package/dist/commands/skill.js.map +1 -0
  19. package/dist/commands/survey.js +1 -1
  20. package/dist/commands/survey.js.map +1 -1
  21. package/dist/commands/update.d.ts +2 -0
  22. package/dist/commands/update.js +76 -0
  23. package/dist/commands/update.js.map +1 -0
  24. package/dist/commands/user-system.js +4 -27
  25. package/dist/commands/user-system.js.map +1 -1
  26. package/dist/index.js +4 -0
  27. package/dist/index.js.map +1 -1
  28. package/dist/lib/command-helpers.d.ts +2 -0
  29. package/dist/lib/command-helpers.js +2 -1
  30. package/dist/lib/command-helpers.js.map +1 -1
  31. package/dist/lib/install-skill.d.ts +23 -0
  32. package/dist/lib/install-skill.js +96 -0
  33. package/dist/lib/install-skill.js.map +1 -0
  34. package/package.json +3 -2
package/README.md CHANGED
@@ -1,889 +1,887 @@
1
- # wjx-cli
2
-
3
- > 问卷星 (Wenjuanxing) CLI — AI Agent 原生命令行工具
4
-
5
- [![license](https://img.shields.io/badge/license-MIT-blue)](LICENSE)
6
- [![node](https://img.shields.io/badge/node-%3E%3D20-green)](https://nodejs.org/)
7
- [![npm](https://img.shields.io/npm/v/wjx-cli)](https://www.npmjs.com/package/wjx-cli)
8
- [![tests](https://img.shields.io/badge/tests-96%20passing-brightgreen)](__tests__/cli.test.mjs)
9
-
10
- wjx-cli 是 [`wjx-ai-kit`](../) monorepo 的命令行入口,将 [wjx-api-sdk](../wjx-api-sdk/) 的 50+ 函数直接暴露为终端命令。设计目标:**让 AI Agent 和人类开发者都能用一行命令操作问卷星 OpenAPI**。
11
-
12
- ---
13
-
14
- ## 目录
15
-
16
- - [特性](#特性)
17
- - [**快速开始**](#快速开始)
18
- - [安装](#安装)
19
- - [认证](#认证)
20
- - [架构](#架构)
21
- - [全局选项](#全局选项)
22
- - [命令参考](#命令参考)
23
- - [survey — 问卷管理](#survey--问卷管理)
24
- - [response — 答卷管理](#response--答卷管理)
25
- - [contacts — 通讯录](#contacts--通讯录)
26
- - [department — 部门管理](#department--部门管理)
27
- - [admin — 管理员](#admin--管理员)
28
- - [tag — 标签管理](#tag--标签管理)
29
- - [user-system — 用户体系](#user-system--用户体系)
30
- - [account — 子账号管理](#account--子账号管理)
31
- - [sso — 单点登录](#sso--单点登录)
32
- - [analytics — 数据分析](#analytics--数据分析)
33
- - [配置与诊断](#配置与诊断)
34
- - [stdin 管道输入](#stdin-管道输入)
35
- - [输出格式](#输出格式)
36
- - [错误协议](#错误协议)
37
- - [Agent 集成指南](#agent-集成指南)
38
- - [环境变量](#环境变量)
39
- - [开发](#开发)
40
- - [常见问题](#常见问题)
41
- - [相关项目](#相关项目)
42
- - [许可证](#许可证)
43
-
44
- ---
45
-
46
- ## 特性
47
-
48
- - **AI Agent 原生** — 默认 JSON stdout + 结构化 JSON stderr,退出码区分错误类型,适合程序解析
49
- - **stdin pipe** — `echo '{"vid":123}' | wjx --stdin survey get`,参数通过管道传入
50
- - **表格输出** — `--table` 切换为人类可读的 `console.table` 格式
51
- - **56 个子命令** — 覆盖问卷、答卷、通讯录、部门、管理员、标签、用户体系、子账号、SSO、数据分析
52
- - **9 个本地命令** — SSO URL 生成和 analytics 计算无需 API Key,离线可用
53
- - **Shell 补全** — `wjx completion bash/zsh/fish` 生成自动补全脚本
54
- - **Dry-run 预览** — `--dry-run` 预览 API 请求(URL/Headers/Body)不实��发送
55
- - **基于 wjx-api-sdk** — 直接调用 SDK 函数,类型安全,行为与 API 一致
56
-
57
- ---
58
-
59
- ## 快速开始
60
-
61
- ```bash
62
- npm install -g wjx-cli
63
- wjx init # 交互式配置 API Key、Base URL、Corp ID
64
- wjx doctor # 环境诊断
65
- wjx survey list # 查看问卷列表
66
- ```
67
-
68
- > **新手?** 阅读 [快速开始教程](docs/getting-started.md),含 [Node.js 安装指引](docs/install-nodejs.md)。
69
-
70
- ---
71
-
72
- ## 前置条件
73
-
74
- - **Node.js >= 20**([安装指引](docs/install-nodejs.md))
75
- - **问卷星 OpenAPI API Key**([申请方式](https://www.wjx.cn/openapi/))
76
-
77
- ---
78
-
79
- ## 安装
80
-
81
- ```bash
82
- npm install -g wjx-cli
83
- ```
84
-
85
- ### 从源码安装(开发者)
86
-
87
- ```bash
88
- git clone <your-repo-url>
89
- cd wjx-ai-kit
90
- npm install
91
- npm run build --workspace=wjx-api-sdk
92
- npm run build --workspace=wjx-cli
93
- npm link --workspace=wjx-cli
94
- ```
95
-
96
- ---
97
-
98
- ## 认证
99
-
100
- 大多数命令需要问卷星 API Key(SSO 和 analytics 命令除外)。
101
-
102
- 凭据解析优先级:`--api-key` 参数 > 环境变量 > `~/.wjxrc` 配置文件。
103
-
104
- ```bash
105
- # 方式 1:交互式配置(推荐,首次使用)
106
- wjx init
107
-
108
- # 方式 2:环境变量
109
- export WJX_API_KEY=your_api_key
110
-
111
- # 方式 3:命令行参数
112
- wjx --api-key your_api_key survey list
113
-
114
- # 方式 4:直接编辑配置文件
115
- cat ~/.wjxrc
116
- # {"apiKey":"your_api_key","baseUrl":"https://www.wjx.cn","corpId":"orgXXX"}
117
- ```
118
-
119
- ---
120
-
121
- ## 架构
122
-
123
- ```
124
- wjx-ai-kit/ # monorepo root
125
- ├── wjx-api-sdk/ # TypeScript SDK(50+ 函数,零依赖)
126
- ├── wjx-mcp-server/ # MCP Server(56 tools,供 Claude/Cursor 使用)
127
- └── wjx-cli/ # ← 本项目
128
- ├── src/
129
- │ ├── index.ts # Commander 入口 + 全局 preAction hook
130
- │ ├── commands/ # 13 个命令模块(每模块 1 个 register 函数)
131
- │ │ ├── init.ts # wjx init 交互式配置向导
132
- │ │ ├── completion.ts # wjx completion bash/zsh/fish
133
- │ │ ├── survey.ts # 14 subcommands
134
- │ │ ├── response.ts # 11 subcommands
135
- │ │ ├── contacts.ts # 3 subcommands
136
- │ │ ├── department.ts # 4 subcommands
137
- │ │ ├── admin.ts # 3 subcommands
138
- │ │ ├── tag.ts # 4 subcommands
139
- │ │ ├── user-system.ts # 6 subcommands
140
- │ │ ├── account.ts # 5 subcommands
141
- │ │ ├── sso.ts # 3 subcommands(无需 API Key)
142
- │ │ ├── analytics.ts # 6 subcommands(本地计算,无需 API Key)
143
- │ │ └── diagnostics.ts # 2 subcommands(whoami + doctor)
144
- │ └── lib/
145
- │ ├── config.ts # ~/.wjxrc 配置文件读写 + applyConfigToEnv
146
- │ ├── command-helpers.ts # executeCommand + strictInt + requireField + dry-run
147
- │ ├── auth.ts # API Key 获取(--api-key > env > config)
148
- │ ├── output.ts # JSON / table 格式化
149
- │ ├── errors.ts # CliError + exit code 路由
150
- │ ├── stdin.ts # stdin JSON 读取 + source-aware merge
151
- │ └── completions.ts # Shell 补全候选项生成
152
- └── __tests__/
153
- └── cli.test.mjs # 96 个端到端测试
154
- ```
155
-
156
- **数据流:** `CLI args / stdin` → `Commander parse` → `executeCommand()` → `wjx-api-sdk function` → `stdout JSON / stderr error`
157
-
158
- ---
159
-
160
- ## 全局选项
161
-
162
- | 选项 | 说明 |
163
- |------|------|
164
- | `--api-key <apiKey>` | WJX API Key(或设置 `WJX_API_KEY` 环境变量) |
165
- | `--json` | JSON 输出(默认) |
166
- | `--table` | 表格输出(`console.table` 格式) |
167
- | `--stdin` | 从 stdin 读取 JSON 参数(见 [stdin 管道输入](#stdin-管道输入)) |
168
- | `--dry-run` | 预览 API 请求(不实际发送,输出到 stderr) |
169
- | `--version` | 显示版本号 |
170
- | `--help` | 显示帮助信息 |
171
-
172
- ---
173
-
174
- ## 命令参考
175
-
176
- ### survey — 问卷管理
177
-
178
- 14 个子命令,覆盖问卷的完整生命周期。
179
-
180
- ```bash
181
- wjx survey list # 列出问卷
182
- wjx survey get --vid 12345 # 获取详情
183
- wjx survey create --title "新问卷" # 创建问卷
184
- wjx survey status --vid 12345 --state 1 # 发布(1=发布, 2=暂停, 3=删除)
185
- wjx survey export-text --vid 12345 # 导出为纯文本
186
- wjx survey url --mode create # 生成创建/编辑 URL
187
- ```
188
-
189
- <details>
190
- <summary>全部选项参考</summary>
191
-
192
- | 子命令 | 选项 | 必填 | 类型 | 说明 |
193
- |--------|------|:----:|------|------|
194
- | **list** | `--page` | | int | 页码 |
195
- | | `--page_size` | | int | 每页数量 |
196
- | | `--status` | | int | 状态筛选 |
197
- | | `--atype` | | int | 问卷类型 |
198
- | | `--name_like` | | string | 名称模糊搜索 |
199
- | **get** | `--vid` | **是** | int | 问卷 ID |
200
- | **create** | `--title` | **是** | string | 问卷标题 |
201
- | | `--type` | | int | 问卷类型(默认 0) |
202
- | | `--description` | | string | 问卷描述 |
203
- | | `--questions` | | json | 题目 JSON 数组 |
204
- | | `--source_vid` | | string | 复制源问卷 ID |
205
- | | `--publish` | | flag | 创建后立即发布 |
206
- | **delete** | `--vid` | **是** | int | 问卷 ID |
207
- | | `--username` | **是** | string | 用户名 |
208
- | | `--completely` | | flag | 彻底删除(不进回收站) |
209
- | **status** | `--vid` | **是** | int | 问卷 ID |
210
- | | `--state` | **是** | int | 目标状态(1=发布, 2=暂停, 3=删除) |
211
- | **settings** | `--vid` | **是** | int | 问卷 ID |
212
- | **update-settings** | `--vid` | **是** | int | 问卷 ID |
213
- | | `--api_setting` | | json | API 设置 |
214
- | | `--after_submit_setting` | | json | 提交后设置 |
215
- | | `--msg_setting` | | json | 消息设置 |
216
- | | `--sojumpparm_setting` | | json | 参数设置 |
217
- | | `--time_setting` | | json | 时间设置 |
218
- | **tags** | `--username` | **是** | string | 用户名 |
219
- | **tag-details** | `--tag_id` | **是** | int | 标签 ID |
220
- | **clear-bin** | `--username` | **是** | string | 用户名 |
221
- | | `--vid` | | int | 指定问卷 ID(不填则清空全部) |
222
- | **upload** | `--file_name` | **是** | string | 文件名 |
223
- | | `--file` | **是** | string | 文件 Base64 内容 |
224
- | **export-text** | `--vid` | **是** | int | 问卷 ID |
225
- | | `--raw` | | flag | 输出纯文本(不包裹 JSON) |
226
- | **url** | `--mode` | | string | `create` 或 `edit`(默认 create) |
227
- | | `--name` | | string | 问卷名称(create 模式) |
228
- | | `--activity` | | int | 问卷 vid(edit 模式必填) |
229
-
230
- </details>
231
-
232
- ### response 答卷管理
233
-
234
- 11 个子命令,管理答卷数据的查询、提交、下载和统计。
235
-
236
- ```bash
237
- wjx response count --vid 12345 # 获取答卷总数
238
- wjx response query --vid 12345 # 查询答卷
239
- wjx response realtime --vid 12345 # 实时最新答卷
240
- wjx response download --vid 12345 # 下载答卷
241
- wjx response submit --vid 12345 --inputcosttime 60 --submitdata "1$2"
242
- wjx response report --vid 12345 # 统计报告
243
- ```
244
-
245
- <details>
246
- <summary>全部选项参考</summary>
247
-
248
- | 子命令 | 选项 | 必填 | 类型 | 说明 |
249
- |--------|------|:----:|------|------|
250
- | **count** | `--vid` | **是** | int | 问卷 ID |
251
- | **query** | `--vid` | **是** | int | 问卷 ID |
252
- | | `--page_index` | | int | 页码 |
253
- | | `--page_size` | | int | 每页数量 |
254
- | | `--sort` | | int | 排序 |
255
- | | `--min_index` | | int | 最小序号 |
256
- | | `--jid` | | string | 答卷 ID |
257
- | | `--sojumpparm` | | string | 自定义参数 |
258
- | | `--qid` | | string | 题目 ID |
259
- | | `--begin_time` | | int | 开始时间 |
260
- | | `--end_time` | | int | 结束时间 |
261
- | | `--file_view_expires` | | int | 文件链接有效期 |
262
- | | `--query_note` | | flag | 查询备注 |
263
- | | `--distinct_user` | | flag | 去重用户 |
264
- | | `--distinct_sojumpparm` | | flag | 去重参数 |
265
- | | `--conds` | | string | 查询条件 |
266
- | **realtime** | `--vid` | **是** | int | 问卷 ID |
267
- | | `--count` | | int | 返回数量 |
268
- | **download** | `--vid` | **是** | int | 问卷 ID |
269
- | | `--taskid` | | string | 任务 ID |
270
- | | `--query_count` | | int | 查询数量 |
271
- | | `--begin_time` | | int | 开始时间 |
272
- | | `--end_time` | | int | 结束时间 |
273
- | | `--min_index` | | int | 最小序号 |
274
- | | `--qid` | | string | 题目 ID |
275
- | | `--sort` | | int | 排序 |
276
- | | `--query_type` | | int | 查询类型 |
277
- | | `--suffix` | | int | 文件后缀 |
278
- | | `--query_record` | | flag | 查询记录 |
279
- | **submit** | `--vid` | **是** | int | 问卷 ID |
280
- | | `--inputcosttime` | **是** | int | 填写耗时(秒) |
281
- | | `--submitdata` | **是** | string | 提交数据 |
282
- | | `--udsid` | | int | 用户系统 ID |
283
- | | `--sojumpparm` | | string | 自定义参数 |
284
- | | `--submittime` | | string | 提交时间 |
285
- | **modify** | `--vid` | **是** | int | 问卷 ID |
286
- | | `--jid` | **是** | int | 答卷 ID |
287
- | | `--answers` | **是** | string | 答案数据 |
288
- | **clear** | `--username` | **是** | string | 用户名 |
289
- | | `--vid` | **是** | int | 问卷 ID |
290
- | | `--reset_to_zero` | | flag | 重置序号 |
291
- | **report** | `--vid` | **是** | int | 问卷 ID |
292
- | | `--min_index` | | int | 最小序号 |
293
- | | `--jid` | | string | 答卷 ID |
294
- | | `--sojumpparm` | | string | 自定义参数 |
295
- | | `--begin_time` | | int | 开始时间 |
296
- | | `--end_time` | | int | 结束时间 |
297
- | | `--distinct_user` | | flag | 去重用户 |
298
- | | `--distinct_sojumpparm` | | flag | 去重参数 |
299
- | | `--conds` | | string | 查询条件 |
300
- | **files** | `--vid` | **是** | int | 问卷 ID |
301
- | | `--file_keys` | **是** | string | 文件 Key 列表 |
302
- | | `--file_view_expires` | | int | 链接有效期 |
303
- | **winners** | `--vid` | **是** | int | 问卷 ID |
304
- | | `--atype` | | int | 活动类型 |
305
- | | `--awardstatus` | | int | 领奖状态 |
306
- | | `--page_index` | | int | 页码 |
307
- | | `--page_size` | | int | 每页数量 |
308
- | **360-report** | `--vid` | **是** | int | 问卷 ID |
309
- | | `--taskid` | | string | 任务 ID |
310
-
311
- </details>
312
-
313
- ### contacts — 通讯录
314
-
315
- ```bash
316
- wjx contacts query --uid user1 # 查询联系人
317
- wjx contacts add --users '[{"name":"张三"}]' # 添加联系人
318
- wjx contacts delete --uids "uid1,uid2" # 删除联系人
319
- ```
320
-
321
- | 子命令 | 选项 | 必填 | 类型 | 说明 |
322
- |--------|------|:----:|------|------|
323
- | **query** | `--uid` | **是** | string | 用户 ID |
324
- | | `--corpid` | | string | 企业 ID |
325
- | **add** | `--users` | **是** | json | 用户 JSON 数组 |
326
- | | `--corpid` | | string | 企业 ID |
327
- | | `--auto_create_udept` | | flag | 自动创建部门 |
328
- | | `--auto_create_tag` | | flag | 自动创建标签 |
329
- | **delete** | `--uids` | **是** | string | 用户 ID 列表(逗号分隔) |
330
- | | `--corpid` | | string | 企业 ID |
331
-
332
- ### department 部门管理
333
-
334
- ```bash
335
- wjx department list # 列出部门
336
- wjx department add --depts '[{"name":"研发"}]'
337
- wjx department modify --depts '[{"id":1,"name":"技术"}]'
338
- wjx department delete --depts '[{"id":1}]' --type 1
339
- ```
340
-
341
- | 子命令 | 选项 | 必填 | 类型 | 说明 |
342
- |--------|------|:----:|------|------|
343
- | **list** | `--corpid` | | string | 企业 ID |
344
- | **add** | `--depts` | **是** | json | 部门路径 JSON 数组 |
345
- | | `--corpid` | | string | 企业 ID |
346
- | **modify** | `--depts` | **是** | json | 部门对象 JSON 数组 |
347
- | | `--corpid` | | string | 企业 ID |
348
- | **delete** | `--type` | **是** | string | 类型(1=按ID, 2=按名称) |
349
- | | `--depts` | **是** | json | 部门标识 JSON 数组 |
350
- | | `--corpid` | | string | 企业 ID |
351
- | | `--del_child` | | flag | 同时删除子部门 |
352
-
353
- ### admin 管理员
354
-
355
- ```bash
356
- wjx admin add --users '[{"uid":"u1","role":1}]'
357
- wjx admin delete --uids "uid1,uid2"
358
- wjx admin restore --uids "uid1"
359
- ```
360
-
361
- | 子命令 | 选项 | 必填 | 类型 | 说明 |
362
- |--------|------|:----:|------|------|
363
- | **add** | `--users` | **是** | json | 管理员 JSON 数组 |
364
- | | `--corpid` | | string | 企业 ID |
365
- | **delete** | `--uids` | **是** | string | 用户 ID 列表(逗号分隔) |
366
- | | `--corpid` | | string | 企业 ID |
367
- | **restore** | `--uids` | **是** | string | 用户 ID 列表(逗号分隔) |
368
- | | `--corpid` | | string | 企业 ID |
369
-
370
- ### tag 标签管理
371
-
372
- ```bash
373
- wjx tag list # 列出标签
374
- wjx tag add --child_names '["VIP","普通"]'
375
- wjx tag modify --tp_id 1 --child_names '["新VIP"]'
376
- wjx tag delete --tags '[{"id":1}]' --type 1
377
- ```
378
-
379
- | 子命令 | 选项 | 必填 | 类型 | 说明 |
380
- |--------|------|:----:|------|------|
381
- | **list** | `--corpid` | | string | 企业 ID |
382
- | **add** | `--child_names` | **是** | json | 标签路径 JSON 数组 |
383
- | | `--corpid` | | string | 企业 ID |
384
- | | `--is_radio` | | flag | 单选标签 |
385
- | **modify** | `--tp_id` | **是** | string | 标签组 ID |
386
- | | `--tp_name` | | string | 标签组名称 |
387
- | | `--child_names` | | json | 标签对象 JSON 数组 |
388
- | | `--corpid` | | string | 企业 ID |
389
- | **delete** | `--type` | **是** | string | 类型(1=按ID, 2=按名称) |
390
- | | `--tags` | **是** | json | 标签标识 JSON 数组 |
391
- | | `--corpid` | | string | 企业 ID |
392
-
393
- ### user-system 用户体系
394
-
395
- 6 个子命令,管理用户系统中的参与者和问卷绑定。
396
-
397
- ```bash
398
- wjx user-system add-participants --username u1 --sysid 1 --users '[...]'
399
- wjx user-system bind --username u1 --sysid 1 --uids "a" --vid 12345
400
- wjx user-system query-binding --username u1 --sysid 1 --vid 12345
401
- wjx user-system query-surveys --username u1 --sysid 1 --uid "a"
402
- ```
403
-
404
- <details>
405
- <summary>全部选项参考</summary>
406
-
407
- | 子命令 | 选项 | 必填 | 类型 | 说明 |
408
- |--------|------|:----:|------|------|
409
- | **add-participants** | `--username` | **是** | string | 用户名 |
410
- | | `--users` | **是** | json | 参与者 JSON |
411
- | | `--sysid` | **是** | int | 系统 ID |
412
- | **modify-participants** | `--username` | **是** | string | 用户名 |
413
- | | `--users` | **是** | json | 参与者 JSON |
414
- | | `--sysid` | **是** | int | 系统 ID |
415
- | **delete-participants** | `--username` | **是** | string | 用户名 |
416
- | | `--uids` | **是** | json | 用户 ID JSON 数组 |
417
- | | `--sysid` | **是** | int | 系统 ID |
418
- | **bind** | `--username` | **是** | string | 用户名 |
419
- | | `--vid` | **是** | int | 问卷 ID |
420
- | | `--sysid` | **是** | int | 系统 ID |
421
- | | `--uids` | **是** | string | 参与者 ID 列表 |
422
- | | `--answer_times` | | int | 可答次数 |
423
- | | `--can_chg_answer` | | flag | 允许修改答案 |
424
- | | `--can_view_result` | | flag | 允许查看结果 |
425
- | | `--can_hide_qlist` | | int | 隐藏问卷列表 |
426
- | **query-binding** | `--username` | **是** | string | 用户名 |
427
- | | `--vid` | **是** | int | 问卷 ID |
428
- | | `--sysid` | **是** | int | 系统 ID |
429
- | | `--page_index` | | int | 页码 |
430
- | | `--page_size` | | int | 每页数量 |
431
- | | `--join_status` | | int | 参与状态 |
432
- | | `--day` | | string | 按天筛选 |
433
- | | `--week` | | string | 按周筛选 |
434
- | | `--month` | | string | 按月筛选 |
435
- | | `--force_join_times` | | flag | 强制参与次数 |
436
- | **query-surveys** | `--username` | **是** | string | 用户名 |
437
- | | `--uid` | **是** | string | 参与者 ID |
438
- | | `--sysid` | **是** | int | 系统 ID |
439
- | | `--page_index` | | int | 页码 |
440
- | | `--page_size` | | int | 每页数量 |
441
-
442
- </details>
443
-
444
- ### account 子账号管理
445
-
446
- ```bash
447
- wjx account list # 查询子账号
448
- wjx account add --subuser test1 --password pass123
449
- wjx account modify --subuser test1 --email new@test.com
450
- wjx account delete --subuser test1
451
- wjx account restore --subuser test1
452
- ```
453
-
454
- <details>
455
- <summary>全部选项参考</summary>
456
-
457
- | 子命令 | 选项 | 必填 | 类型 | 说明 |
458
- |--------|------|:----:|------|------|
459
- | **list** | `--subuser` | | string | 子账号用户名 |
460
- | | `--name_like` | | string | 名称模糊搜索 |
461
- | | `--role` | | int | 角色 |
462
- | | `--group` | | int | 分组 |
463
- | | `--page_index` | | int | 页码 |
464
- | | `--page_size` | | int | 每页数量 |
465
- | | `--mobile` | | string | 手机号 |
466
- | **add** | `--subuser` | **是** | string | 子账号用户名 |
467
- | | `--password` | | string | 密码 |
468
- | | `--mobile` | | string | 手机号 |
469
- | | `--email` | | string | 邮箱 |
470
- | | `--role` | | int | 角色 |
471
- | | `--group` | | int | 分组 |
472
- | **modify** | `--subuser` | **是** | string | 子账号用户名 |
473
- | | `--mobile` | | string | 手机号 |
474
- | | `--email` | | string | 邮箱 |
475
- | | `--role` | | int | 角色 |
476
- | | `--group` | | int | 分组 |
477
- | **delete** | `--subuser` | **是** | string | 子账号用户名 |
478
- | **restore** | `--subuser` | **是** | string | 子账号用户名 |
479
- | | `--mobile` | | string | 手机号 |
480
- | | `--email` | | string | 邮箱 |
481
-
482
- </details>
483
-
484
- ### sso — 单点登录
485
-
486
- > **无需 API Key** SSO 命令在本地生成 URL,不调用 API。
487
-
488
- ```bash
489
- wjx sso subaccount-url --subuser test1 # 子账号 SSO 链接
490
- wjx sso user-system-url --u admin --system_id 1 --uid user1
491
- wjx sso partner-url --username partner1 # 代理商 SSO 链接
492
- ```
493
-
494
- <details>
495
- <summary>全部选项参考</summary>
496
-
497
- | 子命令 | 选项 | 必填 | 类型 | 说明 |
498
- |--------|------|:----:|------|------|
499
- | **subaccount-url** | `--subuser` | **是** | string | 子账号用户名 |
500
- | | `--mobile` | | string | 手机号 |
501
- | | `--email` | | string | 邮箱 |
502
- | | `--role_id` | | int | 角色 ID |
503
- | | `--url` | | string | 登录后跳转 URL |
504
- | | `--admin` | | int | 主账号登录(1) |
505
- | **user-system-url** | `--u` | **是** | string | 账号用户名 |
506
- | | `--system_id` | **是** | int | 用户系统 ID |
507
- | | `--uid` | **是** | string | 参与者 ID |
508
- | | `--uname` | | string | 参与者名称 |
509
- | | `--udept` | | string | 参与者部门 |
510
- | | `--uextf` | | string | 扩展字段 |
511
- | | `--upass` | | string | 密码 |
512
- | | `--is_login` | | int | 是否登录(0/1) |
513
- | | `--activity` | | int | 跳转问卷 vid |
514
- | | `--return_url` | | string | 返回 URL |
515
- | **partner-url** | `--username` | **是** | string | 代理商用户名 |
516
- | | `--mobile` | | string | 手机号 |
517
- | | `--subuser` | | string | 子账号用户名 |
518
-
519
- </details>
520
-
521
- ### analytics — 数据分析
522
-
523
- > **无需 API Key** analytics 命令在本地执行计算,不调用 API。
524
-
525
- ```bash
526
- wjx analytics decode --submitdata "1$2}2$hello" # 解码答卷提交数据
527
- wjx analytics nps --scores "[9,10,7,3,8,10,9]" # 计算 NPS 分数
528
- wjx analytics csat --scores "[4,5,3,5,2]" # 计算 CSAT 分数
529
- wjx analytics csat --scores "[5,6,4]" --scale 7-point
530
- wjx analytics anomalies --responses '[...]' # 异常答卷检测
531
- wjx analytics compare --set_a '{"score":80}' --set_b '{"score":90}'
532
- wjx analytics decode-push --payload "..." --app_key "key"
533
- ```
534
-
535
- | 子命令 | 选项 | 必填 | 类型 | 说明 |
536
- |--------|------|:----:|------|------|
537
- | **decode** | `--submitdata` | **是** | string | 提交数据字符串 |
538
- | **nps** | `--scores` | **是** | json | 评分 JSON 数组(0-10) |
539
- | **csat** | `--scores` | **是** | json | 评分 JSON 数组 |
540
- | | `--scale` | | string | 量表类型:`5-point` `7-point`(默认 5-point) |
541
- | **anomalies** | `--responses` | **是** | json | 答卷数据 JSON 数组 |
542
- | **compare** | `--set_a` | **是** | json | 指标集 A JSON 对象 |
543
- | | `--set_b` | **是** | json | 指标集 B JSON 对象 |
544
- | **decode-push** | `--payload` | **是** | string | 加密推送数据 |
545
- | | `--app_key` | **是** | string | AppKey |
546
- | | `--signature` | | string | 签名 |
547
- | | `--raw_body` | | string | 原始请求体 |
548
-
549
- ### 配置与诊断
550
-
551
- ```bash
552
- wjx init # 交互式引导配置(API Key、Base URL、Corp ID ~/.wjxrc
553
- wjx whoami # 验证 API Key 并显示账号信息
554
- wjx doctor # 环境诊断(配置文件、Node 版本、API Key、API 连接、SDK 版本)
555
- ```
556
-
557
- ### Shell 补全
558
-
559
- ```bash
560
- wjx completion bash # 输出 Bash 补全脚本
561
- wjx completion zsh # 输出 Zsh 补全脚本
562
- wjx completion fish # 输出 Fish 补全脚本
563
- wjx completion install # 自动安装到 Shell 配置文件
564
-
565
- # 手动安装示例(Bash)
566
- eval "$(wjx completion bash)"
567
- ```
568
-
569
- ### Dry-run 预览
570
-
571
- ```bash
572
- wjx survey list --dry-run --api-key your_key
573
- # 输出到 stderr:
574
- # {
575
- # "dry_run": true,
576
- # "request": {
577
- # "method": "POST",
578
- # "url": "https://www.wjx.cn/openapi/...",
579
- # "headers": { "Authorization": "Bearer your****_key" },
580
- # "body": "{...}"
581
- # }
582
- # }
583
- ```
584
-
585
- ---
586
-
587
- ## stdin 管道输入
588
-
589
- 通过 `--stdin` 标志从管道读取 JSON 参数。CLI 显式指定的选项优先于 stdin 中的同名字段(source-aware merge)。
590
-
591
- ```bash
592
- # 基本用法
593
- echo '{"vid": 12345}' | wjx --stdin survey get
594
-
595
- # 多字段
596
- echo '{"page": 1, "page_size": 20}' | wjx --stdin survey list
597
-
598
- # CLI 参数覆盖 stdin(source-aware:只有 CLI 显式指定的值才会覆盖)
599
- echo '{"vid": 12345, "state": 1}' | wjx --stdin survey status --state 2
600
- # state=2(CLI 显式指定),vid=12345(来自 stdin)
601
-
602
- # 配合 jq 链式调用
603
- wjx survey list | jq '.data[0].vid' | xargs -I{} wjx survey get --vid {}
604
-
605
- # Agent 工作流:先查问卷,再导出文本
606
- VID=$(wjx survey list | jq -r '.data.activitys | to_entries[0].value.vid')
607
- wjx survey export-text --vid "$VID" --raw
608
- ```
609
-
610
- **规则:**
611
- - stdin 必须是 JSON 对象(不能是数组或原始值)
612
- - 空 stdin 不报错,等同于不使用 `--stdin`
613
- - 非法 JSON → `INPUT_ERROR` exit 2
614
-
615
- ---
616
-
617
- ## 输出格式
618
-
619
- ### JSON(默认)
620
-
621
- 成功时输出到 stdout:
622
-
623
- ```bash
624
- $ wjx survey url --mode create
625
- {
626
- "url": "https://www.wjx.cn/..."
627
- }
628
- ```
629
-
630
- ### 表格
631
-
632
- ```bash
633
- $ wjx --table survey list
634
- ┌─────────┬───────┬──────────────┬────────┐
635
- (index)vid title status │
636
- ├─────────┼───────┼──────────────┼────────┤
637
- │ 0 │ 12345 │ '客户满意度' │ 1 │
638
- └─────────┴───────┴──────────────┴────────┘
639
- ```
640
-
641
- ### 错误
642
-
643
- 错误输出到 **stderr**(stdout 为空),详见下方 [错误协议](#错误协议)。
644
-
645
- ---
646
-
647
- ## 错误协议
648
-
649
- wjx-cli 使用结构化 JSON 错误输出,方便 AI Agent 和自动化脚本解析。
650
-
651
- ### stderr JSON Schema
652
-
653
- ```json
654
- {
655
- "error": true,
656
- "message": "错误描述(人类可读)",
657
- "code": "API_ERROR | AUTH_ERROR | INPUT_ERROR",
658
- "exitCode": 1
659
- }
660
- ```
661
-
662
- | 字段 | 类型 | 说明 |
663
- |------|------|------|
664
- | `error` | `boolean` | 恒为 `true` |
665
- | `message` | `string` | 错误描述 |
666
- | `code` | `string` | 错误分类(见下表) |
667
- | `exitCode` | `number` | 进程退出码 |
668
-
669
- ### 退出码
670
-
671
- | 退出码 | 错误码 | 含义 | 典型场景 |
672
- |:------:|--------|------|----------|
673
- | **0** | | 成功 | 命令正常完成 |
674
- | **1** | `API_ERROR` | API 错误 | 网络错误、API 返回失败 |
675
- | **1** | `AUTH_ERROR` | 认证错误 | API Key 缺失或无效 |
676
- | **2** | `INPUT_ERROR` | 输入错误 | 缺少必填参数、无效整数、JSON 解析失败 |
677
-
678
- ### 示例
679
-
680
- ```bash
681
- # 缺少 API Key exit 1, AUTH_ERROR
682
- $ wjx survey list 2>&1 >/dev/null
683
- {"error":true,"message":"WJX_API_KEY 未设置。请通过 --api-key 参数、WJX_API_KEY 环境变量、或运行 wjx init 配置。","code":"AUTH_ERROR","exitCode":1}
684
-
685
- # 缺少必填参数 exit 2, INPUT_ERROR
686
- $ wjx survey get 2>&1 >/dev/null
687
- {"error":true,"message":"Missing required option: --vid","code":"INPUT_ERROR","exitCode":2}
688
-
689
- # 无效整数 → exit 2, INPUT_ERROR
690
- $ wjx survey get --vid abc 2>&1 >/dev/null
691
- {"error":true,"message":"Invalid integer: \"abc\"","code":"INPUT_ERROR","exitCode":2}
692
- ```
693
-
694
- ### Agent 错误处理模式
695
-
696
- ```python
697
- import subprocess, json
698
-
699
- result = subprocess.run(["wjx", "survey", "get", "--vid", "12345"],
700
- capture_output=True, text=True)
701
-
702
- if result.returncode == 0:
703
- data = json.loads(result.stdout)
704
- elif result.returncode == 2:
705
- # 输入错误 — 修正参数后重试
706
- err = json.loads(result.stderr)
707
- print(f"Bad input: {err['message']}")
708
- elif result.returncode == 1:
709
- # API/认证错误 检查 API Key 或稍后重试
710
- err = json.loads(result.stderr)
711
- print(f"API error: {err['message']}")
712
- ```
713
-
714
- ---
715
-
716
- ## Agent 集成指南
717
-
718
- wjx-cli 的设计目标是成为 AI Agent 的问卷星 API 操作工具。以下是典型集成模式。
719
-
720
- ### 作为 LLM Tool 使用
721
-
722
- ```json
723
- {
724
- "type": "function",
725
- "function": {
726
- "name": "wjx_survey_list",
727
- "description": "列出问卷星中的所有问卷",
728
- "parameters": {
729
- "type": "object",
730
- "properties": {
731
- "page": { "type": "integer", "description": "页码" },
732
- "page_size": { "type": "integer", "description": "每页数量" }
733
- }
734
- }
735
- }
736
- }
737
- ```
738
-
739
- Agent 实现:
740
-
741
- ```python
742
- def execute_wjx_tool(name, args):
743
- cmd = ["wjx"] + name.replace("wjx_", "").replace("_", " ").split()
744
- for k, v in args.items():
745
- cmd.extend([f"--{k}", str(v)])
746
- result = subprocess.run(cmd, capture_output=True, text=True)
747
- return json.loads(result.stdout) if result.returncode == 0 \
748
- else json.loads(result.stderr)
749
- ```
750
-
751
- ### stdin pipe 批量操作
752
-
753
- ```bash
754
- # 批量查询多个问卷的答卷数
755
- for vid in 12345 12346 12347; do
756
- echo "{\"vid\": $vid}" | wjx --stdin response count
757
- done
758
-
759
- # 结合 jq 构造复杂参数
760
- echo '{"title":"调查","type":0,"questions":"[]"}' | wjx --stdin survey create
761
- ```
762
-
763
- ### wjx-mcp-server 的关系
764
-
765
- | 场景 | 推荐工具 |
766
- |------|----------|
767
- | Claude Desktop / Cursor 等 MCP 客户端 | `wjx-mcp-server` |
768
- | 终端 / shell 脚本 / CI/CD | `wjx-cli` |
769
- | 自定义 Agent(Python/Node/Go) | `wjx-cli`(子进程)或 `wjx-api-sdk`(直接导入) |
770
- | 需要 56 个 MCP tools + resources + prompts | `wjx-mcp-server` |
771
- | 需要简单的 JSON in / JSON out | `wjx-cli` |
772
-
773
- ---
774
-
775
- ## 环境变量
776
-
777
- | 变量 | 必填 | 说明 | 默认值 |
778
- |------|:----:|------|--------|
779
- | `WJX_API_KEY` | 是* | 问卷星 OpenAPI API Key | |
780
- | `WJX_CORP_ID` | 否 | 企业通讯录 ID(通讯录相关操作需要) | — |
781
- | `WJX_BASE_URL` | | 自定义 API 基础域名 | `https://www.wjx.cn` |
782
-
783
- \* SSO analytics 命令不需要 API Key。
784
-
785
- 以上环境变量也可以通过 `wjx init` 写入 `~/.wjxrc` 配置文件,CLI 启动时自动加载。凭据解析优先级:`--api-key` 参数 > 环境变量 > 配置文件。
786
-
787
- ---
788
-
789
- ## 开发
790
-
791
- ```bash
792
- cd wjx-ai-kit/wjx-cli
793
-
794
- npm run build # TypeScript 编译 → dist/
795
- npm test # 构建 + 运行 82 个测试
796
- npm run clean # 清理 dist/
797
-
798
- # 手动测试
799
- node dist/index.js --help
800
- node dist/index.js survey url --mode create
801
- WJX_API_KEY=xxx node dist/index.js survey list
802
- ```
803
-
804
- ### 项目结构
805
-
806
- ```
807
- src/
808
- ├── index.ts # 入口 + Commander program
809
- ├── commands/ # 13 个命令模块
810
- │ └── *.ts # 每个文件导出 register*Commands(program)
811
- └── lib/
812
- ├── config.ts # ~/.wjxrc 配置文件读写
813
- ├── command-helpers.ts # executeCommand / strictInt / requireField / dry-run
814
- ├── completions.ts # Shell 补全候选项生成
815
- ├── auth.ts # API Key 获取(--api-key > env > config)
816
- ├── output.ts # JSON / table 输出
817
- ├── errors.ts # CliError + 退出码路由
818
- └── stdin.ts # stdin 读取 + source-aware merge
819
- ```
820
-
821
- ### 添加新命令
822
-
823
- 1. 在 `wjx-api-sdk` 中确认 SDK 函数已导出
824
- 2. 创建 `src/commands/<module>.ts`,导出 `register<Module>Commands(program)`
825
- 3. `src/index.ts` 中注册
826
- 4. 在 `__tests__/cli.test.mjs` 中添加测试
827
- 5. `npm test` 验证
828
-
829
- ---
830
-
831
- ## 常见问题
832
-
833
- ### `AUTH_ERROR: WJX_API_KEY 未设置`
834
-
835
- 运行交互式配置,或手动设置环境变量:
836
-
837
- ```bash
838
- wjx init # 交互式配置(推荐)
839
- # 或
840
- export WJX_API_KEY=your_api_key # 环境变量
841
- # 或
842
- wjx --api-key your_api_key survey list # 命令行参数
843
- ```
844
-
845
- ### `INPUT_ERROR: Invalid integer: "abc"`
846
-
847
- 整数参数必须是纯数字,不接受 `123abc` `12.5` 等值。
848
-
849
- ### `INPUT_ERROR: stdin JSON must be an object`
850
-
851
- `--stdin` 只接受 JSON 对象,不接受数组或原始值:
852
-
853
- ```bash
854
- # 错误
855
- echo '[1,2,3]' | wjx --stdin survey list
856
-
857
- # 正确
858
- echo '{"page":1}' | wjx --stdin survey list
859
- ```
860
-
861
- ### API 连接问题
862
-
863
- 运行诊断:
864
-
865
- ```bash
866
- wjx doctor
867
- ```
868
-
869
- 如需指向测试环境:
870
-
871
- ```bash
872
- export WJX_BASE_URL=https://your-test-server.com
873
- ```
874
-
875
- ---
876
-
877
- ## 相关项目
878
-
879
- | 项目 | 说明 |
880
- |------|------|
881
- | [wjx-ai-kit](../) | Monorepo 根目录 |
882
- | [wjx-api-sdk](../wjx-api-sdk/) | TypeScript SDK(50+ 函数,零依赖) |
883
- | [wjx-mcp-server](../wjx-mcp-server/) | MCP Server(56 tools,供 Claude/Cursor 使用) |
884
-
885
- ---
886
-
887
- ## 许可证
888
-
889
- [MIT](LICENSE)
1
+ # wjx-cli
2
+
3
+ > 问卷星 (Wenjuanxing) CLI — AI Agent 原生命令行工具
4
+
5
+ [![license](https://img.shields.io/badge/license-MIT-blue)](LICENSE)
6
+ [![node](https://img.shields.io/badge/node-%3E%3D20-green)](https://nodejs.org/)
7
+ [![npm](https://img.shields.io/npm/v/wjx-cli)](https://www.npmjs.com/package/wjx-cli)
8
+ [![tests](https://img.shields.io/badge/tests-122%20passing-brightgreen)](__tests__/cli.test.mjs)
9
+
10
+ wjx-cli 是 [`wjx-ai-kit`](../) monorepo 的命令行入口,将 [wjx-api-sdk](../wjx-api-sdk/) 的 50+ 函数直接暴露为终端命令。设计目标:**让 AI Agent 和人类开发者都能用一行命令操作问卷星 OpenAPI**。
11
+
12
+ ---
13
+
14
+ ## 目录
15
+
16
+ - [特性](#特性)
17
+ - [**快速开始**](#快速开始)
18
+ - [安装](#安装)
19
+ - [认证](#认证)
20
+ - [架构](#架构)
21
+ - [全局选项](#全局选项)
22
+ - [命令参考](#命令参考)
23
+ - [survey — 问卷管理](#survey--问卷管理)
24
+ - [response — 答卷管理](#response--答卷管理)
25
+ - [contacts — 通讯录](#contacts--通讯录)
26
+ - [department — 部门管理](#department--部门管理)
27
+ - [admin — 管理员](#admin--管理员)
28
+ - [tag — 标签管理](#tag--标签管理)
29
+ - [user-system — 用户体系](#user-system--用户体系)
30
+ - [account — 子账号管理](#account--子账号管理)
31
+ - [sso — 单点登录](#sso--单点登录)
32
+ - [analytics — 数据分析](#analytics--数据分析)
33
+ - [配置与诊断](#配置与诊断)
34
+ - [stdin 管道输入](#stdin-管道输入)
35
+ - [输出格式](#输出格式)
36
+ - [错误协议](#错误协议)
37
+ - [Agent 集成指南](#agent-集成指南)
38
+ - [环境变量](#环境变量)
39
+ - [开发](#开发)
40
+ - [常见问题](#常见问题)
41
+ - [相关项目](#相关项目)
42
+ - [许可证](#许可证)
43
+
44
+ ---
45
+
46
+ ## 特性
47
+
48
+ - **AI Agent 原生** — 默认 JSON stdout + 结构化 JSON stderr,退出码区分错误类型,适合程序解析
49
+ - **stdin pipe** — `echo '{"vid":123}' | wjx --stdin survey get`,参数通过管道传入
50
+ - **表格输出** — `--table` 切换为人类可读的 `console.table` 格式
51
+ - **67 个子命令** — 覆盖问卷、答卷、通讯录、部门、管理员、标签、用户体系、子账号、SSO、数据分析
52
+ - **9 个本地命令** — SSO URL 生成和 analytics 计算无需 API Key,离线可用
53
+ - **Shell 补全** — `wjx completion bash/zsh/fish` 生成自动补全脚本
54
+ - **Dry-run 预览** — `--dry-run` 预览 API 请求(URL/Headers/Body)不实��发送
55
+ - **基于 wjx-api-sdk** — 直接调用 SDK 函数,类型安全,行为与 API 一致
56
+
57
+ ---
58
+
59
+ ## 快速开始
60
+
61
+ ```bash
62
+ npm install -g wjx-cli
63
+ wjx init # 交互式配置 API Key、Base URL、Corp ID
64
+ wjx doctor # 环境诊断
65
+ wjx survey list # 查看问卷列表
66
+ ```
67
+
68
+ > **新手?** 阅读 [快速开始教程](docs/getting-started.md),含 [Node.js 安装指引](docs/install-nodejs.md)。
69
+
70
+ ---
71
+
72
+ ## 前置条件
73
+
74
+ - **Node.js >= 20**([安装指引](docs/install-nodejs.md))
75
+ - **问卷星 OpenAPI API Key**([申请方式](https://www.wjx.cn/openapi/))
76
+
77
+ ---
78
+
79
+ ## 安装
80
+
81
+ ```bash
82
+ npm install -g wjx-cli
83
+ ```
84
+
85
+ ### 从源码安装(开发者)
86
+
87
+ ```bash
88
+ git clone https://codeup.aliyun.com/6445da2d020eabef3107e22e/wjxfc/wjxagents.git
89
+ cd wjxagents/wjx-ai-kit
90
+ npm install
91
+ npm run build --workspace=wjx-api-sdk
92
+ npm run build --workspace=wjx-cli
93
+ npm link --workspace=wjx-cli
94
+ ```
95
+
96
+ ---
97
+
98
+ ## 认证
99
+
100
+ 大多数命令需要问卷星 API Key(SSO 和 analytics 命令除外)。
101
+
102
+ 凭据解析优先级:`--api-key` 参数 > 环境变量 > `~/.wjxrc` 配置文件。
103
+
104
+ ```bash
105
+ # 方式 1:交互式配置(推荐,首次使用)
106
+ wjx init
107
+
108
+ # 方式 2:环境变量
109
+ export WJX_API_KEY=your_api_key
110
+
111
+ # 方式 3:命令行参数
112
+ wjx --api-key your_api_key survey list
113
+
114
+ # 方式 4:直接编辑配置文件
115
+ cat ~/.wjxrc
116
+ # {"apiKey":"your_api_key","baseUrl":"https://www.wjx.cn","corpId":"orgXXX"}
117
+ ```
118
+
119
+ ---
120
+
121
+ ## 架构
122
+
123
+ ```
124
+ wjx-ai-kit/ # monorepo root
125
+ ├── wjx-api-sdk/ # TypeScript SDK(50+ 函数,零依赖)
126
+ ├── wjx-mcp-server/ # MCP Server(56 tools,供 Claude/Cursor 使用)
127
+ └── wjx-cli/ # ← 本项目
128
+ ├── src/
129
+ │ ├── index.ts # Commander 入口 + 全局 preAction hook
130
+ │ ├── commands/ # 13 个命令模块(每模块 1 个 register 函数)
131
+ │ │ ├── init.ts # wjx init 交互式配置向导
132
+ │ │ ├── completion.ts # wjx completion bash/zsh/fish
133
+ │ │ ├── survey.ts # 14 subcommands
134
+ │ │ ├── response.ts # 10 subcommands
135
+ │ │ ├── contacts.ts # 3 subcommands
136
+ │ │ ├── department.ts # 4 subcommands
137
+ │ │ ├── admin.ts # 3 subcommands
138
+ │ │ ├── tag.ts # 4 subcommands
139
+ │ │ ├── user-system.ts # 6 subcommands
140
+ │ │ ├── account.ts # 5 subcommands
141
+ │ │ ├── sso.ts # 3 subcommands(无需 API Key)
142
+ │ │ ├── analytics.ts # 6 subcommands(本地计算,无需 API Key)
143
+ │ │ └── diagnostics.ts # 2 subcommands(whoami + doctor)
144
+ │ └── lib/
145
+ │ ├── config.ts # ~/.wjxrc 配置文件读写 + applyConfigToEnv
146
+ │ ├── command-helpers.ts # executeCommand + strictInt + requireField + dry-run
147
+ │ ├── auth.ts # API Key 获取(--api-key > env > config)
148
+ │ ├── output.ts # JSON / table 格式化
149
+ │ ├── errors.ts # CliError + exit code 路由
150
+ │ ├── stdin.ts # stdin JSON 读取 + source-aware merge
151
+ │ └── completions.ts # Shell 补全候选项生成
152
+ └── __tests__/
153
+ └── cli.test.mjs # ~122 个端到端测试
154
+ ```
155
+
156
+ **数据流:** `CLI args / stdin` → `Commander parse` → `executeCommand()` → `wjx-api-sdk function` → `stdout JSON / stderr error`
157
+
158
+ ---
159
+
160
+ ## 全局选项
161
+
162
+ | 选项 | 说明 |
163
+ |------|------|
164
+ | `--api-key <apiKey>` | WJX API Key(或设置 `WJX_API_KEY` 环境变量) |
165
+ | `--json` | JSON 输出(默认) |
166
+ | `--table` | 表格输出(`console.table` 格式) |
167
+ | `--stdin` | 从 stdin 读取 JSON 参数(见 [stdin 管道输入](#stdin-管道输入)) |
168
+ | `--dry-run` | 预览 API 请求(不实际发送,输出到 stderr) |
169
+ | `--version` | 显示版本号 |
170
+ | `--help` | 显示帮助信息 |
171
+
172
+ ---
173
+
174
+ ## 命令参考
175
+
176
+ ### survey — 问卷管理
177
+
178
+ 14 个子命令,覆盖问卷的完整生命周期。
179
+
180
+ ```bash
181
+ wjx survey list # 列出问卷
182
+ wjx survey get --vid 12345 # 获取详情
183
+ wjx survey create --title "新问卷" # 创建问卷
184
+ wjx survey create-by-text --text "..." # DSL 文本创建问卷
185
+ wjx survey status --vid 12345 --state 1 # 发布(1=发布, 2=暂停, 3=删除)
186
+ wjx survey export-text --vid 12345 # 导出为纯文本
187
+ wjx survey url --mode create # 生成创建/编辑 URL
188
+ ```
189
+
190
+ <details>
191
+ <summary>全部选项参考</summary>
192
+
193
+ | 子命令 | 选项 | 必填 | 类型 | 说明 |
194
+ |--------|------|:----:|------|------|
195
+ | **list** | `--page` | | int | 页码 |
196
+ | | `--page_size` | | int | 每页数量 |
197
+ | | `--status` | | int | 状态筛选 |
198
+ | | `--atype` | | int | 问卷类型 |
199
+ | | `--name_like` | | string | 名称模糊搜索 |
200
+ | **get** | `--vid` | **是** | int | 问卷 ID |
201
+ | **create** | `--title` | **是** | string | 问卷标题 |
202
+ | | `--type` | | int | 问卷类型(默认 0) |
203
+ | | `--description` | | string | 问卷描述 |
204
+ | | `--questions` | | json | 题目 JSON 数组 |
205
+ | | `--source_vid` | | string | 复制源问卷 ID |
206
+ | | `--publish` | | flag | 创建后立即发布 |
207
+ | **delete** | `--vid` | **是** | int | 问卷 ID |
208
+ | | `--username` | **是** | string | 用户名 |
209
+ | | `--completely` | | flag | 彻底删除(不进回收站) |
210
+ | **status** | `--vid` | **是** | int | 问卷 ID |
211
+ | | `--state` | **是** | int | 目标状态(1=发布, 2=暂停, 3=删除) |
212
+ | **settings** | `--vid` | **是** | int | 问卷 ID |
213
+ | **update-settings** | `--vid` | **是** | int | 问卷 ID |
214
+ | | `--api_setting` | | json | API 设置 |
215
+ | | `--after_submit_setting` | | json | 提交后设置 |
216
+ | | `--msg_setting` | | json | 消息设置 |
217
+ | | `--sojumpparm_setting` | | json | 参数设置 |
218
+ | | `--time_setting` | | json | 时间设置 |
219
+ | **tags** | `--username` | **是** | string | 用户名 |
220
+ | **tag-details** | `--tag_id` | **是** | int | 标签 ID |
221
+ | **clear-bin** | `--username` | **是** | string | 用户名 |
222
+ | | `--vid` | | int | 指定问卷 ID(不填则清空全部) |
223
+ | **upload** | `--file_name` | **是** | string | 文件名 |
224
+ | | `--file` | **是** | string | 文件 Base64 内容 |
225
+ | **export-text** | `--vid` | **是** | int | 问卷 ID |
226
+ | | `--raw` | | flag | 输出纯文本(不包裹 JSON) |
227
+ | **create-by-text** | `--text` | **是*** | string | DSL 文本(与 `--file` 二选一) |
228
+ | | `--file` | **是*** | string | 从文件读取 DSL 文本 |
229
+ | | `--type` | | int | 问卷类型(1=调查, 6=考试,默认 1) |
230
+ | | `--publish` | | flag | 创建后立即发布 |
231
+ | | `--creater` | | string | 创建者子账号 |
232
+ | **url** | `--mode` | | string | `create` 或 `edit`(默认 create) |
233
+ | | `--name` | | string | 问卷名称(create 模式) |
234
+ | | `--activity` | | int | 问卷 vid(edit 模式必填) |
235
+
236
+ </details>
237
+
238
+ ### response 答卷管理
239
+
240
+ 10 个子命令,管理答卷数据的查询、提交、下载和统计。
241
+
242
+ ```bash
243
+ wjx response count --vid 12345 # 获取答卷总数
244
+ wjx response query --vid 12345 # 查询答卷
245
+ wjx response realtime --vid 12345 # 实时最新答卷
246
+ wjx response download --vid 12345 # 下载答卷
247
+ wjx response submit --vid 12345 --inputcosttime 60 --submitdata "1$2"
248
+ wjx response report --vid 12345 # 统计报告
249
+ ```
250
+
251
+ <details>
252
+ <summary>全部选项参考</summary>
253
+
254
+ | 子命令 | 选项 | 必填 | 类型 | 说明 |
255
+ |--------|------|:----:|------|------|
256
+ | **count** | `--vid` | **是** | int | 问卷 ID |
257
+ | **query** | `--vid` | **是** | int | 问卷 ID |
258
+ | | `--page_index` | | int | 页码 |
259
+ | | `--page_size` | | int | 每页数量 |
260
+ | | `--sort` | | int | 排序 |
261
+ | | `--min_index` | | int | 最小序号 |
262
+ | | `--jid` | | string | 答卷 ID |
263
+ | | `--sojumpparm` | | string | 自定义参数 |
264
+ | | `--qid` | | string | 题目 ID |
265
+ | | `--begin_time` | | int | 开始时间 |
266
+ | | `--end_time` | | int | 结束时间 |
267
+ | | `--file_view_expires` | | int | 文件链接有效期 |
268
+ | | `--query_note` | | flag | 查询备注 |
269
+ | | `--distinct_user` | | flag | 去重用户 |
270
+ | | `--distinct_sojumpparm` | | flag | 去重参数 |
271
+ | | `--conds` | | string | 查询条件 |
272
+ | **realtime** | `--vid` | **是** | int | 问卷 ID |
273
+ | | `--count` | | int | 返回数量 |
274
+ | **download** | `--vid` | **是** | int | 问卷 ID |
275
+ | | `--taskid` | | string | 任务 ID |
276
+ | | `--query_count` | | int | 查询数量 |
277
+ | | `--begin_time` | | int | 开始时间 |
278
+ | | `--end_time` | | int | 结束时间 |
279
+ | | `--min_index` | | int | 最小序号 |
280
+ | | `--qid` | | string | 题目 ID |
281
+ | | `--sort` | | int | 排序 |
282
+ | | `--query_type` | | int | 查询类型 |
283
+ | | `--suffix` | | int | 文件后缀 |
284
+ | | `--query_record` | | flag | 查询记录 |
285
+ | **submit** | `--vid` | **是** | int | 问卷 ID |
286
+ | | `--inputcosttime` | **是** | int | 填写耗时(秒) |
287
+ | | `--submitdata` | **是** | string | 提交数据 |
288
+ | | `--udsid` | | int | 用户系统 ID |
289
+ | | `--sojumpparm` | | string | 自定义参数 |
290
+ | | `--submittime` | | string | 提交时间 |
291
+ | **modify** | `--vid` | **是** | int | 问卷 ID |
292
+ | | `--jid` | **是** | int | 答卷 ID |
293
+ | | `--answers` | **是** | string | 答案数据 |
294
+ | **clear** | `--username` | **是** | string | 用户名 |
295
+ | | `--vid` | **是** | int | 问卷 ID |
296
+ | | `--reset_to_zero` | | flag | 重置序号 |
297
+ | **report** | `--vid` | **是** | int | 问卷 ID |
298
+ | | `--min_index` | | int | 最小序号 |
299
+ | | `--jid` | | string | 答卷 ID |
300
+ | | `--sojumpparm` | | string | 自定义参数 |
301
+ | | `--begin_time` | | int | 开始时间 |
302
+ | | `--end_time` | | int | 结束时间 |
303
+ | | `--distinct_user` | | flag | 去重用户 |
304
+ | | `--distinct_sojumpparm` | | flag | 去重参数 |
305
+ | | `--conds` | | string | 查询条件 |
306
+ | **winners** | `--vid` | **是** | int | 问卷 ID |
307
+ | | `--atype` | | int | 活动类型 |
308
+ | | `--awardstatus` | | int | 领奖状态 |
309
+ | | `--page_index` | | int | 页码 |
310
+ | | `--page_size` | | int | 每页数量 |
311
+ | **360-report** | `--vid` | **是** | int | 问卷 ID |
312
+ | | `--taskid` | | string | 任务 ID |
313
+
314
+ </details>
315
+
316
+ ### contacts 通讯录
317
+
318
+ ```bash
319
+ wjx contacts query --uid user1 # 查询联系人
320
+ wjx contacts add --users '[{"name":"张三"}]' # 添加联系人
321
+ wjx contacts delete --uids "uid1,uid2" # 删除联系人
322
+ ```
323
+
324
+ | 子命令 | 选项 | 必填 | 类型 | 说明 |
325
+ |--------|------|:----:|------|------|
326
+ | **query** | `--uid` | **是** | string | 用户 ID |
327
+ | | `--corpid` | | string | 企业 ID |
328
+ | **add** | `--users` | **是** | json | 用户 JSON 数组 |
329
+ | | `--corpid` | | string | 企业 ID |
330
+ | | `--auto_create_udept` | | flag | 自动创建部门 |
331
+ | | `--auto_create_tag` | | flag | 自动创建标签 |
332
+ | **delete** | `--uids` | **是** | string | 用户 ID 列表(逗号分隔) |
333
+ | | `--corpid` | | string | 企业 ID |
334
+
335
+ ### department 部门管理
336
+
337
+ ```bash
338
+ wjx department list # 列出部门
339
+ wjx department add --depts '[{"name":"研发"}]'
340
+ wjx department modify --depts '[{"id":1,"name":"技术"}]'
341
+ wjx department delete --depts '[{"id":1}]' --type 1
342
+ ```
343
+
344
+ | 子命令 | 选项 | 必填 | 类型 | 说明 |
345
+ |--------|------|:----:|------|------|
346
+ | **list** | `--corpid` | | string | 企业 ID |
347
+ | **add** | `--depts` | **是** | json | 部门路径 JSON 数组 |
348
+ | | `--corpid` | | string | 企业 ID |
349
+ | **modify** | `--depts` | **是** | json | 部门对象 JSON 数组 |
350
+ | | `--corpid` | | string | 企业 ID |
351
+ | **delete** | `--type` | **是** | string | 类型(1=按ID, 2=按名称) |
352
+ | | `--depts` | **是** | json | 部门标识 JSON 数组 |
353
+ | | `--corpid` | | string | 企业 ID |
354
+ | | `--del_child` | | flag | 同时删除子部门 |
355
+
356
+ ### admin 管理员
357
+
358
+ ```bash
359
+ wjx admin add --users '[{"uid":"u1","role":1}]'
360
+ wjx admin delete --uids "uid1,uid2"
361
+ wjx admin restore --uids "uid1"
362
+ ```
363
+
364
+ | 子命令 | 选项 | 必填 | 类型 | 说明 |
365
+ |--------|------|:----:|------|------|
366
+ | **add** | `--users` | **是** | json | 管理员 JSON 数组 |
367
+ | | `--corpid` | | string | 企业 ID |
368
+ | **delete** | `--uids` | **是** | string | 用户 ID 列表(逗号分隔) |
369
+ | | `--corpid` | | string | 企业 ID |
370
+ | **restore** | `--uids` | **是** | string | 用户 ID 列表(逗号分隔) |
371
+ | | `--corpid` | | string | 企业 ID |
372
+
373
+ ### tag 标签管理
374
+
375
+ ```bash
376
+ wjx tag list # 列出标签
377
+ wjx tag add --child_names '["VIP","普通"]'
378
+ wjx tag modify --tp_id 1 --child_names '["新VIP"]'
379
+ wjx tag delete --tags '[{"id":1}]' --type 1
380
+ ```
381
+
382
+ | 子命令 | 选项 | 必填 | 类型 | 说明 |
383
+ |--------|------|:----:|------|------|
384
+ | **list** | `--corpid` | | string | 企业 ID |
385
+ | **add** | `--child_names` | **是** | json | 标签路径 JSON 数组 |
386
+ | | `--corpid` | | string | 企业 ID |
387
+ | | `--is_radio` | | flag | 单选标签 |
388
+ | **modify** | `--tp_id` | **是** | string | 标签组 ID |
389
+ | | `--tp_name` | | string | 标签组名称 |
390
+ | | `--child_names` | | json | 标签对象 JSON 数组 |
391
+ | | `--corpid` | | string | 企业 ID |
392
+ | **delete** | `--type` | **是** | string | 类型(1=按ID, 2=按名称) |
393
+ | | `--tags` | **是** | json | 标签标识 JSON 数组 |
394
+ | | `--corpid` | | string | 企业 ID |
395
+
396
+ ### user-system — 用户体系
397
+
398
+ 6 个子命令,管理用户系统中的参与者和问卷绑定。
399
+
400
+ ```bash
401
+ wjx user-system add-participants --sysid 1 --users '[...]'
402
+ wjx user-system bind --sysid 1 --uids "a" --vid 12345
403
+ wjx user-system query-binding --sysid 1 --vid 12345
404
+ wjx user-system query-surveys --sysid 1 --uid "a"
405
+ ```
406
+
407
+ <details>
408
+ <summary>全部选项参考</summary>
409
+
410
+ | 子命令 | 选项 | 必填 | 类型 | 说明 |
411
+ |--------|------|:----:|------|------|
412
+ | **add-participants** | `--users` | **是** | json | 参与者 JSON |
413
+ | | `--sysid` | **是** | int | 系统 ID |
414
+ | **modify-participants** | `--users` | **是** | json | 参与者 JSON |
415
+ | | `--sysid` | **是** | int | 系统 ID |
416
+ | **delete-participants** | `--uids` | **是** | json | 用户 ID JSON 数组 |
417
+ | | `--sysid` | **是** | int | 系统 ID |
418
+ | **bind** | `--vid` | **是** | int | 问卷 ID |
419
+ | | `--sysid` | **是** | int | 系统 ID |
420
+ | | `--uids` | **是** | string | 参与者 ID 列表 |
421
+ | | `--answer_times` | | int | 可答次数 |
422
+ | | `--can_chg_answer` | | flag | 允许修改答案 |
423
+ | | `--can_view_result` | | flag | 允许查看结果 |
424
+ | | `--can_hide_qlist` | | int | 隐藏问卷列表 |
425
+ | **query-binding** | `--vid` | **是** | int | 问卷 ID |
426
+ | | `--sysid` | **是** | int | 系统 ID |
427
+ | | `--page_index` | | int | 页码 |
428
+ | | `--page_size` | | int | 每页数量 |
429
+ | | `--join_status` | | int | 参与状态 |
430
+ | | `--day` | | string | 按天筛选 |
431
+ | | `--week` | | string | 按周筛选 |
432
+ | | `--month` | | string | 按月筛选 |
433
+ | | `--force_join_times` | | flag | 强制参与次数 |
434
+ | **query-surveys** | `--uid` | **是** | string | 参与者 ID |
435
+ | | `--sysid` | **是** | int | 系统 ID |
436
+ | | `--page_index` | | int | 页码 |
437
+ | | `--page_size` | | int | 每页数量 |
438
+
439
+ </details>
440
+
441
+ ### account — 子账号管理
442
+
443
+ ```bash
444
+ wjx account list # 查询子账号
445
+ wjx account add --subuser test1 --password pass123
446
+ wjx account modify --subuser test1 --email new@test.com
447
+ wjx account delete --subuser test1
448
+ wjx account restore --subuser test1
449
+ ```
450
+
451
+ <details>
452
+ <summary>全部选项参考</summary>
453
+
454
+ | 子命令 | 选项 | 必填 | 类型 | 说明 |
455
+ |--------|------|:----:|------|------|
456
+ | **list** | `--subuser` | | string | 子账号用户名 |
457
+ | | `--name_like` | | string | 名称模糊搜索 |
458
+ | | `--role` | | int | 角色 |
459
+ | | `--group` | | int | 分组 |
460
+ | | `--page_index` | | int | 页码 |
461
+ | | `--page_size` | | int | 每页数量 |
462
+ | | `--mobile` | | string | 手机号 |
463
+ | **add** | `--subuser` | **是** | string | 子账号用户名 |
464
+ | | `--password` | | string | 密码 |
465
+ | | `--mobile` | | string | 手机号 |
466
+ | | `--email` | | string | 邮箱 |
467
+ | | `--role` | | int | 角色 |
468
+ | | `--group` | | int | 分组 |
469
+ | **modify** | `--subuser` | **是** | string | 子账号用户名 |
470
+ | | `--mobile` | | string | 手机号 |
471
+ | | `--email` | | string | 邮箱 |
472
+ | | `--role` | | int | 角色 |
473
+ | | `--group` | | int | 分组 |
474
+ | **delete** | `--subuser` | **是** | string | 子账号用户名 |
475
+ | **restore** | `--subuser` | **是** | string | 子账号用户名 |
476
+ | | `--mobile` | | string | 手机号 |
477
+ | | `--email` | | string | 邮箱 |
478
+
479
+ </details>
480
+
481
+ ### sso — 单点登录
482
+
483
+ > **无需 API Key** — SSO 命令在本地生成 URL,不调用 API。
484
+
485
+ ```bash
486
+ wjx sso subaccount-url --subuser test1 # 子账号 SSO 链接
487
+ wjx sso user-system-url --u admin --system_id 1 --uid user1
488
+ wjx sso partner-url --username partner1 # 代理商 SSO 链接
489
+ ```
490
+
491
+ <details>
492
+ <summary>全部选项参考</summary>
493
+
494
+ | 子命令 | 选项 | 必填 | 类型 | 说明 |
495
+ |--------|------|:----:|------|------|
496
+ | **subaccount-url** | `--subuser` | **是** | string | 子账号用户名 |
497
+ | | `--mobile` | | string | 手机号 |
498
+ | | `--email` | | string | 邮箱 |
499
+ | | `--role_id` | | int | 角色 ID |
500
+ | | `--url` | | string | 登录后跳转 URL |
501
+ | | `--admin` | | int | 主账号登录(1) |
502
+ | **user-system-url** | `--u` | **是** | string | 账号用户名 |
503
+ | | `--system_id` | **是** | int | 用户系统 ID |
504
+ | | `--uid` | **是** | string | 参与者 ID |
505
+ | | `--uname` | | string | 参与者名称 |
506
+ | | `--udept` | | string | 参与者部门 |
507
+ | | `--uextf` | | string | 扩展字段 |
508
+ | | `--upass` | | string | 密码 |
509
+ | | `--is_login` | | int | 是否登录(0/1) |
510
+ | | `--activity` | | int | 跳转问卷 vid |
511
+ | | `--return_url` | | string | 返回 URL |
512
+ | **partner-url** | `--username` | **是** | string | 代理商用户名 |
513
+ | | `--mobile` | | string | 手机号 |
514
+ | | `--subuser` | | string | 子账号用户名 |
515
+
516
+ </details>
517
+
518
+ ### analytics — 数据分析
519
+
520
+ > **无需 API Key** — analytics 命令在本地执行计算,不调用 API。
521
+
522
+ ```bash
523
+ wjx analytics decode --submitdata "1$2}2$hello" # 解码答卷提交数据
524
+ wjx analytics nps --scores "[9,10,7,3,8,10,9]" # 计算 NPS 分数
525
+ wjx analytics csat --scores "[4,5,3,5,2]" # 计算 CSAT 分数
526
+ wjx analytics csat --scores "[5,6,4]" --scale 7-point
527
+ wjx analytics anomalies --responses '[...]' # 异常答卷检测
528
+ wjx analytics compare --set_a '{"score":80}' --set_b '{"score":90}'
529
+ wjx analytics decode-push --payload "..." --app_key "key"
530
+ ```
531
+
532
+ | 子命令 | 选项 | 必填 | 类型 | 说明 |
533
+ |--------|------|:----:|------|------|
534
+ | **decode** | `--submitdata` | **是** | string | 提交数据字符串 |
535
+ | **nps** | `--scores` | **是** | json | 评分 JSON 数组(0-10) |
536
+ | **csat** | `--scores` | **是** | json | 评分 JSON 数组 |
537
+ | | `--scale` | | string | 量表类型:`5-point` 或 `7-point`(默认 5-point) |
538
+ | **anomalies** | `--responses` | **是** | json | 答卷数据 JSON 数组 |
539
+ | **compare** | `--set_a` | **是** | json | 指标集 A JSON 对象 |
540
+ | | `--set_b` | **是** | json | 指标集 B JSON 对象 |
541
+ | **decode-push** | `--payload` | **是** | string | 加密推送数据 |
542
+ | | `--app_key` | **是** | string | AppKey |
543
+ | | `--signature` | | string | 签名 |
544
+ | | `--raw_body` | | string | 原始请求体 |
545
+
546
+ ### 配置与诊断
547
+
548
+ ```bash
549
+ wjx init # 交互式引导配置(API Key、Base URL、Corp ID → ~/.wjxrc)
550
+ wjx whoami # 验证 API Key 并显示账号信息
551
+ wjx doctor # 环境诊断(配置文件、Node 版本、API Key、API 连接、SDK 版本)
552
+ wjx reference # 输出命令参考文档(dsl / question-types / survey / response / analytics
553
+ ```
554
+
555
+ ### Shell 补全
556
+
557
+ ```bash
558
+ wjx completion bash # 输出 Bash 补全脚本
559
+ wjx completion zsh # 输出 Zsh 补全脚本
560
+ wjx completion fish # 输出 Fish 补全脚本
561
+ wjx completion install # 自动安装到 Shell 配置文件
562
+
563
+ # 手动安装示例(Bash)
564
+ eval "$(wjx completion bash)"
565
+ ```
566
+
567
+ ### Dry-run 预览
568
+
569
+ ```bash
570
+ wjx survey list --dry-run --api-key your_key
571
+ # 输出到 stderr:
572
+ # {
573
+ # "dry_run": true,
574
+ # "request": {
575
+ # "method": "POST",
576
+ # "url": "https://www.wjx.cn/openapi/...",
577
+ # "headers": { "Authorization": "Bearer your****_key" },
578
+ # "body": "{...}"
579
+ # }
580
+ # }
581
+ ```
582
+
583
+ ---
584
+
585
+ ## stdin 管道输入
586
+
587
+ 通过 `--stdin` 标志从管道读取 JSON 参数。CLI 显式指定的选项优先于 stdin 中的同名字段(source-aware merge)。
588
+
589
+ ```bash
590
+ # 基本用法
591
+ echo '{"vid": 12345}' | wjx --stdin survey get
592
+
593
+ # 多字段
594
+ echo '{"page": 1, "page_size": 20}' | wjx --stdin survey list
595
+
596
+ # CLI 参数覆盖 stdin(source-aware:只有 CLI 显式指定的值才会覆盖)
597
+ echo '{"vid": 12345, "state": 1}' | wjx --stdin survey status --state 2
598
+ # → state=2(CLI 显式指定),vid=12345(来自 stdin
599
+
600
+ # 配合 jq 链式调用
601
+ wjx survey list | jq '.data[0].vid' | xargs -I{} wjx survey get --vid {}
602
+
603
+ # Agent 工作流:先查问卷,再导出文本
604
+ VID=$(wjx survey list | jq -r '.data.activitys | to_entries[0].value.vid')
605
+ wjx survey export-text --vid "$VID" --raw
606
+ ```
607
+
608
+ **规则:**
609
+ - stdin 必须是 JSON 对象(不能是数组或原始值)
610
+ - 空 stdin 不报错,等同于不使用 `--stdin`
611
+ - 非法 JSON → `INPUT_ERROR` exit 2
612
+
613
+ ---
614
+
615
+ ## 输出格式
616
+
617
+ ### JSON(默认)
618
+
619
+ 成功时输出到 stdout:
620
+
621
+ ```bash
622
+ $ wjx survey url --mode create
623
+ {
624
+ "url": "https://www.wjx.cn/..."
625
+ }
626
+ ```
627
+
628
+ ### 表格
629
+
630
+ ```bash
631
+ $ wjx --table survey list
632
+ ┌─────────┬───────┬──────────────┬────────┐
633
+ (index) │ vid │ title │ status
634
+ ├─────────┼───────┼──────────────┼────────┤
635
+ 0 │ 12345 '客户满意度' 1
636
+ └─────────┴───────┴──────────────┴────────┘
637
+ ```
638
+
639
+ ### 错误
640
+
641
+ 错误输出到 **stderr**(stdout 为空),详见下方 [错误协议](#错误协议)。
642
+
643
+ ---
644
+
645
+ ## 错误协议
646
+
647
+ wjx-cli 使用结构化 JSON 错误输出,方便 AI Agent 和自动化脚本解析。
648
+
649
+ ### stderr JSON Schema
650
+
651
+ ```json
652
+ {
653
+ "error": true,
654
+ "message": "错误描述(人类可读)",
655
+ "code": "API_ERROR | AUTH_ERROR | INPUT_ERROR",
656
+ "exitCode": 1
657
+ }
658
+ ```
659
+
660
+ | 字段 | 类型 | 说明 |
661
+ |------|------|------|
662
+ | `error` | `boolean` | 恒为 `true` |
663
+ | `message` | `string` | 错误描述 |
664
+ | `code` | `string` | 错误分类(见下表) |
665
+ | `exitCode` | `number` | 进程退出码 |
666
+
667
+ ### 退出码
668
+
669
+ | 退出码 | 错误码 | 含义 | 典型场景 |
670
+ |:------:|--------|------|----------|
671
+ | **0** | | 成功 | 命令正常完成 |
672
+ | **1** | `API_ERROR` | API 错误 | 网络错误、API 返回失败 |
673
+ | **1** | `AUTH_ERROR` | 认证错误 | API Key 缺失或无效 |
674
+ | **2** | `INPUT_ERROR` | 输入错误 | 缺少必填参数、无效整数、JSON 解析失败 |
675
+
676
+ ### 示例
677
+
678
+ ```bash
679
+ # 缺少 API Key → exit 1, AUTH_ERROR
680
+ $ wjx survey list 2>&1 >/dev/null
681
+ {"error":true,"message":"WJX_API_KEY 未设置。请通过 --api-key 参数、WJX_API_KEY 环境变量、或运行 wjx init 配置。","code":"AUTH_ERROR","exitCode":1}
682
+
683
+ # 缺少必填参数 exit 2, INPUT_ERROR
684
+ $ wjx survey get 2>&1 >/dev/null
685
+ {"error":true,"message":"Missing required option: --vid","code":"INPUT_ERROR","exitCode":2}
686
+
687
+ # 无效整数 exit 2, INPUT_ERROR
688
+ $ wjx survey get --vid abc 2>&1 >/dev/null
689
+ {"error":true,"message":"Invalid integer: \"abc\"","code":"INPUT_ERROR","exitCode":2}
690
+ ```
691
+
692
+ ### Agent 错误处理模式
693
+
694
+ ```python
695
+ import subprocess, json
696
+
697
+ result = subprocess.run(["wjx", "survey", "get", "--vid", "12345"],
698
+ capture_output=True, text=True)
699
+
700
+ if result.returncode == 0:
701
+ data = json.loads(result.stdout)
702
+ elif result.returncode == 2:
703
+ # 输入错误 — 修正参数后重试
704
+ err = json.loads(result.stderr)
705
+ print(f"Bad input: {err['message']}")
706
+ elif result.returncode == 1:
707
+ # API/认证错误 — 检查 API Key 或稍后重试
708
+ err = json.loads(result.stderr)
709
+ print(f"API error: {err['message']}")
710
+ ```
711
+
712
+ ---
713
+
714
+ ## Agent 集成指南
715
+
716
+ wjx-cli 的设计目标是成为 AI Agent 的问卷星 API 操作工具。以下是典型集成模式。
717
+
718
+ ### 作为 LLM Tool 使用
719
+
720
+ ```json
721
+ {
722
+ "type": "function",
723
+ "function": {
724
+ "name": "wjx_survey_list",
725
+ "description": "列出问卷星中的所有问卷",
726
+ "parameters": {
727
+ "type": "object",
728
+ "properties": {
729
+ "page": { "type": "integer", "description": "页码" },
730
+ "page_size": { "type": "integer", "description": "每页数量" }
731
+ }
732
+ }
733
+ }
734
+ }
735
+ ```
736
+
737
+ Agent 实现:
738
+
739
+ ```python
740
+ def execute_wjx_tool(name, args):
741
+ cmd = ["wjx"] + name.replace("wjx_", "").replace("_", " ").split()
742
+ for k, v in args.items():
743
+ cmd.extend([f"--{k}", str(v)])
744
+ result = subprocess.run(cmd, capture_output=True, text=True)
745
+ return json.loads(result.stdout) if result.returncode == 0 \
746
+ else json.loads(result.stderr)
747
+ ```
748
+
749
+ ### stdin pipe 批量操作
750
+
751
+ ```bash
752
+ # 批量查询多个问卷的答卷数
753
+ for vid in 12345 12346 12347; do
754
+ echo "{\"vid\": $vid}" | wjx --stdin response count
755
+ done
756
+
757
+ # 结合 jq 构造复杂参数
758
+ echo '{"title":"调查","type":0,"questions":"[]"}' | wjx --stdin survey create
759
+ ```
760
+
761
+ ### 与 wjx-mcp-server 的关系
762
+
763
+ | 场景 | 推荐工具 |
764
+ |------|----------|
765
+ | Claude Desktop / Cursor 等 MCP 客户端 | `wjx-mcp-server` |
766
+ | 终端 / shell 脚本 / CI/CD | `wjx-cli` |
767
+ | 自定义 Agent(Python/Node/Go) | `wjx-cli`(子进程)或 `wjx-api-sdk`(直接导入) |
768
+ | 需要 56 MCP tools + resources + prompts | `wjx-mcp-server` |
769
+ | 需要简单的 JSON in / JSON out | `wjx-cli` |
770
+
771
+ ---
772
+
773
+ ## 环境变量
774
+
775
+ | 变量 | 必填 | 说明 | 默认值 |
776
+ |------|:----:|------|--------|
777
+ | `WJX_API_KEY` | 是* | 问卷星 OpenAPI API Key | |
778
+ | `WJX_CORP_ID` | 否 | 企业通讯录 ID(通讯录相关操作需要) | — |
779
+ | `WJX_BASE_URL` | | 自定义 API 基础域名 | `https://www.wjx.cn` |
780
+
781
+ \* SSO analytics 命令不需要 API Key。
782
+
783
+ 以上环境变量也可以通过 `wjx init` 写入 `~/.wjxrc` 配置文件,CLI 启动时自动加载。凭据解析优先级:`--api-key` 参数 > 环境变量 > 配置文件。
784
+
785
+ ---
786
+
787
+ ## 开发
788
+
789
+ ```bash
790
+ cd wjx-ai-kit/wjx-cli
791
+
792
+ npm run build # TypeScript 编译 → dist/
793
+ npm test # 构建 + 运行 ~122 个测试
794
+ npm run clean # 清理 dist/
795
+
796
+ # 手动测试
797
+ node dist/index.js --help
798
+ node dist/index.js survey url --mode create
799
+ WJX_API_KEY=xxx node dist/index.js survey list
800
+ ```
801
+
802
+ ### 项目结构
803
+
804
+ ```
805
+ src/
806
+ ├── index.ts # 入口 + Commander program
807
+ ├── commands/ # 13 个命令模块
808
+ │ └── *.ts # 每个文件导出 register*Commands(program)
809
+ └── lib/
810
+ ├── config.ts # ~/.wjxrc 配置文件读写
811
+ ├── command-helpers.ts # executeCommand / strictInt / requireField / dry-run
812
+ ├── completions.ts # Shell 补全候选项生成
813
+ ├── auth.ts # API Key 获取(--api-key > env > config)
814
+ ├── output.ts # JSON / table 输出
815
+ ├── errors.ts # CliError + 退出码路由
816
+ └── stdin.ts # stdin 读取 + source-aware merge
817
+ ```
818
+
819
+ ### 添加新命令
820
+
821
+ 1. 在 `wjx-api-sdk` 中确认 SDK 函数已导出
822
+ 2. 创建 `src/commands/<module>.ts`,导出 `register<Module>Commands(program)`
823
+ 3. 在 `src/index.ts` 中注册
824
+ 4. `__tests__/cli.test.mjs` 中添加测试
825
+ 5. `npm test` 验证
826
+
827
+ ---
828
+
829
+ ## 常见问题
830
+
831
+ ### `AUTH_ERROR: WJX_API_KEY 未设置`
832
+
833
+ 运行交互式配置,或手动设置环境变量:
834
+
835
+ ```bash
836
+ wjx init # 交互式配置(推荐)
837
+ # 或
838
+ export WJX_API_KEY=your_api_key # 环境变量
839
+ # 或
840
+ wjx --api-key your_api_key survey list # 命令行参数
841
+ ```
842
+
843
+ ### `INPUT_ERROR: Invalid integer: "abc"`
844
+
845
+ 整数参数必须是纯数字,不接受 `123abc` `12.5` 等值。
846
+
847
+ ### `INPUT_ERROR: stdin JSON must be an object`
848
+
849
+ `--stdin` 只接受 JSON 对象,不接受数组或原始值:
850
+
851
+ ```bash
852
+ # 错误
853
+ echo '[1,2,3]' | wjx --stdin survey list
854
+
855
+ # 正确
856
+ echo '{"page":1}' | wjx --stdin survey list
857
+ ```
858
+
859
+ ### API 连接问题
860
+
861
+ 运行诊断:
862
+
863
+ ```bash
864
+ wjx doctor
865
+ ```
866
+
867
+ 如需指向测试环境:
868
+
869
+ ```bash
870
+ export WJX_BASE_URL=https://your-test-server.com
871
+ ```
872
+
873
+ ---
874
+
875
+ ## 相关项目
876
+
877
+ | 项目 | 说明 |
878
+ |------|------|
879
+ | [wjx-ai-kit](../) | Monorepo 根目录 |
880
+ | [wjx-api-sdk](../wjx-api-sdk/) | TypeScript SDK(50+ 函数,零依赖) |
881
+ | [wjx-mcp-server](../wjx-mcp-server/) | MCP Server(56 tools,供 Claude/Cursor 使用) |
882
+
883
+ ---
884
+
885
+ ## 许可证
886
+
887
+ [MIT](LICENSE)