feat: 优化AI助手及报告对比界面,完成金额精度专项验证
- 调整环境配置切换至测试服 - 实现AI助手上下文折叠展开功能,优化界面布局 - 新增报告对比首屏短参数展示,简化信息呈现 - 调整报告页布局,优化导出组件为紧凑模式 - 完成原型08金额精度三轮真实专项验证,新增金额守卫逻辑 - 更新文档记录部署、数据库切换及验收进展
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
<view class="page assistant-page" :style="pageStyle()">
|
||||
<AppHeader title="AI融资助手" :customBack="true" @back="back" />
|
||||
<view class="chat-shell">
|
||||
<view class="chat-toolbar"><text class="toolbar-note">{{ chatId.length > 0 ? '对话已保存' : '您的融资问题,继续聊聊' }}</text><view class="toolbar-actions"><text class="toolbar-link" @click="showHistory">历史对话</text><text class="toolbar-link" @click="newChat">新对话</text></view></view>
|
||||
<view class="chat-toolbar"><text class="toolbar-note">{{ chatId.length > 0 ? '对话已保存' : '您的融资问题,继续聊聊' }}</text><view class="toolbar-actions"><text class="toolbar-link history-entry" @click="showHistory">历史对话</text><text class="toolbar-link" @click="newChat">新对话</text></view></view>
|
||||
<scroll-view scroll-y class="chat-scroll" :scroll-into-view="scrollTarget" :style="contentStyle(300, false)">
|
||||
<view v-if="active" class="chat-content">
|
||||
<view v-if="historyOpen" class="history-panel">
|
||||
@@ -16,10 +16,13 @@
|
||||
<view v-if="pageError.length > 0" class="error-panel"><text class="error-title">暂时无法继续对话</text><text class="error-text">{{ pageError }}</text><text v-if="routeError.length == 0" class="toolbar-link" @click="load">重新加载</text><text class="toolbar-link" @click="back">返回来源页面</text></view>
|
||||
<template v-if="context != null">
|
||||
<view v-if="context!.assessmentId.length > 0" class="context-card">
|
||||
<view class="context-heading"><text class="context-title">{{ context!.title }}</text><text class="context-link" @click="source">{{ sourceLabel }}</text></view>
|
||||
<view class="context-heading" @click="contextOpen = !contextOpen"><text class="context-summary">{{ context!.title }} · {{ context!.products.length > 0 ? context!.products.length.toString() + '项产品' : '报告解读' }}</text><text class="context-toggle">{{ contextOpen ? '收起' : '展开' }}</text></view>
|
||||
<template v-if="contextOpen">
|
||||
<text v-if="context!.products.length == 0" class="context-note">围绕这份已保存报告解答,不重新评估</text>
|
||||
<view v-for="item in context!.products" :key="item.id" class="context-product"><text class="context-product-name">{{ item.name }}</text><text :class="item.state == 'eligible' ? 'product-state good-state' : 'product-state'">{{ item.stateLabel }}</text></view>
|
||||
<text v-if="hasDemo" class="context-note">演示产品 · 仅供功能验证</text>
|
||||
<text class="context-link context-source" @click="source">{{ sourceLabel }}</text>
|
||||
</template>
|
||||
</view>
|
||||
<view class="assistant-intro"><image src="/packages/finance/static/robot.png" mode="aspectFit" class="intro-image" /><view class="intro-bubble"><text class="bubble-text">您好!我是您的 AI 融资助手。
|
||||
{{ context!.assessmentId.length > 0 ? '我可以结合本次报告,帮您理解产品条件、匹配原因和需要准备的资料。' : '我可以帮您解答关于银行产品、申请条件、资料准备等问题。' }}</text></view></view>
|
||||
@@ -49,6 +52,8 @@
|
||||
const { pageStyle, contentStyle, bottomStyle } = usePageLayout()
|
||||
const assessmentId = ref(''); const productIds = ref<string[]>([]); const chatId = ref(''); const from = ref('')
|
||||
const context = ref<AssistantContext | null>(null); const messages = ref<AssistantTurn[]>([])
|
||||
// 展开只影响展示;切换会话或账户时恢复折叠,不改变已绑定的报告和产品。
|
||||
const contextOpen = ref(false)
|
||||
const active = ref(false); const loading = ref(false); const sending = ref(false); const paging = ref(false)
|
||||
const draft = ref(''); const pageError = ref(''); const routeError = ref(''); const sendError = ref(''); const queryError = ref('')
|
||||
const scrollTarget = ref(''); const more = ref(false); const cursor = ref(''); const pollStopped = ref(false)
|
||||
@@ -73,7 +78,7 @@
|
||||
const back = () => { if (getCurrentPages().length > 1) uni.navigateBack(); else source() }
|
||||
const login = () => { uni.redirectTo({ url: '/packages/account/login/login?resumeAssistant=1&assessmentId=' + assessmentId.value + '&productIds=' + productIds.value.join(',') + '&chatId=' + chatId.value + '&from=' + from.value }) }
|
||||
const stopTimer = () => { if (timer != 0) { clearInterval(timer); timer = 0 } }
|
||||
const clearContent = () => { context.value = null; messages.value = []; draft.value = ''; sendText = ''; sendKey = ''; uncertain.value = false; histories.value = []; historyCursor = ''; historyOpen.value = false; sendError.value = ''; queryError.value = '' }
|
||||
const clearContent = () => { context.value = null; contextOpen.value = false; messages.value = []; draft.value = ''; sendText = ''; sendKey = ''; uncertain.value = false; histories.value = []; historyCursor = ''; historyOpen.value = false; sendError.value = ''; queryError.value = '' }
|
||||
// 请求代次与登录Token双重校验;离页、退出、换账号后旧响应不得回填个人对话。
|
||||
const current = (ticket: number, token: string): boolean => {
|
||||
if (!active.value || ticket != generation) return false
|
||||
@@ -169,12 +174,16 @@
|
||||
onUnload(() => { active.value = false; generation++; stopTimer(); clearContent() })
|
||||
</script>
|
||||
<style>
|
||||
.context-summary { flex: 1; font-size: 24rpx; line-height: 36rpx; color: #45617f; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
.context-toggle { flex-shrink: 0; color: #527ba8; font-size: 22rpx; margin-left: 16rpx; line-height: 36rpx; }
|
||||
.context-source { margin-top: 16rpx; }
|
||||
.assistant-page { background-color: #fcfdff; }
|
||||
.chat-shell { flex: 1; }
|
||||
.chat-toolbar { padding: 8rpx 30rpx 18rpx; min-height: 60rpx; flex-direction: row; align-items: center; justify-content: space-between; }
|
||||
.toolbar-note { color: #95a1b3; font-size: 21rpx; }
|
||||
.toolbar-actions { flex-direction: row; }
|
||||
.toolbar-link { color: #2672d9; font-size: 23rpx; line-height: 40rpx; margin-left: 22rpx; }
|
||||
.history-entry { color: #7b899c; font-size: 21rpx; }
|
||||
.chat-content { padding: 14rpx 30rpx 36rpx; }
|
||||
.context-card { padding: 20rpx 22rpx; margin-bottom: 30rpx; border-radius: 14rpx; background-color: #f0f6ff; border: 1rpx solid #e0ebfb; }
|
||||
.context-heading, .context-product, .history-title { flex-direction: row; justify-content: space-between; align-items: center; }
|
||||
|
||||
@@ -5,13 +5,32 @@
|
||||
<view class="content">
|
||||
<text class="eyebrow">评估 #{{ assessmentId }} · 历史产品快照</text>
|
||||
<text class="headline">并排看清,选择更有依据</text>
|
||||
<text class="intro">对照同一次评估的产品条件,不代表授信或获批。金额单位为万元,展示顺序不代表优劣。</text>
|
||||
<text class="intro">同次评估 · 金额单位为万元 · 条件判断不代表获批</text>
|
||||
<view v-if="routeError.length > 0" class="panel"><text class="warning">{{ routeError }}</text><button class="secondary" @click="toMatches">返回本次匹配</button></view>
|
||||
<template v-else>
|
||||
<view class="toolbar"><view class="summary"><text class="summary-title">已选 {{ ids.length }} / 3 项</text><text class="hint">{{ complete ? '已读取同一版本的完整对比' : (ids.length < 2 ? '再选产品后开始对比' : '对比尚不完整,请查看各列状态') }}</text></view><button class="add" @click="toMatches">{{ ids.length < 3 ? '补选产品' : '调整选择' }}</button></view>
|
||||
<text v-if="ids.length > 0" class="scroll-hint">左右滑动查看各产品 · 长内容可在单元格内上下滑动</text>
|
||||
<view v-if="ids.length == 0" class="panel"><text class="summary-title">还没有选择产品</text><text class="intro">从本次匹配中选择2–3项,也可对照不符条件和待核实的产品。</text><button class="secondary" @click="toMatches">去选择产品</button></view>
|
||||
<view v-else class="table">
|
||||
<template v-else>
|
||||
<view class="overview-table">
|
||||
<view class="overview-row">
|
||||
<view class="overview-label overview-head"><text class="row-label">核心参数</text></view>
|
||||
<scroll-view v-for="column in columns" :key="column.id" scroll-y class="overview-value overview-head">
|
||||
<view class="overview-product">
|
||||
<template v-if="usable(column)"><text class="overview-name">{{ column.data!.item.product.name }}</text><text class="overview-bank">{{ column.data!.item.product.bank }}</text><text class="overview-link" @click="detail(column.id)">产品详情 ›</text></template>
|
||||
<template v-else><text class="overview-name">产品 #{{ column.id }}</text><text class="overview-bank">{{ column.loading ? '读取中…' : problem(column) }}</text><text v-if="!column.loading" class="overview-link" @click="loadColumn(column.id)">重试此列</text></template>
|
||||
<text class="overview-remove" @click="remove(column.id)">移除</text>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
<view v-for="row in overviewRows" :key="row.id" class="overview-row">
|
||||
<view class="overview-label"><text class="row-label">{{ row.label }}</text></view>
|
||||
<view v-for="column in columns" :key="column.id" class="overview-value"><text :class="overviewClass(column, row.id)">{{ cell(column, row.id) }}</text></view>
|
||||
</view>
|
||||
</view>
|
||||
<text class="overview-note">{{ hasDemo ? '含演示产品,仅供功能验证。' : '' }}展示顺序不代表优劣。</text>
|
||||
<view class="details-toggle" @click="detailsOpen = !detailsOpen"><text class="summary-title">详细条件与匹配依据</text><text class="detail-toggle-label">{{ detailsOpen ? '收起' : '展开' }}</text></view>
|
||||
<text v-if="detailsOpen" class="scroll-hint">左右滑动查看各产品 · 长内容可在单元格内上下滑动</text>
|
||||
<view v-if="detailsOpen" class="table">
|
||||
<view class="rail"><view class="rail-head"><text class="rail-title">对比指标</text><text class="hint">同次评估</text></view><view v-for="row in rows" :key="row.id" class="label-cell" :style="rowStyle(row)"><text class="row-label">{{ row.label }}</text></view></view>
|
||||
<scroll-view scroll-x class="horizontal">
|
||||
<view class="columns" :style="columnsStyle()">
|
||||
@@ -34,6 +53,7 @@
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</template>
|
||||
<text class="footer-note">历史参数保留评估时版本;当前可用状态单独展示。缺失信息不会被推断为零,演示产品仅供功能验证。</text>
|
||||
<button class="secondary" @click="consult">产品差异,咨询AI</button>
|
||||
<button class="secondary" @click="toMatches">返回本次匹配</button>
|
||||
@@ -53,6 +73,9 @@
|
||||
type CompareRow = { id: string, label: string, height: number }
|
||||
const { pageStyle, contentStyle } = usePageLayout()
|
||||
const assessmentId = ref(''); const ids = ref<string[]>([]); const columns = ref<CompareColumn[]>([]); const routeError = ref('')
|
||||
const detailsOpen = ref(false)
|
||||
// 首屏并排展示短参数;长证据保留原宽表,展开后读取完整内容,不截断判断依据。
|
||||
const overviewRows: CompareRow[] = [{ id: 'state', label: '匹配状态', height: 0 }, { id: 'amount', label: '额度范围', height: 0 }, { id: 'term', label: '期限范围', height: 0 }, { id: 'rate', label: '年化利率', height: 0 }]
|
||||
let visible = false; let generation = 0
|
||||
const rows: CompareRow[] = [
|
||||
{ id: 'availability', label: '当前状态', height: 160 }, { id: 'coverage', label: '需求覆盖依据', height: 360 },
|
||||
@@ -73,9 +96,17 @@
|
||||
}
|
||||
const usable = (column: CompareColumn): boolean => !column.loading && column.data != null && problem(column).length == 0
|
||||
const complete = computed((): boolean => ids.value.length >= 2 && columns.value.length == ids.value.length && columns.value.every((c: CompareColumn): boolean => usable(c)))
|
||||
const hasDemo = computed((): boolean => columns.value.some((c: CompareColumn): boolean => usable(c) && c.data!.item.product.demo))
|
||||
const overviewClass = (column: CompareColumn, key: string): string => {
|
||||
if (key == 'amount') return 'overview-text overview-amount'
|
||||
if (key != 'state' || !usable(column)) return 'overview-text'
|
||||
return 'overview-text ' + (column.data!.item.state == 'eligible' ? 'good' : (column.data!.item.state == 'ineligible' ? 'blocked' : 'pending'))
|
||||
}
|
||||
const cell = (column: CompareColumn, key: string): string => {
|
||||
if (!usable(column)) return column.loading ? '读取中…' : '本列未就绪'
|
||||
const m = column.data!.item; const p = m.product
|
||||
// 核心表也保留当前不可用提示,不能让历史符合条件被误读为现在仍可办理。
|
||||
if (key == 'state') return m.stateLabel + (m.availability != 'available' ? ' · ' + m.availabilityLabel : '')
|
||||
if (key == 'availability') return m.availabilityLabel + ';不改变历史结论'
|
||||
if (key == 'coverage') {
|
||||
const demand = m.positive.concat(m.blocking).concat(m.cautions).filter((r: MatchReason): boolean => r.fields.some((f: string): boolean => ['requestedAmountYuan','requestedTermMonths','purposeCode'].includes(f)))
|
||||
@@ -148,6 +179,21 @@
|
||||
onUnload(() => { visible = false; generation++; columns.value = [] })
|
||||
</script>
|
||||
<style>
|
||||
.overview-table { border: 1rpx solid #dfe8f3; border-radius: 14rpx; overflow: hidden; background-color: #fff; }
|
||||
.overview-row { flex-direction: row; border-bottom: 1rpx solid #e7edf5; }
|
||||
.overview-label { width: 120rpx; flex-shrink: 0; padding: 22rpx 12rpx; background-color: #eef4fb; justify-content: center; }
|
||||
.overview-value { flex: 1; width: 0; padding: 22rpx 12rpx; border-left: 1rpx solid #e7edf5; justify-content: center; }
|
||||
.overview-head { height: 270rpx; padding-top: 18rpx; padding-bottom: 18rpx; }
|
||||
.overview-product { padding: 0; }
|
||||
.overview-name { font-size: 24rpx; line-height: 35rpx; font-weight: 700; color: #243f60; }
|
||||
.overview-bank { color: #788ba2; font-size: 20rpx; line-height: 30rpx; margin-top: 10rpx; }
|
||||
.overview-link, .overview-remove { font-size: 22rpx; line-height: 34rpx; color: #0868f7; padding-top: 12rpx; }
|
||||
.overview-remove { color: #788ba2; }
|
||||
.overview-text { font-size: 23rpx; line-height: 36rpx; color: #455f7c; }
|
||||
.overview-amount { font-weight: 700; color: #154779; }
|
||||
.overview-note { color: #8494a7; font-size: 21rpx; line-height: 34rpx; margin-top: 14rpx; }
|
||||
.details-toggle { flex-direction: row; align-items: center; justify-content: space-between; padding: 28rpx 0; }
|
||||
.detail-toggle-label { color: #0868f7; font-size: 24rpx; }
|
||||
.content { padding: 28rpx 22rpx 60rpx; }
|
||||
.eyebrow { color: #6d829c; font-size: 22rpx; }
|
||||
.headline { color: #193653; font-size: 36rpx; font-weight: 700; margin-top: 14rpx; }
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
<template>
|
||||
<view class="export-area">
|
||||
<view class="export-row"><text class="export-label">报告已保存至融资档案</text><button class="export-button" :disabled="busy" @click="download">{{ busy ? '正在生成…' : '下载PDF' }}</button></view>
|
||||
<view :class="compact ? 'export-area export-compact' : 'export-area'">
|
||||
<view class="export-row"><text class="export-label">{{ compact ? '评估 #' + assessmentId + ' · 已保存' : '报告已保存至融资档案' }}</text><button class="export-button" :disabled="busy" @click="download">{{ busy ? '正在生成…' : '下载PDF' }}</button></view>
|
||||
<text v-if="message.length > 0" :class="failed ? 'export-message export-error' : 'export-message'">{{ message }}</text>
|
||||
<text v-if="message.length == 0" class="export-message">导出不含身份信息,请妥善保管下载文件。</text>
|
||||
<text v-if="message.length == 0 && !compact" class="export-message">导出不含身份信息,请妥善保管下载文件。</text>
|
||||
</view>
|
||||
</template>
|
||||
<script setup lang="uts">
|
||||
import { getSession } from '@/services/api.uts'
|
||||
import { ReportDownload, downloadReportPdf } from '@/packages/finance/services/report-export.uts'
|
||||
const props = defineProps({ assessmentId: { type: String, required: true } })
|
||||
// 报告页使用紧凑入口,下载进度和错误始终展示;其他页面保留原布局。
|
||||
const props = defineProps({ assessmentId: { type: String, required: true }, compact: { type: Boolean, default: false } })
|
||||
const emit = defineEmits(['authrequired', 'sessionchanged'])
|
||||
const busy = ref(false); const message = ref(''); const failed = ref(false)
|
||||
let operation: ReportDownload | null = null; let generation = 0
|
||||
@@ -39,4 +40,5 @@
|
||||
.export-button { font-size: 24rpx; color: #0868f7; background-color: #eaf3ff; border-radius: 10rpx; margin-left: 18rpx; padding-left: 24rpx; padding-right: 24rpx; }
|
||||
.export-message { color: #8393a6; font-size: 22rpx; line-height: 36rpx; margin-top: 12rpx; }
|
||||
.export-error { color: #a05d37; }
|
||||
.export-compact { margin-top: 0; margin-bottom: 0; }
|
||||
</style>
|
||||
|
||||
@@ -4,12 +4,14 @@
|
||||
<view class="tabs"><view v-for="item in tabs" :key="item.id" :class="tab == item.id ? 'tab active' : 'tab'" @click="switchTab(item.id)"><text :class="tab == item.id ? 'tab-label selected' : 'tab-label'">{{ item.label }}</text></view></view>
|
||||
<scroll-view scroll-y :style="contentStyle(186, false)">
|
||||
<view class="report-content">
|
||||
<text class="eyebrow">评估记录 #{{ assessmentId.length > 0 ? assessmentId : '待选择' }}</text>
|
||||
<!-- 离页清空报告时只切换可见性,避免在页面销毁过程中重新挂载文本节点。 -->
|
||||
<text v-show="report == null" class="eyebrow">评估记录 #{{ assessmentId.length > 0 ? assessmentId : '待选择' }}</text>
|
||||
<text v-if="loading" class="body-text">正在读取已保存报告…</text>
|
||||
<view v-if="error.length > 0" class="panel"><text class="section-title">报告暂不可读取</text><text class="body-text">{{ error }}</text><button v-if="routeError.length == 0" class="secondary" @click="loadReport">重新加载报告</button><text class="action" @click="history">前往融资档案</text></view>
|
||||
<template v-if="report != null">
|
||||
<ReportExport :assessmentId="assessmentId" @authrequired="login" @sessionchanged="loadReport" />
|
||||
<text class="report-note">生成于 {{ report!.generatedAt }} · 用户自填资料分析</text>
|
||||
<ReportExport :assessmentId="assessmentId" :compact="true" @authrequired="login" @sessionchanged="loadReport" />
|
||||
<text class="metadata-toggle" @click="metadataOpen = !metadataOpen">用户自填资料分析 · 报告信息{{ metadataOpen ? '收起' : '展开' }}</text>
|
||||
<view v-if="metadataOpen" class="metadata"><text class="report-note">生成于 {{ report!.generatedAt }}</text><text class="report-note">报告已保存至融资档案。导出不含身份信息,请妥善保管下载文件。</text></view>
|
||||
<view v-if="report!.version == 1" class="legacy"><text class="report-note">这是一份旧版自填报告,当时未采集融资需求、未计算完整度与准备状态,也未执行产品匹配。历史内容保持原样。</text></view>
|
||||
<template v-if="tab == 'overview'">
|
||||
<view class="hero">
|
||||
@@ -43,9 +45,9 @@
|
||||
</template>
|
||||
</template>
|
||||
<template v-else>
|
||||
<text class="headline">让下一次准备更充分</text><text class="intro">依据本次报告和产品条件整理。补充资料后需重新提交新评估,改善不保证获批。</text>
|
||||
<text class="headline">让下一次准备更充分</text><text class="intro">依据本次报告整理 · 改善不保证获批</text>
|
||||
<view v-if="report!.version == 2" class="panel"><text class="section-title">优先补充与核实</text><text v-if="missingItems.length == 0" class="report-note">{{ report!.completenessPercent == null ? '本次未评定缺失字段,不能据此认为资料齐全。' : '本次字段清单没有待补充或格式待核实项,仍需准备核验材料。' }}</text><view class="fact-row" v-for="item in missingItems" :key="item.label"><text class="fact-label">{{ item.label }}</text><text class="fact-value">{{ item.value }}</text></view><text class="body-text" v-for="(item, index) in report!.readinessBasis" :key="index">{{ item }}</text></view>
|
||||
<view class="panel"><text class="section-title">已保存的AI改善建议</text><text v-if="report!.suggestions.length == 0" class="report-note">暂无有依据的额外建议,不代表已经完成核验。</text><text class="body-text" v-for="(item, index) in report!.suggestions" :key="index">{{ item }}</text><text class="source-note">保留报告生成时的文本与依据,不重新调用模型。</text></view>
|
||||
<view class="panel"><text class="section-title">已保存的AI改善建议</text><text v-if="report!.suggestions.length == 0" class="report-note">暂无有依据的额外建议,不代表已经完成核验。</text><text class="body-text" v-for="(item, index) in report!.suggestions" :key="index">{{ item }}</text><text class="source-note">保留报告生成时的文本与依据;补充资料后需发起新评估。</text></view>
|
||||
<view v-if="report!.matching.status != 'completed'" class="panel"><text class="section-title">产品条件提示</text><text class="report-note">本次未执行产品匹配,没有可关联的产品改善依据。</text></view>
|
||||
<template v-else><view v-for="group in adviceGroups" :key="group.id" class="panel"><text class="section-title">{{ group.label }}</text><text class="report-note">仅展示本组前3项产品的已有依据,可进入完整列表查看更多。</text><text v-if="group.loading" class="body-text">正在读取产品依据…</text><template v-if="group.error.length > 0"><text class="body-text">{{ group.error }}</text><button class="secondary" @click="loadAdvice(group.id)">重试{{ group.label }}</button></template><text v-if="!group.loading && group.error.length == 0 && group.items.length == 0" class="report-note">本组暂无产品依据。</text><view v-for="item in group.items" :key="item.id" class="advice-product"><text class="product-name" @click="openProduct(item.id)">{{ item.product.name }} ›</text><text class="source-note">{{ item.stateLabel }} · 评估时版本 v{{ item.product.version }}</text><view v-for="reason in adviceReasons(item)" :key="reason.id"><text class="body-text">{{ reason.text }}</text><text v-for="line in reason.evidence" :key="line" class="evidence">{{ line }}</text></view><text v-if="item.availability != 'available'" class="availability">{{ item.availabilityLabel }}</text></view><text class="action" @click="allMatches(group.id)">查看全部{{ group.label }} ›</text></view></template>
|
||||
</template>
|
||||
@@ -73,13 +75,15 @@
|
||||
const tabs: ReportTab[] = [{ id: 'overview', label: '评估概况' }, { id: 'matches', label: '匹配结果' }, { id: 'improvements', label: '改善建议' }]
|
||||
const assessmentId = ref(''); const tab = ref('overview'); const loading = ref(false); const error = ref(''); const routeError = ref('')
|
||||
const report = ref<AnalysisReport | null>(null); const factsOpen = ref(false); const completenessOpen = ref(false)
|
||||
// 日期与导出说明按需展开,首屏优先呈现准备状态和当前栏目的内容。
|
||||
const metadataOpen = ref(false)
|
||||
const candidates = ref<MatchView[]>([]); const candidateLoading = ref(false); const candidateError = ref('')
|
||||
const adviceGroups = ref<AdviceGroup[]>([])
|
||||
let generation = 0; let visible = false
|
||||
const login = () => { uni.redirectTo({ url: '/packages/account/login/login?resumeReport=1&assessmentId=' + assessmentId.value + '&tab=' + tab.value }) }
|
||||
const missingItems = computed((): AssessmentField[] => report.value == null ? [] : report.value!.completenessItems.filter((item: AssessmentField): boolean => ['待补充','需核实'].includes(item.value)))
|
||||
const adviceReasons = (item: MatchView): MatchReason[] => item.state == 'ineligible' ? item.blocking.concat(item.cautions) : item.cautions
|
||||
const reset = () => { report.value = null; candidates.value = []; adviceGroups.value = []; candidateLoading.value = false; candidateError.value = ''; factsOpen.value = false; completenessOpen.value = false }
|
||||
const reset = () => { report.value = null; candidates.value = []; adviceGroups.value = []; candidateLoading.value = false; candidateError.value = ''; factsOpen.value = false; completenessOpen.value = false; metadataOpen.value = false }
|
||||
const current = (request: number, token: string): boolean => visible && request == generation && getSession()?.getString('token') == token
|
||||
const sessionChanged = (request: number, token: string): boolean => {
|
||||
if (!visible || request != generation) return true
|
||||
@@ -168,16 +172,18 @@
|
||||
.selected { color: #0868f7; font-weight: 700; }
|
||||
.report-content { padding: 28rpx 28rpx 65rpx; }
|
||||
.eyebrow { color: #778ba3; font-size: 22rpx; }
|
||||
.headline { color: #1a3859; font-size: 36rpx; font-weight: 700; margin-top: 28rpx; }
|
||||
.headline { color: #1a3859; font-size: 34rpx; font-weight: 700; margin-top: 22rpx; }
|
||||
.intro { color: #73869d; font-size: 24rpx; line-height: 40rpx; margin-top: 14rpx; }
|
||||
.hero { background-color: #155dd1; border-radius: 22rpx; padding: 32rpx; margin-top: 24rpx; }
|
||||
.hero-label { color: #d8e8ff; font-size: 24rpx; }
|
||||
.hero-title { color: #fff; font-size: 42rpx; font-weight: 700; line-height: 60rpx; margin-top: 14rpx; }
|
||||
.hero-note { color: #d8e8ff; font-size: 22rpx; line-height: 36rpx; margin-top: 12rpx; }
|
||||
.hero-divider { height: 1rpx; background-color: #4983dc; margin-top: 26rpx; margin-bottom: 24rpx; }
|
||||
.percent { color: #fff; font-size: 38rpx; font-weight: 700; }
|
||||
.progress-track { height: 12rpx; border-radius: 6rpx; background-color: #4983dc; margin-top: 18rpx; overflow: hidden; }
|
||||
.progress-fill { height: 12rpx; background-color: #bde6ff; border-radius: 6rpx; }
|
||||
.metadata-toggle { color: #78889e; font-size: 21rpx; line-height: 36rpx; padding-top: 8rpx; padding-bottom: 4rpx; }
|
||||
.metadata { padding: 0 0 12rpx; }
|
||||
.hero { background-color: #eef5ff; border: 1rpx solid #dfeafb; border-radius: 18rpx; padding: 26rpx; margin-top: 18rpx; }
|
||||
.hero-label { color: #627c9c; font-size: 24rpx; }
|
||||
.hero-title { color: #165cb9; font-size: 42rpx; font-weight: 700; line-height: 56rpx; margin-top: 8rpx; }
|
||||
.hero-note { color: #7086a1; font-size: 22rpx; line-height: 34rpx; margin-top: 8rpx; }
|
||||
.hero-divider { height: 1rpx; background-color: #d9e5f6; margin-top: 18rpx; margin-bottom: 16rpx; }
|
||||
.percent { color: #285c9d; font-size: 30rpx; font-weight: 700; }
|
||||
.progress-track { height: 8rpx; border-radius: 4rpx; background-color: #dbe7f8; margin-top: 12rpx; overflow: hidden; }
|
||||
.progress-fill { height: 8rpx; background-color: #4c8beb; border-radius: 4rpx; }
|
||||
.panel { margin-top: 24rpx; padding: 28rpx; border-radius: 18rpx; background-color: #fff; border: 1rpx solid #e7edf6; }
|
||||
.panel-heading { flex-direction: row; justify-content: space-between; align-items: center; }
|
||||
.section-title { color: #253f5e; font-size: 29rpx; font-weight: 700; line-height: 42rpx; }
|
||||
|
||||
Reference in New Issue
Block a user