wjw-cli 0.1.0

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 (68) hide show
  1. package/README.md +29 -0
  2. package/dist/api/normalize.d.ts +14 -0
  3. package/dist/api/normalize.d.ts.map +1 -0
  4. package/dist/api/normalize.js +282 -0
  5. package/dist/api/normalize.js.map +1 -0
  6. package/dist/api/project-detail.d.ts +7 -0
  7. package/dist/api/project-detail.d.ts.map +1 -0
  8. package/dist/api/project-detail.js +200 -0
  9. package/dist/api/project-detail.js.map +1 -0
  10. package/dist/api/structure-narrow.d.ts +21 -0
  11. package/dist/api/structure-narrow.d.ts.map +1 -0
  12. package/dist/api/structure-narrow.js +259 -0
  13. package/dist/api/structure-narrow.js.map +1 -0
  14. package/dist/api/survey-api.d.ts +48 -0
  15. package/dist/api/survey-api.d.ts.map +1 -0
  16. package/dist/api/survey-api.js +551 -0
  17. package/dist/api/survey-api.js.map +1 -0
  18. package/dist/argv.d.ts +9 -0
  19. package/dist/argv.d.ts.map +1 -0
  20. package/dist/argv.js +62 -0
  21. package/dist/argv.js.map +1 -0
  22. package/dist/cli.d.ts +3 -0
  23. package/dist/cli.d.ts.map +1 -0
  24. package/dist/cli.js +7 -0
  25. package/dist/cli.js.map +1 -0
  26. package/dist/commands/main.d.ts +2 -0
  27. package/dist/commands/main.d.ts.map +1 -0
  28. package/dist/commands/main.js +568 -0
  29. package/dist/commands/main.js.map +1 -0
  30. package/dist/config.d.ts +23 -0
  31. package/dist/config.d.ts.map +1 -0
  32. package/dist/config.js +37 -0
  33. package/dist/config.js.map +1 -0
  34. package/dist/credentials-store.d.ts +9 -0
  35. package/dist/credentials-store.d.ts.map +1 -0
  36. package/dist/credentials-store.js +38 -0
  37. package/dist/credentials-store.js.map +1 -0
  38. package/dist/handbook.d.ts +3 -0
  39. package/dist/handbook.d.ts.map +1 -0
  40. package/dist/handbook.js +43 -0
  41. package/dist/handbook.js.map +1 -0
  42. package/dist/http/request.d.ts +15 -0
  43. package/dist/http/request.d.ts.map +1 -0
  44. package/dist/http/request.js +65 -0
  45. package/dist/http/request.js.map +1 -0
  46. package/dist/index.d.ts +8 -0
  47. package/dist/index.d.ts.map +1 -0
  48. package/dist/index.js +7 -0
  49. package/dist/index.js.map +1 -0
  50. package/dist/io/readInput.d.ts +7 -0
  51. package/dist/io/readInput.d.ts.map +1 -0
  52. package/dist/io/readInput.js +39 -0
  53. package/dist/io/readInput.js.map +1 -0
  54. package/dist/sign.d.ts +6 -0
  55. package/dist/sign.d.ts.map +1 -0
  56. package/dist/sign.js +46 -0
  57. package/dist/sign.js.map +1 -0
  58. package/dist/token.d.ts +4 -0
  59. package/dist/token.d.ts.map +1 -0
  60. package/dist/token.js +65 -0
  61. package/dist/token.js.map +1 -0
  62. package/dist/version.d.ts +2 -0
  63. package/dist/version.d.ts.map +1 -0
  64. package/dist/version.js +2 -0
  65. package/dist/version.js.map +1 -0
  66. package/package.json +40 -0
  67. package/references/README.md +4 -0
  68. package/references/project_json_structure_guide.md +910 -0
@@ -0,0 +1,910 @@
1
+ # 问卷网项目 JSON 结构生成指南
2
+
3
+ > 本文档用于指导 AI 生成符合问卷网 API 要求的 `project_json` 数据结构
4
+
5
+ ---
6
+ ## 说明(wjw-cli 精简版)
7
+
8
+ 本文件从完整《问卷网项目 JSON 结构生成指南》中**仅保留与「每道题目 / 各题型」相关的章节**:题目通用字段、各 `en_name` 题型规则、预设信息题、考试测评题、题型速查、`option_list` 全局规则及线上下落对照。
9
+
10
+ **项目级字段**(`title`、`type_id`、`p_type`、`welcome`、`survey_result` 等)与**完整问卷示例**请用 `wjw project create` 时由 CLI 组装或参考原 wenjuan-survey 仓库完整版文档。
11
+
12
+ 正文内原「见第十二节」等指代仍对应下文 **「线上下落 question_type 与 option_list 对照」** 一节。
13
+
14
+ ---
15
+
16
+ ## 三、题目通用结构
17
+
18
+ 每道题必须包含以下字段:
19
+
20
+ ```json
21
+ {
22
+ "title": "题目文本",
23
+ "en_name": "QUESTION_TYPE_XXX",
24
+ "custom_attr": {},
25
+ "option_list": [
26
+ {"title": "占位选项", "is_open": false, "custom_attr": {}}
27
+ ]
28
+ }
29
+ ```
30
+
31
+ | 字段 | 类型 | 必填 | 说明 |
32
+ |------|------|------|------|
33
+ | `title` | string | ✅ | 题目内容 |
34
+ | `en_name` | string | ✅ | 题型标识(见题型对照表) |
35
+ | `custom_attr` | object | ✅ | 自定义属性(可为空对象 `{}`) |
36
+ | `option_list` | array | ✅ | **非空**选项列表(**禁止** `[]`);条数下限见第四节、第五章、第十一节、第十二节;**矩阵类题型**另有 **`matrixrow_list`**(见 §6 / §7) |
37
+
38
+ ### 选项结构 (option_list 元素)
39
+
40
+ ```json
41
+ {
42
+ "title": "选项文本",
43
+ "is_open": false,
44
+ "custom_attr": {}
45
+ }
46
+ ```
47
+
48
+ | 字段 | 类型 | 必填 | 说明 |
49
+ |------|------|------|------|
50
+ | `title` | string | ✅ | 选项内容 |
51
+ | `is_open` | boolean | 否 | 是否允许填空(默认 false) |
52
+ | `custom_attr` | object | 否 | 选项自定义属性 |
53
+
54
+ ---
55
+ ## 四、题型对照表及生成规则
56
+
57
+ > **参考样例项目(线上下落)**:以下「`edit_project` 返回」字段来自问卷网编辑接口实测,用于与本地导入 JSON 的 **`option_list` 非空结构** 对照。
58
+ > - 普通问卷:`project_id` **`69d257be4d1e8d523899937b`**(`survey`,14 题)
59
+ > - 考试测评:`project_id` **`69d2570bef3af30a3376fd24`**(`assess`,15 题)
60
+ > - **矩阵评价(矩阵单选 + `matrixrow_list`)**:`project_id` **`69e4d0a6ef3af30a18db16c3`** — 请在本机登录后执行 `fetch_project` 拉取该题完整字段(行/列与 `question_type`)
61
+ > 汇总表见 **第十二节**。
62
+
63
+ ### 1. 单选题 (QUESTION_TYPE_SINGLE)
64
+
65
+ **适用场景**:单选、下拉单选、判断题
66
+
67
+ **规则**:
68
+ - 必须有 2 个及以上选项
69
+ - 选项存于 `option_list`
70
+
71
+ **变体设置**:
72
+ - 下拉单选:`custom_attr.disp_type = "dropdown"`
73
+ - **判断题**:`custom_attr.disp_type = "judge"`。**须** `option_list` **2 条**(如「是」「否」);**线上下落**为单选题 `question_type: 2`;测评需在选项上标 **`is_correct` / `score`**(与项目 `69d2570b…` 一致)。
74
+
75
+ **线上下落(判断题,测评)**:`question_type: 2`,`custom_attr.disp_type: "judge"`,`option_list` 长度 **2**;正确项 `custom_attr.is_correct: "1"` 与分值,错误项可 `score: 0`。
76
+
77
+ **导入 JSON 推荐(判断题 · 测评)**:
78
+ ```json
79
+ {
80
+ "title": "判断题",
81
+ "en_name": "QUESTION_TYPE_SINGLE",
82
+ "custom_attr": {
83
+ "disp_type": "judge",
84
+ "show_seq": "on",
85
+ "total_score": 5
86
+ },
87
+ "option_list": [
88
+ {"title": "是", "is_open": false, "custom_attr": {"is_correct": "1", "score": 5}},
89
+ {"title": "否", "is_open": false, "custom_attr": {"score": 0}}
90
+ ]
91
+ }
92
+ ```
93
+
94
+ **示例(普通单选)**:
95
+ ```json
96
+ {
97
+ "title": "您的性别是?",
98
+ "en_name": "QUESTION_TYPE_SINGLE",
99
+ "custom_attr": {},
100
+ "option_list": [
101
+ {"title": "男", "is_open": false, "custom_attr": {}},
102
+ {"title": "女", "is_open": false, "custom_attr": {}}
103
+ ]
104
+ }
105
+ ```
106
+
107
+ ---
108
+
109
+ ### 2. 多选题 (QUESTION_TYPE_MULTIPLE)
110
+
111
+ **适用场景**:可多选的选择题
112
+
113
+ **规则**:
114
+ - 必须有 2 个及以上选项
115
+ - 可通过 `custom_attr` 设置最少/最多选择数
116
+
117
+ **custom_attr 可选值**:
118
+ - `min_answer_num`: 最少选择数量
119
+ - `max_answer_num`: 最多选择数量
120
+
121
+ **示例**:
122
+ ```json
123
+ {
124
+ "title": "您喜欢哪些颜色?(可多选)",
125
+ "en_name": "QUESTION_TYPE_MULTIPLE",
126
+ "custom_attr": {
127
+ "min_answer_num": 1,
128
+ "max_answer_num": 3
129
+ },
130
+ "option_list": [
131
+ {"title": "红色", "is_open": false, "custom_attr": {}},
132
+ {"title": "蓝色", "is_open": false, "custom_attr": {}},
133
+ {"title": "绿色", "is_open": false, "custom_attr": {}},
134
+ {"title": "其他", "is_open": true, "custom_attr": {}}
135
+ ]
136
+ }
137
+ ```
138
+
139
+ ---
140
+
141
+ ### 3. 填空题 (QUESTION_TYPE_BLANK)
142
+
143
+ **适用场景**:单行文本、多行文本输入
144
+
145
+ **规则**:
146
+ - **`option_list` 禁止为空数组 `[]`**:单行/多行填空均须 **至少 1 条**占位选项(常见 `title`「填空1」),并设置 `text_row`、`text_col`;**测评**中该选项常带 **`score`**(与项目 `69d2570b…` 一致)。
147
+ - 通过 `custom_attr.blank_type` 区分单行/多行
148
+
149
+ **custom_attr 可选值**:
150
+ - `blank_type`: `"single"` (单行) | `"multiple"` (多行)
151
+
152
+ **导入 JSON 推荐(与线上一致)**:单行/多行均带 **1 项** `option_list`,并设置 `text_row` / `text_col`;测评再加选项级 `score`。
153
+
154
+ **示例**:
155
+ ```json
156
+ // 单行填空(问卷)
157
+ {
158
+ "title": "填空题",
159
+ "en_name": "QUESTION_TYPE_BLANK",
160
+ "custom_attr": {"blank_type": "single", "show_seq": "on"},
161
+ "option_list": [
162
+ {"title": "填空1", "is_open": false, "custom_attr": {"text_row": 1, "text_col": 20}}
163
+ ]
164
+ }
165
+
166
+ // 多行填空(须 1 项占位 + 行列)
167
+ {
168
+ "title": "请留下您的建议:",
169
+ "en_name": "QUESTION_TYPE_BLANK",
170
+ "custom_attr": {"blank_type": "multiple", "show_seq": "on"},
171
+ "option_list": [
172
+ {"title": "填空1", "is_open": false, "custom_attr": {"text_row": 4, "text_col": 40}}
173
+ ]
174
+ }
175
+
176
+ // 测评填空(单空 + 分值)
177
+ {
178
+ "title": "填空",
179
+ "en_name": "QUESTION_TYPE_BLANK",
180
+ "custom_attr": {"blank_type": "single", "show_seq": "on", "total_score": 5},
181
+ "option_list": [
182
+ {"title": "填空1", "is_open": false, "custom_attr": {"score": 5, "text_row": 1, "text_col": 20}}
183
+ ]
184
+ }
185
+ ```
186
+
187
+ ---
188
+
189
+ ### 4. 多项填空题 (QUESTION_TYPE_MULTIPLE_BLANK)
190
+
191
+ **适用场景**:多个填空项(如联系方式各字段)
192
+
193
+ **规则**:
194
+ - **`option_list` 禁止为 `[]`**;每个填空项作为 `option_list` 的一个元素(多项时通常 **≥2** 项)
195
+ - 每个选项的 `title` 为填空项标签
196
+
197
+ **示例**:
198
+ ```json
199
+ {
200
+ "title": "请填写您的联系方式",
201
+ "en_name": "QUESTION_TYPE_MULTIPLE_BLANK",
202
+ "custom_attr": {},
203
+ "option_list": [
204
+ {"title": "手机号码", "is_open": false, "custom_attr": {}},
205
+ {"title": "电子邮箱", "is_open": false, "custom_attr": {}},
206
+ {"title": "微信号", "is_open": false, "custom_attr": {}}
207
+ ]
208
+ }
209
+ ```
210
+
211
+ ---
212
+
213
+ ### 5. 量表类题目 (`question_type: 50`,QUESTION_TYPE_SCORE)
214
+
215
+ **适用场景**:普通打分、量表(两端文案/圆点等)、评价(星级+标签)、NPS 等。接口层 **`question_type` 均为 `50`**,靠 **`custom_attr.disp_type`**(或**不写** `disp_type`)、**`option_list` 条数**区分形态。
216
+
217
+ **线上下证实例**(同一页三题对照):项目 **`69fb1eb5ef3af3a7745c0e6b`** 的 `project_structure` 中「打分题 / 量表题 / 评价题」——创建新题时建议先 `project_structure` 拉该页再改文案与分值。
218
+
219
+ #### 形态速查(创建 `question_struct` 时先选行)
220
+
221
+ | 产品称呼 | `question_type` | 题目 `custom_attr` 要点 | `option_list` 条数 |
222
+ |----------|-----------------|---------------------------|-------------------|
223
+ | **普通打分题** | `50` | **不设** `disp_type`;`min_answer_num` / `max_answer_num` + **`magnitude_scale`**(常见 `1`) | **1** 占位(如「选项1」) |
224
+ | **量表题** | `50` | **`disp_type: "scale"`**;`score_display`(如 `circle`)、`desc_left` / `desc_right`、`scale_tag`、`magnitude_scale` 等 | **1** 占位 |
225
+ | **评价题**(星级+标签) | `50` | **`disp_type: "evaluation"`**;`open_eval: "on"`、`score_display`(如 `star`)、`base_on` 等 | **2**(见下文「评价题」小节) |
226
+ | **NPS** | `50` | **`disp_type: "nps_score"`**;`min_answer_num: 0`、`max_answer_num: 10` 等 | **1** 占位 |
227
+
228
+ > **勿与矩阵混淆**:下文 **§6 矩阵单选**是「多行×多列」的矩阵题(`question_type: 4`);本节 **「评价题」** 指 **`disp_type: "evaluation"` 的单列星级+标签题**(`question_type: 50`),二者不同。
229
+
230
+ #### 普通打分题(无 `disp_type`,`magnitude_scale`)
231
+
232
+ 刻度由 **`min_answer_num` / `max_answer_num` + `magnitude_scale`** 控制,**不写** `disp_type`;**`option_list` 仅 1 条占位**。
233
+
234
+ ```json
235
+ {
236
+ "title": "打分题",
237
+ "question_type": 50,
238
+ "custom_attr": {
239
+ "min_answer_num": 1,
240
+ "show_seq": "on",
241
+ "max_answer_num": 5,
242
+ "magnitude_scale": 1
243
+ },
244
+ "option_list": [
245
+ {"title": "选项1", "is_open": false, "custom_attr": {}}
246
+ ]
247
+ }
248
+ ```
249
+
250
+ #### 量表题(`disp_type: "scale"`)
251
+
252
+ 典型字段:**`disp_type: "scale"`**、`score_display`(如 `circle`)、**`desc_left` / `desc_right`**(两端锚点文案)、`scale_tag`、`magnitude_scale`、`min_answer_num` / `max_answer_num`、`answer_score`(如 `off`)、`show_seq`。**`option_list` 仍 1 条占位**。
253
+
254
+ ```json
255
+ {
256
+ "title": "量表题",
257
+ "question_type": 50,
258
+ "custom_attr": {
259
+ "scale_tag": 2,
260
+ "score_display": "circle",
261
+ "min_answer_num": 1,
262
+ "max_answer_num": 5,
263
+ "answer_score": "off",
264
+ "disp_type": "scale",
265
+ "desc_left": "非常不满意",
266
+ "magnitude_scale": 1,
267
+ "show_seq": "on",
268
+ "desc_right": "非常满意"
269
+ },
270
+ "option_list": [
271
+ {"title": "选项1", "is_open": false, "custom_attr": {}}
272
+ ]
273
+ }
274
+ ```
275
+
276
+ #### 评价题(`disp_type: "evaluation"`,星级 + 标签)
277
+
278
+ - **`option_list` 固定 2 条**:第 1 条 **`title` 多为「分数」**,`custom_attr` 可为 `{}`;第 2 条 **`title` 多为「标签」**,在 **`custom_attr.label_data`** 内按分值 **`"1"`~`"5"`**(字符串键)配置每档的 **`label_list`**(可选标签文案数组)与 **`score_desc`**(该档简述)。
279
+ - 题目 **`custom_attr`** 常见:`disp_type: "evaluation"`、`open_eval: "on"`、`score_display: "star"`、`base_on`(如 `service`)、`min_answer_num` / `max_answer_num`、`show_seq`。
280
+
281
+ ```json
282
+ {
283
+ "title": "评价题",
284
+ "question_type": 50,
285
+ "custom_attr": {
286
+ "score_display": "star",
287
+ "max_answer_num": 5,
288
+ "base_on": "service",
289
+ "open_eval": "on",
290
+ "disp_type": "evaluation",
291
+ "show_seq": "on",
292
+ "min_answer_num": 1
293
+ },
294
+ "option_list": [
295
+ {"title": "分数", "is_open": false, "custom_attr": {}},
296
+ {
297
+ "title": "标签",
298
+ "is_open": false,
299
+ "custom_attr": {
300
+ "label_data": {
301
+ "1": {"label_list": ["态度冷淡", "推销多", "技术差"], "score_desc": "非常不满意"},
302
+ "2": {"label_list": ["速度慢", "仪表乱", "不专业"], "score_desc": "比较不满意"},
303
+ "3": {"label_list": ["无互动", "不积极", "业务不精"], "score_desc": "一般"},
304
+ "4": {"label_list": ["文明礼貌", "速度快", "较专业"], "score_desc": "比较满意"},
305
+ "5": {"label_list": ["热情好客", "敬业精神", "技能专业"], "score_desc": "非常满意"}
306
+ }
307
+ }
308
+ }
309
+ ]
310
+ }
311
+ ```
312
+
313
+ #### NPS(`disp_type: "nps_score"`)
314
+
315
+ ```json
316
+ {
317
+ "title": "您向朋友或同事推荐我们的可能性有多大?",
318
+ "question_type": 50,
319
+ "custom_attr": {
320
+ "disp_type": "nps_score",
321
+ "show_seq": "on",
322
+ "min_answer_num": 0,
323
+ "max_answer_num": 10
324
+ },
325
+ "option_list": [
326
+ {"title": "选项1", "is_open": false, "custom_attr": {}}
327
+ ]
328
+ }
329
+ ```
330
+
331
+ **本指南要求**:`question_type: 50` 各形态 **`option_list` 不得为 `[]`**,条数见上文「形态速查」表。
332
+
333
+ **如何避免「结构不准 / 与线不一致」**(自己拼 `question_create` / 导入 JSON 时):
334
+
335
+ 1. **以线上回包为真**:同一环境下,**`project_structure` 或 `fetch_project` 里已有题目的 `question_struct`** 优于任何口头模板;新建或改题后若表现不对,**再拉一次结构**,对照 `custom_attr`、`option_list` 条数与字段名逐项对齐。
336
+ 2. **先查本节「形态速查」表选对子类**:普通打分 / 量表 `scale` / 评价 `evaluation` / NPS 四选一,**不要混用**「无 `disp_type` 的多条分档 `option_list`」与线上下证结构。
337
+ 3. **慎用「多条 1 分~5 分」式 `option_list` 代替量表**:与本节线上下证**不一致**;若答题页或统计异常,改回本节「普通打分 / 量表 / 评价」各小节推荐形态,或**在同一项目内复制已验证的一题**再改文案。
338
+ 4. **文档滞后于产品**:若接口升级,仍以 **第 1 条** 拉回 JSON 为准。
339
+ 5. **`option_list` 禁止 `[]`**:与本指南其它题型一致,量表类也必须带足占位条数。
340
+
341
+ ---
342
+
343
+ ### 6. 矩阵单选题 (QUESTION_TYPE_MATRIX_SINGLE)
344
+
345
+ **适用场景**:矩阵单选(典型「满意度评价」:多**行**维度 × 多**列**等级)
346
+
347
+ **规则(与编辑接口 / `fetch_project` 一致)**:
348
+ - **`matrixrow_list`**:**矩阵行** = 评价维度(如「服务态度」「产品质量」),每项一条,**至少 1 行**;行内字段与 `option_list` 元素相同(`title`、`is_open`、`custom_attr`)。
349
+ - **`option_list`**:**矩阵列** = 评价等级/刻度(如「非常不满意」~「非常满意」),**至少 2 列**。
350
+ - **常见错误**:只写 `option_list`、不写 **`matrixrow_list`** —— 导入后往往只有「列」没有「行」,题面不完整或不符合预期;**矩阵满意度类题必须同时提供行、列两组列表**(参考项目 **`69e4d0a6ef3af30a18db16c3`**,请 `fetch_project` 对照)。**注意**:这与 **第四节 · 量表类 · `disp_type: "evaluation"` 的单列评价题**(`question_type: 50`、见上文)不是同一题型。
351
+ - **线上下落**:`question_type: **4**`(见 `references/fetch_project.md`「题目类型代码」)。
352
+
353
+ **示例**:
354
+ ```json
355
+ {
356
+ "title": "请对以下方面进行满意度评价",
357
+ "en_name": "QUESTION_TYPE_MATRIX_SINGLE",
358
+ "custom_attr": { "show_seq": "on" },
359
+ "matrixrow_list": [
360
+ {"title": "服务态度", "is_open": false, "custom_attr": {}},
361
+ {"title": "产品质量", "is_open": false, "custom_attr": {}},
362
+ {"title": "物流速度", "is_open": false, "custom_attr": {}}
363
+ ],
364
+ "option_list": [
365
+ {"title": "非常不满意", "is_open": false, "custom_attr": {}},
366
+ {"title": "不满意", "is_open": false, "custom_attr": {}},
367
+ {"title": "一般", "is_open": false, "custom_attr": {}},
368
+ {"title": "满意", "is_open": false, "custom_attr": {}},
369
+ {"title": "非常满意", "is_open": false, "custom_attr": {}}
370
+ ]
371
+ }
372
+ ```
373
+
374
+ ---
375
+
376
+ ### 7. 矩阵多选题 (QUESTION_TYPE_MATRIX_MULTIPLE)
377
+
378
+ **适用场景**:矩阵多选(行 × 列,每格可多选列)
379
+
380
+ **规则**:
381
+ - 与矩阵单选相同:**必须同时提供 `matrixrow_list`(行)与 `option_list`(列)**,语义同上。
382
+ - **线上下落**:`question_type: **7**`(矩阵多选 / 部分场景下称矩阵打分,仍以接口返回为准)。
383
+
384
+ **示例**:
385
+ ```json
386
+ {
387
+ "title": "以下方面中,您使用过哪些?(可多选)",
388
+ "en_name": "QUESTION_TYPE_MATRIX_MULTIPLE",
389
+ "custom_attr": { "show_seq": "on" },
390
+ "matrixrow_list": [
391
+ {"title": "功能A", "is_open": false, "custom_attr": {}},
392
+ {"title": "功能B", "is_open": false, "custom_attr": {}},
393
+ {"title": "功能C", "is_open": false, "custom_attr": {}}
394
+ ],
395
+ "option_list": [
396
+ {"title": "从未使用", "is_open": false, "custom_attr": {}},
397
+ {"title": "偶尔使用", "is_open": false, "custom_attr": {}},
398
+ {"title": "经常使用", "is_open": false, "custom_attr": {}}
399
+ ]
400
+ }
401
+ ```
402
+
403
+ ---
404
+
405
+ ### 8. 排序题 (QUESTION_TYPE_SORT)
406
+
407
+ **适用场景**:拖拽排序
408
+
409
+ **规则**:
410
+ - 选项为待排序项
411
+ - 答题时用户拖拽调整顺序
412
+
413
+ **示例**:
414
+ ```json
415
+ {
416
+ "title": "请按喜好程度排序",
417
+ "en_name": "QUESTION_TYPE_SORT",
418
+ "custom_attr": {},
419
+ "option_list": [
420
+ {"title": "选项A", "is_open": false, "custom_attr": {}},
421
+ {"title": "选项B", "is_open": false, "custom_attr": {}},
422
+ {"title": "选项C", "is_open": false, "custom_attr": {}},
423
+ {"title": "选项D", "is_open": false, "custom_attr": {}}
424
+ ]
425
+ }
426
+ ```
427
+
428
+ ---
429
+
430
+ ### 9. 文字说明题 (QUESTION_TYPE_DESC)
431
+
432
+ **适用场景**:问卷说明、段落文字
433
+
434
+ **规则**:
435
+ - 只显示文字,无需作答,但 **`option_list` 仍不得为 `[]`**
436
+ - 使用 **至少 1 条**占位选项(与线上下落一致;`title` 可与说明文案一致或由后台展示逻辑决定)
437
+
438
+ **示例**:
439
+ ```json
440
+ {
441
+ "title": "以下是问卷说明,请注意阅读...",
442
+ "en_name": "QUESTION_TYPE_DESC",
443
+ "custom_attr": {},
444
+ "option_list": [
445
+ {"title": "说明", "is_open": false, "custom_attr": {}}
446
+ ]
447
+ }
448
+ ```
449
+
450
+ ---
451
+
452
+ ### 10. 下拉级联题 (QUESTION_TYPE_CASCADE)
453
+
454
+ **适用场景**:省市区三级联动等
455
+
456
+ **规则**:
457
+ - `custom_attr.disp_type = "cascader"`
458
+ - **`option_list` 禁止为 `[]`**:至少 **1 条**占位选项;级联选项数据多由平台加载,占位用于满足结构与编辑器一致。
459
+
460
+ **注意(textproject 导入)**:占位过少或结构不完整时,实测可能落为 **`question_type: 8` 且无有效级联数据**,答题端出现「未找到结果」。**无官方级联数据源时**,不要用本题型凑「两个下拉」——应改为 **两道 `QUESTION_TYPE_SINGLE` + `disp_type: dropdown`**(见 `examples/template_survey_uzbzjvlxdv_clone.json` 修正方式)。
461
+
462
+ **示例**:
463
+ ```json
464
+ {
465
+ "title": "请选择您的地址",
466
+ "en_name": "QUESTION_TYPE_CASCADE",
467
+ "custom_attr": {"disp_type": "cascader"},
468
+ "option_list": [
469
+ {"title": "级联占位", "is_open": false, "custom_attr": {}}
470
+ ]
471
+ }
472
+ ```
473
+
474
+ ---
475
+
476
+ ### 11. 上传题 (QUESTION_TYPE_UPLOAD)
477
+
478
+ **适用场景**:文件上传、图片上传
479
+
480
+ **规则**:
481
+ - 文件上传:`custom_attr.disp_type = "upload_file"`
482
+ - 图片上传:使用 `QUESTION_TYPE_IMAGE_UPLOAD`,`custom_attr.disp_type = "image_upload"`
483
+ - **线上下落**:`question_type: 95`,**各 1 条**选项;文件常见 `title`「选择文件上传」,图片常见「请上传图片」。测评场景题目上可有 `answer_score: "on"`、`upload_num`、`upload_size` 等(项目 `69d257be…`)。
484
+
485
+ **导入 JSON 推荐**:
486
+ ```json
487
+ // 文件上传
488
+ {
489
+ "title": "请上传文件",
490
+ "en_name": "QUESTION_TYPE_UPLOAD",
491
+ "custom_attr": {"disp_type": "upload_file", "show_seq": "on"},
492
+ "option_list": [
493
+ {"title": "选择文件上传", "is_open": false, "custom_attr": {}}
494
+ ]
495
+ }
496
+
497
+ // 图片上传
498
+ {
499
+ "title": "请上传图片",
500
+ "en_name": "QUESTION_TYPE_IMAGE_UPLOAD",
501
+ "custom_attr": {"disp_type": "image_upload", "show_seq": "on"},
502
+ "option_list": [
503
+ {"title": "请上传图片", "is_open": false, "custom_attr": {}}
504
+ ]
505
+ }
506
+ ```
507
+
508
+ ---
509
+
510
+ ### 12. 地址题 (QUESTION_TYPE_ADDRESS)
511
+
512
+ **适用场景**:地址填写
513
+
514
+ **规则**:
515
+ - `custom_attr.disp_type = "address"`
516
+ - **线上下落**:`question_type: 8`(与普通填空 6 不同),常见 **`drop_type: "address"`**,**固定 4 条**选项:`省份`、`城市`、`区/县`、`详细地址`(项目 `69d2570b…`)。
517
+
518
+ **导入 JSON 推荐**:
519
+ ```json
520
+ {
521
+ "title": "地址",
522
+ "en_name": "QUESTION_TYPE_ADDRESS",
523
+ "custom_attr": {"disp_type": "address", "drop_type": "address"},
524
+ "option_list": [
525
+ {"title": "省份", "is_open": false, "custom_attr": {}},
526
+ {"title": "城市", "is_open": false, "custom_attr": {}},
527
+ {"title": "区/县", "is_open": false, "custom_attr": {}},
528
+ {"title": "详细地址", "is_open": false, "custom_attr": {}}
529
+ ]
530
+ }
531
+ ```
532
+
533
+ **本指南要求**:地址题 **`option_list` 须为上述 4 项**,不得省略为 `[]`。
534
+
535
+ ---
536
+
537
+ ### 13. 手写签名题 (QUESTION_TYPE_SIGNATURE)
538
+
539
+ **适用场景**:电子签名
540
+
541
+ **规则**:
542
+ - `custom_attr.disp_type = "signature"`
543
+ - **线上下落**:`question_type: 95`,**1 条**选项(常见 `title`「填空1」)(项目 `69d257be…`)。
544
+
545
+ **导入 JSON 推荐**:
546
+ ```json
547
+ {
548
+ "title": "签名",
549
+ "en_name": "QUESTION_TYPE_SIGNATURE",
550
+ "custom_attr": {"disp_type": "signature", "show_seq": "on"},
551
+ "option_list": [
552
+ {"title": "填空1", "is_open": false, "custom_attr": {}}
553
+ ]
554
+ }
555
+ ```
556
+
557
+ ---
558
+
559
+ ### 14. 分页题 (QUESTION_TYPE_SPLIT_PAGE)
560
+
561
+ **适用场景**:问卷分页
562
+
563
+ **规则**:
564
+ - `custom_attr.disp_type = "page_break"`
565
+ - **`option_list` 禁止为 `[]`**:至少 **1 条**占位选项(常见 `title` 与线上一致即可)
566
+
567
+ **示例**:
568
+ ```json
569
+ {
570
+ "title": "分页",
571
+ "en_name": "QUESTION_TYPE_SPLIT_PAGE",
572
+ "custom_attr": {"disp_type": "page_break"},
573
+ "option_list": [
574
+ {"title": "分页", "is_open": false, "custom_attr": {}}
575
+ ]
576
+ }
577
+ ```
578
+
579
+ ---
580
+
581
+ ## 五、预设信息题(自动验证格式)
582
+
583
+ | 题型 | en_name | 说明 |
584
+ |------|---------|------|
585
+ | 性别 | `QUESTION_TYPE_SEX` | 线上下落多为单选 `question_type: 2`,**2 项** 男/女 |
586
+ | 手机 | `QUESTION_TYPE_MOBILE` | 常为填空 `6` + **1 项** + `checkmethod: mobile` |
587
+ | 邮箱 | `QUESTION_TYPE_EMAIL` | 常为填空 `6` + **1 项** + `checkmethod: email` |
588
+ | 日期 | `QUESTION_TYPE_DATE` | 线上下落多为 `question_type: 95` + **1 项** |
589
+ | 时间 | 编辑器中的时间题 | 线上下落 `question_type: 95` + **2 项**(时/分),见 §5.2 |
590
+ | 姓名 | `QUESTION_TYPE_NAME` | 填空 `6` + **1 项** |
591
+ | 年龄 / 学历 | 编辑器预设 | 多为单选 `2` + **多条** 固定选项,见 §5.2 |
592
+ | 学号 / 班级 / 部门 | 多用 `QUESTION_TYPE_BLANK` + `content_type` | 见 §5.3 |
593
+ | 工号 | `QUESTION_TYPE_BLANK` + `disp_type: employee_id` 等 | 见 §5.3 |
594
+ | 身份证 | `QUESTION_TYPE_ID_CARD` 或见 §5.1 推荐 | 身份证号格式校验 |
595
+
596
+ **通用规则(导入 JSON)**:
597
+ - **禁止** `option_list: []`;预设题须按 **§5.1~§5.4** 与 **第十二节** 使用**非空** `option_list`。
598
+ - 手机/邮箱等须设置 `custom_attr.disp_type` 或选项级 `checkmethod`(见 §5.2)。
599
+
600
+ ### 5.1 身份证:线上下落结构(`edit_project` 返回)
601
+
602
+ 导入成功后,在编辑接口中「身份证号」题常见结构为 **填空题骨架 + 身份证校验**,而非单独枚举题型:
603
+
604
+ | 位置 | 字段 | 典型值 | 说明 |
605
+ |------|------|--------|------|
606
+ | 题目 | `question_type` | `6` | 与填空题一致 |
607
+ | 题目 | `custom_attr.content_type` | `"id_card"` | 标记为身份证控件 |
608
+ | 题目 | `custom_attr.show_seq` / `total_score` | 视项目而定 | 与其它题一致 |
609
+ | 选项(1 条) | `title` | 如 `"填空1"` | 占位展示文案,后台可改 |
610
+ | 选项 | `custom_attr.checkmethod` | `"id_num"` | 触发身份证号校验 |
611
+ | 选项 | `custom_attr.text_row` / `text_col` | 如 `1` / `10` | 输入框行列 |
612
+
613
+ **导入 JSON 推荐写法(与线上一致)**:使用 **`QUESTION_TYPE_BLANK`**,并带上 **`content_type` + 单选项 + `checkmethod`**:
614
+
615
+ ```json
616
+ {
617
+ "title": "身份证号",
618
+ "en_name": "QUESTION_TYPE_BLANK",
619
+ "custom_attr": {
620
+ "show_seq": "on",
621
+ "content_type": "id_card"
622
+ },
623
+ "option_list": [
624
+ {
625
+ "title": "身份证号",
626
+ "is_open": false,
627
+ "custom_attr": {
628
+ "checkmethod": "id_num",
629
+ "text_row": 1,
630
+ "text_col": 10
631
+ }
632
+ }
633
+ ]
634
+ }
635
+ ```
636
+
637
+ **关于 `QUESTION_TYPE_ID_CARD`**:不推荐单独依赖该枚举;若使用,**仍须**带 **至少 1 项** `option_list`(结构以 `fetch_project` 回包为准)。**表单类项目优先采用上一段 `QUESTION_TYPE_BLANK` 写法**。
638
+
639
+ ### 5.2 姓名 / 手机 / 邮箱 / 日期 / 时间 / 性别 / 年龄 / 学历(线上下落与推荐导入)
640
+
641
+ 以下线上下落字段来自项目 **`69d257be…`(问卷)**、**`69d2570b…`(测评)** 的 `edit_project` 实测。
642
+
643
+ | 预设能力 | 典型 `question_type` | `option_list` 条数 | 题目 `custom_attr` 要点 | 选项 `custom_attr` 要点 |
644
+ |----------|---------------------|-------------------|---------------------------|---------------------------|
645
+ | 姓名 | `6`(填空) | **1** | `disp_type: "name"` | `text_row` / `text_col`;测评可加 **`score`** |
646
+ | 手机 | `6` | **1** | `disp_type: "mobile"`,常配合 `blank_type: "single"` | **`checkmethod: "mobile"`** + 行列 |
647
+ | 邮箱 | `6` | **1** | `disp_type: "email"` | **`checkmethod: "email"`** + 行列 |
648
+ | 日期 | `95` | **1** | `disp_type: "date"` | 常为 `{}`;测评选项可带 **`score: 0`** |
649
+ | 时间 | `95` | **2** | `disp_type: "time"` | 两条分别为「时」「分」,测评可各带 **`score`** |
650
+ | 性别 | `2`(单选) | **2** | `disp_type: "sex"`,`content_type: "sex"` | 男/女;测评选项可带 **`score`** |
651
+ | 年龄 | `2` | **多条**(如 7 档) | `disp_type: "age"`,`content_type: "age"` | 各档文案 + 测评 **`score`** |
652
+ | 学历 | `2` | **多条**(如 6 档) | `disp_type: "education"`,`content_type: "education"` | 各档文案 + 测评 **`score`** |
653
+
654
+ **导入 JSON 推荐示例(手机 · 单选项)**:
655
+ ```json
656
+ {
657
+ "title": "手机",
658
+ "en_name": "QUESTION_TYPE_MOBILE",
659
+ "custom_attr": {"disp_type": "mobile", "blank_type": "single", "show_seq": "on"},
660
+ "option_list": [
661
+ {
662
+ "title": "填空1",
663
+ "is_open": false,
664
+ "custom_attr": {"checkmethod": "mobile", "text_row": 1, "text_col": 20}
665
+ }
666
+ ]
667
+ }
668
+ ```
669
+
670
+ **日期 / 时间(`QUESTION_TYPE_DATE` 等,线上下落为 `question_type: 95`)**:
671
+ ```json
672
+ {
673
+ "title": "日期",
674
+ "en_name": "QUESTION_TYPE_DATE",
675
+ "custom_attr": {"disp_type": "date", "show_seq": "on"},
676
+ "option_list": [
677
+ {"title": "日期", "is_open": false, "custom_attr": {}}
678
+ ]
679
+ }
680
+ ```
681
+ 时间题须 **2 项**:`{"title": "时", ...}`、`{"title": "分", ...}`(与样例项目一致)。
682
+
683
+ ### 5.3 学号 / 工号 / 班级 / 部门(测评常见,`question_type: 6`)
684
+
685
+ 线上下落均为 **1 条**占位选项,`title` 多为「填空1」,题目侧用 **`content_type`** 或 **`disp_type`** 区分(项目 **`69d2570b…`**):
686
+
687
+ | 题干场景 | 题目 `custom_attr` | 选项 `custom_attr`(测评) |
688
+ |----------|-------------------|---------------------------|
689
+ | 学号 | `content_type: "student_id"` | `score`、`text_row`、`text_col` |
690
+ | 工号 | `disp_type: "employee_id"`,可配合 `blank_type: "single"` | 同上 |
691
+ | 班级 | `content_type: "classes"` | 同上 |
692
+ | 部门 | `content_type: "department"` | 同上 |
693
+
694
+ **导入 JSON 推荐(学号示例)**:
695
+ ```json
696
+ {
697
+ "title": "学号",
698
+ "en_name": "QUESTION_TYPE_BLANK",
699
+ "custom_attr": {"content_type": "student_id", "total_score": 0},
700
+ "option_list": [
701
+ {"title": "填空1", "is_open": false, "custom_attr": {"score": 0, "text_row": 1, "text_col": 10}}
702
+ ]
703
+ }
704
+ ```
705
+
706
+ ### 5.4 地理位置多格(`disp_type: geographical_multiple_blank`)
707
+
708
+ 测评样例「所在位置」:**`question_type: 95`**,`custom_attr.disp_type: "geographical_multiple_blank"`,**3 条**选项,常见 `name_en` 为 **`address` / `longitude` / `latitude`**(项目 **`69d2570b…`**)。导入时宜按三格分别建 `option_list` 三项并在 `custom_attr` 中携带对应 `name_en`(若导入接口支持)。
709
+
710
+ **示例**:
711
+ ```json
712
+ {
713
+ "title": "所在位置",
714
+ "en_name": "QUESTION_TYPE_MULTIPLE_BLANK",
715
+ "custom_attr": {"disp_type": "geographical_multiple_blank", "total_score": 0},
716
+ "option_list": [
717
+ {"title": "填空1", "is_open": false, "custom_attr": {"name_en": "address"}},
718
+ {"title": "填空2", "is_open": false, "custom_attr": {"name_en": "longitude"}},
719
+ {"title": "填空3", "is_open": false, "custom_attr": {"name_en": "latitude"}}
720
+ ]
721
+ }
722
+ ```
723
+
724
+ **注意**:`edit_project` 中该题 `question_type` 为 **95**,与 `QUESTION_TYPE_MULTIPLE_BLANK` 的导入映射未必一致;若导入失败,以 **`fetch_project` 回包** 或官方模板为准调整 `en_name`。
725
+
726
+ **预设题须非空 `option_list`(与 §5.2 一致)**:
727
+ ```json
728
+ // 手机号(1 项 + checkmethod)
729
+ {
730
+ "title": "您的手机号码",
731
+ "en_name": "QUESTION_TYPE_MOBILE",
732
+ "custom_attr": {"disp_type": "mobile", "blank_type": "single", "show_seq": "on"},
733
+ "option_list": [
734
+ {"title": "手机号", "is_open": false, "custom_attr": {"checkmethod": "mobile", "text_row": 1, "text_col": 20}}
735
+ ]
736
+ }
737
+
738
+ // 日期(1 项占位)
739
+ {
740
+ "title": "请选择日期",
741
+ "en_name": "QUESTION_TYPE_DATE",
742
+ "custom_attr": {"disp_type": "date", "show_seq": "on"},
743
+ "option_list": [
744
+ {"title": "日期", "is_open": false, "custom_attr": {}}
745
+ ]
746
+ }
747
+ ```
748
+
749
+ ---
750
+
751
+ ## 六、考试测评题(带正确答案)
752
+
753
+ **适用场景**:考试、测验、知识竞赛
754
+
755
+ **规则**:
756
+ - `p_type` 必须为 `2`
757
+ - `type_id` 使用考试测评类型
758
+ - 每题设置 `custom_attr`:
759
+ - `calculation`: `"auto_score"` (自动计分)
760
+ - `answer_analysis`: 答案解析文本
761
+ - `answer_score`: `"on"` (开启计分)
762
+ - `total_score`: 题目总分
763
+ - 选项设置 `custom_attr.is_correct`: `"1"` (正确) / `"0"` (错误)
764
+ - 选项设置 `custom_attr.score`: 选项分值
765
+
766
+ **单选题示例**:
767
+ ```json
768
+ {
769
+ "title": "Python的创建者是?",
770
+ "en_name": "QUESTION_TYPE_SINGLE",
771
+ "custom_attr": {
772
+ "calculation": "auto_score",
773
+ "answer_analysis": "Python由Guido van Rossum于1991年创建",
774
+ "answer_score": "on",
775
+ "total_score": 10
776
+ },
777
+ "option_list": [
778
+ {"title": "Guido van Rossum", "is_open": false, "custom_attr": {"is_correct": "1", "score": "10"}},
779
+ {"title": "James Gosling", "is_open": false, "custom_attr": {"is_correct": "0"}},
780
+ {"title": "Brendan Eich", "is_open": false, "custom_attr": {"is_correct": "0"}},
781
+ {"title": "Dennis Ritchie", "is_open": false, "custom_attr": {"is_correct": "0"}}
782
+ ]
783
+ }
784
+ ```
785
+
786
+ **多选题示例**:
787
+ ```json
788
+ {
789
+ "title": "以下哪些是Python的数据类型?",
790
+ "en_name": "QUESTION_TYPE_MULTIPLE",
791
+ "custom_attr": {
792
+ "calculation": "auto_score",
793
+ "answer_analysis": "list、dict、tuple是Python基础数据类型",
794
+ "answer_score": "on",
795
+ "total_score": 10
796
+ },
797
+ "option_list": [
798
+ {"title": "list", "is_open": false, "custom_attr": {"is_correct": "1", "score": "5"}},
799
+ {"title": "dict", "is_open": false, "custom_attr": {"is_correct": "1", "score": "5"}},
800
+ {"title": "tuple", "is_open": false, "custom_attr": {"is_correct": "1", "score": "5"}},
801
+ {"title": "array", "is_open": false, "custom_attr": {"is_correct": "0"}}
802
+ ]
803
+ }
804
+ ```
805
+
806
+ **填空题示例**:
807
+ ```json
808
+ {
809
+ "title": "Python的输出函数是______",
810
+ "en_name": "QUESTION_TYPE_BLANK",
811
+ "custom_attr": {
812
+ "blank_type": "single",
813
+ "calculation": "auto_score",
814
+ "answer_analysis": "print是Python的输出函数",
815
+ "answer_score": "on",
816
+ "total_score": 5
817
+ },
818
+ "option_list": [
819
+ {"title": "print", "is_open": false, "custom_attr": {"is_correct": "1"}}
820
+ ]
821
+ }
822
+ ```
823
+
824
+ ---
825
+
826
+ ---
827
+
828
+ ## 十、题型选择速查表
829
+
830
+ | 需求描述 | en_name |
831
+ |---------|---------|
832
+ | 单选(圆点) | QUESTION_TYPE_SINGLE |
833
+ | 下拉单选 | QUESTION_TYPE_SINGLE + disp_type: dropdown |
834
+ | 判断题 | QUESTION_TYPE_SINGLE + disp_type: judge + **2 项**选项(是/否,测评带 `is_correct`/`score`) |
835
+ | 多选(方框) | QUESTION_TYPE_MULTIPLE |
836
+ | 单行填空 | QUESTION_TYPE_BLANK + blank_type: single |
837
+ | 多行填空 | QUESTION_TYPE_BLANK + blank_type: multiple |
838
+ | 多项填空(多个输入框) | QUESTION_TYPE_MULTIPLE_BLANK |
839
+ | 普通打分(1~N 刻度) | QUESTION_TYPE_SCORE + **无** `disp_type` + **1 项**占位 + `magnitude_scale`(见 **第四节 ·5 量表类**) |
840
+ | 量表题(圆点/两端文案) | QUESTION_TYPE_SCORE + `disp_type: scale` + **1 项**占位(见 **第四节 ·5**) |
841
+ | 评价题(星级+标签) | QUESTION_TYPE_SCORE + `disp_type: evaluation` + **2 项**(分数+标签,`label_data`)(见 **第四节 ·5**) |
842
+ | NPS评分(0-10) | QUESTION_TYPE_SCORE + disp_type: nps_score + **1 项** + min/max 0~10 |
843
+ | 矩阵单选 | QUESTION_TYPE_MATRIX_SINGLE |
844
+ | 矩阵多选 | QUESTION_TYPE_MATRIX_MULTIPLE |
845
+ | 拖拽排序 | QUESTION_TYPE_SORT |
846
+ | 文字说明 | QUESTION_TYPE_DESC |
847
+ | 省市区级联 | QUESTION_TYPE_CASCADE + disp_type: cascader |
848
+ | 文件上传 | QUESTION_TYPE_UPLOAD + disp_type: upload_file + **1 项** |
849
+ | 图片上传 | QUESTION_TYPE_IMAGE_UPLOAD + disp_type: image_upload + **1 项** |
850
+ | 地址填写 | QUESTION_TYPE_ADDRESS + disp_type: address + **4 项**(省/市/区/详细) |
851
+ | 手写签名 | QUESTION_TYPE_SIGNATURE + disp_type: signature + **1 项** |
852
+ | 日期 | QUESTION_TYPE_DATE + `disp_type: date` + **1 项**(见 §5.2) |
853
+ | 时间 | 编辑器时间题 + `disp_type: time` + **2 项**(时/分,见 §5.2) |
854
+ | 分页 | QUESTION_TYPE_SPLIT_PAGE + disp_type: page_break |
855
+ | 性别 | QUESTION_TYPE_SEX + **2 项**(男/女,见 §5.2) |
856
+ | 手机号 | QUESTION_TYPE_MOBILE + disp_type: mobile + **1 项** + `checkmethod: mobile` |
857
+ | 邮箱 | QUESTION_TYPE_EMAIL + **1 项** + `checkmethod: email` |
858
+ | 姓名 | QUESTION_TYPE_NAME + **1 项**占位(见 §5.2) |
859
+ | 学号/工号/班级/部门 | 见 §5.3(多为 `QUESTION_TYPE_BLANK` + `content_type` / `disp_type`) |
860
+ | 身份证 | **`QUESTION_TYPE_BLANK`** + `content_type: id_card` + **`option_list` 至少 1 项** + `checkmethod: id_num`(见 §5.1);勿使用空 `option_list` |
861
+
862
+
863
+ ---
864
+
865
+ ## 十一、`option_list` 全局规则(禁止空数组)
866
+
867
+ - **任何题目均不得使用 `option_list: []`**。须按题型填入第四节、第五章、第十二节规定的**最少条数**(单选/多选 ≥2、填空/上传/签名/日期等 ≥1、地址 4、量表见第四节 ·5、评价 2 项等)。
868
+ - **文字说明、分页、级联**:虽不依赖选项答题,仍须 **至少 1 条**占位项以满足结构与线上下落一致(见 §9、§10、§14)。
869
+ - 若对条数有疑问,以 **`project_structure` / `fetch_project` 回包** 为准复制再改文案。
870
+
871
+
872
+ ---
873
+
874
+ ## 十二、线上下落 `question_type` 与 `option_list` 对照(参考项目)
875
+
876
+ 以下为 **`GET …/edit_project/`** 返回中的典型形态,源项目:
877
+
878
+ - **`69d257be4d1e8d523899937b`**(`survey`)
879
+ - **`69d2570bef3af30a3376fd24`**(`assess`)
880
+ - **`69fb1eb5ef3af3a7745c0e6b`**(`question_type: 50`:普通打分 / `scale` 量表 / `evaluation` 评价 三题对照)
881
+
882
+ 导入 JSON 的 `en_name` 与下列 **`question_type`(数字)** 为不同层级的标识,对照用于核对本地 **`option_list` 条数与字段** 是否与线上下落一致(**禁止**本地使用 `option_list: []`)。
883
+
884
+ | 场景(题干示例) | `question_type` | `option_list` 条数 | 题目 `custom_attr` 要点 | 选项侧要点 |
885
+ |------------------|-----------------|-------------------|---------------------------|------------|
886
+ | 单行填空 | `6` | **1** | `blank_type: single` 等 | `text_row`、`text_col` |
887
+ | 判断题 | `2` | **2** | `disp_type: judge` | `is_correct`、`score`(测评) |
888
+ | 姓名 | `6` | **1** | `disp_type: name` | 行列;测评 `score` |
889
+ | 手机 | `6` | **1** | `disp_type: mobile` | **`checkmethod: mobile`** |
890
+ | 邮箱 | `6` | **1** | `disp_type: email` | **`checkmethod: email`** |
891
+ | 学号 | `6` | **1** | `content_type: student_id` | 测评 `score` + 行列 |
892
+ | 工号 | `6` | **1** | `disp_type: employee_id` | 同上 |
893
+ | 班级 | `6` | **1** | `content_type: classes` | 同上 |
894
+ | 部门 | `6` | **1** | `content_type: department` | 同上 |
895
+ | 性别 | `2` | **2** | `disp_type: sex`,`content_type: sex` | 男/女;测评 `score` |
896
+ | 年龄 | `2` | **多** | `disp_type: age`,`content_type: age` | 各档 + 测评 `score` |
897
+ | 学历 | `2` | **多** | `disp_type: education` | 各档 + 测评 `score` |
898
+ | NPS | `50` | **1** | `disp_type: nps_score`,`min/max_answer_num` | 占位项 |
899
+ | 普通打分(如 1~5) | `50` | **1** | **无** `disp_type`;`min_answer_num` / `max_answer_num`,`magnitude_scale` 等 | 占位「选项1」 |
900
+ | 量表题(`scale`) | `50` | **1** | `disp_type: "scale"`;`desc_left` / `desc_right`;`score_display` 等 | 占位项 |
901
+ | 评价题(`evaluation`) | `50` | **2** | `disp_type: "evaluation"`;`open_eval`、`score_display` 等 | 第 2 项含 `label_data`(`"1"`~`"N"` 键) |
902
+ | 文件上传 | `95` | **1** | `disp_type: upload_file` | `title` 如「选择文件上传」 |
903
+ | 图片上传 | `95` | **1** | `disp_type: image_upload` | `title` 如「请上传图片」 |
904
+ | 日期 | `95` | **1** | `disp_type: date` | 常为 `{}` |
905
+ | 时间 | `95` | **2** | `disp_type: time` | 「时」「分」 |
906
+ | 签名 | `95` | **1** | `disp_type: signature` | 占位「填空1」等 |
907
+ | 地理三格 | `95` | **3** | `disp_type: geographical_multiple_blank` | `name_en`: address/longitude/latitude |
908
+ | 地址(四级) | `8` | **4** | `disp_type: address`,`drop_type: address` | 省/市/区/详细地址 |
909
+
910
+ **说明**:同一 `question_type: 95` 对应多种 UI,需以题目 **`custom_attr.disp_type`** 区分。同一 **`question_type: 50`** 对应多种量表 UI,需以 **`disp_type`(或省略)与 `option_list` 条数** 区分,详见 **第四节 · 题型表 · 第 5 类(量表类)**。身份证题见 **第五章 ·5.1**(`question_type: 6` + `content_type: id_card` + `checkmethod: id_num`)。