Files
competition-website/app/model/bigQuestion.js
qubiaobiao 2ab0991310 fix(admin): 复核页选择题选项渲染修复 + 阅卷导出 Word + 评分两位小数(R28)
针对测试人员反馈的四项:
1) 复核明细「选择题大量空白」:options 为 text 列存 JSON 字符串,原先被原样透传,
   前端 v-for 对字符串逐字符迭代(op.key/op.text 皆 undefined)⇒ 每字符渲染一行。
   新增 parseOptions()(仅 string 才 JSON.parse,失败降级 null)。
2) 选项与答案不随机:仅题目用 RAND() 抽题,normalizeQuestion 无 shuffle,字母无歧义。
3) 评分精度:DECIMAL(6,1) -> DECIMAL(6,2),migration 026 覆盖 17 列(与 025 同范围),
   lib/decimal_score.js 与 11 个 model 注释同步;汇总收敛 round2(×100/100)。
4) 阅卷导出:GET /api/admin/big-answers/:group/export?ids=
   单选考生 -> 直接 .docx;多位/全部 -> 每位考生单独 .docx 打包 .zip。
   路由为 3 段,注册在 :group 通配段之前。

验证:verify_big_question 51 PASS/1 FAIL(唯一 FAIL=测试人员新数据,非本次改动)、
verify_score_leak_all_channels 24/24、verify_question_no_answer_leak 4/3/0/1。
2026-09-28 15:50:46 +08:00

93 lines
2.6 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use strict';
/**
* 综合大题模型 - BigQuestion
*
* 对应 big_questions 表(2026-09-21 新增)。
* 中职组(zhongzhi) / 高职组(gaozhi) 取消 Word 文件上传题后,改为从本表随机抽取一道大题:
* 题干 = 文字描述 + 富文本表格(HTML),下设三小问,每小问 score_per_sub 分(默认 10),
* 大题总分 total_score(默认 30)。
*
* 说明:本模型为**新增隔离模型**,与既有 word_questions(已弃用)互不影响,
* 也不参与 choice_questions / judge_questions 客观题链路。
*/
module.exports = app => {
const { STRING, INTEGER, DATE, TEXT } = app.Sequelize;
// 分数列统一走共享工厂(DECIMAL(6,2) + Number 兜底,见 app/lib/decimal_score.js)
const decimalScore = require('../lib/decimal_score')(app);
return app.model.define('BigQuestion', {
id: {
type: INTEGER,
primaryKey: true,
autoIncrement: true,
comment: '大题ID',
},
question_uid: {
type: STRING(64),
allowNull: false,
comment: '大题稳定标识(全局唯一,形如 big_12)',
},
group: {
type: STRING(20),
allowNull: false,
comment: '组别:zhongzhi/gaozhi',
},
title: {
type: STRING(200),
allowNull: false,
comment: '大题标题',
},
description: {
type: TEXT('medium'),
allowNull: true,
comment: '题干富文本 HTML(含表格)',
},
sub_prompt_1: {
type: TEXT,
allowNull: true,
comment: '第1小问题干',
},
sub_prompt_2: {
type: TEXT,
allowNull: true,
comment: '第2小问题干',
},
sub_prompt_3: {
type: TEXT,
allowNull: true,
comment: '第3小问题干',
},
score_per_sub: decimalScore('score_per_sub', '每小题分值', { allowNull: false, defaultValue: 10 }),
total_score: decimalScore('total_score', '大题总分', { allowNull: false, defaultValue: 30 }),
sort_order: {
type: INTEGER,
allowNull: false,
defaultValue: 0,
comment: '排序',
},
status: {
type: INTEGER,
allowNull: false,
defaultValue: 1,
comment: '状态:1=启用(参与抽题),0=停用',
},
created_at: {
type: DATE,
defaultValue: app.Sequelize.NOW,
comment: '创建时间',
},
updated_at: {
type: DATE,
defaultValue: app.Sequelize.NOW,
comment: '更新时间',
},
}, {
tableName: 'big_questions',
timestamps: true,
createdAt: 'created_at',
updatedAt: 'updated_at',
});
};