This commit is contained in:
zpc 2026-02-25 11:11:31 +08:00
parent ebb5225b2d
commit 934530c7f9
2 changed files with 111 additions and 6 deletions

View File

@ -135,3 +135,26 @@ export function exportRecords(params: AssessmentRecordQuery): Promise<ApiRespons
responseType: 'blob'
})
}
/** 批量重新生成结果 */
export interface BatchRegenerateResult {
successCount: number
skippedCount: number
}
/** 重新生成报告 */
export function regenerateReport(id: number): Promise<ApiResponse<null>> {
return request<null>({
url: '/admin/assessmentRecord/regenerateReport',
method: 'post',
data: { id }
})
}
/** 批量重新生成报告 */
export function batchRegenerateReport(ids: number[]): Promise<ApiResponse<BatchRegenerateResult>> {
return request<BatchRegenerateResult>({
url: '/admin/assessmentRecord/batchRegenerateReport',
method: 'post',
data: { ids }
})
}

View File

@ -8,6 +8,10 @@
<span class="page-description">查看用户测评记录答案详情和测评报告</span>
</div>
<div class="header-right">
<el-button type="warning" @click="handleBatchRegenerate" :loading="state.batchRegenerateLoading">
<el-icon><RefreshRight /></el-icon>
批量重新生成
</el-button>
<el-button type="success" @click="handleExport" :loading="state.exportLoading">
<el-icon><Download /></el-icon>
导出Excel
@ -33,6 +37,7 @@
<el-option label="测评中" :value="2" />
<el-option label="生成中" :value="3" />
<el-option label="已完成" :value="4" />
<el-option label="生成失败" :value="5" />
</el-select>
</el-form-item>
<el-form-item label="创建时间">
@ -62,7 +67,8 @@
<!-- 数据表格 -->
<el-card v-loading="state.loading" class="table-card">
<el-table :data="state.tableData" row-key="id" stripe>
<el-table :data="state.tableData" row-key="id" stripe @selection-change="handleSelectionChange">
<el-table-column type="selection" width="50" />
<el-table-column prop="id" label="ID" width="80" />
<el-table-column label="用户" min-width="120">
<template #default="{ row }">
@ -102,7 +108,7 @@
</template>
</el-table-column>
<el-table-column prop="createTime" label="创建时间" width="170" align="center" />
<el-table-column label="操作" width="160" fixed="right" align="center">
<el-table-column label="操作" width="230" fixed="right" align="center">
<template #default="{ row }">
<el-button type="primary" link size="small" @click="handleViewDetail(row)">
<el-icon><View /></el-icon>
@ -118,6 +124,16 @@
<el-icon><Document /></el-icon>
报告
</el-button>
<el-button
v-if="row.status === 3 || row.status === 5"
type="warning"
link
size="small"
@click="handleRegenerate(row)"
>
<el-icon><RefreshRight /></el-icon>
重新生成
</el-button>
</template>
</el-table-column>
</el-table>
@ -270,13 +286,15 @@
* @description 查看用户测评记录答案详情和测评报告支持搜索导出
*/
import { reactive, ref, onMounted } from 'vue'
import { Search, Refresh, View, Download, Document } from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus'
import { Search, Refresh, View, Download, Document, RefreshRight } from '@element-plus/icons-vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import {
getRecordList,
getRecordDetail,
getRecordReport,
exportRecords,
regenerateReport,
batchRegenerateReport,
type AssessmentRecordItem,
type AssessmentRecordDetail,
type AssessmentReport,
@ -331,6 +349,8 @@ interface RecordPageState {
report: AssessmentReport | null
exportLoading: boolean
scoreOptionMap: Map<number, ScoreOptionItem>
batchRegenerateLoading: boolean
selectedRows: AssessmentRecordItem[]
}
// ============ Refs ============
@ -359,7 +379,9 @@ const state = reactive<RecordPageState>({
reportLoading: false,
report: null,
exportLoading: false,
scoreOptionMap: new Map()
scoreOptionMap: new Map(),
batchRegenerateLoading: false,
selectedRows: []
})
// ============ Helper Functions ============
@ -368,12 +390,13 @@ const state = reactive<RecordPageState>({
* 获取状态标签类型
* 待测评=info, 测评中=primary, 生成中=warning, 已完成=success
*/
function getStatusTagType(status: number): 'info' | 'primary' | 'warning' | 'success' {
function getStatusTagType(status: number): 'info' | 'primary' | 'warning' | 'success' | 'danger' {
switch (status) {
case 1: return 'info'
case 2: return 'primary'
case 3: return 'warning'
case 4: return 'success'
case 5: return 'danger'
default: return 'info'
}
}
@ -547,6 +570,65 @@ function handleViewReport(row: AssessmentRecordItem) {
loadRecordReport(row.id)
}
/** 表格选择变化 */
function handleSelectionChange(rows: AssessmentRecordItem[]) {
state.selectedRows = rows
}
/** 单条重新生成报告 */
async function handleRegenerate(row: AssessmentRecordItem) {
try {
await ElMessageBox.confirm(
`确定要重新生成记录 ID=${row.id} 的报告吗?`,
'重新生成报告',
{ confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }
)
const res = await regenerateReport(row.id)
if (res.code === 0) {
ElMessage.success('已提交重新生成,请稍后刷新查看')
loadRecordList()
} else {
throw new Error(res.message || '重新生成失败')
}
} catch (error) {
if (error === 'cancel' || (error as any)?.toString?.().includes('cancel')) return
const message = error instanceof Error ? error.message : '重新生成失败'
ElMessage.error(message)
}
}
/** 批量重新生成报告 */
async function handleBatchRegenerate() {
const eligibleRows = state.selectedRows.filter(r => r.status === 3 || r.status === 5)
if (eligibleRows.length === 0) {
ElMessage.warning('请先勾选状态为"生成中"或"生成失败"的记录')
return
}
try {
await ElMessageBox.confirm(
`已选中 ${eligibleRows.length} 条符合条件的记录,确定批量重新生成?`,
'批量重新生成报告',
{ confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }
)
state.batchRegenerateLoading = true
const ids = eligibleRows.map(r => r.id)
const res = await batchRegenerateReport(ids)
if (res.code === 0) {
const { successCount, skippedCount } = res.data!
ElMessage.success(`成功入队 ${successCount} 条,跳过 ${skippedCount}`)
loadRecordList()
} else {
throw new Error(res.message || '批量重新生成失败')
}
} catch (error) {
if (error === 'cancel' || (error as any)?.toString?.().includes('cancel')) return
const message = error instanceof Error ? error.message : '批量重新生成失败'
ElMessage.error(message)
} finally {
state.batchRegenerateLoading = false
}
}
async function handleExport() {
state.exportLoading = true
try {