diff --git a/src/api/admin.js b/src/api/admin.js index c3128e7..2ec14e3 100644 --- a/src/api/admin.js +++ b/src/api/admin.js @@ -84,6 +84,17 @@ export function setTimes(data) { return request.put('/admin/times', { times }) } +/** + * 节点备份调度器状态(P1「生产备份静默失败」可见性) + * + * silent: true —— 本接口是「状态展示」而非「用户动作」,失败由页面内提示承载, + * 不希望拦截器再弹一次全局错误(同族双弹纪律)。 + * @returns {Promise} { available, enabled, isProduction, buffer, keepDays, plans, history, artifacts, health, paths } + */ +export function getNodeBackupStatus() { + return request.get('/admin/node-backup/status', { silent: true }) +} + /** * 设置评分 * @param {string} group - 组别标识 @@ -477,6 +488,61 @@ export function setBigAnswerScores(group, uid, scores) { return request.put(`/admin/big-answers/${group}/${uid}/scores`, scores) } +/** + * 下载「综合大题成绩导入」模板(R172) + * + * 模板两页:`成绩导入`(小组编号 / 分数)+ `填写说明`。 + * @param {string} group - 组别标识(zhongzhi / gaozhi) + * @returns {Promise} + */ +export function getBigScoreImportTemplate(group) { + return request.get(`/admin/big-answers/${group}/import-template`, { + responseType: 'blob', + timeout: 60000, + }) +} + +/** + * 预览成绩导入(R172 · ⛔ 零写入;R174 改三小问四列制) + * + * 服务端逐行判定:可导入 / 将覆盖 / 被拒绝(附原因),前端据此让管理员确认后再导入。 + * @param {string} group + * @param {FormData} formData - 含 Excel 文件(字段名 file) + * @returns {Promise} { + * total, importable, overwritable, blocked, skippedBlank, + * rows: [{ row, teamNumber, subRaws, subs, total, status, message, blocking, + * contestantId, contestantName, contestantIdNumber, teamUid, + * memberCount, operatorCount, currentScores }] + * } + * · subRaws = 三小问原始填报值(报错行也有,用于定位) + * · subs = 校验通过后的三小问得分;total = 三者之和(判定通过时才有) + */ +export function previewBigScoreImport(group, formData) { + // silent: true —— 错误提示由调用方统一给出,避免拦截器 + 调用方双弹 + return request.post(`/admin/big-answers/${group}/import-preview`, formData, { + timeout: 120000, + silent: true, + }) +} + +/** + * 执行成绩导入(R172) + * + * 写入仍走唯一评分路径(setSubScores → service.admin.updateScores), + * 不新增第二条写成绩通路。 + * @param {string} group + * @param {FormData} formData - 含 Excel 文件(字段名 file) + * @param {boolean} [overwrite=false] - 是否覆盖已评分 + * @returns {Promise} { imported, skipped, overwritten, errors: [{ row, teamNumber, message }] } + */ +export function importBigScores(group, formData, overwrite = false) { + return request.post(`/admin/big-answers/${group}/import-scores`, formData, { + params: { overwrite: overwrite ? 1 : 0 }, + timeout: 300000, + silent: true, + }) +} + // ==================== 成绩复核 ==================== // 场景:考生对成绩有异议 → 按「姓名 / 身份证号 / 电话」任一检索 → 核对全卷题目与作答。 diff --git a/src/views/Admin.vue b/src/views/Admin.vue index 34eb1b4..c70d9ed 100644 --- a/src/views/Admin.vue +++ b/src/views/Admin.vue @@ -752,6 +752,18 @@ @@ -945,6 +1057,14 @@ + +
导出全部 Word + + + 下载成绩模板 + 导入成绩 + 共 {{ bigAnswersTotal }} 人,已抽题 {{ bigAnswersDrawn }} 人 @@ -1043,6 +1191,14 @@ > + + + + @@ -1099,6 +1255,87 @@ + + + + +
+ 共 {{ bigScorePreview.total }} 行 + 可导入 {{ bigScorePreview.importable }} + 将覆盖 {{ bigScorePreview.overwritable }} + 被拒绝 {{ bigScorePreview.blocked }} + 空行 {{ bigScorePreview.skippedBlank }} +
+ + + + + + + + + + + + + + + + + + +