fix(frontend): 重置测试数据文案对齐后端契约(未激活+需短信激活)并透传后端 message

- Admin.vue 确认弹窗:「已激活 + 默认口令」→「未激活 + 默认口令」
  (后端 service/admin.js:1619 实际置 activated:false)
- Admin.vue 提示行:「重置后可直接用默认口令登录重测」→「需先用默认口令完成短信激活才能登录重测」
- Admin.vue 成功提示: 改为透传后端 message(后端 :1730 已含正确指引),不再自拼后丢弃
- api/request.js: 新增可选开关 returnMessage(不传时默认行为完全不变)
- api/admin.js: resetTestData 启用该开关,后端成为唯一真相源

依据: service/admin.js:1619/:1730 + scripts/verify_testdata_mgmt.py:5-9「Req2 重置须重置账号激活状态」
This commit is contained in:
2026-09-30 10:27:40 +08:00
parent 4e7493a809
commit f77330ad27
3 changed files with 26 additions and 6 deletions

View File

@@ -341,10 +341,15 @@ export function toggleTestFlag(id, testFlag) {
/** /**
* 重置测试数据(仅重置 test_flag=1 的选手及其提交记录) * 重置测试数据(仅重置 test_flag=1 的选手及其提交记录)
* @returns {Promise} *
* returnMessage: true —— 保留后端 message(不再被响应拦截器丢弃)。
* 后端提示含「已恢复为『未激活 + 默认口令 X』,需先用默认口令完成短信激活即可登录重测」
* 这一关键指引;前端自拼文案曾写成「可直接用默认口令登录重测」,
* 与后端 activated:false 自相矛盾(用户反馈 Req2)。以后端文案为唯一真相源。
* @returns {Promise<{code:number,message:string,data:object}>}
*/ */
export function resetTestData() { export function resetTestData() {
return request.post('/admin/reset-test-data') return request.post('/admin/reset-test-data', null, { returnMessage: true })
} }
// ==================== 综合大题管理(中职/高职) ==================== // ==================== 综合大题管理(中职/高职) ====================

View File

@@ -168,6 +168,13 @@ request.interceptors.response.use(
return Promise.reject(new Error(res.message || '请求失败')) return Promise.reject(new Error(res.message || '请求失败'))
} }
// 正常返回,只暴露 data 部分 // 正常返回,只暴露 data 部分
// 例外:调用方显式传 config.returnMessage = true 时返回**整个业务体**(含 message)。
// 用途:需要原样透传后端提示文案的场景(如「重置测试数据」的结果指引含
// 「需先用默认口令完成短信激活」等关键信息,前端自拼文案会与后端契约漂移)。
// ⛔ 默认行为完全不变(不传该开关时仍只返回 data)。
if (response.config && response.config.returnMessage) {
return res
}
return res.data !== undefined ? res.data : res return res.data !== undefined ? res.data : res
} }

View File

@@ -104,7 +104,7 @@
<!-- 测试数据重置 --> <!-- 测试数据重置 -->
<div class="reset-section"> <div class="reset-section">
<el-popconfirm <el-popconfirm
title="⚠️ 此操作将重置所有标记为「测试」的选手数据(恢复为「已激活 + 默认口令」,并清空提交记录),确定继续?" title="⚠️ 此操作将重置所有标记为「测试」的选手数据(账号恢复为「未激活 + 默认口令」,并清空提交记录与已上传的作品文件),确定继续?"
confirm-button-text="确认重置" confirm-button-text="确认重置"
cancel-button-text="取消" cancel-button-text="取消"
confirm-button-type="danger" confirm-button-type="danger"
@@ -116,7 +116,7 @@
</el-button> </el-button>
</template> </template>
</el-popconfirm> </el-popconfirm>
<span class="reset-hint">仅重置标记为"测试"的选手数据,生产数据不受影响。重置后可直接用默认口令「{{ testDefaultPasswordHint }}」登录重测</span> <span class="reset-hint">仅重置标记为"测试"的选手数据,生产数据不受影响。⚠️ 重置后账号回到「未激活」,需先用默认口令「{{ testDefaultPasswordHint }}」完成短信激活才能登录重测</span>
</div> </div>
</template> </template>
@@ -1687,11 +1687,19 @@ async function handleToggleTestFlag(row, val) {
async function handleResetTestData() { async function handleResetTestData() {
resetLoading.value = true resetLoading.value = true
try { try {
const data = await adminApi.resetTestData() // returnMessage 模式:拿到完整业务体,以便透传后端 message。
// 后端提示含「已恢复为『未激活 + 默认口令 X』,需先用默认口令完成短信激活即可登录重测」
// —— 这才是唯一真相源;此前前端自拼成「可直接用默认口令登录重测」,
// 与后端 activated:false 自相矛盾(用户反馈 Req2),已弃用自拼文案。
const res = await adminApi.resetTestData()
const data = (res && res.data) || res || {}
if (data.testContestantsFound === 0) { if (data.testContestantsFound === 0) {
ElMessage.warning('没有找到测试数据,请先在选手管理中将选手标记为"测试"') ElMessage.warning('没有找到测试数据,请先在选手管理中将选手标记为"测试"')
} else { } else {
ElMessage.success(`测试数据已重置:${data.contestantsReset} 名选手,${data.examSubmissionsDeleted + data.workSubmissionsDeleted} 条提交记录`) ElMessage.success((res && res.message)
|| `测试数据已重置:${data.contestantsReset} 名选手,`
+ `${(data.examSubmissionsDeleted || 0) + (data.workSubmissionsDeleted || 0)} 条提交记录。`
+ '账号已回到「未激活」,需先用默认口令完成短信激活才能登录重测')
} }
// 刷新统计数据 // 刷新统计数据
await fetchStats() await fetchStats()