diff --git a/server/MiAssessment/src/MiAssessment.Admin.Business/Constants/BusinessPermissions.cs b/server/MiAssessment/src/MiAssessment.Admin.Business/Constants/BusinessPermissions.cs
index 6d4992c..8d6090b 100644
--- a/server/MiAssessment/src/MiAssessment.Admin.Business/Constants/BusinessPermissions.cs
+++ b/server/MiAssessment/src/MiAssessment.Admin.Business/Constants/BusinessPermissions.cs
@@ -257,6 +257,11 @@ public static class BusinessPermissions
/// 导出测评记录
///
public const string Export = "assessmentRecord:export";
+
+ ///
+ /// 删除测评记录
+ ///
+ public const string Delete = "assessmentRecord:delete";
}
#endregion
@@ -344,6 +349,7 @@ public static class BusinessPermissions
// 测评记录管理模块
new PermissionDefinition(AssessmentRecord.View, "查看测评记录", AssessmentRecord.Module, "查看测评记录列表和详情"),
new PermissionDefinition(AssessmentRecord.Export, "导出测评记录", AssessmentRecord.Module, "导出测评记录为Excel文件"),
+ new PermissionDefinition(AssessmentRecord.Delete, "删除测评记录", AssessmentRecord.Module, "删除测评记录"),
// 业务介绍页管理模块
new PermissionDefinition(BusinessPage.View, "查看业务介绍页", BusinessPage.Module, "查看业务介绍页列表和详情"),
diff --git a/server/MiAssessment/src/MiAssessment.Admin.Business/Controllers/AssessmentRecordController.cs b/server/MiAssessment/src/MiAssessment.Admin.Business/Controllers/AssessmentRecordController.cs
index 91ee32f..0a243f0 100644
--- a/server/MiAssessment/src/MiAssessment.Admin.Business/Controllers/AssessmentRecordController.cs
+++ b/server/MiAssessment/src/MiAssessment.Admin.Business/Controllers/AssessmentRecordController.cs
@@ -184,4 +184,33 @@ public class AssessmentRecordController : BusinessControllerBase
}
}
+ ///
+ /// 删除测评记录
+ ///
+ /// 删除请求
+ /// 操作结果
+ [HttpPost("delete")]
+ [BusinessPermission(BusinessPermissions.AssessmentRecord.Delete)]
+ public async Task Delete([FromBody] RegenerateReportRequest request)
+ {
+ if (request.Id <= 0)
+ {
+ return ValidationError("测评记录ID无效");
+ }
+
+ try
+ {
+ await _assessmentRecordService.DeleteRecordAsync(request.Id);
+ return Ok();
+ }
+ catch (BusinessException ex)
+ {
+ return Error(ex.Code, ex.Message);
+ }
+ catch (Exception)
+ {
+ return Error(ErrorCodes.SystemError, "删除测评记录失败");
+ }
+ }
+
}
diff --git a/server/MiAssessment/src/MiAssessment.Admin.Business/Services/AssessmentRecordService.cs b/server/MiAssessment/src/MiAssessment.Admin.Business/Services/AssessmentRecordService.cs
index 475cc44..a4050f7 100644
--- a/server/MiAssessment/src/MiAssessment.Admin.Business/Services/AssessmentRecordService.cs
+++ b/server/MiAssessment/src/MiAssessment.Admin.Business/Services/AssessmentRecordService.cs
@@ -595,6 +595,25 @@ public class AssessmentRecordService : IAssessmentRecordService
};
}
+ ///
+ public async Task DeleteRecordAsync(long id)
+ {
+ var record = await _dbContext.AssessmentRecords
+ .FirstOrDefaultAsync(r => r.Id == id && !r.IsDeleted);
+
+ if (record == null)
+ {
+ throw new BusinessException(ErrorCodes.AssessmentRecordNotFound, "测评记录不存在");
+ }
+
+ // 软删除
+ record.IsDeleted = true;
+ record.UpdateTime = DateTime.Now;
+ await _dbContext.SaveChangesAsync();
+
+ _logger.LogInformation("测评记录已删除,ID: {RecordId}", id);
+ }
+
#region 私有方法
///
diff --git a/server/MiAssessment/src/MiAssessment.Admin.Business/Services/Interfaces/IAssessmentRecordService.cs b/server/MiAssessment/src/MiAssessment.Admin.Business/Services/Interfaces/IAssessmentRecordService.cs
index d6abff5..1c9e750 100644
--- a/server/MiAssessment/src/MiAssessment.Admin.Business/Services/Interfaces/IAssessmentRecordService.cs
+++ b/server/MiAssessment/src/MiAssessment.Admin.Business/Services/Interfaces/IAssessmentRecordService.cs
@@ -48,4 +48,10 @@ public interface IAssessmentRecordService
/// 测评记录ID列表
/// 批量操作结果
Task BatchRegenerateReportAsync(List recordIds);
+
+ ///
+ /// 删除测评记录(软删除)
+ ///
+ /// 记录ID
+ Task DeleteRecordAsync(long id);
}
diff --git a/server/MiAssessment/src/MiAssessment.Admin/admin-web/src/api/business/assessmentRecord.ts b/server/MiAssessment/src/MiAssessment.Admin/admin-web/src/api/business/assessmentRecord.ts
index d73df56..b076af0 100644
--- a/server/MiAssessment/src/MiAssessment.Admin/admin-web/src/api/business/assessmentRecord.ts
+++ b/server/MiAssessment/src/MiAssessment.Admin/admin-web/src/api/business/assessmentRecord.ts
@@ -158,3 +158,12 @@ export function batchRegenerateReport(ids: number[]): Promise> {
+ return request({
+ url: '/admin/assessmentRecord/delete',
+ method: 'post',
+ data: { id }
+ })
+}
diff --git a/server/MiAssessment/src/MiAssessment.Admin/admin-web/src/views/business/assessment/record/index.vue b/server/MiAssessment/src/MiAssessment.Admin/admin-web/src/views/business/assessment/record/index.vue
index efd872a..31c3112 100644
--- a/server/MiAssessment/src/MiAssessment.Admin/admin-web/src/views/business/assessment/record/index.vue
+++ b/server/MiAssessment/src/MiAssessment.Admin/admin-web/src/views/business/assessment/record/index.vue
@@ -108,7 +108,7 @@
-
+
@@ -134,6 +134,15 @@
重新生成
+
+
+ 删除
+
@@ -286,7 +295,7 @@
* @description 查看用户测评记录、答案详情和测评报告,支持搜索、导出
*/
import { reactive, ref, onMounted } from 'vue'
-import { Search, Refresh, View, Download, Document, RefreshRight } from '@element-plus/icons-vue'
+import { Search, Refresh, View, Download, Document, RefreshRight, Delete } from '@element-plus/icons-vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import {
getRecordList,
@@ -295,6 +304,7 @@ import {
exportRecords,
regenerateReport,
batchRegenerateReport,
+ deleteRecord,
type AssessmentRecordItem,
type AssessmentRecordDetail,
type AssessmentReport,
@@ -629,6 +639,28 @@ async function handleBatchRegenerate() {
}
}
+/** 删除测评记录 */
+async function handleDelete(row: AssessmentRecordItem) {
+ try {
+ await ElMessageBox.confirm(
+ `确定要删除记录 ID=${row.id} 吗?删除后不可恢复。`,
+ '删除测评记录',
+ { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }
+ )
+ const res = await deleteRecord(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 handleExport() {
state.exportLoading = true
try {
diff --git a/server/MiAssessment/src/MiAssessment.Infrastructure/Cache/RedisService.cs b/server/MiAssessment/src/MiAssessment.Infrastructure/Cache/RedisService.cs
index 5f93524..95ab959 100644
--- a/server/MiAssessment/src/MiAssessment.Infrastructure/Cache/RedisService.cs
+++ b/server/MiAssessment/src/MiAssessment.Infrastructure/Cache/RedisService.cs
@@ -120,14 +120,20 @@ public class RedisService : IRedisService, IDisposable
if (_database == null || !_isConnected)
return null;
- // 使用 BRPOP 命令实现阻塞弹出
- var result = await _database.ExecuteAsync("BRPOP", key, (int)timeout.TotalSeconds);
- if (result.IsNull)
- return null;
+ // 使用非阻塞 RPOP + 轮询代替 BRPOP,避免 StackExchange.Redis 命令超时
+ // BRPOP 的阻塞时间会超过客户端的 syncTimeout/asyncTimeout 导致 RedisTimeoutException
+ var deadline = DateTime.UtcNow.Add(timeout);
+ while (DateTime.UtcNow < deadline)
+ {
+ var value = await _database.ListRightPopAsync(key);
+ if (!value.IsNullOrEmpty)
+ return value.ToString();
- // BRPOP 返回数组:[key, value]
- var results = (RedisResult[])result!;
- return results[1].ToString();
+ // 空队列时等待 1 秒后重试,避免频繁轮询
+ await Task.Delay(1000);
+ }
+
+ return null;
}
///