# update_logic 工具参考 ## 概述 更新问卷的自定义逻辑设置(DSL 代码)。可通过 `get_survey` 返回的 `survey_dsl` 字段获取当前逻辑代码,修改后整体传入。传入空字符串可清空所有逻辑。 ## 参数 | 参数 | 类型 | 必填 | 说明 | |------|------|:----:|------| | `survey_id` | number | **是** | 问卷 ID | | `dsl` | string | **是** | 问卷自定义逻辑代码(DSL 脚本语法) | > **重要**:`dsl` 中引用题目和选项时需使用反引号包裹的 ID 格式(如 `` `q-1-abcd::o-100-ABCD` ``),ID 可从 `get_survey` 返回的题目和选项信息中获取。 ## 返回值 ### 成功响应 ```json { "survey_id": 716128, "result": "success" } ``` ### 失败响应 ```json { "survey_id": 716128, "result": "failed", "error": "invalid_dsl_syntax: ..." } ``` ### 字段说明 | 字段 | 类型 | 说明 | |------|------|------| | `survey_id` | number | 问卷 ID | | `result` | string | `"success"` 表示成功,`"failed"` 表示失败 | | `error` | string | 仅失败时返回,错误描述信息 | ## DSL 语法说明 自定义逻辑使用 DSL(Domain-Specific Language)脚本语法。多条规则用换行分隔。 > 📖 完整语法文档:https://wj.qq.com/docs/dsl/grammar ### 引用格式 在通过 MCP 工具编写 DSL 时,题目和选项 ID 需要使用**反引号包裹**: | 元素 | 格式 | 示例 | |------|------|------| | 题目 | `` `q-1-xxxx` `` | `` `q-1-abcd` `` | | 选项 | `` `q-1-xxxx::o-100-ABCD` `` | `` `q-1-abcd::o-100-EFGH` `` | | 矩阵子问题 | `` `q-1-xxxx::s-200-IJKL` `` | `` `q-1-abcd::s-200-IJKL` `` | | 填空项 | `` `q-1-xxxx::b-300-MNOP` `` | `` `q-1-abcd::b-300-MNOP` `` | > **注意**:ID 值必须从 `get_survey` 返回的数据中获取,不能自行构造。 ### 条件操作符 | 操作符 | 说明 | 示例 | |--------|------|------| | `and` | 逻辑与 | `if Q1A1 and Q2A2 then show Q3` | | `or` | 逻辑或 | `if Q1A1 or Q1A2 then show Q2` | | `not` | 逻辑非 | `if Q1 and not Q1A3 then show Q2` | | `()` | 分组 | `if (Q1A1 or Q1A2) and Q2A1 then show Q3` | | `>` `>=` `==` `<` `<=` | 比较 | `if Q1 > 5 then show Q2` | | `+` `-` `*` `/` | 算数运算 | `if Q1 + Q2 > 10 then show Q3` | ### 行为控制语句 | 语句类型 | 语法格式 | 说明 | |---------|---------|------| | **条件显示** | `if <条件> then show <目标>` | 满足条件时显示题目或选项 | | **条件隐藏** | `if <条件> then hide <目标>` | 满足条件时隐藏题目或选项 | | **直接隐藏** | `hide <目标>` | 直接隐藏题目或选项(无条件) | | **连线跳转** | `if <条件> then branch from <题目> to <目标>` | 满足条件时从某题跳转到指定题目或 `END` | | **内容替换** | `replace "<文本>" in <题目> title with <来源>` | 将题目标题中的指定文本替换为另一题的回答 | | **随机排序** | `shuffle <范围>` | 对题目或选项进行随机排序 | | **随机抽取** | `random show <数量> from <范围>` | 从题目或选项中随机抽取指定数量显示 | | **自动圈选** | `set <选项>` | 自动选中指定选项 | | **自动填充** | `set <题目> = <来源>` | 自动填充文本题内容 | ### 特殊关键字 | 关键字 | 说明 | 示例 | |--------|------|------| | `END` | 结束页,用于跳转到问卷结尾 | `branch from Q1 to END` | | `len` | 答案个数 | `if len Q1 > 2 then show Q3` | | `index` | 答案排在第几位 | `if index Q1A1 == 1 then show Q2` | | `RANDBETWEEN(min, max)` | 随机生成整数 | `if RANDBETWEEN(1, 10) > 5 then show Q2` | | `LANG()` | 获取答题者语言 | `if LANG() == "zhs" then show Q1` | | `PARAMS("key")` | 获取自定义参数 | `if PARAMS("source") == "wechat" then show Q2` | | `#` | 注释 | `# 这是注释,不会被执行` | ### 范围表示 | 格式 | 说明 | 示例 | |------|------|------| | `Q1~3` | 题目 Q1 到 Q3 | `shuffle Q1~3` | | `Q1A1~4` | 题目 Q1 的选项 A1 到 A4 | `shuffle Q1A1~4` | | `Q1,Q3,Q5` | 不连续的题目 | `random show 1 from Q1,Q3,Q5` | > 当连续 3 个以上序号时,系统会自动合并为 `~` 格式。 ### weight 权重 `random show` 支持设置权重: ``` random show 1 from Q1~3 weight by 1:1:2 ``` 表示 Q3 被抽取的概率是 Q1、Q2 的两倍。 ## 调用示例 ### 典型工作流 ``` # 1. 先获取问卷详情,确认题目和选项 ID get_survey(survey_id=716128) # 返回中查看 survey_dsl.code 获取当前逻辑代码 # 从 pages → questions → options 中获取题目和选项的 ID # 2. 编写并更新逻辑 update_logic(survey_id=716128, dsl="if `q-1-abcd::o-100-EFGH` then show `q-1-ijkl`") ``` ### 条件显示逻辑 ``` # 选择了第1题的第1个选项时,显示第2题 update_logic(survey_id=716128, dsl="if `q-1-abcd::o-100-EFGH` then show `q-1-ijkl`") ``` ### 多条件组合 ``` # 第1题选了A 且 第2题选了B 时,显示第3题 update_logic(survey_id=716128, dsl="if `q-1-abcd::o-100-EFGH` and `q-1-ijkl::o-200-MNOP` then show `q-1-qrst`") ``` ### 连线跳转(甄别题) ``` # 选择了第1题某选项时,跳转到问卷结束 update_logic(survey_id=716128, dsl="if `q-1-abcd::o-100-EFGH` then branch from `q-1-abcd` to END") ``` ### 内容替换 ``` # 将第3题标题中的"XXX"替换为第1题的回答 update_logic(survey_id=716128, dsl="replace \"XXX\" in `q-1-qrst` title with `q-1-abcd`") ``` ### 随机排序与随机抽取 ``` # 随机排序第1题的选项1~4 update_logic(survey_id=716128, dsl="shuffle `q-1-abcd::o-100-A`~`q-1-abcd::o-100-D`") # 从题目1~3中随机抽取1道显示 update_logic(survey_id=716128, dsl="random show 1 from `q-1-abcd`~`q-1-qrst`") ``` ### 多条规则组合 ``` # 多条规则用换行分隔 update_logic(survey_id=716128, dsl="if `q-1-abcd::o-100-EFGH` then show `q-1-ijkl`\nif `q-1-abcd::o-100-MNOP` then show `q-1-qrst`\nreplace \"XXX\" in `q-1-uvwx` title with `q-1-abcd`") ``` ### 清空所有逻辑 ``` update_logic(survey_id=716128, dsl="") ``` ### mcporter 调用 ```bash # 设置条件显示逻辑 mcporter call tencent-survey.update_logic --args '{"survey_id": 716128, "dsl": "if `q-1-abcd::o-100-EFGH` then show `q-1-ijkl`"}' # 清空所有逻辑 mcporter call tencent-survey.update_logic --args '{"survey_id": 716128, "dsl": ""}' ``` ## 权限要求 调用此接口需要满足以下权限条件(逐级校验): | 校验层 | 说明 | |--------|------| | `WithSurveyClaims` | 问卷归属校验:问卷必须属于当前 Token 绑定的团队 | | `WithSurveyEditorClaims` | 编辑权限校验:当前用户需具有该问卷的编辑权限 | | `WithSurveyEditableClaims` | 可编辑状态校验:问卷必须处于可编辑状态(如草稿状态) | ## 错误码 | error.type | 错误描述 | 解决方案 | |------------|---------|---------| | `invalid_dsl_syntax` | DSL 语法错误 | 检查 DSL 代码语法是否正确,参考语法文档 | | `invalid_reference` | 引用的题目/选项 ID 不存在 | 确认 ID 从 get_survey 返回数据中获取 | | `claim_error` | 权限校验错误 | 问卷不属于当前 Token 绑定的团队,或无编辑权限 | | `survey_not_editable` | 问卷不可编辑 | 问卷可能正在回收中,需先暂停回收 | | `invalid_argument` | 参数校验不通过 | 检查 survey_id、dsl 是否正确 | ## 注意事项 1. **先获取再更新**:必须先调用 `get_survey` 获取问卷详情,从返回数据中获取正确的题目 ID 和选项 ID 2. **整体覆盖**:`dsl` 参数为问卷的完整逻辑代码,每次调用会覆盖所有已有逻辑。如需追加规则,需先获取当前 `survey_dsl.code`,在其基础上修改后整体传入 3. **非幂等操作**:每次调用都会覆盖原有逻辑配置 4. **ID 使用反引号**:通过 MCP 工具编写 DSL 时,题目和选项 ID 需使用反引号包裹(如 `` `q-1-abcd::o-100-EFGH` ``) 5. **多条规则换行分隔**:在 JSON 参数中,多条规则之间使用 `\n` 分隔 6. **清空逻辑**:传入空字符串(`""`)可清空所有自定义逻辑 7. **问卷状态要求**:问卷必须处于可编辑状态,正在回收中的问卷需先暂停才能编辑 8. **与基础逻辑共存**:自定义逻辑与基础逻辑可同时设置,执行顺序为先执行基础逻辑、再执行自定义逻辑 9. **付费功能**:自定义逻辑为付费高级功能。如调用时返回 `paid_function_trial_no_permission` 错误,说明当前团队未购买该功能权限,需引导用户前往[腾讯问卷购买页](https://wj.qq.com/pricing)进行付费升级(升级为付费版本)后再使用 ## Annotations(工具注解) | 注解 | 值 | 说明 | |------|---|------| | `readOnlyHint` | false | 非只读操作,会修改问卷逻辑配置 | | `destructiveHint` | false | 非破坏性操作(更新而非删除) | | `idempotentHint` | false | **非幂等**,每次调用都覆盖逻辑配置 | | `openWorldHint` | false | 内部调用 |