<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title>评分 - tag - 沐木</title><link>https://oldletter.cn/tags/%E8%AF%84%E5%88%86/</link><description>评分 - tag - 沐木</description><generator>Hugo -- gohugo.io</generator><language>zh-cn</language><lastBuildDate>Sat, 11 Jul 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://oldletter.cn/tags/%E8%AF%84%E5%88%86/" rel="self" type="application/rss+xml"/><item><title>测评平台（二）：多资源快照、作答、评分与报告</title><link>https://oldletter.cn/posts/assessment-platform-02-multi-resource-runtime/</link><pubDate>Sat, 11 Jul 2026 00:00:00 +0000</pubDate><author>mumu</author><guid>https://oldletter.cn/posts/assessment-platform-02-multi-resource-runtime/</guid><description><![CDATA[<blockquote>
<p>系列导航：<a href="/posts/assessment-platform-01-resource-release-task/" rel="">5</a> | <a href="/posts/assessment-platform-02-multi-resource-runtime/" rel="">6</a> | <a href="/posts/assessment-platform-03-draft-preview-publish/" rel="">7</a></p></blockquote>
<p>一次测评可能包含问卷、考试、阅读材料、多个量表和报告模板。运行期间如果每个页面都去读取资源当前版本，后台编辑会让同一参与者前后拿到不同题目。运行单位应当是一个绑定发布包的实例，所有子资源从同一份快照派生。</p>
<h2 id="建立运行实例">建立运行实例</h2>
<p>任务启动时校验任务状态、访问模式、时间窗和提交令牌，再创建 <code>assessment_run</code>。实例写入任务 ID、<code>release_id</code>、参与者 ID、开始时间和状态。后续查询不再接受客户端选择的资源版本，服务端通过 <code>AssessmentRelease</code> 找到冻结的 FormDSL、题目快照和报告配置。</p>
<div class="mermaid" id="id-2" data-mermaid-definition="c2VxdWVuY2VEaWFncmFtCiAgICBwYXJ0aWNpcGFudCBQIGFzIOWPguS4juiAhQogICAgcGFydGljaXBhbnQgQVBJIGFzIOi/kOihjCBBUEkKICAgIHBhcnRpY2lwYW50IFQgYXMg5Lu75Yqh5LiO5Y&#43;R5biD5YyFCiAgICBwYXJ0aWNpcGFudCBSIGFzIOi/kOihjOWunuS&#43;iwogICAgcGFydGljaXBhbnQgUyBhcyDor4TliIbkuI7miqXlkYoKICAgIFAtPj5BUEk6IHN0YXJ0KHRhc2tJZCwgdG9rZW4pCiAgICBBUEktPj5UOiDmoKHpqowgYWNjZXNzX21vZGUg5LiOIHJlbGVhc2VfaWQKICAgIFQtLT4&#43;QVBJOiDlhrvnu5Plv6vnhacKICAgIEFQSS0&#43;PlI6IOWIm&#43;W7uui/kOihjOWunuS&#43;iwogICAgUC0&#43;PkFQSTogYXV0b3NhdmUoYW5zd2VyIHBhdGNoKQogICAgQVBJLT4&#43;Ujog5qCh6aqM5bm25L&#43;d5a2Y6KeE6IyD5YyW562U5qGICiAgICBQLT4&#43;QVBJOiBzdWJtaXQoKQogICAgQVBJLT4&#43;Uzog6K&#43;75Y&#43;W5ZCM5LiAIHJlbGVhc2VfaWQKICAgIFMtLT4&#43;UDog57uT5p6c5LiO5oql5ZGK">sequenceDiagram
    participant P as 参与者
    participant API as 运行 API
    participant T as 任务与发布包
    participant R as 运行实例
    participant S as 评分与报告
    P-&gt;&gt;API: start(taskId, token)
    API-&gt;&gt;T: 校验 access_mode 与 release_id
    T--&gt;&gt;API: 冻结快照
    API-&gt;&gt;R: 创建运行实例
    P-&gt;&gt;API: autosave(answer patch)
    API-&gt;&gt;R: 校验并保存规范化答案
    P-&gt;&gt;API: submit()
    API-&gt;&gt;S: 读取同一 release_id
    S--&gt;&gt;P: 结果与报告</div><h2 id="formdsl-是输入不是信任边界">FormDSL 是输入，不是信任边界</h2>
<p>运行服务从冻结快照解析题目类型、选项、必填规则和可见性条件。客户端提交的字段只作为候选值，服务端重新检查题目标识、数据类型、选项范围、矩阵结构和条件规则。题目被删除或版本不匹配时，提交失败并记录具体项，不把未知字段写入答案表。</p>
<p>答案保存分为原始接收和规范化结果。原始请求用于审计时应做长度和字段限制，评分只读取服务端生成的规范化对象。NUMBER 类型的答案使用 <code>numberValue</code>，不能依赖前端展示用的 <code>rawValue</code>。这个区别曾造成草稿试答提交失败，修复点在 <code>FrozenFormAnswerResolver</code>：它从冻结 FormDSL 解析标准值，再交给评分器。</p>
<h2 id="自动保存要可重放">自动保存要可重放</h2>
<p>自动保存请求携带 <code>runId</code>、客户端序号和答案补丁。服务端按题目标识合并补丁，并以运行实例版本或乐观锁防止旧请求覆盖新答案。重复请求返回同一版本，网络重试不会产生重复答案记录。保存成功只表示答案落盘，不表示题目已完成或评分已通过。</p>]]></description></item></channel></rss>