• cxk123
    问卷与投票
    ID survey_poll版本 11.1.0插件制作者 cxk123售价 30 积分7210 行 / 432.9 KBHook / 路由 / 后台页
    三分钟做出一份能收上来、能看懂、能导出的问卷或投票:单选、多选、评分、填空与矩阵评分(逐行统计)、图片链接,支持匿名、游客填写、多条件 AND/OR 显示逻辑与跳转到指定题、分页作答(长问卷每页 N 题,翻页自动存草稿、回来接着填)、截止与回收目标(距截止不足设定小时会自动提醒发起人),题目可上移/下移/复制、可单题存进题库并插入任意问卷,选项可随机(同一答卷内顺序稳定)并支持逐选项名额与分组共享名额,结果页支持交叉分析与两份问卷并排对比、单选/多选/评分三题型带纯内联 SVG 图表(环形图 / 百分比堆叠条 / 评分仪表,零外部依赖、零新增查询)、可逐份回看任意一份答卷的逐题作答、可生成只读结果快照分享链接(随时撤销),导出支持宽表 / 长表 / 交叉表 / 按题汇总四种 CSV,发布后改题会自动留版本快照(可看历史与逐题对比、不回溯已收数据),发起人还能看到答卷质量审计(秒填 / 同设备多份 / 直线作答的可疑计数与清单)并按关键词检索文字作答、查看跨问卷的「我的作答档案」,问卷可设「截止前允许填答者撤回或修改自己的作答」(默认一人一次不可改),后台另有数据自检与一键修复,并提供只读聚合 JSON 接口(token 可撤销、按分钟限频、只出聚合不出身份)。
    收费插件安装说明购买后点击“授权码”获取一次性授权码;在后台 > 插件广场点击在线安装或更新,并填写该授权码。已购买用户更新免费:每次在线安装或更新前,重新点击“授权码”获取新的一次性授权码即可,无需再次购买;也可直接下载新版后用后台“插件上传”更新。尊重并感谢他人劳动,请勿传播代码。
    app/plugins/survey_poll/plugin.php
    开发日志最新 10 条

    此项目接受所有登录用户协助维护和提交更新。

    • cxk123
      cxk123
      版本 11.1.0 4067e3644c28 更新:## survey_poll 11.1.0 ### 结果可视化:单选环形图 / 多选百分比堆叠条 / 评分仪表(纯内联 SVG) - 结果页与**只读分享页**都多了一层图形化结果:单选题是一枚**环形图**(占比结构一眼可见,圆心写作答人数, 右侧逐项图例给出计数与百分比);多选题是一条**百分比堆叠条**(各选项占作答人数的比例, 并写明「平均每人选 N 项」);评分题是一段**仪表弧**(平release
    • cxk123
      cxk123
      版本 11.0.0 cf4835154a38 更新:## survey_poll 11.0.0 ### 四项新能力 - **逐份答卷回看**:结果页的「答卷明细」每一行都多了一个「查看这份作答」入口,点开就是那一份答卷的 **逐题作答**(含选项、评分、矩阵逐行、文字与图片链接),还能按上一份 / 下一份连续翻看图省事。 它是只读页:权限沿用结果页的可见性(看不到聚合结果的人同样打不开),匿名问卷只写「匿名」, 页面不输出账号、认领键或设备指纹;图
    • cxk123
      cxk123
      版本 10.0.1 3fbe41ede441 更新:**10.0.1 修复:后台设置保存失败时看不到真正的错误原因** * 后台「保存设置」在校验失败时直接 fall through 成整页 HTML,而这张表单被核心前端接管(fetch + JSON 解析)→ 用户只看到笼统的「操作失败」,**真正的校验提示被吞掉**(例如「单份问卷题目上限需要填写 1 到 30 之间的整数」)。 * 修法:错误是「一条消息」而不是一整页 → AJAX 请求回
    • cxk123
      cxk123
      版本 10.0.0 78129ba7a776 更新:## 10.0.0 大版本更新:四处真缺陷修复 + 四项新能力 本轮四条缺陷都先在实验室**真机复现**(取证脚本 `tools/probe_survey_v10_bugs.sh`:同一套操作分别对 9.0.0 与 10.0.0 各跑一遍,把观察值原样打出来),再修,再在套件里留回归断言。 ### 一、修掉的 4 处真缺陷(现象 → 根因 → 修法) 1. **后台点一次「保存设置」,匿名问卷的「
    • cxk123
      cxk123
      版本 9.0.0 c593002ff351 更新:## 9.0.0 大版本更新:匿名认领键稳定性修复 + 「找回我的作答」 ### 一、修掉的缺陷(同一处问题的两个侧面,都会让匿名问卷的「我的作答」凭空消失) 1. **站点改名就让匿名问卷的「我的作答」全体打不开** 现象:填答者看不到自己填过的内容、列表里「已作答」标记消失;他以为没答过想再答一次,又会被去重拦住——用户看到的是「系统说我答过,但我什么都看不到」,而答卷其实好好地在库里。 根因
    • cxk123
      cxk123
      版本 8.0.0 655bf0b9e644 更新:## 8.0.0 大版本更新:三处数据完整性 BUG + 投放渠道 / 作答时段 / 长表导出 本次仍是「先修 BUG,再加功能」:**修掉 4 处真实缺陷**(其中「发布后改题」会直接吃掉已收答卷的统计),再补三项新能力。 ### 一、修掉的 4 处缺陷(都可复现、都留了回归断言) 1. **发布后改题会让已收答卷的统计全部归零** 现象:一份已收 2 份答卷的问卷,用「改题」把第 1 题换个说
    • cxk123
      cxk123
      版本 7.0.0 4646404336b7 更新:【7.0.0】问卷更像专业工具了:显示条件 2.0(多条件 + 跳题)+ 选项随机与分组配额 + 宽表/交叉表导出 + 版本留档与逐题对比 + 只读聚合接口 一、新增 1. 显示条件 2.0:多条件与跳题 - 支持多条件 AND(`0=甲&&1=乙`)与 OR(`0=甲||1=乙`),也支持「只跳转不带条件」(`-> 4`)。 - 新增**跳转到指定题**(`-> N`,1 起、只能向后,因此不可
    • cxk123
      cxk123
      版本 6.0.0 78865e388602 更新:【6.0.0】收到的数据要能信、长问卷要能填、问卷之间要能比:答卷质量审计 / 分页作答 / 结果对比 / 题库单题复用 一、新增 1. 答卷质量审计(结果页,只给发起人) - 提交时记录「填写时长」与三类可疑标记:秒填、同设备多份、直线作答(三点以上选择类作答全落同一项)。 - 结果页给发起人一块「答卷质量审计」:三类各多少份 + 命中合计,并可按「查看可疑答卷」看清单 (最多最近 200 份,
    • cxk123
      cxk123
      版本 5.0.0 74208b0dba3c 更新:【5.0.0】从「收数据」到「看懂数据」:交叉分析 / 模板库 / 结果快照分享 / 选项名额与防刷 一、新增 1. 交叉分析(结果页) - 结果页多了一块「交叉分析」:选一题做「分组维度」、再选一题做「统计题目」,一键生成交叉表; 每行右侧给出合计,多选参与时表头会写成「组合合计」。 - 只发一条聚合查询;没选参数时一条都不发,所以默认结果页的查询量与 4.0.0 完全一样。 - 矩阵题、评分题
    • cxk123
      cxk123
      版本 4.0.0 2e73b4382f7a 更新:4.0.0 更新(矩阵逐行统计、结束通知、题目重排与导出升级) 新增 ① 矩阵评分题按行给结果,每行单独显示分布与平均分 ② 问卷结束通知:到点/收满后通知发起人,可选择同时通知所有填答者 ③ 题目支持上移/下移/复制,跳题条件自动跟随 ④ 导出升级:矩阵题每行单列、匿名问卷不再导出填写者列 修复 ⑤ 修复 5 处:矩阵只给混合平均分;跳题条件失效会静默隐藏题目(现在校验并提示);列表角标可能重复
    主楼
  • cxk123

    版本 1.0.0 更新:
    1.0.0 首次发布
    · 五种题型:单选、多选(可设上限)、评分(1-5 星)、填空、矩阵评分,一份问卷最多 10 题
    · 作答校验:必答、选项白名单、多选上限、矩阵逐行评分,错误提示精确到「第 N 题」
    · 生命周期:草稿 → 发布 → 结束;到点或收满目标份数自动结束;发布后题目冻结,防止样本被污染
    · 一人一次:登录用户按账号去重,游客按设备去重(只保存哈希,不记录原始 IP)
    · 匿名作答:可选,开启后不记录填写者;与「一人一次」互斥,界面已明示
    · 结果页:条形图、评分分布与平均分、答卷明细分页;三种可见性(提交后立即 / 结束后 / 仅发起人)
    · 导出:CSV 一行一份答卷,带题目标题,矩阵题合并为「行名:分数」
    · 主题内嵌:发帖时挂上问卷,帖子内直接投票,版块与首页列表显示「投票中 · N 人参与」
    · 后台:概览、立即结束到期问卷、允许游客/默认匿名/结果公开等 10 项设置

    #1
  • 质量报告

    插件质量报告

    插件:survey_poll

    Hook功能范围循环使用频率文件读写修改系统表读写系统表读写自己的表
    page.footer全站页面页脚否5----
    topic.after_render首页/版块列表/主题查看逐条渲染是(列表跳过)5---写 plugin_survey_poll_forms, plugin_survey_poll_answers, plugin_survey_poll_items, plugin_survey_poll_questions, plugin_survey_poll_drafts, plugin_survey_poll_templates, plugin_survey_poll_shares, plugin_survey_poll_versions, plugin_survey_poll_api_tokens 修正❗️
    topic.index_data.loaded首页/版块/用户主题列表查询后否5---读 plugin_survey_poll_forms, plugin_survey_poll_answers
    topic.title_suffix首页/版块主题列表逐条标题是5----
    topic.after_save主题保存后否3---写 plugin_survey_poll_forms

    颜色说明:黄色表示有数据读写,红色表示 Hook 在系统循环中执行,浅蓝色表示有文件写入。“列表跳过”表示回调在列表路径会提前返回,“回调内”表示操作位于回调自身或其帮助函数的循环体内。“文件批处理”表示逐个处理用户一次提交的文件,属于必要操作,不标记修正。只有操作实际处于需要优化的循环路径时,才会标记“修正❗️”。

    数据字典

    plugin_survey_poll_forms

    字段类型可空默认值约束
    -动态定义--无法静态解析

    plugin_survey_poll_questions

    字段类型可空默认值约束
    -动态定义--无法静态解析

    plugin_survey_poll_answers

    字段类型可空默认值约束
    -动态定义--无法静态解析

    plugin_survey_poll_items

    字段类型可空默认值约束
    -动态定义--无法静态解析

    plugin_survey_poll_templates

    字段类型可空默认值约束
    -动态定义--无法静态解析

    plugin_survey_poll_shares

    字段类型可空默认值约束
    -动态定义--无法静态解析

    plugin_survey_poll_versions

    字段类型可空默认值约束
    -动态定义--无法静态解析

    plugin_survey_poll_api_tokens

    字段类型可空默认值约束
    -动态定义--无法静态解析

    plugin_survey_poll_drafts

    字段类型可空默认值约束
    -动态定义--无法静态解析
    #2
  • cxk123

    版本 2.0.0 更新:
    2.0.0 更新
    · 新增「图片链接」题型:可以让填写者上传现场照片或粘贴图片地址,支持站内附件上传,危险链接会被直接丢弃
    · 新增「复制为新问卷」:一键把已有问卷(含全部题目与选项)复制成新草稿,改一改就能复用,不用重新录入
    · 修复:列表页在设置了「回收目标」的问卷上会逐行查询已收份数(已改为整页一次批查,行渲染零查询)
    · 修复:主题投票角标给每个列表页增加 2 条查询(改为写入时维护开关,站点没有主题问卷时零开销;首页查询量回到 6 条)
    · 修复:发布问卷现在会正确触发对外的发布事件,供「关注与动态」等插件消费

    #3
  • cxk123

    版本 2.1.0 更新:
    2.1.0 更新
    · 修复:站点存在「挂在主题上的问卷」时,版块与首页列表会无条件多做两次预载查询(与行数无关但白花)——现在与角标开关共用同一个标记,没有主题问卷时首页查询量回到 6 条
    · 完善:验收套件拆分为三个专项套件(题型逻辑 38 项 / 跨插件联动 20 项 / 性能与审计 15 项),加上原有总套件共 127 项自动化检查,覆盖六种题型逐项校验、发布冻结、截止与回收目标、级联删除、主题内嵌与角标、数据量放大 25 倍的查询量不变、以及两个静态审计脚本的结论

    #4
  • cxk123

    版本 2.1.1 更新:
    2.1.1 更新
    · 按 Hook 审计表修正:主题列表行标题钩子(每行调用)不再读任何数据表,改为只读整页预载缓存;没有预载数据时不显示角标,而不是退化成逐行查询
    · 站点「是否存在主题问卷」的开关改为写路径维护 + 读路径自愈,避免标记过期导致角标静默消失
    · 验收补充:三个专项套件新增「列表页查询量不随行数增长」「渲染钩子零查询」相关断言

    #5
  • cxk123

    版本 3.0.0 更新:
    3.0.0 更新
    · 新增「跳题逻辑」:题目可设「仅当第 N 题选择了某选项时才出现」(只支持一跳),作答页自动显隐,服务端按同一条件跳过校验与入库,必答只在题目真正出现时生效
    · 新增「我的作答」:填写过的人可以在结果页看到自己提交的每一题答案;即使发起人关闭了聚合结果的公开可见,参与者依然能看到自己的作答
    · 修复:列表行投票角标改由列表行渲染钩子输出(读整页预载缓存、零数据库访问),解决部分列表场景下角标不显示的问题
    · 修复:题目逻辑字段此前只建了列、没有任何入口与效果,现在编辑页有「显示条件」输入框并全程生效

    #6
  • cxk123

    版本 4.0.0 更新:
    4.0.0 更新(矩阵逐行统计、结束通知、题目重排与导出升级)

    新增
    ① 矩阵评分题按行给结果,每行单独显示分布与平均分
    ② 问卷结束通知:到点/收满后通知发起人,可选择同时通知所有填答者
    ③ 题目支持上移/下移/复制,跳题条件自动跟随
    ④ 导出升级:矩阵题每行单列、匿名问卷不再导出填写者列

    修复
    ⑤ 修复 5 处:矩阵只给混合平均分;跳题条件失效会静默隐藏题目(现在校验并提示);列表角标可能重复或整个消失(整页预载取错主题 id);只有「我的作答」时会渲染他人明细(越权);匿名问卷认不出本人作答

    #7
  • cxk123

    版本 5.0.0 更新:
    【5.0.0】从「收数据」到「看懂数据」:交叉分析 / 模板库 / 结果快照分享 / 选项名额与防刷

    一、新增

    1. 交叉分析(结果页)
    • 结果页多了一块「交叉分析」:选一题做「分组维度」、再选一题做「统计题目」,一键生成交叉表;

    每行右侧给出合计,多选参与时表头会写成「组合合计」。

    • 只发一条聚合查询;没选参数时一条都不发,所以默认结果页的查询量与 4.0.0 完全一样。
    • 矩阵题、评分题、单选题、多选题都能参与;权限沿用结果页原有的可见性规则。
    1. 问卷模板库(新页面)
    • 编辑页新增「另存为模板」;模板库页 ?a=survey_template 列出自己的模板(管理团队看全站),

    每行可「以模板建问卷」(一键生成草稿)或「用模板预填表单」。

    • 模板里保存题干、题型、选项、必答、多选上限、跳题条件与选项名额,与问卷结构同构。
    • 每人模板数量上限由后台配置 template_max 控制(1–200)。
    1. 结果快照分享(只读链接)
    • 结果页可生成一条只读分享链接,随时可撤销;有效期由后台配置 share_days 控制(0 = 长期)。
    • 分享页只展示聚合统计(条形 / 评分 / 交叉),不含逐份答卷、填写者身份,也没有导出入口。
    • 链接 token 为 32 位随机 hex;撤销后旧链接立即失效。面板只在 ?panel=share 时查询。
    1. 选项名额与防刷
    • 题目可逐选项设置「名额上限」(编辑页第 4 个输入框,与选项一一对应,逗号分隔,0/空 = 不限)。
    • 答题页显示「剩余 N 个名额」;某个选项满额后直接置灰不可选并标「名额已满」,提交时也会再拦一次。
    • 新增后台配置 daily_limit(0–100,0 = 关闭):开启后按设备指纹限制同一设备的每日提交次数。

    二、修复

    • 模板库里每个模板都显示「0 题」、题目摘要空白(点进去建出来的问卷题目却是齐的)——

    列表查询漏取了模板的题目 JSON 列,现已补上,模板列表恢复正常。

    • 旧库升级后打开模板库 / 分享页报错——读取函数补上 schema 兜底。
    • 以模板建问卷时题目顺序与来源不一致——补回排序字段。
    • 复制问卷后选项名额丢失——复制分支现在会一并搬运名额。
    • 已填过的页面仍多发一条名额查询——按页面状态短路,不再多发。

    三、性能

    • 交叉分析、名额校验、分享页都是整批一条查询,页面请求路径上零循环内查库。
    • 无配额的问卷在答题页不会因为新功能多查一次;交叉块不带参数时不查询;分享面板非分享模式不查询。
    • 实测查询数:列表页 6、答题页 5(有配额 6)、结果页 9、交叉页 10、模板库 3、分享页 5、首页 8,

    数据量翻 25 倍后不变。

    四、已知行为(请先读这三条)

    1. 多选交叉的合计是「选项组合数」,不是人数。 分组题或统计题是多选时,一份答卷会同时落进多个格子,

    所以行/列合计会大于答卷份数;表头会写成「组合合计」并给出说明。单选题 × 单选题时合计恰好等于答卷数。

    1. 名额是软上限。 判定是「先查后插」,没有加事务/行锁;极端并发(同一秒多人抢同一个满额选项)

    可能超出 1–2 人。需要硬约束请用既有的「收满即结束」机制:把问卷的目标份数 target 设上,收满自动结束。

    1. 设备指纹的时序。 daily_limit = 0 时系统不写任何设备标识(隐私取向);

    因此事后才开启每日上限时,历史答卷没有指纹,当天的计数从「开启那一刻」重新起算。

    五、升级说明

    • 原地升级,无需卸载重装;老库第一次读写时会自动建表/补列/补索引,重复安装幂等。
    • 新增两张表:plugin_survey_poll_templates(模板)、plugin_survey_poll_shares(分享链接)。
    • 新增两列:questions.quota_json(逐选项名额)、answers.device_key(设备指纹)。
    • 新增三项后台配置:daily_limit(0–100)、share_days(0–365)、template_max(1–200);

    这次起后台配置表单是「没提交的键沿用当前值」,旧配置不会被新字段覆盖成默认值。

    • 未设置名额、未开启日限的问卷行为与 4.0.0 完全一致。
    #8
  • cxk123

    版本 6.0.0 更新:
    【6.0.0】收到的数据要能信、长问卷要能填、问卷之间要能比:答卷质量审计 / 分页作答 / 结果对比 / 题库单题复用

    一、新增

    1. 答卷质量审计(结果页,只给发起人)
    • 提交时记录「填写时长」与三类可疑标记:秒填、同设备多份、直线作答(三点以上选择类作答全落同一项)。
    • 结果页给发起人一块「答卷质量审计」:三类各多少份 + 命中合计,并可按「查看可疑答卷」看清单

    (最多最近 200 份,只给发起人与管理团队)。可疑答卷不会被自动剔除,统计里仍然计入。

    • 三个计数与「答卷总数」共用同一条 GROUP BY quality_flags 查询,所以审计功能给结果页增加 0 条查询。
    • 清单刻意不显示填写者身份;秒填阈值由后台配置 min_seconds 控制(0 = 关闭该维度)。
    1. 分页作答(长问卷多屏填写)
    • 后台配置 page_size(0–10,0 = 不分页):每页 N 题,长问卷自动切成多屏,带进度条与上/下一页。
    • 跨页的跳题条件仍由服务端判定:条件题在上一页时,条件成立就照常渲染、不成立这一页干脆不渲染,

    不再依赖浏览器对隐藏框的 :checked 判断。

    • 上一页的作答以隐藏字段原样携带,最终提交仍是一次整卷校验;页码越界(0 / 负数 / 非数字 / 999)

    一律回落到合法页,不会出现空白页或缺答提交。

    1. 结果对比(两份问卷并排)
    • 结果页新增入口 ?a=survey_compare&left=&right=:两份问卷的聚合结果并排显示,题目按文本对齐,

    对不上的题显式标注「另一份问卷没有这道题」;评分题给并排平均分。

    • 一条聚合查询取回两边的题 × 取值计数后纯内存对齐;权限沿用结果页可见性,

    看不到结果的人连选择器都看不到。已发布的私有结果问卷,他人访问直接 403。

    1. 题库单题复用(模板库升级为题库)
    • 编辑页可以把某一行「存入题库」(kind=question 单题,与整卷模板同一张表、同一套解析器)。
    • 也可以把题库里的一题「插入到问卷」的指定位置:插入前做结构同构校验(题型、选项、名额、

    必答/多选上限与来源一致),受 max_questions 与 template_max 双上限约束;已发布问卷题目冻结,不能插入。

    二、修复

    • 统计静默截断(本轮最严重):结果页/分享页过去是「先取回前 2 万行明细再在内存里聚合」,

    超过两万行的问卷统计会静默失真(数字变小但不报错),大问卷还会把全部明细读进内存。
    现改为一条 GROUP BY 聚合查询(题 × 行 × 取值 → 计数),口径与总数一致,且小问卷查询量不变。

    • 秒填答卷反而逃过标记:提交时长过去用 0 同时表示「同一秒内提交」和「没带起始时间戳(未知)」,

    而判据写的是「时长 > 0 才算秒填」,于是最快的答卷(0 秒)不被标记。现在 -1 = 未知、0 = 真的 0 秒,
    0 秒会被正常记为秒填,未知时长不会被误判。

    • 删除问卷后留下悬空引用:分享链接与模板的来源引用未清理,删除后分享页/模板库仍指向已删问卷。现已级联清理。
    • CSV 公式注入(CWE-1236):导出的答卷里,以 =、+、-、@ 开头的文本会被 Excel 当公式执行。

    现在导出时统一中和(前缀单引号),文本内容不变、打开不再有执行风险。

    • 已发布问卷的受限保存会丢字段:已发布问卷的保存分支只写提交上来的字段,未提交的字段被写成空值。

    现在受限保存只更新提交过的字段,其余保持原值。

    三、性能

    • 结果页仍是「一次表单 + 一次聚合 + 一次分页查答卷」:实测 9 条,与 5.0.0 持平(审计没有多花一条查询)。
    • 实测查询数:作答页 5(分页全在内存里算,不新增查询)、编辑页 5(题库只多一条列表查询)、

    对比页 8、分享页 6;数据量翻 25 倍后不变。

    • 页面请求路径上没有任何循环体内的数据库调用(静态审计:0 处)。

    四、已知行为(请先读这三条)

    1. 可疑标记是启发式,不是判决。 秒填看的是「页面下发的时间戳到提交的间隔」,客户端可伪造;

    同设备多份只在开启「每日提交上限」时才可能命中(关闭时不写任何设备标识);直线作答只对
    3 个以上选择类作答点生效。标记只做提示,不会删数据、不会改统计,请结合业务判断。

    1. 分页的页数只由题数与 page_size 决定,与作答进度无关;改小 page_size 会让进行中的填写人换页边界,

    建议在问卷未发布时决定。

    1. 题库只做结构同构校验,不做语义查重:题干文本相同但结构不同的题不会被判为重复,可各自入库;

    插入时按位置插入,原有题目的相对顺序不变。

    五、升级说明

    • 原地升级,无需卸载重装;老库第一次读写时自动补列/补索引,重复安装幂等。
    • 新增列:answers.duration(填写秒数,-1 = 未知)、answers.quality_flags(可疑标记位)、

    templates.kind(form 整卷 / question 单题,老数据默认为 form)。

    • 新增索引:answers(form_id,quality_flags)、answers(device_key,created_at)。
    • 新增两项后台配置:page_size(0–10)、min_seconds(0–3600);后台表单仍是「没提交的键沿用当前值」。
    • 默认配置下(page_size = 0)填写体验与 5.0.0 完全一致;审计块只对发起人可见,普通填答者页面不变。
    #9
  • cxk123

    版本 7.0.0 更新:
    【7.0.0】问卷更像专业工具了:显示条件 2.0(多条件 + 跳题)+ 选项随机与分组配额 + 宽表/交叉表导出 + 版本留档与逐题对比 + 只读聚合接口

    一、新增

    1. 显示条件 2.0:多条件与跳题
    • 支持多条件 AND(0=甲&&1=乙)与 OR(0=甲||1=乙),也支持「只跳转不带条件」(-> 4)。
    • 新增跳转到指定题(-> N,1 起、只能向后,因此不可能成环):条件不成立的那道题连同它后面的题一起不显示,

    分页作答时整页被跳过会在页面上给出可见提示,不会出现空白页。

    • 渲染、必答校验、入库三处走同一份服务端推进结果:被跳过的题既不渲染、也不校验、更不会入库。
    • 结构性非法的条件(语法错、超条数、&& 与 || 混用、自引用、跳转目标不成形或非前向)在保存期就被拒绝,一行数据都不写。
    1. 选项随机化 + 分组配额
    • 题级 / 问卷级选项随机(单选、多选):同一份答卷内顺序稳定(跨页、报错重渲染都不变),不同填写者顺序不同。
    • 顺序由身份键与题目 id 确定性推导,不依赖随机源,也不落库;统计口径不变(明细里存的始终是选项文本)。
    • 评分题与矩阵行不打乱(它们的顺序自带语义)。
    • 分组配额:多个选项共享一个名额,写法 上限:选项1|选项2#组名,多组用 ; 分隔;拼错的成员被忽略,不会让整题报错。
    1. 导出增强
    • 宽表 CSV:一行一答卷、题目为列,矩阵逐行展开,没有行数上限。
    • 交叉表 CSV:行 = 分组维度、列 = 统计维度、末行末列给合计;?a=survey_export&id=N&format=cross&group=题号&target=题号。
    • 两种导出的数字与结果页同源同口径,CSV 一律做公式注入中和。
    1. 版本留档与逐题对比
    • 发布、草稿保存、题目调整、题库插入、以及发布后改题,都会自动留一份快照(题数 / 题目定义 / 时间 / 操作者 / 原因);

    与上一份内容完全相同则不重复留档。

    • 快照页可看历史,并与当前题目做字段级逐题对比(题干 / 题型 / 选项 / 必答 / 多选上限 / 条件 / 名额 / 随机)。
    • 快照只记录「当时的题目长什么样」,不回溯已收答卷。
    1. 只读聚合 JSON 接口
    • ?a=survey_api&token=… 返回「题 × 选项计数 + 答卷数」(评分给均分、矩阵逐行给均分),方便接入自己的看板。
    • token 在结果页生成 / 撤销,可随时作废;按分钟限频(默认每分钟 60 次,后台可调),超限返回 429。
    • 只出聚合:没有逐份答卷、没有答卷 id、没有填写者身份,文字题与图片题连作答内容都不返回。

    二、修复(本轮实测复现的真实缺陷)

    1. 导出静默丢数据:收了 5005 份答卷的问卷,宽表 CSV 只导出前 5000 行,页面上没有任何提示;

    而「填写者」列的批查会把全部答卷 id 拼进 IN (…),答卷数超过数据库变量上限时导出直接报错(截断恰好把这个问题挡住)。
    修法:宽表改为「答卷头 1 条查询 + 明细 1 条 JOIN 查询 + 游标流式输出」,没有行数上限;填写者昵称改走子查询批查。

    1. 填答页把「不能填」说成「已填过」:未登录访客打开「仅限登录」的问卷、发起人预览草稿、站点关闭游客填写这三种情况,

    页面都只显示「你已经填写过了,感谢参与。」,让人既不知道自己没答过,也不知道该登录还是等发布。
    修法:新增五状态判定(可填 / 已答过 / 未登录 / 草稿 / 已结束),每种状态给准确文案,未登录时给登录入口。

    1. 投票角标整片消失:站点标记缺失时(刚安装 / 站点导入 / 标记被清掉),第一次浏览恰好落到「本页没有挂问卷的主题」

    就会把标记写成 0,此后首页与版块列表的角标被永久短路,且没有任何提示。
    修法:两条「本页没命中」分支共用一次存在性检查 —— 确认真没有才落 0,确认真有就把缺失标记自愈成 1。

    1. 提交校验失败整屏丢内容:少填一道必答题被拒后,已填好的内容全丢(单页模式连本页输入都不回显,

    分页模式连前几页藏在隐藏字段里的作答也一起丢),只能从头再填。
    修法:校验失败不再重定向,留在原屏重渲染(回显 + 跨页隐藏字段 + 计时戳都在),成功仍走 PRG 跳转。

    三、性能

    • 既有页面查询量不变或更省:列表 6 / 首页 6~9 / 答题页 ≤6 / 结果页 ≤9 / 编辑页 GET ≤6(已发布问卷 2 条)/ 分享页 ≤7。
    • 新增页面自带上限:版本快照页 3、接口面板 ≤10、只读接口 4、宽表导出 2(答卷头 + 一条 JOIN 流式明细)。
    • 跳转判定与选项随机都是纯内存:0 条数据库往返、0 行落库,页面请求路径上没有循环体内查询(静态门禁 0 处)。

    四、已知行为(请先读这五条)

    1. 跳转只能向后:-> N 的目标必须是本题之后的题号,保存期即拒绝其它取值,因此不可能成环。
    2. 随机的粒度:只对单选 / 多选打乱;游客的身份键含「每日盐」,所以同一个游客跨天再来会拿到另一套顺序

    (与既有的「按天去重」口径一致)。

    1. 整页被跳过时页码不缩水:页数只由题数与每页题数决定,被跳过的页会给可见提示,不会空白死循环。
    2. 版本快照不回溯数据:它记录的是题目定义的历史,不改变已经收到的答卷。
    3. 导出规模:宽表按答卷顺序游标流式输出,不再有行数上限;答卷头仍一次性读回,超大问卷的导出耗时随数据量线性增长。

    五、升级说明

    • 原地升级,无需卸载重装;老库第一次读写时自动建表 / 补列 / 建索引,重复安装幂等;结构标记由 6 升到 7。
    • 新增两张表:plugin_survey_poll_versions(版本快照)、plugin_survey_poll_api_tokens(只读接口 token),各带一枚索引;

    加上 questions.random / questions.quota_group_json 与 forms.random_options 三处新列(共 8 表 / 16 索引)。

    • 删除问卷时级联再补两处:接口 token 立即作废(保留调用痕迹)、版本快照整份删除。
    • 不用条件 2.0、不开随机与配额、不发接口 token 的老问卷,行为与 6.0.0 完全一致(老的单条件结构继续可读)。
    #10
  • cxk123

    版本 8.0.0 更新:

    8.0.0 大版本更新:三处数据完整性 BUG + 投放渠道 / 作答时段 / 长表导出

    本次仍是「先修 BUG,再加功能」:修掉 4 处真实缺陷(其中「发布后改题」会直接吃掉已收答卷的统计),再补三项新能力。

    一、修掉的 4 处缺陷(都可复现、都留了回归断言)

    1. 发布后改题会让已收答卷的统计全部归零

    现象:一份已收 2 份答卷的问卷,用「改题」把第 1 题换个说法保存后,结果页每一题都显示「0 份作答」,导出与交叉表也一起归零——答卷本体还在库里,但明细全部变成了孤儿行。
    根因:保存题目走的是「先把该表单的题目行整表删掉、再整批 INSERT」,而题目主键是 AUTOINCREMENT:重新插入的题目拿到全新 id,而 plugin_survey_poll_items.question_id 指向的还是旧 id。
    修法:改成按内容指纹复用——题型 + 题面 + 选项完全相同的题目保留原行(明细继续有效),只有真正被改写的题目才是新题(统计从 0 开始,语义正确);顺序与必答 / 显示条件 / 多选上限 / 名额 / 随机 / 分组配额的变化用一条 CASE 多列 UPDATE 写回。被换掉的老题只删题目行,答卷明细原样留档(兑现 7.0.0 的「不回溯已收数据」),且因为主键不复用,留档明细永远不会错挂到新题上。

    1. 匿名问卷的作答去重键直接写明文 u:<uid>,与「匿名」承诺不符

    现象:勾了「匿名作答(不记录填写者,提交后无法追溯)」,可库里 bucket_key 里明明白白写着 u:42——任何能读到这张表的人都能把每份答卷对回具体账号。
    修法:拆成两个键——去重键 bucket_key 用每份问卷独有的私盐做 HMAC(同一问卷内仍能一人一次,但键值不含 uid、也无法跨问卷比对);「我的作答」另用站点盐化的 owner_key 认领,功能不受影响。勾选项与后台开关的文案也改成如实描述(结果与导出都不显示填写者、库内只存不可逆去重键)。

    1. 结束广播超过 200 位填答者时:前 200 人每轮重复收通知,第 201 人永远收不到

    现象:收满 201 份答卷的问卷结束后,计划任务每 5 分钟给同一批前 200 人再发一遍「问卷已结束」,第 201 位填答者一次都收不到,问卷永远停在「还没发完」。
    根因:批量广播用 GROUP BY user_id LIMIT 201 取「第一页」,发完 200 条后既不推进游标也不置位。
    修法:新增 notify_cursor 记录「已经发到哪个 user_id」,每轮从游标之后续发 200 人;取不满一页即归档。实测 200 → 201 → 201,每人恰好一条。

    1. 发起人结束小结是 check-then-act,两轮任务重叠会重复通知

    修法:改成 CAS 抢占(UPDATE … SET notified_at=? WHERE id=? AND notified_at=0,按 rowCount 判定),notify_state 的归档同样带守卫。诚实说明:CAS 的原子性需要真并发才能复现,串行套件造不出交错,因此证据是「结构断言 + 重复运行不重复发」。

    二、三项新能力

    • 投放渠道归因:结果页给出一键复制的渠道链接(?a=survey_view&id=N&ch=微信,内置站内 / 微信 / 邮件三个现成按钮),填答页把渠道随表单带回并落库到 answers.channel;结果页新增「投放渠道」面板(按渠道回收量排序 + 未标记份数 + 每条链接可复制),宽表与长表导出都带「渠道」列。渠道只是归因标签(像 UTM),不参与任何权限判定。
    • 作答时段分布:结果页新增「作答时段」面板——24 小时柱状分布 + 最近 14 天趋势 + 回收高峰小时 + 跨天跨度;数据来自一条 GROUP BY,小时与日期在内存里归并,零 N+1。
    • 长表导出:?a=survey_poll_export&id=N&mode=long 一行一个答案(答卷号 / 填写者 / 提交时间 / 渠道 / 题号 / 题目 / 题型 / 矩阵行 / 答案文本 / 数值),直接喂给 pandas / R / SQL;仍然是「一条 JOIN + 游标流式输出」,没有行数上限,匿名问卷同样不输出填写者列。

    三、验证

    • 八套 tools/lab_verify_survey*.sh 串行全绿(v8 新增 99 项断言;既有套件的期望值随版本推进就地更新并注明理由:版本号 / 结构标记 schema=8 / 索引 15→17 / 宽表与矩阵导出列数 +1 渠道列 / 结果页预算 9→11)。
    • 六道静态门禁全部通过;计划任务仍为 2 个(close + cleanup)。
    • 四张新预览图(投放渠道 / 作答时段 / 长表导出 / 匿名结果)与 7.0.0、6.0.0 的图聚合为 12 张。
    #11
  • cxk123

    版本 9.0.0 更新:

    9.0.0 大版本更新:匿名认领键稳定性修复 + 「找回我的作答」

    一、修掉的缺陷(同一处问题的两个侧面,都会让匿名问卷的「我的作答」凭空消失)

    1. 站点改名就让匿名问卷的「我的作答」全体打不开

    现象:填答者看不到自己填过的内容、列表里「已作答」标记消失;他以为没答过想再答一次,又会被去重拦住——用户看到的是「系统说我答过,但我什么都看不到」,而答卷其实好好地在库里。
    根因:匿名认领键的站点私盐每次都从站点名派生、从不落库,改名即全体失配。
    修法:首次使用时生成随机私盐并落库;认领查询改成「当前口径 + 历史派生口径」的键集合,老答卷仍然认领得到。

    1. 「落库」之后私盐每个请求都换一把(同一现象、不同根因)

    根因:配置读取器没把该键读回来,site_salt() 每次调用都以为「还没有盐」而重新生成并写库。
    修法:读取器补上该键。实测:修复前 3 次请求 3 把不同的盐,修复后恒定。

    二、新增能力:找回我的作答(自助)

    匿名问卷里,当「你确实答过(去重键命中)但当前认领键查不到你那份」时,填答页出现「找回我的作答」:
    一键把认领键修正为当前口径,结果页的「我的作答」立刻恢复。它同时是历史数据修复的用户侧入口,
    不需要站务改库;校验严格(本人身份键 + 去重键双重命中,只能改自己那一行),不能凭 ID 猜别人的答卷。

    三、验证

    • 专项套件扩到 111 项 / 0 失败(新增 11 项:私盐落库与稳定、认领键形态、本人的「我的作答」、他人不可见、历史口径兼容、失配时自助找回与恢复)。
    • 六道静态门禁全绿(含循环内查库审计)。
    • 市场登记原地更新(topic 1617),verify_market.sh 输出「市场登记与本地源码完全一致」。
    #12
  • cxk123

    版本 10.0.0 更新:

    10.0.0 大版本更新:四处真缺陷修复 + 四项新能力

    本轮四条缺陷都先在实验室真机复现(取证脚本 tools/probe_survey_v10_bugs.sh:同一套操作分别对 9.0.0 与 10.0.0
    各跑一遍,把观察值原样打出来),再修,再在套件里留回归断言。

    一、修掉的 4 处真缺陷(现象 → 根因 → 修法)

    1. 后台点一次「保存设置」,匿名问卷的「我的作答」全体再次失配(9.0.0 修复的回归,本轮性质最重)

    现象:管理员保存一次插件设置,匿名问卷的填答者就看到「你已经填写过这份问卷了」,却什么也看不到。
    实测:保存前站点私盐 anon_site_salt 有值,保存后变成空串;用保存后的盐重算认领键 → 命中 0 份。
    根因:配置写入是 config_json 的整体覆盖(不是 merge),而后台写入器只回传它自己校验的 18 个键,
    读取器里的 anon_site_salt 被整行抹掉,下一次用得着时又随机生成一枚。
    修法:写入器以当前配置为基线,只覆盖它真正拥有的键 —— 读写字段集合天然对称,以后新增键也不会再被抹掉。

    1. 「复制为新问卷」静默丢掉「选项随机」与「分组名额」

    现象:副本里题级「随机」变回「跟随问卷」、分组共享名额整组消失(选项还在,但超额再也拦不住),页面没有任何提示。
    根因:复制分支手写了一份字段清单,7.0.0 新增的两个字段没有同步进来。
    修法:改用唯一的那份序列化器(与「另存为模板 / 存题库 / 版本快照」共用同一份字段清单)。

    1. 从题库插入一道题,会把整份问卷的显示条件与跳转规则清空

    现象:插入后所有题的条件输入框变空、作答页不再跳题,而提示只说「已插入题目」,一个字都没提条件丢了。
    根因:插入路径用了一个从未赋值的变量($old_total)来构造「旧题号映射」,映射恒为空 → 每个条件都取不到
    引用目标而被丢弃;丢弃发生在重映射阶段而不是清理阶段,所以连「有 N 处条件被清空」的提示都不会出现。
    修法:在插入之前先取一次题目数,映射按「被引用题目的身份」把条件与跳转目标平移到插入后的新位置。

    1. 多选题 / 矩阵题的「N 份作答」把答项数当成了人数

    现象:多选题 3 人各选 2 项显示「6 份作答」;矩阵题 2 行 × 3 人显示「6 份作答」,而同一块里每行又写着「3 人评分」。
    只读 JSON 接口与结果对比页照抄了同一口径。
    根因:统计里的 total 数的是明细行数,单选/评分/填空恰好一题一行所以等于人数,多选/矩阵则不是。
    修法:同一趟数据库往返里追加一段「每题作答人数」(COUNT(DISTINCT answer_id)),
    页头 / 分享页 / 对比页 / JSON 接口 / 导出全部改读它;答项数另开字段保留,两个口径不再混淆。

    二、新增的 4 项能力

    • 按题汇总 CSV(?a=survey_export&format=summary):一行一个「题目 × 项目」,含作答人数、计数与占比;

    单选多选逐选项、评分 1–5 星 + 平均分、矩阵展开到「行 · 分数」+ 每行均分。最适合直接交给别人看结论。

    • 文字作答关键词检索(结果页 ?kw=):在填空 / 图片题里按关键词找到具体作答,最多 100 条;

    % _ 一律按字面量匹配(a_b 不会再命中 axb),只给发起人与管理团队,不扩大逐条内容的可见范围。

    • 我的作答档案(?a=survey_mine):跨问卷查看「我答过哪些、每道题我选了什么」,并可一键导出「我的作答 CSV」。

    归属只用本人认领键,别人看不到。

    • 后台数据自检与一键修复:一条语句取回 7 项数据完整性不变量(孤儿明细 / 无明细答卷 / 匿名问卷缺私盐 /

    悬空分享 / 悬空接口 token / 孤儿版本快照 / 悬空主题回链),悬空引用可一键修复;
    刻意保留「历史留档的作答明细」与「当时被条件全部跳过的答卷」并写明理由——那两类删掉才是数据丢失。

    三、兼容与性能

    • 既有行为不推翻:默认导出仍是宽表、填答与结果口径不变;单选 / 评分 / 填空 / 图片题的页面输出逐字节不变。
    • 三处新页面都不随行数增长:检索面板一条查询(不传 kw 时 0 条)、档案页固定 3 条、后台自检固定 1 条;

    结果页与分享页的查询条数没有变化。

    四、验证

    • 六道静态门禁全绿;新套件 tools/lab_verify_survey_v10.sh 覆盖 4 处修复的回归断言 + 4 项能力 + 结构幂等;
    • 既有 9 套 survey_poll 套件全部复跑通过,版本相关断言已随 10.0.0 抬正并在行内注明理由。
    #13
  • cxk123

    版本 10.0.1 更新:
    10.0.1 修复:后台设置保存失败时看不到真正的错误原因

    • 后台「保存设置」在校验失败时直接 fall through 成整页 HTML,而这张表单被核心前端接管(fetch + JSON 解析)→ 用户只看到笼统的「操作失败」,真正的校验提示被吞掉(例如「单份问卷题目上限需要填写 1 到 30 之间的整数」)。
    • 修法:错误是「一条消息」而不是一整页 → AJAX 请求回 {"ok":0,"message":…} 信封;无 JS 浏览器(ajax_request() 为假)仍走原来的整页渲染,字节不变。
    • 新增 3 张预览图(10.0.0 的三项能力):按题汇总 CSV(format=summary)· 文字作答关键词检索(?kw=)· 我的作答档案(?a=survey_mine)。
    #14
  • cxk123

    版本 11.0.0 更新:

    survey_poll 11.0.0

    四项新能力

    • 逐份答卷回看:结果页的「答卷明细」每一行都多了一个「查看这份作答」入口,点开就是那一份答卷的

    逐题作答(含选项、评分、矩阵逐行、文字与图片链接),还能按上一份 / 下一份连续翻看图省事。
    它是只读页:权限沿用结果页的可见性(看不到聚合结果的人同样打不开),匿名问卷只写「匿名」,
    页面不输出账号、认领键或设备指纹;图片题只给链接不内联渲染(内联会把查看者的 IP 送给填答者的图片服务器)。
    出图/页面查询量与题数、答卷数无关;结果页新增的入口是纯内存拼链接,查询数 +0。

    • 作答草稿(长问卷跨会话续填):长问卷按「每页 N 题」分屏作答时,翻到下一页会自动把整卷已填内容存成草稿;

    关掉标签页、换设备、断网之后回来重新打开,会自动恢复到你上次填的那一页并给出提示,
    另有显式的「保存草稿」与「放弃草稿,从头填」。草稿只属于填写者本人(与答卷同一把身份键),
    提交成功后立刻删除。载荷有明确上界(只收作答字段、单值 200 字、最多 300 个位置、20KB),
    题目或选项在两次填写之间被改过时,草稿里那些已经不存在的位置会被丢弃,不会把野值塞进页面。

    • 截止前撤回 / 修改我的作答:问卷可勾选「允许填答者在截止前撤回 / 修改自己的作答」(默认关闭,

    保持「一份问卷一份样本」的既有语义)。打开后,填答页与结果页都会给填答者两个入口:
    「修改我的作答」把已提交的作答整卷回填一遍供修改,「撤回我的作答」直接撤回(撤回后可以重新填)。
    改答覆盖自己那一行(答卷份数不增加),并且会先把自己占用的选项名额退还,
    否则在满额问卷里「保留原来的选择」会被自己的旧记录判成名额已满。

    • 到期前提醒发起人:距截止时间不足设定小时数(默认 24 小时,可在后台调,填 0 关闭)时,

    计划任务会提醒一次发起人「问卷将在 X 时间截止」,可以去看回收进度或延长截止时间。
    提醒是抢占式的,计划任务重叠执行也只会发一次;关闭时这一步一次查询都不发。

    修掉的七处缺陷

    • 匿名问卷保存后收到的答卷会「失联」(最严重的一处):过去只要保存一次问卷,匿名问卷的去重私盐就会被换成

    一枚新随机盐 —— 该问卷已经收到的答卷因此既认不出重复填写(同一个人可以再投一次),
    也认不出「我答过」(「已作答」标记与「我的作答」一起消失,用户看到「系统说我答过,但我什么也看不到」)。
    现在保存时会固化原有的派生盐(所有历史去重键逐字节继续成立),只有新建或刚切到匿名才生成新盐。

    • 后台「一键修复」会把上面这个问题主动执行一遍:它的「补齐匿名私盐」写回的也是一枚新随机盐,

    修完反而让老答卷失配。现在它固化派生盐,修完历史答卷仍然全部认领得到。

    • 双击提交会把同一份答卷的明细写两遍:快速双击(或网络重试、脚本并发)时,后到的那次请求虽然被

    一人一次的约束挡住插入,却仍然把自己的作答追加进了先到者的答卷 —— 选项计数与平均分被算重,
    导出里同一题出现两行,而用户看到的是「提交成功」。现在每次提交带一枚声明串,只有真正建出这份答卷的
    那次请求才会写明细,其余一律回「你已经填写过这份问卷了」。

    • 列表页「全部」标签名不副实:过去它被一条无条件条件压成了「进行中 + 我自己发起的」,

    游客点「全部」看到的与「进行中」一模一样,登录用户也永远看不到别人已结束的问卷。
    现在四个标签各按自己的语义取数,别人的草稿在任何标签下都不出现。

    • 已发布问卷的编辑页有「看起来能改、实际被吞」的控件:改了「回收目标」页面回一句「问卷已更新」,

    库里还是旧值。现在回收目标与「可撤回 / 可修改」在已发布后也会真正保存;
    而会改变作答口径的三个开关(匿名 / 允许游客填写 / 选项随机)改为真的置灰并写明冻结原因。

    • 「同设备多份」是个恒为 0 的假指标:设备指纹只在开启「每日提交上限」时才落库(这是既有的隐私口径),

    但结果页一直把它当成一个可看的计数展示。现在日限关闭时该维度直接标注「未启用」并说明原因 ——
    隐私口径一个字没放松,界面不再撒谎。

    • 后台「数据自检」的说明文字把 Markdown 星号原样显示给管理员看(**不修复** 这种),已改成正常的文案。

    结构与兼容

    • 新增一张草稿表 plugin_survey_poll_drafts 与三个列(答卷的 claim_token、问卷的 editable / warned_at),

    全部走幂等补列;结构标记 8 → 9,老版本升级上来会自动补齐。

    • 删除问卷时会一并清掉它的作答草稿;后台数据自检新增「孤儿作答草稿」这一条不变量,可一键修复。
    • 打开「可撤回 / 可修改」之前的问卷,行为与上一版完全一致(默认关闭 = 一人一次不可改)。
    • 列表页 / 结果页 / 导出路径查询数不变;填答页在「尚未作答」时固定多一条查询(查找草稿),没有草稿也只花这一条。
    #15
  • cxk123

    版本 11.1.0 更新:

    survey_poll 11.1.0

    结果可视化:单选环形图 / 多选百分比堆叠条 / 评分仪表(纯内联 SVG)

    • 结果页与只读分享页都多了一层图形化结果:单选题是一枚环形图(占比结构一眼可见,圆心写作答人数,

    右侧逐项图例给出计数与百分比);多选题是一条百分比堆叠条(各选项占作答人数的比例,
    并写明「平均每人选 N 项」);评分题是一段仪表弧(平均分落在 1–5 的哪一档,配一句档位结论)。

    • 全部是纯内联 SVG + 现有 CSS:不引任何外部库、不发任何额外请求、页面里没有脚本 —— 分享页会把这段

    标记原样发给站外的人,所以它必须自洽。图形化这一步不新增任何查询(数据全部取自结果页原有的那条聚合结果)。

    • 原有的条形与数字一个都没动:图形只是加在它们前面,按数字核对、导出核对的老用法完全不受影响。
    • 选项很多时自动收敛:只画有票的选项,超过 8 项时尾部合并成「其他」(精确计数仍在图例里)。

    升级与并发:两条最容易留暗坑的路径,各补一次实测与一处修复

    • 升级路径自愈:从老版本升上来时(尤其是 8.0.0 之前建的匿名问卷,它们的去重私盐从来没落过库),

    第一次打开问卷相关页面就会自动把结构补齐,并把「匿名 + 私盐为空」的历史问卷一次性固化派生盐 ——
    固化接的正是原来那个现算的值,所以历史答卷的去重键与认领键逐字节不变(换版不换盐、不丢认领),
    数据自检里那条「匿名问卷缺私盐」的告警也随之归零。

    • 改答的并发正确性:两个标签页同时提交「修改我的作答」时,过去会交错成「删 A → 删 B → 插 A → 插 B」,

    同一份答卷的明细被写两遍(统计跟着翻倍)。现在改答先抢一次乐观锁,后到者一条明细都不动并提示刷新重试。

    修掉的缺陷

    • 复选框的「取消勾选」过去永远无效:匿名作答 / 允许游客填写 / 选项随机 / 截止前可撤回可修改

    这四个开关只能打开、关不掉(保存后仍是勾选状态)。原因是上次给所有字段统一加了「没提交就沿用库里的值」——
    这对文本框是对的,但浏览器取消勾选时根本不提交这个键。现在编辑页带一个隐藏标记,
    带了它「缺席 = 取消勾选」,不带(发布 / 复制 / 题库这些程序化提交)仍然沿用库里的值。

    • 匿名问卷「取消匿名 → 再开匿名」会换盐:这条路径过去会生成一枚新随机盐,让该问卷历史答卷的去重键与

    认领键再次全体失配(同一批用户可以再投一次、「我的作答」消失)。现在判据改成「库里有没有按匿名键落库的答卷」,
    有就一律固化派生盐。

    • 问卷列表页多出来的一条查询已优化回基线:结构升级标记改在插件配置里放一份内存副本,

    每次请求的「结构是否最新」判断变成零查询(A/B 实测:列表页与 11.0.0 同为 6 条)。

    • 挂问卷的版块列表页也少一次白付的查询:站点标记已经是「有」时不再重复做存在性检查

    (A/B 实测:11.0.0 与 11.1.0 同为 12 条,无增长)。

    • 静态门禁从「3 条待人工确认」收敛到 0 条:配置解析函数内补上请求方法闸、

    编辑页里直接读 $_POST 的匿名闭包换成具名助手(表单数组当参数传)、
    主题钩子里显式复核 CSRF 令牌(与核心同一套比对口径);另修掉一处 LIKE 片段缺 ESCAPE 的写法。

    兼容性

    • 老版本升上来无需任何手工操作:结构标记自动推进,列与表自动补齐,历史答卷、分享链接、接口 token、

    版本快照、草稿全部原样保留。

    • 不打开新开关时,作答行为与上一版完全一致;结果页/分享页新增的图形只是渲染层的变化,导出格式一个字节没改。
    #16

发表回复

登录后回复