feat: 优化AI助手及报告对比界面,完成金额精度专项验证

- 调整环境配置切换至测试服
- 实现AI助手上下文折叠展开功能,优化界面布局
- 新增报告对比首屏短参数展示,简化信息呈现
- 调整报告页布局,优化导出组件为紧凑模式
- 完成原型08金额精度三轮真实专项验证,新增金额守卫逻辑
- 更新文档记录部署、数据库切换及验收进展
This commit is contained in:
hujun
2026-09-29 17:27:25 +08:00
parent 79feb03b19
commit 542c107317
10 changed files with 394 additions and 44 deletions
+12 -3
View File
@@ -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; }