feat: 重构评估流程为内存状态管理并接入真实提交与报告接口

本次重构将评估草稿改为内存状态管理,移除本地存储草稿,新增评估流程内存状态模块;接入真实的账户资料获取、头像上传接口,新增账户缓存清理逻辑;重构评估提交逻辑,接入真实提交接口并返回评估ID;新增分析页和报告页的真实状态查询、报告获取功能;更新README文档,记录开发进度和接口状态。
This commit is contained in:
hujun
2026-09-24 11:50:07 +08:00
parent dcf12a4471
commit dbfd637388
22 changed files with 1468 additions and 434 deletions
+59 -26
View File
@@ -1,37 +1,69 @@
<template>
<view class="analyzing-page" :style="pageStyle()">
<view class="safe" :style="statusStyle(80)"></view>
<text class="analyzing-title">AI分析中</text>
<text class="analyzing-sub">正在整理融资评估信息…</text>
<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>
<view class="analysis-list"><view class="analysis-item" v-for="(item,index) in items" :key="item"><view :class="progress > index ? 'analysis-check done' : 'analysis-check'"><text class="analysis-mark">{{ progress > index ? '✓' : '·' }}</text></view><text class="analysis-label">{{ item }}</text></view></view>
<text class="estimate">正在生成评估报告,请稍候…</text>
<text class="view-now" @click="finish">查看评估结果</text>
<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'
const { statusStyle, pageStyle } = usePageLayout()
const progress = ref(0)
const items = ['数据解析中', '信用评估中', '匹配方案中', '风险检测中']
let timer = 0
let finishTimer = 0
let finished = false
const finish = () => {
if (finished) return
finished = true
clearInterval(timer)
clearTimeout(finishTimer)
uni.redirectTo({ url: '/packages/finance/report/report' })
}
onShow(() => {
if (finished) return
timer = setInterval(() => { if (progress.value < 4) progress.value++; else clearInterval(timer) }, 550)
finishTimer = setTimeout(() => finish(), 3200)
})
onHide(() => { clearInterval(timer); clearTimeout(finishTimer) })
onUnmounted(() => { clearInterval(timer); clearTimeout(finishTimer) })
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>
@@ -51,6 +83,7 @@
.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>