Merge branch 'master' of http://192.168.195.14:3000/outsource/mi-assessment
This commit is contained in:
commit
feb181a130
|
|
@ -34,7 +34,8 @@ public class AssessmentRecordService : IAssessmentRecordService
|
|||
{ 3, "生成中" },
|
||||
{ 4, "已完成" },
|
||||
{ 5, "生成失败" },
|
||||
{ 6, "数据已就绪" }
|
||||
{ 6, "数据已就绪" },
|
||||
{ 7, "需重测" }
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -106,10 +106,14 @@
|
|||
<el-table-column prop="orderNo" label="订单号" width="170" show-overflow-tooltip />
|
||||
<el-table-column prop="submitTime" label="提交时间" width="170" align="center">
|
||||
<template #default="{ row }">
|
||||
{{ row.submitTime || '-' }}
|
||||
{{ formatDateTime(row.submitTime) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="创建时间" width="170" align="center">
|
||||
<template #default="{ row }">
|
||||
{{ formatDateTime(row.createTime) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="createTime" label="创建时间" width="170" align="center" />
|
||||
<el-table-column label="操作" width="380" fixed="right" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-button type="primary" link size="small" @click="handleViewDetail(row)">
|
||||
|
|
@ -219,10 +223,10 @@
|
|||
</el-tag>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="订单号" :span="2">{{ state.detail.orderNo || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="开始时间">{{ state.detail.startTime || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="提交时间">{{ state.detail.submitTime || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="完成时间">{{ state.detail.completeTime || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="创建时间">{{ state.detail.createTime }}</el-descriptions-item>
|
||||
<el-descriptions-item label="开始时间">{{ formatDateTime(state.detail.startTime) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="提交时间">{{ formatDateTime(state.detail.submitTime) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="完成时间">{{ formatDateTime(state.detail.completeTime) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="创建时间">{{ formatDateTime(state.detail.createTime) }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</div>
|
||||
|
||||
|
|
@ -482,6 +486,16 @@ const editConclusionDialogVisible = computed({
|
|||
|
||||
// ============ Helper Functions ============
|
||||
|
||||
/**
|
||||
* 格式化时间戳:去掉T,秒数不带小数点
|
||||
* 例:2026-03-31T07:50:35.7396316 → 2026-03-31 07:50:35
|
||||
*/
|
||||
function formatDateTime(val: string | null | undefined): string {
|
||||
if (!val) return '-'
|
||||
// 取到秒(前19位),将T替换为两个空格
|
||||
return val.substring(0, 19).replace('T', ' ')
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取状态标签类型
|
||||
* 待支付=info, 待测评=info, 测评中=primary, 生成中=warning, 已完成=success
|
||||
|
|
@ -495,6 +509,7 @@ function getStatusTagType(status: number): 'info' | 'primary' | 'warning' | 'suc
|
|||
case 4: return 'success'
|
||||
case 5: return 'danger'
|
||||
case 6: return 'primary'
|
||||
case 7: return 'warning'
|
||||
default: return 'info'
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using System.Text.Json;
|
||||
using MiAssessment.Core.Exceptions;
|
||||
using MiAssessment.Core.Interfaces;
|
||||
using MiAssessment.Core.Models;
|
||||
using MiAssessment.Core.Services;
|
||||
|
|
@ -165,6 +166,13 @@ public class ReportQueueConsumer : BackgroundService
|
|||
await UpdateRecordStatusToFailedAsync(message.RecordId);
|
||||
}
|
||||
}
|
||||
catch (AllScoresEqualException asEx)
|
||||
{
|
||||
// 同分异常:不重试,直接设置状态为需重测(Status=7)
|
||||
_logger.LogWarning("检测到全同分情况,RecordId: {RecordId}, ScoreType: {ScoreType}, Message: {Message}",
|
||||
message.RecordId, asEx.ScoreType, asEx.Message);
|
||||
await UpdateRecordStatusToRetestAsync(message.RecordId);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// 报告生成失败,执行重试或死信逻辑
|
||||
|
|
@ -257,4 +265,41 @@ public class ReportQueueConsumer : BackgroundService
|
|||
_logger.LogError(ex, "更新测评记录状态为生成失败时发生异常,RecordId: {RecordId}", recordId);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新测评记录状态为需重测(Status=7)
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 当检测到八大智能8项全同分或40项细分维度全同分时调用,
|
||||
/// 不生成PDF,提示用户重新测评。
|
||||
/// </remarks>
|
||||
/// <param name="recordId">测评记录ID</param>
|
||||
private async Task UpdateRecordStatusToRetestAsync(long recordId)
|
||||
{
|
||||
try
|
||||
{
|
||||
using var scope = _serviceScopeFactory.CreateScope();
|
||||
var dbContext = scope.ServiceProvider.GetRequiredService<MiAssessmentDbContext>();
|
||||
|
||||
var record = await dbContext.AssessmentRecords
|
||||
.FirstOrDefaultAsync(r => r.Id == recordId);
|
||||
|
||||
if (record != null)
|
||||
{
|
||||
record.Status = 7;
|
||||
record.UpdateTime = DateTime.Now;
|
||||
await dbContext.SaveChangesAsync();
|
||||
|
||||
_logger.LogInformation("测评记录状态已更新为需重测,RecordId: {RecordId}", recordId);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogWarning("更新状态失败,测评记录不存在,RecordId: {RecordId}", recordId);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "更新测评记录状态为需重测时发生异常,RecordId: {RecordId}", recordId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,5 +14,7 @@ RUN dotnet publish "src/MiAssessment.Api/MiAssessment.Api.csproj" -c Release -o
|
|||
|
||||
FROM base AS final
|
||||
WORKDIR /app
|
||||
# 安装字体(页码渲染需要)
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends fonts-dejavu-core && rm -rf /var/lib/apt/lists/*
|
||||
COPY --from=build /app/publish .
|
||||
ENTRYPOINT ["dotnet", "MiAssessment.Api.dll"]
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
namespace MiAssessment.Core.Exceptions;
|
||||
|
||||
/// <summary>
|
||||
/// 所有分数相同异常(八大智能全同分或40项细分全同分)
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 当检测到八大智能8项全部同分或40项细分维度全部同分时抛出,
|
||||
/// 表示无法生成有效的差异化报告,需要用户重新测评。
|
||||
/// </remarks>
|
||||
public class AllScoresEqualException : Exception
|
||||
{
|
||||
/// <summary>
|
||||
/// 同分类型:Intelligence=八大智能同分,Ability=细分维度同分
|
||||
/// </summary>
|
||||
public string ScoreType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="scoreType">同分类型</param>
|
||||
/// <param name="message">异常信息</param>
|
||||
public AllScoresEqualException(string scoreType, string message)
|
||||
: base(message)
|
||||
{
|
||||
ScoreType = scoreType;
|
||||
}
|
||||
}
|
||||
|
|
@ -119,6 +119,11 @@ public class AssessmentService : IAssessmentService
|
|||
{
|
||||
record.Message = "报告生成失败,请联系客服";
|
||||
}
|
||||
// 对需重测状态设置提示信息
|
||||
else if (record.Status == 7)
|
||||
{
|
||||
record.Message = "分析得出多个智能处于同一梯队,我们需要更细致的分析维度,接下来请您重新进行测评";
|
||||
}
|
||||
|
||||
_logger.LogDebug("查询报告状态成功,status: {Status}, isCompleted: {IsCompleted}", record.Status, record.IsCompleted);
|
||||
}
|
||||
|
|
@ -218,8 +223,8 @@ public class AssessmentService : IAssessmentService
|
|||
throw new UnauthorizedAccessException("无权限访问该测评记录");
|
||||
}
|
||||
|
||||
// 验证记录状态(只有待测评或测评中状态才能提交答案)
|
||||
if (record.Status != 1 && record.Status != 2)
|
||||
// 验证记录状态(只有待测评、测评中或需重测状态才能提交答案)
|
||||
if (record.Status != 1 && record.Status != 2 && record.Status != 7)
|
||||
{
|
||||
_logger.LogWarning("测评记录状态不允许提交答案,status: {Status}, recordId: {RecordId}",
|
||||
record.Status, request.RecordId);
|
||||
|
|
@ -655,6 +660,7 @@ public class AssessmentService : IAssessmentService
|
|||
4 => "已完成",
|
||||
5 => "生成失败",
|
||||
6 => "报告生成中",
|
||||
7 => "需重测",
|
||||
_ => "未知"
|
||||
};
|
||||
}
|
||||
|
|
@ -689,7 +695,7 @@ public class AssessmentService : IAssessmentService
|
|||
.AsNoTracking()
|
||||
.Where(r => r.UserId == userId
|
||||
&& r.AssessmentTypeId == typeId
|
||||
&& (r.Status == 1 || r.Status == 2)
|
||||
&& (r.Status == 1 || r.Status == 2 || r.Status == 7)
|
||||
&& !r.IsDeleted)
|
||||
.OrderByDescending(r => r.CreateTime)
|
||||
.Select(r => new PendingRecordDto
|
||||
|
|
|
|||
|
|
@ -904,6 +904,7 @@ public class OrderService : IOrderService
|
|||
4 => "已测评",
|
||||
5 => "生成失败",
|
||||
6 => "报告生成中",
|
||||
7 => "待测评",
|
||||
_ => GetOrderStatusText(orderStatus)
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -449,17 +449,27 @@ public class PdfGenerationService : IPdfGenerationService
|
|||
private static void BuildAndSavePdf(List<byte[]> images, string filePath)
|
||||
{
|
||||
using var document = new PdfDocument();
|
||||
var totalPages = images.Count;
|
||||
var font = new XFont("DejaVu Sans", 10, XFontStyle.Regular);
|
||||
var brush = new XSolidBrush(XColor.FromArgb(153, 153, 153)); // #999999
|
||||
|
||||
foreach (var imageBytes in images)
|
||||
for (var i = 0; i < totalPages; i++)
|
||||
{
|
||||
var imageBytes = images[i];
|
||||
var page = document.AddPage();
|
||||
page.Width = XUnit.FromPoint(PageWidthPt);
|
||||
page.Height = XUnit.FromPoint(PageHeightPt);
|
||||
|
||||
using var stream = new MemoryStream(imageBytes);
|
||||
using var xImage = XImage.FromStream(() => new MemoryStream(imageBytes));
|
||||
using var gfx = XGraphics.FromPdfPage(page);
|
||||
gfx.DrawImage(xImage, 0, 0, page.Width, page.Height);
|
||||
|
||||
// 绘制页码(底部居中)
|
||||
var pageNumber = $"{i + 1} / {totalPages}";
|
||||
var size = gfx.MeasureString(pageNumber, font);
|
||||
var x = (page.Width - size.Width) / 2;
|
||||
var y = page.Height - 20; // 距底部 20pt
|
||||
gfx.DrawString(pageNumber, font, brush, x, y);
|
||||
}
|
||||
|
||||
document.Save(filePath);
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
using MiAssessment.Core.Exceptions;
|
||||
using MiAssessment.Model.Data;
|
||||
using MiAssessment.Model.Entities;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
|
@ -60,6 +61,9 @@ public class ReportGenerationService
|
|||
_logger.LogDebug("父级汇总完成,recordId: {RecordId}, 新增父级数量: {Count}, 总数量: {Total}",
|
||||
recordId, parentScores.Count, categoryScores.Count);
|
||||
|
||||
// 步骤3.6:检测同分情况(八大智能全同分或细分维度全同分)
|
||||
CheckAllScoresEqual(categoryScores);
|
||||
|
||||
// 步骤4:按 CategoryType 分组排名
|
||||
var rankedScores = CalculateRanks(categoryScores);
|
||||
|
||||
|
|
@ -300,6 +304,39 @@ public class ReportGenerationService
|
|||
return parentScores;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检测同分情况:八大智能8项全同分或细分维度全同分
|
||||
/// </summary>
|
||||
/// <param name="categoryScores">所有分类得分(含叶子和父级)</param>
|
||||
/// <exception cref="AllScoresEqualException">当检测到全同分时抛出</exception>
|
||||
internal static void CheckAllScoresEqual(List<CategoryScore> categoryScores)
|
||||
{
|
||||
// CategoryType=1 为八大智能(父级汇总后的得分)
|
||||
var intelligenceScores = categoryScores
|
||||
.Where(s => s.CategoryType == 1)
|
||||
.Select(s => s.Percentage)
|
||||
.ToList();
|
||||
|
||||
if (intelligenceScores.Count >= 8 && intelligenceScores.Distinct().Count() == 1)
|
||||
{
|
||||
throw new AllScoresEqualException("Intelligence",
|
||||
$"八大智能8项得分全部相同({intelligenceScores.First()}%),无法生成差异化报告");
|
||||
}
|
||||
|
||||
// CategoryType=3 为细分能力维度
|
||||
var abilityScores = categoryScores
|
||||
.Where(s => s.CategoryType == 3)
|
||||
.Select(s => s.Percentage)
|
||||
.ToList();
|
||||
|
||||
if (abilityScores.Count >= 40 && abilityScores.Distinct().Count() == 1)
|
||||
{
|
||||
throw new AllScoresEqualException("Ability",
|
||||
$"40项细分维度得分全部相同({abilityScores.First()}%),无法生成差异化报告");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 分类得分计算结果
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ namespace MiAssessment.Model.Models.Assessment;
|
|||
public class ResultStatusDto
|
||||
{
|
||||
/// <summary>
|
||||
/// 状态:0待支付 1待测评 2测评中 3生成中 4已完成 5生成失败
|
||||
/// 状态:0待支付 1待测评 2测评中 3生成中 4已完成 5生成失败 6数据已就绪 7需重测
|
||||
/// </summary>
|
||||
public int Status { get; set; }
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name" : "学业邑规划",
|
||||
"appid" : "__UNI__A612028",
|
||||
"appid" : "__UNI__1BAACAB",
|
||||
"description" : "",
|
||||
"versionName" : "1.0.0",
|
||||
"versionCode" : "100",
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
"path": "pages/team/index",
|
||||
"style": {
|
||||
"navigationStyle": "custom",
|
||||
"navigationBarTitleText": "团队"
|
||||
"navigationBarTitleText": "产品"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -147,7 +147,7 @@
|
|||
},
|
||||
{
|
||||
"pagePath": "pages/team/index",
|
||||
"text": "团队",
|
||||
"text": "产品",
|
||||
"iconPath": "static/tabbar/message.png",
|
||||
"selectedIconPath": "static/tabbar/message_s.png"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -21,7 +21,8 @@ const ASSESSMENT_STATUS = {
|
|||
GENERATING: 3, // 生成中
|
||||
COMPLETED: 4, // 已完成
|
||||
FAILED: 5, // 生成失败
|
||||
DATA_READY: 6 // 数据已就绪(PDF生成中)
|
||||
DATA_READY: 6, // 数据已就绪(PDF生成中)
|
||||
NEED_RETEST: 7 // 需重测(全同分)
|
||||
}
|
||||
|
||||
// 状态
|
||||
|
|
@ -46,7 +47,8 @@ function getStatusClass(status) {
|
|||
[ASSESSMENT_STATUS.GENERATING]: 'status-generating',
|
||||
[ASSESSMENT_STATUS.COMPLETED]: 'status-completed',
|
||||
[ASSESSMENT_STATUS.FAILED]: 'status-failed',
|
||||
[ASSESSMENT_STATUS.DATA_READY]: 'status-generating'
|
||||
[ASSESSMENT_STATUS.DATA_READY]: 'status-generating',
|
||||
[ASSESSMENT_STATUS.NEED_RETEST]: 'status-retest'
|
||||
}
|
||||
return classMap[status] || ''
|
||||
}
|
||||
|
|
@ -155,6 +157,14 @@ function viewResult(record) {
|
|||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 需重测 - 跳转到测评首页重新开始
|
||||
if (record.status === ASSESSMENT_STATUS.NEED_RETEST) {
|
||||
uni.navigateTo({
|
||||
url: `/pages/assessment/info/index?typeId=${record.assessmentTypeId || 1}`
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -208,13 +218,19 @@ onMounted(() => {
|
|||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 卡片底部:已完成显示查看报告 -->
|
||||
<!-- 卡片底部:已完成显示查看报告,需重测显示重新测试 -->
|
||||
<view class="card-footer" v-if="record.status === ASSESSMENT_STATUS.COMPLETED || record.status === ASSESSMENT_STATUS.DATA_READY">
|
||||
<view class="view-btn">
|
||||
<text>查看报告</text>
|
||||
<view class="arrow-icon"></view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="card-footer" v-else-if="record.status === ASSESSMENT_STATUS.NEED_RETEST">
|
||||
<view class="view-btn retest-btn">
|
||||
<text>重新测试</text>
|
||||
<view class="arrow-icon"></view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 加载更多 -->
|
||||
|
|
@ -296,6 +312,18 @@ onMounted(() => {
|
|||
color: $success-color;
|
||||
background-color: rgba(82, 196, 26, 0.1);
|
||||
}
|
||||
|
||||
// 生成失败 - 红色
|
||||
&.status-failed {
|
||||
color: $error-color;
|
||||
background-color: rgba(255, 77, 79, 0.1);
|
||||
}
|
||||
|
||||
// 需重测 - 橙色
|
||||
&.status-retest {
|
||||
color: $warning-color;
|
||||
background-color: rgba(250, 173, 20, 0.1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -331,6 +359,15 @@ onMounted(() => {
|
|||
align-items: center;
|
||||
color: $primary-color;
|
||||
font-size: $font-size-md;
|
||||
|
||||
&.retest-btn {
|
||||
color: $warning-color;
|
||||
|
||||
.arrow-icon {
|
||||
border-right-color: $warning-color;
|
||||
border-bottom-color: $warning-color;
|
||||
}
|
||||
}
|
||||
|
||||
.arrow-icon {
|
||||
width: 12rpx;
|
||||
|
|
|
|||
|
|
@ -584,53 +584,59 @@
|
|||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 邀请码弹窗 -->
|
||||
<view v-if="showInvitePopup" class="popup-mask" @click="closeInvitePopup">
|
||||
<view class="popup-container" @click.stop>
|
||||
<view class="popup-header">
|
||||
<text class="popup-title">填写测评邀请码</text>
|
||||
<view class="popup-close" @click="closeInvitePopup">
|
||||
<text>×</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="popup-body">
|
||||
<input class="invite-input" type="text" placeholder="请输入5位邀请码"
|
||||
placeholder-style="letter-spacing: 0rpx;" :value="inviteCode" @input="onInviteCodeInput"
|
||||
maxlength="5" />
|
||||
</view>
|
||||
<view class="popup-footer">
|
||||
<view class="popup-btn" :class="{ 'btn-loading': inviteLoading }" @click="submitInviteCode">
|
||||
<text>{{ inviteLoading ? '验证中...' : '提交' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 进行中测评弹窗 -->
|
||||
<view v-if="showPendingPopup" class="popup-mask" @click="handleDismissPending">
|
||||
<view class="popup-container pending-popup" @click.stop>
|
||||
<view class="popup-header">
|
||||
<text class="popup-title">发现进行中的测评</text>
|
||||
</view>
|
||||
<view class="popup-body">
|
||||
<view class="pending-msg">
|
||||
您有一份未完成的测评记录,是否继续?
|
||||
</view>
|
||||
<view class="pending-info">
|
||||
<text>姓名:{{ pendingRecord?.name }}</text>
|
||||
<text>手机号:{{ pendingRecord?.phone }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="pending-footer">
|
||||
<view class="popup-btn-outline" @click="handleDismissPending">
|
||||
<text>重新开始</text>
|
||||
</view>
|
||||
<view class="popup-btn" @click="handleContinuePending">
|
||||
<text>继续测评</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 邀请码弹窗 -->
|
||||
<view v-if="showInvitePopup" class="popup-mask" @click="closeInvitePopup">
|
||||
<view class="popup-container" @click.stop>
|
||||
<view class="popup-header">
|
||||
<text class="popup-title">填写测评邀请码</text>
|
||||
<view class="popup-close" @click="closeInvitePopup">
|
||||
<text>×</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="popup-body">
|
||||
<input
|
||||
class="invite-input"
|
||||
type="text"
|
||||
placeholder="请输入5位邀请码"
|
||||
placeholder-style="letter-spacing: 0rpx;"
|
||||
:value="inviteCode"
|
||||
@input="onInviteCodeInput"
|
||||
maxlength="5"
|
||||
/>
|
||||
</view>
|
||||
<view class="popup-footer">
|
||||
<view class="popup-btn" :class="{ 'btn-loading': inviteLoading }" @click="submitInviteCode">
|
||||
<text>{{ inviteLoading ? '验证中...' : '提交' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 进行中测评弹窗 -->
|
||||
<view v-if="showPendingPopup" class="popup-mask" @click="handleDismissPending">
|
||||
<view class="popup-container pending-popup" @click.stop>
|
||||
<view class="popup-header">
|
||||
<text class="popup-title">发现进行中的测评</text>
|
||||
</view>
|
||||
<view class="popup-body">
|
||||
<view class="pending-msg">
|
||||
您有一份未完成的测评记录,是否继续?
|
||||
</view>
|
||||
<view class="pending-info">
|
||||
<text>姓名:{{ pendingRecord?.name }}</text>
|
||||
<text>手机号:{{ pendingRecord?.phone }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="pending-footer">
|
||||
<view class="popup-btn-outline" @click="handleDismissPending">
|
||||
<text>重新开始</text>
|
||||
</view>
|
||||
<view class="popup-btn" @click="handleContinuePending">
|
||||
<text>继续测评</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
* - 显示提示文字
|
||||
* - 轮询查询报告生成状态(3秒间隔)
|
||||
* - 生成完成自动跳转结果页
|
||||
* - Status=7 需重测:显示提示和重新测试按钮
|
||||
*/
|
||||
|
||||
import { ref, onMounted, onUnmounted } from 'vue'
|
||||
|
|
@ -19,6 +20,7 @@ const userStore = useUserStore()
|
|||
|
||||
// 页面参数
|
||||
const recordId = ref('')
|
||||
const typeId = ref('')
|
||||
|
||||
// 轮询定时器
|
||||
let pollTimer = null
|
||||
|
|
@ -32,6 +34,10 @@ const MAX_POLL_COUNT = 100
|
|||
// 当前轮询次数
|
||||
const pollCount = ref(0)
|
||||
|
||||
// 是否需要重新测评(Status=7)
|
||||
const needRetest = ref(false)
|
||||
const retestMessage = ref('')
|
||||
|
||||
/**
|
||||
* 开始轮询查询状态
|
||||
*/
|
||||
|
|
@ -90,7 +96,7 @@ async function checkStatus() {
|
|||
if (res && res.code === 0 && res.data) {
|
||||
const status = res.data.status
|
||||
|
||||
// 状态:3-生成中 4-已完成 5-失败
|
||||
// 状态:3-生成中 4-已完成 5-失败 7-需重测
|
||||
if (status === 4) {
|
||||
// 生成完成,跳转结果页
|
||||
stopPolling()
|
||||
|
|
@ -100,6 +106,11 @@ async function checkStatus() {
|
|||
uni.redirectTo({
|
||||
url: `/pages/assessment/result/index?recordId=${recordId.value}&reportUrl=${encodeURIComponent(reportUrl)}`
|
||||
})
|
||||
} else if (status === 7) {
|
||||
// 需重测:停止轮询,显示提示和重新测试按钮
|
||||
stopPolling()
|
||||
needRetest.value = true
|
||||
retestMessage.value = res.data.message || '分析得出多个智能处于同一梯队,我们需要更细致的分析维度,接下来请您重新进行测评'
|
||||
} else if (status === 5) {
|
||||
// 生成失败
|
||||
stopPolling()
|
||||
|
|
@ -115,7 +126,7 @@ async function checkStatus() {
|
|||
}
|
||||
})
|
||||
}
|
||||
// status === 3 继续轮询
|
||||
// status === 3 或 6 继续轮询
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('查询状态失败:', error)
|
||||
|
|
@ -123,11 +134,28 @@ async function checkStatus() {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 重新测试
|
||||
*/
|
||||
function handleRetest() {
|
||||
// 跳转到测评首页重新开始
|
||||
if (typeId.value) {
|
||||
uni.redirectTo({
|
||||
url: `/pages/assessment/info/index?typeId=${typeId.value}`
|
||||
})
|
||||
} else {
|
||||
uni.switchTab({
|
||||
url: '/pages/index/index'
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 页面加载
|
||||
*/
|
||||
onLoad((options) => {
|
||||
recordId.value = options.recordId || ''
|
||||
typeId.value = options.typeId || ''
|
||||
|
||||
// 恢复用户登录状态
|
||||
userStore.restoreFromStorage()
|
||||
|
|
@ -149,8 +177,17 @@ onUnmounted(() => {
|
|||
<!-- 导航栏 -->
|
||||
<Navbar title="多元智能测评" :showBack="true" />
|
||||
|
||||
<!-- 需重测提示 -->
|
||||
<view v-if="needRetest" class="retest-content">
|
||||
<image class="retest-image" src="/static/cepingzhong.png" mode="aspectFit" />
|
||||
|
||||
<view class="retest-text">
|
||||
<text class="retest-title">{{ retestMessage }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 加载内容区域 -->
|
||||
<view class="loading-content">
|
||||
<view v-else class="loading-content">
|
||||
<!-- 加载图片 -->
|
||||
<image class="loading-image" src="/static/cepingzhong.png" mode="aspectFit" />
|
||||
|
||||
|
|
@ -160,6 +197,13 @@ onUnmounted(() => {
|
|||
<text class="loading-tip">可在往期测评中查看测评结果</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 重新测试按钮 -->
|
||||
<view v-if="needRetest" class="bottom-action">
|
||||
<view class="retest-btn" @click="handleRetest">
|
||||
<text>重新测试</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
|
|
@ -170,6 +214,8 @@ onUnmounted(() => {
|
|||
.assessment-loading-page {
|
||||
min-height: 100vh;
|
||||
background-color: $bg-white;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.loading-content {
|
||||
|
|
@ -205,4 +251,64 @@ onUnmounted(() => {
|
|||
font-size: $font-size-md;
|
||||
color: $text-placeholder;
|
||||
}
|
||||
|
||||
// 需重测内容
|
||||
.retest-content {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: $spacing-xl 64rpx;
|
||||
}
|
||||
|
||||
.retest-image {
|
||||
width: 360rpx;
|
||||
height: 360rpx;
|
||||
margin-bottom: $spacing-xl;
|
||||
}
|
||||
|
||||
.retest-text {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.retest-title {
|
||||
display: block;
|
||||
font-size: $font-size-lg;
|
||||
color: $text-secondary;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
// 底部操作栏
|
||||
.bottom-action {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
padding: $spacing-lg $spacing-xl;
|
||||
padding-bottom: calc(#{$spacing-lg} + env(safe-area-inset-bottom));
|
||||
background-color: transparent;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
// 重新测试按钮
|
||||
.retest-btn {
|
||||
width: 100%;
|
||||
height: 88rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: linear-gradient(135deg, #FF8A6B 0%, #FF6B6B 100%);
|
||||
border-radius: $border-radius-round;
|
||||
|
||||
text {
|
||||
font-size: $font-size-lg;
|
||||
color: $text-white;
|
||||
font-weight: $font-weight-medium;
|
||||
}
|
||||
|
||||
&:active {
|
||||
opacity: 0.85;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -198,7 +198,7 @@ async function handleSubmit() {
|
|||
|
||||
if (res && res.code === 0) {
|
||||
const resRecordId = res.data?.recordId || res.data?.id || recordId.value
|
||||
uni.redirectTo({ url: `/pages/assessment/loading/index?recordId=${resRecordId}` })
|
||||
uni.redirectTo({ url: `/pages/assessment/loading/index?recordId=${resRecordId}&typeId=${typeId.value}` })
|
||||
} else {
|
||||
uni.showToast({ title: res?.message || '提交失败,请重试', icon: 'none' })
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ function getDisplayStatus(order) {
|
|||
|
||||
// 已支付/已完成的订单,根据测评记录状态显示
|
||||
if (assessmentStatus) {
|
||||
const map = { 1: '待测评', 2: '测评中', 3: '测评生成中', 4: '已测评' }
|
||||
const map = { 1: '待测评', 2: '测评中', 3: '测评生成中', 4: '已测评', 7: '待测评' }
|
||||
return map[assessmentStatus] || order.statusText || '已支付'
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user