本次重构将评估草稿改为内存状态管理,移除本地存储草稿,新增评估流程内存状态模块;接入真实的账户资料获取、头像上传接口,新增账户缓存清理逻辑;重构评估提交逻辑,接入真实提交接口并返回评估ID;新增分析页和报告页的真实状态查询、报告获取功能;更新README文档,记录开发进度和接口状态。
90 lines
6.5 KiB
Plaintext
90 lines
6.5 KiB
Plaintext
<template>
|
|
<view class="analyzing-page" :style="pageStyle()">
|
|
<view class="safe" :style="statusStyle(80)"></view>
|
|
<text class="analyzing-title">{{ title }}</text>
|
|
<text class="analyzing-sub">正式提交记录 · {{ assessmentId }}</text>
|
|
<view class="orbital"><view class="orbit orbit-one"></view><view class="orbit orbit-two"></view><view class="ai-core"><image src="/static/mobile/images/robot-cutout.png" mode="aspectFit" class="ai-core-image"></image></view></view>
|
|
<text class="status-message">{{ message }}</text>
|
|
<text v-if="error.length > 0" class="status-message">{{ error }}</text>
|
|
<text v-if="canRetry" class="view-now" @click="retry">{{ retrying ? '正在提交…' : '重新分析' }}</text>
|
|
<text v-if="succeeded" class="view-now" @click="report">查看分析报告</text>
|
|
<text class="view-now" @click="loadStatus">刷新状态</text>
|
|
<text class="view-now" @click="archive">查看已提交资料</text>
|
|
</view>
|
|
</template>
|
|
|
|
<script setup lang="uts">
|
|
import { usePageLayout } from '@/services/layout.uts'
|
|
import { getSession } from '@/services/api.uts'
|
|
import { fetchAssessmentStatus, retryAssessment } from '@/packages/finance/services/records.uts'
|
|
const { statusStyle, pageStyle } = usePageLayout()
|
|
const title = ref('正在读取评估状态')
|
|
const message = ref(''); const error = ref(''); const assessmentId = ref('')
|
|
const canRetry = ref(false); const succeeded = ref(false); const retrying = ref(false)
|
|
let retryKey = ''; let retryTask = ''; let retryOwner = ''
|
|
let timer = 0; let visible = false; let generation = 0
|
|
async function loadStatus(): Promise<void> {
|
|
clearTimeout(timer)
|
|
if (assessmentId.value.length == 0) { title.value = '缺少评估记录'; message.value = '请从融资档案选择已提交的记录。'; return }
|
|
const session = getSession()
|
|
if (session == null) { uni.redirectTo({ url: '/packages/account/login/login' }); return }
|
|
const owner = session['token'] as string
|
|
const request = ++generation
|
|
error.value = ''
|
|
try {
|
|
const result = await fetchAssessmentStatus(assessmentId.value)
|
|
if (!visible || request != generation || getSession()?.getString('token') != owner) return
|
|
canRetry.value = result.canRetry; succeeded.value = result.status == 'succeeded'
|
|
if (retryTask != result.taskId || retryOwner != owner) { retryKey = ''; retryTask = result.taskId; retryOwner = owner }
|
|
title.value = result.statusLabel
|
|
message.value = result.message.length > 0 ? result.message : (result.status == 'processing' ? (result.stage == 'queued' ? '资料已保存,等待分析。您可以稍后从档案查看。' : '正在分析自填资料,您可以稍后从档案查看。') : '分析已完成,可查看本次报告。')
|
|
// 只轮询服务端仍在处理的任务,不用计时器模拟完成。
|
|
if (result.status == 'processing') timer = setTimeout(() => { loadStatus() }, 5000)
|
|
} catch (err) { if (visible && request == generation) { title.value = '状态加载失败'; error.value = err instanceof Error ? err.message : '请稍后重试' } }
|
|
}
|
|
const retry = async () => {
|
|
if (retrying.value || !canRetry.value) return
|
|
const session = getSession()
|
|
if (session == null) { loadStatus(); return }
|
|
const owner = session['token'] as string
|
|
if (retryOwner != owner) { retryKey = ''; retryOwner = owner }
|
|
// 网络失败保留当前键;状态中的任务ID变化后才为下次尝试生成新键。
|
|
if (retryKey.length == 0) retryKey = 'retry_' + Date.now().toString() + '_' + Math.random().toString(36).substring(2, 14)
|
|
retrying.value = true; error.value = ''; clearTimeout(timer)
|
|
const request = ++generation
|
|
try {
|
|
await retryAssessment(assessmentId.value, retryKey)
|
|
if (visible && request == generation && getSession()?.getString('token') == owner) { canRetry.value = false; await loadStatus() }
|
|
} catch (err) { if (visible && request == generation) error.value = err instanceof Error ? err.message : '重新分析失败,请重试' }
|
|
finally { retrying.value = false }
|
|
}
|
|
const report = () => { uni.navigateTo({ url: '/packages/finance/report/report?assessmentId=' + encodeURIComponent(assessmentId.value) }) }
|
|
const archive = () => { uni.reLaunch({ url: '/packages/finance/archive/archive?assessmentId=' + encodeURIComponent(assessmentId.value) }) }
|
|
onLoad((options) => { if (options != null) assessmentId.value = options['assessmentId'] ?? '' })
|
|
onShow(() => { visible = true; loadStatus() })
|
|
onHide(() => { visible = false; generation++; clearTimeout(timer); canRetry.value = false; succeeded.value = false; message.value = ''; error.value = '' })
|
|
onUnload(() => { visible = false; generation++; clearTimeout(timer) })
|
|
</script>
|
|
|
|
<style>
|
|
.analyzing-page { background: linear-gradient(160deg, #061c49, #002c75); align-items: center; color: #fff; }
|
|
.safe { }
|
|
.analyzing-title { font-size: 45rpx; font-weight: 800; }
|
|
.analyzing-sub { margin-top: 20rpx; color: #c6d9ff; font-size: 25rpx; }
|
|
.orbital { width: 400rpx; height: 400rpx; margin-top: 55rpx; align-items: center; justify-content: center; position: relative; }
|
|
.orbit { position: absolute; border-radius: 50%; border: 2rpx solid rgba(79, 176, 255, .46); }
|
|
.orbit-one { width: 350rpx; height: 350rpx; }
|
|
.orbit-two { width: 280rpx; height: 280rpx; border-color: rgba(57, 235, 255, .5); }
|
|
.ai-core { width: 220rpx; height: 220rpx; border-radius: 50%; background-color: rgba(10, 102, 247, .32); box-shadow: 0 0 70rpx rgba(0, 165, 255, .48); align-items: center; justify-content: center; }
|
|
.ai-core-image { width: 185rpx; height: 185rpx; border-radius: 50%; }
|
|
.analysis-list { margin-top: 30rpx; width: 390rpx; }
|
|
.analysis-item { flex-direction: row; align-items: center; margin-top: 23rpx; font-size: 26rpx; color: #d8e6ff; }
|
|
.analysis-label { font-size: 27rpx; color: #d8e6ff; }
|
|
.analysis-mark { font-size: 24rpx; color: #ffffff; }
|
|
.analysis-check { width: 38rpx; height: 38rpx; border-radius: 50%; border: 2rpx solid #4c73a7; align-items: center; justify-content: center; margin-right: 17rpx; }
|
|
.analysis-check.done { background-color: #158aff; border-color: #41d7ff; color: white; }
|
|
.status-message { margin: 32rpx; color: #d8e6ff; font-size: 28rpx; line-height: 44rpx; text-align: center; }
|
|
.estimate { margin-top: 64rpx; color: #8faeda; font-size: 22rpx; }
|
|
.view-now { margin-top: 28rpx; color: #62c8ff; font-size: 23rpx; }
|
|
</style>
|