fix(assessment): 修复往期测评数据显示问题

- DTO新增Name和AssessmentTypeId字段,前端可显示测评人姓名
- 修正前端状态映射:1待测评 2测评中 3生成中 4已完成(与后端一致)
- 直接使用后端返回的statusText,避免前后端状态不同步
- 后端查询改用左连接,避免缺少关联数据时丢失记录
- 待测评/测评中状态点击可跳转继续答题
This commit is contained in:
zpc 2026-02-23 00:19:24 +08:00
parent 7a54c91154
commit 143a8fa5f2
3 changed files with 73 additions and 76 deletions

View File

@ -132,29 +132,39 @@ public class AssessmentService : IAssessmentService
// 获取总数
var total = await query.CountAsync();
// 分页查询
// 分页查询(使用左连接避免缺少关联数据时丢失记录)
var records = await query
.OrderByDescending(r => r.CreateTime)
.Skip((page - 1) * pageSize)
.Take(pageSize)
.Join(
.GroupJoin(
_dbContext.Orders.AsNoTracking(),
r => r.OrderId,
o => o.Id,
(r, o) => new { Record = r, Order = o }
(r, orders) => new { Record = r, Orders = orders }
)
.Join(
.SelectMany(
ro => ro.Orders.DefaultIfEmpty(),
(ro, o) => new { ro.Record, Order = o }
)
.GroupJoin(
_dbContext.AssessmentTypes.AsNoTracking(),
ro => ro.Record.AssessmentTypeId,
at => at.Id,
(ro, at) => new AssessmentHistoryDto
(ro, types) => new { ro.Record, ro.Order, Types = types }
)
.SelectMany(
rot => rot.Types.DefaultIfEmpty(),
(rot, at) => new AssessmentHistoryDto
{
Id = ro.Record.Id,
OrderNo = ro.Order.OrderNo,
AssessmentName = at.Name,
Status = ro.Record.Status,
StatusText = GetStatusText(ro.Record.Status),
TestDate = ro.Record.CreateTime.ToString("yyyy-MM-dd")
Id = rot.Record.Id,
OrderNo = rot.Order != null ? rot.Order.OrderNo : "",
AssessmentName = at != null ? at.Name : "多元智能测评",
Name = rot.Record.Name,
AssessmentTypeId = rot.Record.AssessmentTypeId,
Status = rot.Record.Status,
StatusText = GetStatusText(rot.Record.Status),
TestDate = rot.Record.CreateTime.ToString("yyyy-MM-dd")
}
)
.ToListAsync();

View File

@ -20,6 +20,16 @@ public class AssessmentHistoryDto
/// </summary>
public string AssessmentName { get; set; } = null!;
/// <summary>
/// 测评人姓名
/// </summary>
public string Name { get; set; } = null!;
/// <summary>
/// 测评类型ID
/// </summary>
public long AssessmentTypeId { get; set; }
/// <summary>
/// 状态1待测评 2测评中 3生成中 4已完成
/// </summary>

View File

@ -14,11 +14,12 @@ import Loading from '@/components/Loading/index.vue'
const userStore = useUserStore()
const { checkLogin } = useAuth()
//
//
const ASSESSMENT_STATUS = {
GENERATING: 1, //
COMPLETED: 2, //
FAILED: 3 //
PENDING: 1, //
TESTING: 2, //
GENERATING: 3, //
COMPLETED: 4 //
}
//
@ -32,44 +33,20 @@ const noMore = ref(false)
//
const isEmpty = computed(() => !loading.value && historyList.value.length === 0)
const hasMore = computed(() => historyList.value.length < total.value)
/**
* 获取测评状态文本
*/
function getStatusText(status) {
const statusMap = {
[ASSESSMENT_STATUS.GENERATING]: '生成中',
[ASSESSMENT_STATUS.COMPLETED]: '已完成',
[ASSESSMENT_STATUS.FAILED]: '生成失败'
}
return statusMap[status] || '未知状态'
}
/**
* 获取测评状态样式类
*/
function getStatusClass(status) {
const classMap = {
[ASSESSMENT_STATUS.PENDING]: 'status-pending',
[ASSESSMENT_STATUS.TESTING]: 'status-testing',
[ASSESSMENT_STATUS.GENERATING]: 'status-generating',
[ASSESSMENT_STATUS.COMPLETED]: 'status-completed',
[ASSESSMENT_STATUS.FAILED]: 'status-failed'
[ASSESSMENT_STATUS.COMPLETED]: 'status-completed'
}
return classMap[status] || ''
}
/**
* 格式化日期
*/
function formatDate(dateStr) {
if (!dateStr) return ''
const date = new Date(dateStr)
const year = date.getFullYear()
const month = String(date.getMonth() + 1).padStart(2, '0')
const day = String(date.getDate()).padStart(2, '0')
return `${year}-${month}-${day}`
}
/**
* 加载测评历史列表
*/
@ -142,6 +119,15 @@ onReachBottom(() => {
* 查看测评结果
*/
function viewResult(record) {
// -
if (record.status === ASSESSMENT_STATUS.COMPLETED) {
uni.navigateTo({
url: `/pages/assessment/result/index?recordId=${record.id}`
})
return
}
// -
if (record.status === ASSESSMENT_STATUS.GENERATING) {
uni.showToast({
title: '报告生成中,请稍后查看',
@ -150,24 +136,13 @@ function viewResult(record) {
return
}
if (record.status === ASSESSMENT_STATUS.FAILED) {
uni.showToast({
title: '报告生成失败,请联系客服',
icon: 'none'
// / -
if (record.status === ASSESSMENT_STATUS.PENDING || record.status === ASSESSMENT_STATUS.TESTING) {
uni.navigateTo({
url: `/pages/assessment/info/index?typeId=${record.assessmentTypeId || 1}`
})
return
}
uni.navigateTo({
url: `/pages/assessment/result/index?recordId=${record.id}`
})
}
/**
* 判断是否显示查看结果按钮
*/
function showViewResultBtn(status) {
return status === ASSESSMENT_STATUS.COMPLETED
}
/**
@ -201,28 +176,28 @@ onMounted(() => {
:key="record.id"
@click="viewResult(record)"
>
<!-- 卡片头部 -->
<!-- 卡片头部测评名称 + 状态 -->
<view class="card-header">
<view class="assessment-name">{{ record.assessmentName || '多元智能测评' }}</view>
<view class="assessment-status" :class="getStatusClass(record.status)">
{{ getStatusText(record.status) }}
{{ record.statusText }}
</view>
</view>
<!-- 卡片内容 -->
<!-- 卡片内容测评人 + 测评日期 -->
<view class="card-content">
<view class="info-row">
<text class="info-label">测评人</text>
<text class="info-value">{{ record.userName || '--' }}</text>
<text class="info-value">{{ record.name || '--' }}</text>
</view>
<view class="info-row">
<text class="info-label">测评日期</text>
<text class="info-value">{{ formatDate(record.createTime) }}</text>
<text class="info-value">{{ record.testDate || '--' }}</text>
</view>
</view>
<!-- 卡片底部操作 -->
<view class="card-footer" v-if="showViewResultBtn(record.status)">
<!-- 卡片底部已完成显示查看报告 -->
<view class="card-footer" v-if="record.status === ASSESSMENT_STATUS.COMPLETED">
<view class="view-btn">
<text>查看报告</text>
<view class="arrow-icon"></view>
@ -260,7 +235,6 @@ onMounted(() => {
padding-bottom: calc(#{$spacing-lg} + env(safe-area-inset-bottom));
}
//
.history-list {
.history-card {
background-color: $bg-white;
@ -269,7 +243,6 @@ onMounted(() => {
overflow: hidden;
box-shadow: $shadow-sm;
//
.card-header {
display: flex;
align-items: center;
@ -288,10 +261,16 @@ onMounted(() => {
padding: 4rpx 16rpx;
border-radius: $border-radius-sm;
// - 绿
&.status-completed {
color: $success-color;
background-color: rgba(82, 196, 26, 0.1);
// -
&.status-pending {
color: $warning-color;
background-color: rgba(250, 173, 20, 0.1);
}
// -
&.status-testing {
color: $primary-color;
background-color: rgba(74, 144, 226, 0.1);
}
// -
@ -300,15 +279,14 @@ onMounted(() => {
background-color: rgba(74, 144, 226, 0.1);
}
// -
&.status-failed {
color: $error-color;
background-color: rgba(255, 77, 79, 0.1);
// - 绿
&.status-completed {
color: $success-color;
background-color: rgba(82, 196, 26, 0.1);
}
}
}
//
.card-content {
padding: $spacing-md $spacing-lg;
@ -330,7 +308,6 @@ onMounted(() => {
}
}
//
.card-footer {
display: flex;
justify-content: flex-end;