From 79feb03b196f4a21ac9b41815a38fb442a472c56 Mon Sep 17 00:00:00 2001 From: hujun Date: Mon, 28 Sep 2026 17:50:46 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AE=8C=E6=88=90=E5=8E=9F=E5=9E=8B04-?= =?UTF-8?q?10=E5=85=A8=E9=93=BE=E8=B7=AF=E5=8A=9F=E8=83=BD=E5=BC=80?= =?UTF-8?q?=E5=8F=91=EF=BC=8C=E5=8C=85=E6=8B=ACAI=E5=8A=A9=E6=89=8B?= =?UTF-8?q?=E3=80=81PDF=E5=AF=BC=E5=87=BA=E7=AD=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 16 +- docs/上下文AI助手开发契约.md | 53 +++ docs/产品匹配规则开发契约.md | 55 ++++ docs/原型04-10页面改造与跳转方案.md | 38 ++- docs/开发文档.md | 47 ++- docs/开发进度.md | 143 +++++++- docs/新会话交接.md | 102 ++++++ docs/需求与评估结果数据契约.md | 2 +- packages/account/login/login.uvue | 20 +- packages/finance/assistant/assistant.uvue | 308 +++++++++++++----- packages/finance/compare/compare.uvue | 3 + packages/finance/components/ReportExport.uvue | 42 +++ packages/finance/next-step/next-step.uvue | 178 ++++++++++ packages/finance/product/product.uvue | 98 +++--- packages/finance/report/report.uvue | 12 +- packages/finance/services/api.uts | 12 - packages/finance/services/assistant.uts | 42 +++ packages/finance/services/report-export.uts | 64 ++++ packages/finance/static/action-chat.svg | 1 + packages/finance/static/action-improve.svg | 1 + packages/finance/static/action-prepare.svg | 1 + packages/finance/static/action-report.svg | 1 + packages/finance/static/send.svg | 1 + pages.json | 1 + services/assistant-return.uts | 11 + services/next-step-route.uts | 6 + services/report-route.uts | 5 + 27 files changed, 1083 insertions(+), 180 deletions(-) create mode 100644 docs/上下文AI助手开发契约.md create mode 100644 docs/新会话交接.md create mode 100644 packages/finance/components/ReportExport.uvue create mode 100644 packages/finance/next-step/next-step.uvue create mode 100644 packages/finance/services/assistant.uts create mode 100644 packages/finance/services/report-export.uts create mode 100644 packages/finance/static/action-chat.svg create mode 100644 packages/finance/static/action-improve.svg create mode 100644 packages/finance/static/action-prepare.svg create mode 100644 packages/finance/static/action-report.svg create mode 100644 packages/finance/static/send.svg create mode 100644 services/assistant-return.uts create mode 100644 services/next-step-route.uts create mode 100644 services/report-route.uts diff --git a/README.md b/README.md index 86dda0e..01095a9 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,15 @@ # AI 融资移动端 -基于 uni-app x、Vue 3、UTS 的移动端原型,包含 26 个页面。使用 HBuilderX(VDOM 模式)开发,已验证 5.24 和 5.26 的本地编译;本项目没有独立的 npm 构建入口。 +基于 uni-app x、Vue 3、UTS 的移动端原型,包含 27 个页面。使用 HBuilderX(VDOM 模式)开发,已验证 5.24 和 5.26 的本地编译;本项目没有独立的 npm 构建入口。 2026-09-28:原型07产品对比已接通,匹配列表/本次产品详情可选择2—3项历史产品,支持补选、移除、刷新恢复、失败列重试及手机横向滚动。复用本人冻结匹配详情,不新增表或模型调用;当前26页,真实产品与跨平台验收仍待完成。见[开发进度6.16](docs/开发进度.md)。 2026-09-28:原型09报告已改为“评估概况/匹配结果/改善建议”,支持栏目URL刷新、最多3项历史候选、分组产品依据与局部重试;重新评估进入空白个人/企业表单,旧报告不补算。PDF、上下文助手与行动页继续独立开发。验证见[开发进度6.17](docs/开发进度.md)。 +2026-09-28:原型10下一步行动已接通报告/产品入口,支持材料准备、查看已存报告、优化资料后同类型空白重评和上下文AI咨询;登录返回与当前可用性守卫已验证。H5 38项检查、Android/微信编译通过;09 PDF待开发,真实产品/真机待验收。见[开发进度6.20](docs/开发进度.md)。 + +2026-09-28:09报告与10行动页已接入普通H5 PDF下载:鉴权、冻结数据、中文分页、脱敏及失败重试;29项文件检查、20项HTTP及24项浏览器检查通过,Android/微信编译通过。微信内浏览器/原生下载与生产容量待验收。见[开发进度6.21](docs/开发进度.md)。 + ## 本地运行 2026-09-24:本地产品库已按用户要求上架6条演示产品(ID22—27)。新评估会冻结目录、计算三态及证据并保存匹配结果;报告已展示实际统计和演示标记,旧报告不补算。匹配列表/详情API和03/04/05/06基础已接通,可从新报告进入本次匹配;07—10扩展待开发。数据、脚本与参数见[产品规则契约第7节](docs/产品匹配规则开发契约.md),验收进度见[开发进度6.12](docs/开发进度.md)。 @@ -145,3 +149,13 @@ $projectPath = (Get-Location).Path “我的融资档案”恢复个人/企业切换、完整度与四组资料卡;默认读取该类型最新提交,支持历史分页选择与只读展开。完整度使用所选成功报告中的冻结结果,旧版/未完成/无记录显示未评定说明;底部可查看同次报告或发起空白新评估。不恢复草稿,不编辑历史资料。后端沿用GET /assessments的type过滤及详情/报告接口,验证范围见docs/开发进度.md第6.14节。 2026-09-28:个人中心入口去重,顶部为“开始评估”(选择个人/企业)和“最近报告”(本人最近提交且已完成的报告直达),下方“我的融资档案”管理历史资料。无报告但有任务时可查看进度,无记录时明确提示;不重新提交或调用模型。验证范围见开发进度6.15。 + +## 2026-09-28 原型04/05与单产品解释 + +已按原型还原产品匹配详情,接通逐条DeepSeek解释、状态查询、失败重试和历史保存。新增POST /api/v1/assessments/:id/matches/:productId/explanation,body仅requestId,返回匹配详情中的异步状态;GET不调用模型。复用fa_ai_chat匹配JSON和fa_ai_chat_log,无新表/迁移。analysis:work新增消费解释任务,更新代码后重启进程;成功解释重复打开不收费,失败须明确新键重试,每产品最多三次,与报告共享每日用户额度。 + +原型08上下文咨询、09 PDF、10行动页和真实产品验收仍待完成。51项解释回归、70项匹配HTTP/快照检查及真实Flash/浏览器验证详见前端docs/开发进度.md第6.18节;模型凭据只从后端配置读取。 + +## 2026-09-28 原型08上下文AI助手 + +已接普通/报告/产品/对比的持久会话、消息分页、异步回复、原键重试和登录返回,界面参考原型08。需保持后端analysis:work运行;进入页面、点击快捷问题不调用模型,明确发送才预留调用。后端本机增量迁移已获授权并完成;原报告未改写。助手70项及相关回归通过,Android/微信编译与H5手机/桌面联调通过;真实多轮DeepSeek语义、真机和生产容量待验收。详见[助手契约](docs/上下文AI助手开发契约.md)及[开发进度6.19](docs/开发进度.md)。 diff --git a/docs/上下文AI助手开发契约.md b/docs/上下文AI助手开发契约.md new file mode 100644 index 0000000..1d6dcc2 --- /dev/null +++ b/docs/上下文AI助手开发契约.md @@ -0,0 +1,53 @@ +# 原型08上下文AI助手 + +版本1.0,2026-09-28。CHAT-001—003完成本地接口和页面联调,待验收;CHAT-004异常与额度本地检查通过,真实DeepSeek多轮语义、移动端真机与商业额度仍待验收。 + +## 1. 会话与事实边界 + +- 复用`fa_ai_chat`/`fa_ai_chat_log`,不新增业务表。助手始终`scene=assistant`、`assessment_id=NULL`、`analysis_context=NULL`。 +- `context_assessment_id`可空,仅引用本人成功评估;复合外键`(context_assessment_id,user_id)`防跨账户绑定。`context_data`保存版本、创建幂等键、最多3个产品ID和冻结事实摘要,不接收客户端报告正文。 +- 普通、报告、单产品、2—3项对比均可进入。服务端读取冻结报告、匹配理由和证据,白名单排除姓名、手机、证件、附件、职业及自由用途说明;产品名称/数字/判定采用评估时版本,不读取当前产品替换历史事实。 +- 会话固定上下文。URL指定的评估及产品须与chatId一致;上下文删除、失效或摘要变化则拒绝。后续单产品AI解释和当前上下架状态不参与摘要,不影响会话恢复。 +- 模型仅解释,不改变规则结论,不生成匹配率、获批概率或授信承诺。系统约束和输出格式校验不等同于语义完全正确,正式上线仍需真实多轮人工验收。 + +## 2. 已实现接口 + +均为会员Bearer、`Cache-Control: no-store`、FastAdmin响应格式。业务成功HTTP200不表示异步模型完成。 + +| 方法与路径(前缀/api/v1) | 参数 | 返回data | +| --- | --- | --- | +| GET /assistant/context | contextAssessmentId可空字符串、contextProductIds逗号列表 | 上下文标题、产品名/实际状态、快捷问题和说明;不创建会话、不调用模型 | +| GET /assistant/chats | limit字符串1—30,默认20;cursor可空 | 本人普通会话items、hasMore、nextCursor;按创建ID倒序 | +| POST /assistant/chats | requestId;contextAssessmentId字符串或null;contextProductIds字符串数组 | chatId、title、context;只创建会话,不调用模型 | +| GET /assistant/chats/:id | 可选contextAssessmentId/contextProductIds,同preview格式 | chatId、title、context;传入上下文时严格核对一致 | +| GET /assistant/chats/:id/messages | limit字符串1—30,默认20;cursor可空 | chatId、items、hasMore、nextCursor;首屏最新20轮,页内按时间正序 | +| POST /assistant/chats/:id/messages | requestId、message、retryAttempt整数0—2 | chatId、item;queued/running/completed/failed | + +requestId为8—64位字母、数字、下划线、短横线。message为1—800字纯文本。拒绝额外参数、无评估产品列表、重复产品或超过3项产品。创建同键不同绑定、发送同键不同正文均409;越权或不存在404,未完成报告409,未配置模型503,超额度429,非法参数422。 + +每轮DTO为`{id,requestId,message,reply,status,attempt,canRetry,createdAt}`,reply仅成功时非空。消息内部调用行、错误码、凭据、用量不透传页面。加密游标绑定用户及会话,不能跨会话使用。 + +## 3. 异步、重试与额度 + +- 用户明确发送后,在用户行锁及会话行锁中保存用户消息并预留assistant调用行。`ast:`前缀调用日志是持久待办,既有`analysis:work`在报告和产品解释队列空闲时消费。 +- 每会话最多100轮、同一时间只有一条回复在排队/执行。每用户每天最多新建30个会话。模型调用与报告和产品解释共享`deepseek.daily_calls_per_user`(本地默认20),失败也占预留次数,防止故障重试无限计费。 +- 第一次retryAttempt=0。HTTP回执丢失必须原requestId/正文/重试序号重放,不增加调用。已确认失败后,用户手动重试保持requestId、retryAttempt递增,最多3次;只能重试最近一轮,成功和运行中均不能重跑。 +- 每次尝试独立assistant日志,reply_id指向同一用户消息。保留所有尝试用量;tokens未知保持null,不把失败当零消耗。MySQL可重复读下关键幂等、序号和额度查询使用锁定当前读,避免旧快照绕过串行用户锁。 +- 运行租约`max(180秒,供应商timeout+60秒)`。超时由worker恢复扫描标失败,不自动收费重试;迟到响应只能补原调用用量,不能改成成功或覆盖新尝试。 +- 默认Flash,复用既有DeepSeekClient。上下文保留最近6轮成功问答(失败不发送),回复最长1200字,总请求序列化最多96KB;用户主动输入的手机号、身份证及长银行卡号脱敏后才发送模型。不声称自由文本已完全去除所有个人信息。 + +## 4. 页面与返回 + +机器人、问候气泡、浅蓝快捷问题及底部输入栏参考原型08,复用现有素材;上下文卡为必要增补。普通模式不假定已有报告。快捷问题按实际判定生成,点击仅填入问题,点击发送才请求模型。 + +首次发送创建会话并在H5地址中保存chatId,刷新重新鉴权恢复;历史对话入口可恢复普通或上下文会话。消息3秒轮询,最多60次,超限/查询失败提供继续查询。失败明确提示并支持原键重试。消息、报告不落本机持久缓存;离页清理渲染和轮询,Token变化拒绝迟到回包并清除内容。 + +04/05咨询入口保留产品ID,07保留产品选择,09带本次评估;navigateBack优先保持原页面状态。冷启动的返回产品/对比/报告仅由白名单来源与编号重建;普通模式回首页。登录页只支持白名单助手返回,拒绝任意returnUrl;登录后再次校验归属。 + +## 5. 迁移与验证 + +本轮用户明确授权本机迁移后,执行后端`database/migrate_assistant_context.py --apply --worker-stopped`。新增2列、索引、归属外键与场景检查约束共5项;复跑预检0项。备份位于`D:/AAdesk/202609/airz-backups/assistant-context-20260928-154651-271907/`。恢复优先回退助手代码并保留可空列,不整表覆盖后续业务数据,详见后端`database/assistant-context-migration.md`。 + +后端70项助手检查、51项产品解释、31项任务、36项评估HTTP、70项匹配HTTP/快照检查通过。HBuilderX5.26 Android与微信编译通过。H5 Chromium390×844、1280×900验证普通/上下文、三入口、发送/刷新/失败重试、回执丢失、23轮历史分页、上下文冲突、跨账号及真实密码登录返回;模型输出使用假模型,未新发收费DeepSeek调用。最终正常流程无业务console.error/warn。 + +临时截图/脚本:`C:/Users/JUN/AppData/Local/Temp/airz-assistant-20260928/`。合成账号/评估/会话/日志/令牌/队列已清理,隔离服务和浏览器已关闭。原有2份评估会话及2条调用记录逐条对照迁移前备份未改写。未验收:真实多轮模型语义、真实产品人工金标准、微信内H5/Safari、真机键盘/安全区以及生产守护/容量。 diff --git a/docs/产品匹配规则开发契约.md b/docs/产品匹配规则开发契约.md index 0b6fed5..e1b1bc0 100644 --- a/docs/产品匹配规则开发契约.md +++ b/docs/产品匹配规则开发契约.md @@ -241,3 +241,58 @@ productSnapshot包含产品ID/版本/名称/机构/类型,amountMinYuan、amou 报告入口携带assessmentId;列表三组统计与分页来自同次结果;卡片只预览最多三条主要理由,详情保留全部不符/待核实理由,已满足项可展开。无评估编号时选择历史或重新评估;非法编号明确错误,绝不读取最近结果。详情无assessmentId只展示公共资料,有assessmentId始终读取本人快照。页面离开清空结果,响应返回时校验当前Token和请求序号,防止旧账户迟到响应恢复界面。 本轮`tests/match_records.php --worker-stopped`62项验证接口身份/方法、三组、游标分页和篡改、快照归属、未知键投影、损坏数据、下架/过期/删除/改价后历史、旧版报告、重复读取无副作用。产品变化只在测试连接事务内发生并回滚,随机账户及队列清理;停止正式worker以避免恢复扫描拾取合成评估。浏览器结果及截图见开发进度6.13。 + +## 9. 单产品解释任务与原型04/05(2026-09-28已实现,覆盖第7/8节的未接入状态) + +### 9.1 接口与状态 + +`POST /api/v1/assessments/:id/matches/:productId/explanation`要求会员Bearer Token、本人成功且未删除评估及该产品冻结结果,Content-Type为application/json。请求只允许`{"requestId":"explanation_20260928_001"}`;requestId为8—64位ASCII字母/数字/下划线/短横线,无金额或模型参数。重复读取GET不生成解释。 + +HTTP200沿用`{code:1,msg,time,data}`,data与匹配详情相同,不表示模型已经完成;客户端检查item.aiExplanation.status。queued/running期间轮询原GET匹配详情。例: + +```json +{ + "status": "completed", + "text": "该项信息来自自填资料,仍需核对证明材料。", + "evidenceRefs": ["product:22:rule:base_amount"], + "reasonExplanations": [{ + "reasonId": "product:22:rule:base_amount:reason", + "text": "该项信息来自自填资料,仍需核对证明材料。", + "evidenceRefs": ["product:22:rule:base_amount"] + }], + "generatedAt": "2026-09-28T07:07:00+00:00", + "errorCode": null, + "canRetry": false +} +``` + +上例只说明结构,不是完整产品样例。text/evidenceRefs兼容已有消费者;逐条渲染使用reasonExplanations,数值/来源仍取确定性证据,不能从模型文本反解析金额。首次not_requested;queued/running保留空文本/数组;失败为failed,errorCode仅固定错误码,canRetry表示未超过三次上限;成功为completed并带生成时间。有效的旧not_requested对象缺新增字段时,前端按空值兼容。 + +| HTTP/错误 | 含义与行为 | +| --- | --- | +| 401 AUTH_REQUIRED | 会话失效;客户端清理并回登录 | +| 404 ASSESSMENT_NOT_FOUND / MATCH_NOT_FOUND | 非本人、已删记录或产品不在本次快照;不回退公共产品 | +| 409 REPORT_NOT_READY / MATCH_RESULT_UNAVAILABLE | 报告未成功或存储结构损坏,不调用模型 | +| 422 VALIDATION_ERROR | 非法requestId或多余请求字段 | +| 503 ANALYSIS_NOT_CONFIGURED | 模型服务未配置,不预留新调用 | +| 429 AI_DAILY_LIMIT | 与报告共用当日用户预留额度,开发默认二十次 | +| 409 AI_ATTEMPT_LIMIT | 每评估每产品最多三次尝试,不再创建任务 | + +模型/网络失败写入状态,不使用供应商异常正文:AI_TIMEOUT、AI_NETWORK、AI_AUTH、AI_CONFIGURATION、AI_BALANCE、AI_RATE_LIMIT、AI_PROVIDER_ERROR、AI_INVALID_RESPONSE、AI_INVALID_REPORT、AI_TASK_INTERRUPTED等。用户可读状态与规则理由仍保留;不自动重新调用收费模型。 + +### 9.2 持久化、幂等和恢复 + +- fa_ai_chat.match_result中的单项ai_explanation保存状态、reason_explanations及生成时间;内部还保存task_id/request_keys/attempts/lease_until。只更新这一个对象,不修改冻结参数、证据、判定、排序、报告或评估生命周期。不同产品更新同一JSON时使用会话行锁,防止相互覆盖。 +- fa_ai_chat_log使用role=assistant、request_id前缀`pex:`、pending/streaming/completed/failed以及已存在的模型/Token/耗时/错误字段。用户行锁串行预算预留;会话锁串行序号和快照写入。数据库事务原子保存任务和快照状态,不新增业务表/索引/迁移。 +- 相同requestId重放返回当前状态;queued/running期间不同键也合并为同一任务;成功后不同键返回历史解释。明确failed后用户使用新键重试,最多三次。次数包含失败和不确定超时,防止无限收费。 +- analysis:work继续优先处理既有报告队列,空闲时领取一条持久解释日志;pending任务无需Redis投递,进程重启不会丢失。租约为max(180秒,供应商超时+60秒),streaming过期改失败;`--recover-only`也回收解释租约,不调用模型。服务停机期间queued保持等待,恢复进程后继续消费。 +- 多worker用日志状态和会话锁只允许一次领取。迟到回复不得回写已失效任务,已发生用量仍补记原日志。删除评估/禁用账户后不保存成功解释。运营需关注pending积压、失败错误码和调用用量;当前未实现独立解释后台管理页。 +- 分页摘要排除ai_explanation,解释生成不使产品分页失效;其他冻结字段仍参与摘要并校验。部署时已有旧摘要游标可收到一次MATCH_CURSOR_INVALID,重新从首屏读取即可,不改历史报告。 + +### 9.3 模型边界与页面 + +使用已配置deepseek-v4-flash-0731,只发该产品规则理由、字段白名单、actual/expected/source/outcome,不发送姓名、电话、证件、附件、机构说明自由文本或完整报告。模型输出仅reasons数组,每项reasonId/text;按ID集合检验恰好覆盖所有理由,无重复、遗漏和外来ID,恢复规则顺序后由服务端附原证据引用。每条最多九十字,数字/金额/期限/HTML/明显授信承诺等拦截。确定性校验不能替代真实产品人工语义金标准,正式机构资料仍待验收。 + +页面生成期间可离开,重新打开读取保存状态;每三秒查询、最多六十次,断网/轮询结束提供手动查询,不重提任务。页面离开清理个人数据和计时器;迟到回包校验Token/请求序号/可见性。初始依据、AI解释失败、已保存解释可区分;已有数值仍以万元精确展示。布局与有意差异见原型方案第8节。 + +验证入口:`php tests/product_explanations.php --worker-stopped`(51项,假模型);可选`--live`额外调用一次真实Flash。`php tests/match_records.php --worker-stopped`更新为70项,含解释POST方法、归属、参数、删除记录和幂等回执。必须先停止worker,测试仅清理其随机账号/日志/评估/队列。真实模型和浏览器验证记录见开发进度6.18。 diff --git a/docs/原型04-10页面改造与跳转方案.md b/docs/原型04-10页面改造与跳转方案.md index f364a32..d4f55a6 100644 --- a/docs/原型04-10页面改造与跳转方案.md +++ b/docs/原型04-10页面改造与跳转方案.md @@ -1,11 +1,11 @@ # 原型04—10页面改造与跳转方案 -版本:1.3。日期:2026-09-28。依据:[原型图](原型.jpg)、[开发文档](开发文档.md)、[数据契约](需求与评估结果数据契约.md)。本轮用户明确要求补齐04—10页面并随后进入产品匹配开发;此前“对比/PDF另行排期”的范围限制,自本方案起由下列正式任务覆盖。 +版本:1.7。日期:2026-09-28。依据:[原型图](原型.jpg)、[开发文档](开发文档.md)、[数据契约](需求与评估结果数据契约.md)。本轮用户明确要求补齐04—10页面并随后进入产品匹配开发;此前“对比/PDF另行排期”的范围限制,自本方案起由下列正式任务覆盖。 ## 1. 范围与落地原则 - 04、05是同一产品匹配详情的不同判定状态,06是同一详情页的产品信息栏;复用现有product/product,不机械新增三个页面。 -- 07产品对比、10下一步行动新增两个融资分包页面。compare已注册,当前pages.json共26页;next-step仍待开发注册,最终目标27页。 +- 07产品对比、10下一步行动新增两个融资分包页面。compare与next-step均已注册,当前pages.json共27页。 - 08复用assistant/assistant;09复用report/report并改为“评估概况/匹配结果/改善建议”。03匹配列表作为04—10的必要入口一并改造。 - 保留蓝白主色、卡片、银行标识、正反理由分组和清晰底部行动区。数据必须来自本人本次评估;原型的92%/B+不作为默认值。 - 首版使用既有三态准入:符合已知条件、条件不符、待核实。score=null,不展示匹配百分比;稳定顺序采用productId升序并注明不代表优劣。真实评分、运营优先级另发版本化策略。 @@ -17,13 +17,13 @@ | 原型 | 页面实现 | 页面内容与行为 | 任务 | 当前状态 | | --- | --- | --- | --- | --- | -| 04 单家银行AI解释 | product/product,tab=explanation,eligible状态 | 银行/产品名、条件判定、已满足条件、注意事项、证据来源、AI解释、对比/准备申请 | PRODUCT-004 | 基础已接规则理由/证据/历史快照及对比;单产品AI解释和行动页待开发 | -| 05 其他银行不推荐解释 | 同一页面,ineligible或unknown状态 | 不符条件与待核实项分组;已满足部分称“已满足条件”;查看资料/询问AI,不建议直接申请 | PRODUCT-004 | 已接不符/待核实及证据;AI咨询待接;服务端判定决定状态 | +| 04 单家银行AI解释 | product/product,tab=explanation,eligible状态 | 银行/产品名、条件判定、已满足条件、注意事项、证据来源、AI解释、对比/准备申请 | PRODUCT-004 | 布局按原型还原;逐条DeepSeek解释/持久任务/失败重试本地验证通过;准备入口已接10,真实产品/平台待验收 | +| 05 其他银行不推荐解释 | 同一页面,ineligible或unknown状态 | 不符条件与待核实项分组;已满足部分称“已满足条件”;查看资料/询问AI,不建议直接申请 | PRODUCT-004 | 已接不符/待核实、逐条解释和证据;AI咨询已接08上下文;服务端判定决定状态 | | 06 产品详情 | product/product,tab=details或conditions | 额度/期限/年化利率范围、还款方式、材料、渠道、适用对象、来源及版本;独立显示当前可用性 | PRODUCT-003、PRODUCT-004 | 已接三栏、公共/历史双模式及当前可用性;真实机构资料待录入 | | 07 同类产品对比 | 新增compare/compare | 同一评估2—3个产品列式对比,首列指标固定,移动端横向滚动;条件判定、金额/利率/期限、材料、差异依据 | PRODUCT-005 | 基础完成,本地联调通过;真实产品及平台待验收 | -| 08 AI助手延伸问答 | assistant/assistant | 本次评估及选定产品上下文卡、按实际判定生成快捷问题、持久会话、分页、重试、返回报告/产品 | CHAT-001—004 | 页面已有;真实上下文问答待接 | -| 09 我的融资报告 | report/report | 三栏内容、资料准备状态、完整度、最多三个候选及查看更多、改善项、PDF下载、重新评估、下一步行动 | REPORT-004、REPORT-005 | 三栏/历史候选/改善证据基础已联调;PDF及行动入口待独立任务 | -| 10 下一步行动 | 新增next-step/next-step | 准备申请、查看已保存报告、下载PDF、优化资料、咨询AI、回首页;依结果决定可用行动 | REPORT-006 | 新增任务,未开始 | +| 08 AI助手延伸问答 | assistant/assistant | 本次评估及选定产品上下文卡、按实际判定生成快捷问题、持久会话、分页、重试、返回报告/产品 | CHAT-001—004 | 页面已有;持久上下文/异步问答/分页重试已本地联调,真实语义与真机待验收 | +| 09 我的融资报告 | report/report | 三栏内容、资料准备状态、完整度、最多三个候选及查看更多、改善项、PDF下载、重新评估、下一步行动 | REPORT-004、REPORT-005 | 三栏/历史候选/改善证据基础已联调;行动入口已接10,PDF普通H5基础完成,跨浏览器/真机待验收 | +| 10 下一步行动 | 新增next-step/next-step | 准备申请、查看已保存报告、下载PDF、优化资料、咨询AI、回首页;依结果决定可用行动 | REPORT-006 | 本地联调完成,38项H5检查与Android/微信编译通过;真实产品与平台待验收 | ### 03 匹配列表入口(必要配套) @@ -41,7 +41,7 @@ 产品快照中的额度/利率/期限保持评估时版本。读取时发现当前产品下架/过期,另加状态条并禁用准备申请;查询当前状态失败也不能假定可用。允许查看历史解释、参与带状态标识的历史对比或咨询AI。 -金额以万元范围展示,期限以月、年化利率以百分比范围展示。缺还款方式/审批时长/渠道等资料时显示“未提供”,不得采用原型示例值。银行Logo只使用已提供或可合法使用的真实素材;缺失时用文字简称,不生造银行标志。 +金额以万元范围展示,期限以月、年化利率以百分比范围展示。缺还款方式/审批时长/渠道等资料时显示“未提供”,不得采用原型示例值。银行Logo只使用已提供或可合法使用的真实素材;缺失时用文字简称或既有通用机构图标,不生造银行标志。 “准备申请”仅当eligible且currentAvailability=available时进入10的准备区域;“查看同类产品对比”进入07并保留当前产品选择;“我有疑问,咨询AI”进入08,展示上下文而不自动发送消息或调用模型。 @@ -58,7 +58,7 @@ - 有assessmentId时,只使用本人已成功报告和指定产品的冻结理由;可不指定产品、指定单项或指定对比的2—3项。 - 快捷问题按实际状态生成,例如“这些条件为什么符合”“哪些条件不满足”“还需要核实哪些资料”“两项产品有哪些差异”;无匹配时不出现“为什么推荐这家银行”。 - 输入问题后由用户发送;仅打开页面不创建模型请求。失败重试保持消息requestId,切换账号清理页面内容。 -- 普通会话继续使用scene=assistant,assessment_id=NULL;计划随CHAT-001增量迁移新增context_assessment_id及context_data,前者保存本人评估引用,后者保存产品ID及报告摘要引用。当前库尚无这两列,本轮不迁移;已有普通会话两列为NULL,新增归属索引/约束需先检查历史数据,不复用或覆盖正式评估的analysis_context。 +- 普通会话继续使用scene=assistant,assessment_id=NULL;CHAT-001已增量迁移新增context_assessment_id及context_data,前者保存本人评估引用,后者保存产品ID及报告摘要引用。2026-09-28已获用户授权完成两列、归属索引/外键及场景约束迁移;原有记录新增列为NULL,不复用或覆盖正式评估的analysis_context。 - chatId恢复时以服务端已保存上下文为准;URL与会话上下文冲突拒绝,不静默改绑定。失效上下文提示重新选择,不能回答成另一份报告。 ### 09 报告三栏与PDF @@ -136,9 +136,9 @@ flowchart TD | GET /api/v1/assessments/:id/matches | 已实现 | 03/09,三态分页、默认limit=3;既有契约字段不变 | | GET /api/v1/assessments/:id/matches/:productId | 已实现 | 04/05/06,以及07每次最多读取三项;本人成功记录、本次冻结产品,404不得回退公共数据 | | GET /api/v1/products/:id | 已实现,会员Bearer | 06公共模式;不含个人判定及理由,当前资料与历史快照分开 | -| POST /api/v1/assistant/chats | 计划新增 | contextAssessmentId:string或null、contextProductIds:string[]、requestId;服务端校验同一评估和产品快照,不接客户端报告正文 | -| GET/POST /api/v1/assistant/chats/:id/messages | 计划新增 | 08消息分页、提交与幂等;上下文由会话固定 | -| GET /api/v1/assessments/:id/report.pdf | 计划新增,REPORT-005 | Bearer鉴权;成功application/pdf,Content-Disposition安全文件名、no-store;401/404/409/503为JSON错误;失败不生成报告或调用模型 | +| POST /api/v1/assistant/chats | 已实现,见助手契约 | contextAssessmentId:string或null、contextProductIds:string[]、requestId;服务端校验同一评估和产品快照,不接客户端报告正文 | +| GET/POST /api/v1/assistant/chats/:id/messages | 已实现,见助手契约 | 08消息分页、提交与幂等;上下文由会话固定 | +| GET /api/v1/assessments/:id/report.pdf | 已实现,REPORT-005待验收 | Bearer鉴权;成功application/pdf,Content-Disposition安全文件名、no-store;401/404/409/503为JSON错误;失败不生成报告或调用模型 | PDF接口owner校验先于渲染,未完成返回409 REPORT_NOT_READY,格式不支持409 REPORT_FORMAT_UNAVAILABLE,能力不可用503 REPORT_EXPORT_UNAVAILABLE。仅由受控模板渲染,用户文本转义,禁止任意HTML/外部图片URL触发文件或网络读取。客户端按状态码和Content-Type区分PDF与JSON,不把错误响应另存为PDF。 @@ -205,3 +205,17 @@ report/report的overview/matches/improvements已接现有报告与匹配只读 匹配栏默认eligible前3项,改善栏分别读取ineligible/unknown前3项,各有完整列表和产品详情入口,不把摘要当全部结果。关联产品证据直接展示规则理由、字段值和来源;AI改善文字保留报告中的字段/准备依据标签。读取时核对报告与列表的版本、目录标识及三态统计,异常保留其他可用区块并单独重试。 “重新评估”选择主体后清空流程内存进入空白表单,历史报告不编辑。PDF、下一步行动及上下文问答按钮待对应能力完成后接入。26页、63任务编号和历史估时不变;REPORT-004整体保持开发中,具体验证/剩余边界见[开发进度6.17](开发进度.md)。 + +## 8. 2026-09-28 原型04/05还原记录 + +- 已实现:白底、紧凑机构头部、状态标签、三栏蓝色选中线、绿色/橙色编号、理由标题和灰色解释、双按钮底栏。将重复“资料尚需核验”从长标题移至说明和证据,避免窄屏标题折断;全部原始证据仍可展开。 +- 数据差异:无匹配百分比;只展示有依据的真实数量,不凑三正三反;不符/未知产品的绿色标题使用“已满足的条件”;机构资料尚为明确标注的演示数据,使用通用图标。 +- 操作差异:立即申请暂用“查看资料准备”,只切申请条件栏;05的咨询按钮待08上下文问答完成后接入,当前为可用的产品对比入口。生成AI解释为独立明确点击,成功后逐条补充且重新打开不重复生成。 +- 栏目切换替换当前路由,保留assessmentId/productId/productIds/from;刷新停留原栏,退出页面停止轮询并清理个人数据。默认每三秒读状态,最多六十次,失败或停止后可手动重新查询;不发起新模型任务。 +- 视觉/功能验证:Chromium 390×844、390×1000、1280×900;参考图原始单页约220×568像素,已查看原图和放大局部,并用接近其纵横比的390×1000屏幕检查。记录见开发进度6.18,不代表微信内浏览器或真机验收。 + +2026-09-28原型08实施补充:创建/详情/历史/上下文预览和消息API、重试序号及迁移恢复以[上下文AI助手开发契约](上下文AI助手开发契约.md)为准。CHAT-001—003本地联调后待验收,CHAT-004真实语义/生产容量仍开发中。 + +### 2026-09-28 PDF落地补充 + +09顶部与10页共用鉴权下载组件,服务端内存生成并输出二进制,无公开文件。Dompdf3.1.6及Noto Sans SC中文字体独立锁定;逐字段脱敏、转义和远程读取禁用。普通H5真实下载,微信内/原生/小程序提示使用普通浏览器。29项模板、20项HTTP、24项受控浏览器检查通过,平台/容量待验收;详见进度6.21。 diff --git a/docs/开发文档.md b/docs/开发文档.md index fbc96f1..7a04074 100644 --- a/docs/开发文档.md +++ b/docs/开发文档.md @@ -1,9 +1,37 @@ # AI 融资平台开发文档 -> 版本:v1.14 · 基线日期:2026-09-22 · 更新日期:2026-09-28 · 状态:匹配分页/详情及公共产品详情已接通;03/04/05/06基础接入,07对比与09报告三栏本地联调通过;08助手、09PDF、10行动待开发 +> 版本:v1.18 · 基线日期:2026-09-22 · 更新日期:2026-09-28 · 状态:匹配分页/详情及公共产品详情已接通;04/05按原型还原并接通单产品DeepSeek解释,07对比与09报告三栏本地联调通过;08上下文助手本地联调通过,真实多轮语义/真机待验收;10行动本地联调通过;09PDF普通H5本地验证通过,平台/容量待验收 > 配套台账:[开发进度](开发进度.md)。本文定义范围、接口和验收口径,台账记录实际执行与证据。 > 文档初始规划后已开始开发;以下更新记录优先于原始基线。除明确列为已实现的部分外,计划接口和增量数据仍待开发。 +### 0.20 2026-09-28 原型09报告PDF导出 + +REPORT-005完成本地实施,状态待验收。09报告顶部与10行动页接入同一下载组件;用户点击后才以Bearer请求`GET /api/v1/assessments/:id/report.pdf`,不提供永久公开链接、不重跑模型、不修改已存报告或产品。27页、63项任务不变。 + +后端复用本人成功报告与全部冻结匹配快照,模板包含需求、概况、结构化事实、完整度/准备状态、匹配三态/产品理由、建议、版本、时间和免责声明;旧v1不补造v2指标。排除身份、联系方式、企业名和自由填写内容,纯文本转义;引擎禁止远程资源、脚本和任意文件读取。精确元字符串转万元,PDF中文字体嵌入,页脚编号、长理由分页。 + +导出引擎Dompdf3.1.6及传递依赖单独锁定在后端extend/report-pdf,中文Noto Sans SC Sans2.004固定400字重、字体来源/哈希/许可入库;根依赖不变,无迁移。成功响应application/pdf、no-store/private、安全文件名;401/404/409/503为JSON。引擎缺失/关闭明确503,不生成空文件。 + +H5检查状态、MIME及PDF首尾标识后创建Blob下载;失败可重试且保留报告,离页取消、换账号拒绝迟到文件并清空旧报告,401白名单回登录。首版普通H5开放;微信内浏览器提示“在浏览器打开并重新登录下载”,App/小程序明确未开放,不假报成功。真实Safari/微信/原生下载未验收。 + +29项PDF检查、20项真实HTTP检查、24项浏览器检查及Android/微信编译通过,样本渲染和文字提取通过;证据与局限见开发进度6.21。下一步为08真实多轮语义、真实产品样例及跨浏览器/真机验收,生产导出容量仍需评估。 + +### 0.19 2026-09-28 原型10下一步行动 + +REPORT-006页面与入口已完成本地联调,状态待验收。新增`packages/finance/next-step/next-step`,当前27个页面、63项稳定任务。界面按原型采用白底、蓝色图标、四个行动行、重要提示和首页按钮;关键守卫与业务边界有中文注释。 + +本人成功报告与冻结产品只读展示;仅eligible且当前available展示申请准备材料,进入/返回/刷新重新读取状态,快照不一致时关闭准备。未选产品回本次匹配,不符/待核实/不可用可查看报告、优化资料与咨询。材料与来源使用冻结数据,渠道未提供时明确说明,不提交银行申请、不增加PDF假操作。 + +优化资料先展示待补/待核实项与已存建议,再清空流程内存进入同类型空白表单;不覆盖历史。AI咨询携带评估和可选产品,进入不发送。支持白名单登录返回、归属复验、离页清空及迟到响应隔离;冷启动返回本次报告,首页reLaunch。 + +H5 Chromium手机/桌面38项检查与最终Android/微信编译通过;详见进度6.20。复用已有API,未改后端业务、未迁移、未调用收费模型。下一步为09 PDF;08真实多轮语义、真实产品、微信内H5/Safari和真机仍未验收。 + +### 0.18 2026-09-28 原型08上下文AI助手 + +CHAT-001—003已实现持久会话、消息分页、固定评估/产品上下文、异步回复、原键重试和页面接入,状态待验收;CHAT-004本地异常/额度检查通过,整体仍开发中。普通问答及04/05产品、07对比、09报告入口已接通,进入页面不调用模型,快捷问题只填入输入框。关键实现增加中文注释,保留26个页面和63项任务。 + +经本轮用户明确授权,后端fa_ai_chat新增context_assessment_id/context_data及归属约束,正式assessment_id/analysis_context和已有报告不改写。模型调用默认Flash,复用analysis:work,助手/报告/产品解释共用每日预留额度。完整接口、重试、迁移恢复和验证见[上下文AI助手开发契约](上下文AI助手开发契约.md)。下一步为原型10及09 PDF;08真实多轮语义/真机与生产容量仍需验收。 + ## 0. 2026-09-22 实施更新 - 用户最新决定:删除fa_user_token,会员Token仅存Redis;已备份并删除本地表,当前25张表。fa_user和各业务关系保持不变。运行配置不再依赖MySQL Token驱动。 @@ -176,6 +204,16 @@ REPORT-004页面子项完成本地联调:report/report改为评估概况、匹 继续无草稿。“重新评估”选择个人/企业并清空当前流程内存,进入空白填写页;只有再次正式提交才创建新assessmentId。页面仍26个,未改后端业务、未迁移、未调用收费模型。PDF(REPORT-005)、下一步行动(REPORT-006)与上下文助手按独立任务推进,未展示虚假可用按钮。REPORT-004整体仍开发中,真实产品/外部渠道与微信内H5、真机尚未验收;证据见开发进度6.17。 +### 0.17 2026-09-28 原型04/05与单产品AI解释 + +本轮优先完成04、05,复用product/product的eligible/ineligible/unknown三种状态。按原型恢复紧凑机构信息、AI解释/产品详情/申请条件三栏、绿色序号理由、橙色注意事项和底部双按钮;额度/年化/期限移入产品详情。每组默认最多三条,可展开全部和逐条依据。非候选的绿色区域称“已满足的条件”,不把部分满足理解为推荐。无真实Logo时沿用通用机构图标,演示产品保留标记。 + +新增已实现POST `/api/v1/assessments/:id/matches/:productId/explanation`,Bearer鉴权,JSON体仅`requestId:string`(8—64位字母/数字/下划线/短横线);HTTP200回传与GET匹配详情相同的data,异步状态为queued/running/completed/failed,首次未请求为not_requested。GET只读;仅点击生成/重试调用POST,不自动重跑评估。状态和逐条解释保存在fa_ai_chat.match_result,fa_ai_chat_log预留并记录调用,无新表和迁移。完整接口与故障边界见[产品匹配契约第9节](产品匹配规则开发契约.md)。 + +复用analysis:work消费持久调用日志;同产品并发/成功缓存/相同请求键重放不重复调用,每评估每产品最多三次尝试,与报告共用每日用户调用额度。租约失效明确失败,手动新键重试;旧回复只补用量,不覆盖新任务。DeepSeek仅解释该产品冻结理由,逐条引用由服务端绑定;模型输出允许调整顺序,按理由ID校验无缺失/重复/外来项后恢复规则顺序。禁止模型输出数值与授信承诺。 + +已完成本地验证,PRODUCT-004整体仍开发中;原工时/依赖与63个任务编号不变。原型08上下文咨询和10行动页未完成,当前底部为产品对比、产品详情及资料准备说明,不提供假咨询/假申请。真实产品/人工业务金标准、微信内H5/Safari及真机仍待验收。 + ## 1. 项目目标与现状 ### 1.1 已确认范围 @@ -190,7 +228,7 @@ REPORT-004页面子项完成本地联调:report/report改为评估概况、匹 | 项目 | 当前事实 | 规划用途 | | --- | --- | --- | -| 前端 | uni-app x / Vue 3 / UTS,26 页,无独立 npm 构建入口 | 沿用 HBuilderX 和现有分包,不重新搭建前端 | +| 前端 | uni-app x / Vue 3 / UTS,27 页,无独立 npm 构建入口 | 沿用 HBuilderX 和现有分包,不重新搭建前端 | | 后端 | FastAdmin / ThinkPHP 5.0.28 / PHP 7.4 | 复用认证、后台、模型与队列依赖,新增业务 API/服务 | | 数据库 | MySQL 8.0.44,删除空 Token 表后实际 25 张 InnoDB 表 | 已核对本地库并更新结构快照;恢复点见进度第0节 | | 当前前端模式 | 开发环境已连接本地 v1 API,模拟请求开关关闭 | 密码账户流程已接入,内容与产品匹配等页面仍有原型数据,不按页面数计算完成度 | @@ -217,9 +255,9 @@ REPORT-004页面子项完成本地联调:report/report改为评估概况、匹 ## 2. 页面与功能覆盖 -路由以 [pages.json](../pages.json) 为准。以下覆盖现有全部 26 页;反馈表单、历史列表等优先补入所属现有页面,若交互确需新增页面,在所属分包注册并同步台账。 +路由以 [pages.json](../pages.json) 为准。以下覆盖现有全部 27 页;反馈表单、历史列表等优先补入所属现有页面,若交互确需新增页面,在所属分包注册并同步台账。 -原型07路由`packages/finance/compare/compare`(PRODUCT-005)已注册,现共26页;`packages/finance/next-step/next-step`(REPORT-006)待开发注册,目标共27页。04/05/06均复用product/product,报告PDF不另加页面。参数与返回矩阵见专项页面方案第3节。 +原型07路由`packages/finance/compare/compare`(PRODUCT-005)与10路由`packages/finance/next-step/next-step`(REPORT-006)均已注册,现共27页。04/05/06均复用product/product,报告PDF不另加页面。参数与返回矩阵见专项页面方案第3节。 | 序号 | 页面路由 | 功能职责 | 主要任务 | | --- | --- | --- | --- | @@ -249,6 +287,7 @@ REPORT-004页面子项完成本地联调:report/report改为评估概况、匹 | 24 | packages/content/classroom/classroom | 课程分类和推荐 | CONTENT-002 | | 25 | packages/content/lesson/lesson | 图文章节、学习状态 | CONTENT-001、CONTENT-003 | | 26 | packages/finance/compare/compare | 同次评估2—3产品冻结结果对比、补选及独立重试 | PRODUCT-005 | +| 27 | packages/finance/next-step/next-step | 材料准备、已存报告、资料优化及同类型新评估、上下文AI与首页 | REPORT-006 | ## 3. 数据与架构约定 diff --git a/docs/开发进度.md b/docs/开发进度.md index 812cedd..f59dcd2 100644 --- a/docs/开发进度.md +++ b/docs/开发进度.md @@ -1,6 +1,8 @@ # AI 融资平台开发进度 -基线日期:2026-09-22。文档版本:1.14。最新规划及实施见0.16节与6.17节;此前章节保留阶段记录。技术方案和接口说明见[开发文档](./开发文档.md)。本台账现有63项任务,编号与开发文档保持一致。 +基线日期:2026-09-22。文档版本:1.18。最新规划及实施见0.20节与6.21节;此前章节保留阶段记录。技术方案和接口说明见[开发文档](./开发文档.md)。本台账现有63项任务,编号与开发文档保持一致。 + +会话交接(2026-09-28):已整理[新会话交接](新会话交接.md),包含当前成果、验证边界、业务约定、代码入口和环境状态。原型08、10及09 PDF已完成本地实施,当前边界见0.18—0.20与6.19—6.21节;下一步为真实模型语义、产品与跨平台验收。 ## 0. 2026-09-22 首轮实施更新(优先于初始基线) @@ -175,6 +177,46 @@ REPORT-004页面子项完成本地联调:report/report改为评估概况、匹 继续无草稿。“重新评估”选择个人/企业并清空当前流程内存,进入空白填写页;只有再次正式提交才创建新assessmentId。页面仍26个,未改后端业务、未迁移、未调用收费模型。PDF(REPORT-005)、下一步行动(REPORT-006)与上下文助手按独立任务推进,未展示虚假可用按钮。REPORT-004整体仍开发中,真实产品/外部渠道与微信内H5、真机尚未验收;证据见开发进度6.17。 +### 0.17 2026-09-28 原型04/05与单产品AI解释 + +本轮优先完成04、05,复用product/product的eligible/ineligible/unknown三种状态。按原型恢复紧凑机构信息、AI解释/产品详情/申请条件三栏、绿色序号理由、橙色注意事项和底部双按钮;额度/年化/期限移入产品详情。每组默认最多三条,可展开全部和逐条依据。非候选的绿色区域称“已满足的条件”,不把部分满足理解为推荐。无真实Logo时沿用通用机构图标,演示产品保留标记。 + +新增已实现POST `/api/v1/assessments/:id/matches/:productId/explanation`,Bearer鉴权,JSON体仅`requestId:string`(8—64位字母/数字/下划线/短横线);HTTP200回传与GET匹配详情相同的data,异步状态为queued/running/completed/failed,首次未请求为not_requested。GET只读;仅点击生成/重试调用POST,不自动重跑评估。状态和逐条解释保存在fa_ai_chat.match_result,fa_ai_chat_log预留并记录调用,无新表和迁移。完整接口与故障边界见[产品匹配契约第9节](产品匹配规则开发契约.md)。 + +复用analysis:work消费持久调用日志;同产品并发/成功缓存/相同请求键重放不重复调用,每评估每产品最多三次尝试,与报告共用每日用户调用额度。租约失效明确失败,手动新键重试;旧回复只补用量,不覆盖新任务。DeepSeek仅解释该产品冻结理由,逐条引用由服务端绑定;模型输出允许调整顺序,按理由ID校验无缺失/重复/外来项后恢复规则顺序。禁止模型输出数值与授信承诺。 + +已完成本地验证,PRODUCT-004整体仍开发中;原工时/依赖与63个任务编号不变。原型08上下文咨询和10行动页未完成,当前底部为产品对比、产品详情及资料准备说明,不提供假咨询/假申请。真实产品/人工业务金标准、微信内H5/Safari及真机仍待验收。 + +### 0.18 2026-09-28 原型08上下文AI助手 + +CHAT-001—003已实现持久会话、消息分页、固定评估/产品上下文、异步回复、原键重试和页面接入,状态待验收;CHAT-004本地异常/额度检查通过,整体仍开发中。普通问答及04/05产品、07对比、09报告入口已接通,进入页面不调用模型,快捷问题只填入输入框。关键实现增加中文注释,保留26个页面和63项任务。 + +经本轮用户明确授权,后端fa_ai_chat新增context_assessment_id/context_data及归属约束,正式assessment_id/analysis_context和已有报告不改写。模型调用默认Flash,复用analysis:work,助手/报告/产品解释共用每日预留额度。完整接口、重试、迁移恢复和验证见[上下文AI助手开发契约](上下文AI助手开发契约.md)。下一步为原型10及09 PDF;08真实多轮语义/真机与生产容量仍需验收。 + +### 0.19 2026-09-28 原型10下一步行动 + +REPORT-006页面与入口已完成本地联调,状态待验收。新增`packages/finance/next-step/next-step`,当前27个页面、63项稳定任务。界面按原型采用白底、蓝色图标、四个行动行、重要提示和首页按钮;关键守卫与业务边界有中文注释。 + +本人成功报告与冻结产品只读展示;仅eligible且当前available展示申请准备材料,进入/返回/刷新重新读取状态,快照不一致时关闭准备。未选产品回本次匹配,不符/待核实/不可用可查看报告、优化资料与咨询。材料与来源使用冻结数据,渠道未提供时明确说明,不提交银行申请、不增加PDF假操作。 + +优化资料先展示待补/待核实项与已存建议,再清空流程内存进入同类型空白表单;不覆盖历史。AI咨询携带评估和可选产品,进入不发送。支持白名单登录返回、归属复验、离页清空及迟到响应隔离;冷启动返回本次报告,首页reLaunch。 + +H5 Chromium手机/桌面38项检查与最终Android/微信编译通过;详见进度6.20。复用已有API,未改后端业务、未迁移、未调用收费模型。下一步为09 PDF;08真实多轮语义、真实产品、微信内H5/Safari和真机仍未验收。 + + +### 0.20 2026-09-28 原型09报告PDF导出 + +REPORT-005完成本地实施,状态待验收。09报告顶部与10行动页接入同一下载组件;用户点击后才以Bearer请求`GET /api/v1/assessments/:id/report.pdf`,不提供永久公开链接、不重跑模型、不修改已存报告或产品。27页、63项任务不变。 + +后端复用本人成功报告与全部冻结匹配快照,模板包含需求、概况、结构化事实、完整度/准备状态、匹配三态/产品理由、建议、版本、时间和免责声明;旧v1不补造v2指标。排除身份、联系方式、企业名和自由填写内容,纯文本转义;引擎禁止远程资源、脚本和任意文件读取。精确元字符串转万元,PDF中文字体嵌入,页脚编号、长理由分页。 + +导出引擎Dompdf3.1.6及传递依赖单独锁定在后端extend/report-pdf,中文Noto Sans SC Sans2.004固定400字重、字体来源/哈希/许可入库;根依赖不变,无迁移。成功响应application/pdf、no-store/private、安全文件名;401/404/409/503为JSON。引擎缺失/关闭明确503,不生成空文件。 + +H5检查状态、MIME及PDF首尾标识后创建Blob下载;失败可重试且保留报告,离页取消、换账号拒绝迟到文件并清空旧报告,401白名单回登录。首版普通H5开放;微信内浏览器提示“在浏览器打开并重新登录下载”,App/小程序明确未开放,不假报成功。真实Safari/微信/原生下载未验收。 + +29项PDF检查、20项真实HTTP检查、24项浏览器检查及Android/微信编译通过,样本渲染和文字提取通过;证据与局限见开发进度6.21。下一步为08真实多轮语义、真实产品样例及跨浏览器/真机验收,生产导出容量仍需评估。 + + ## 1. 项目状态与维护规则 当前已具备25个页面原型、部分本机交互、优化后的数据库结构和评估内部生命周期服务;密码账户基础已完成本地前后端联调,短信、评估、报告、匹配等完整业务仍待完成。AI供应商确定为DeepSeek,模型已确定为deepseek-v4-pro-0813和deepseek-v4-flash-0731,两个模型权限及自填报告已真实验证,商业预算、余额及生产容量仍待核验;其他服务商待定。 @@ -244,9 +286,9 @@ P0 表示核心流程、安全、首发外部能力或发布门槛;P1 表示 | 编译与页面金额检查 | 上一轮 Web 与 Android 编译通过;手机 390×844、桌面 1280×900 浏览器检查金额输入、超限、确认、模拟提交和产品显示 | [前端 README](../README.md)、[页面注册](../pages.json);前序任务会话验证记录 | 不是短信/AI/上传真实联调;无 iOS/Xcode 或 Android 真机上线结论;独立历史日志路径未留档,后续回归须新增证据 | | 迁移与恢复基础 | 本机迁移及仓库外备份已完成 | [数据库迁移说明](D:/AAdesk/202609/airz/database/README.md) | 旧迁移限定业务空表,不得直接用于已有业务数据环境;未完成通用部署和恢复演练 | -### 2.2 全部 26 个页面的验收归属 +### 2.2 全部 27 个页面的验收归属 -页面路径以[pages.json](../pages.json)为准。下表记录页面真实业务的主要收口任务;其内部依赖仍需全部完成。当前 26 页均未通过一期真实业务验收。 +页面路径以[pages.json](../pages.json)为准。下表记录页面真实业务的主要收口任务;其内部依赖仍需全部完成。当前 27 页均未通过一期真实业务验收。 | 页面 | 注册路径 | 主要任务 | 当前状态 | | --- | --- | --- | --- | @@ -257,9 +299,10 @@ P0 表示核心流程、安全、首发外部能力或发布门槛;P1 表示 | 分析中 | packages/finance/analyzing/analyzing | REPORT-004 | 按assessmentId轮询状态、失败重试、成功后打开真实报告 | | 评估报告 | packages/finance/report/report | REPORT-004 | 三栏已接本人冻结报告、匹配候选与改善证据;真实业务及平台验收未完成 | | 匹配结果 | packages/finance/matches/matches | PRODUCT-004、REPORT-004 | 已接本人冻结结果、三态/分页及对比选择;演示产品联调 | -| 产品详情 | packages/finance/product/product | PRODUCT-004 | 已接历史理由/证据和参数、对比入口;单产品AI解释待开发 | +| 产品详情 | packages/finance/product/product | PRODUCT-004 | 已接原型04/05、历史理由/参数、逐条DeepSeek解释与失败重试;08咨询待接 | | 产品对比 | packages/finance/compare/compare | PRODUCT-005 | 2—3项冻结对比本地联调通过,真实产品与平台待验收 | -| AI 助手 | packages/finance/assistant/assistant | CHAT-004 | 模拟对话 | +| 下一步行动 | packages/finance/next-step/next-step | REPORT-006 | 四项行动与上下文/返回本地联调通过,真实产品及平台待验收 | +| AI 助手 | packages/finance/assistant/assistant | CHAT-004 | 持久上下文对话已本地联调,真实语义/真机待验收 | | 融资档案 | packages/finance/archive/archive | ASSESS-004、REPORT-004 | 本人历史分页、脱敏只读详情、刷新恢复 | | 启动引导 | packages/account/index/index | BASE-003、AUTH-002 | 原型/本机引导 | | 登录 | packages/account/login/login | AUTH-002、LOGIN-004 | 未完成真实认证 | @@ -432,7 +475,7 @@ DEC-DEMAND已确认并发布,需求录入/提交/历史子范围已实现; | PRODUCT-001 | 全栈开发(待指定) | 发布规则与人工样例可审阅;非法字段/操作符阻止发布;fail优先于unknown,匹配指标不作为审批概率。 | 首版字段/操作符/来源门槛已形成规则契约;64项内存测试;真实产品发布依据与业务样例待验收 | 2026-09-24 | | PRODUCT-002 | 全栈开发(待指定) | 同输入/快照结果稳定;未知不当满足,配置错误不归咎用户;需求不拆额、不改期;未运行与零候选区分。 | 目录冻结/排序/理由已接正式worker;51项内存和19项任务测试通过;真实产品金标准、规模/生产验收仍待完成 | 2026-09-24 | | PRODUCT-003 | 全栈开发(待指定) | 产品用途/地区/额度/期限有真实依据;规则可配置并启停,版本变化留依据;公共详情无个人分数。 | 发布预检及模型保存已实现;本地6条演示产品已授权上架,重复录入不覆盖;公共详情已接;真实资料/发布验收、结构化编辑和公共列表待完成 | 2026-09-24 | -| PRODUCT-004 | 全栈开发(待指定) | 每条解释可追溯且不凑三正三反;当前产品变化不改历史;跨账户拒绝;unavailable/零候选/failed不混淆。 | 匹配分页/详情和03/04/05/06基础已接;62项HTTP/快照检查及H5验证见6.13;单产品AI解释、真实业务验收待完成 | 2026-09-24 | +| PRODUCT-004 | 全栈开发(待指定) | 每条解释可追溯且不凑三正三反;当前产品变化不改历史;跨账户拒绝;unavailable/零候选/failed不混淆。 | 原型04/05和逐条DeepSeek解释本地完成;51项任务/输出检查、70项HTTP/快照检查与浏览器验证见6.18;真实机构资料及平台验收待完成 | 2026-09-28 | | PRODUCT-005 | 全栈开发(待指定) | 不跨评估/混用现价;缺值不同于0;手机横向表格可读,单项失败明确;不重跑模型。 | compare页面及6.16本地编译/真实读取与异常注入证据;真实机构产品和微信内H5/真机待验收 | 2026-09-28 | 剩余门槛:DEC-MATCH开发口径已采用既有契约,真实产品规则/金标准业务签收待完成;PRODUCT-003真实发布仍依赖DEC-PRODUCT。纯规则、后台模型预检及字段编译已实施,未解除整模块验收依赖。 @@ -447,8 +490,8 @@ DEC-DEMAND已确认并发布,需求录入/提交/历史子范围已实现; | REPORT-002 | 异步任务与补偿 | 保留Redis派发、补投、租约和taskId隔离;沿用提交时input_snapshot,一次性补入execution_snapshot并在重试时复用,支持跨部署v1/v2任务。 | P0 | ASSESS-003、REPORT-001 | 2.5–4 | 开发中 | | REPORT-003 | 报告生成与持久化 | 保留v1自填报告;补v2需求、完整度/准备等级、规则证据及定性AI区块;版本快照和正式结果原子落库。 | P0 | REPORT-002、DATA-004、PRODUCT-002、PRODUCT-003、DEC-MATCH、DEC-READINESS | 2–3 | 阻塞 | | REPORT-004 | 分析报告历史联调 | 保留轮询/重试和v1历史;接v2需求、完整度、准备等级、三态匹配及证据解释,不显示无规则分数/雷达。 | P0 | REPORT-003、PRODUCT-004、ASSESS-004 | 2–3 | 开发中 | -| REPORT-005 | 报告PDF导出 | 鉴权流式下载、受控中文模板、报告与产品冻结快照、H5保存与失败提示。 | P1 | REPORT-004 | 2.5–4 | 未开始 | -| REPORT-006 | 下一步行动 | 新增next-step页,准备材料、查看已存报告、优化资料、新评估、咨询及首页导航。 | P1 | PRODUCT-004、REPORT-004、CHAT-003 | 1–2 | 未开始 | +| REPORT-005 | 报告PDF导出 | 鉴权流式下载、受控中文模板、报告与产品冻结快照、H5保存与失败提示。 | P1 | REPORT-004 | 2.5–4 | 待验收 | +| REPORT-006 | 下一步行动 | 新增next-step页,准备材料、查看已存报告、优化资料、新评估、咨询及首页导航。 | P1 | PRODUCT-004、REPORT-004、CHAT-003 | 1–2 | 待验收 | | 任务编号 | 负责人 | 验收条件 | 证据 | 更新时间 | | --- | --- | --- | --- | --- | @@ -456,8 +499,8 @@ DEC-DEMAND已确认并发布,需求录入/提交/历史子范围已实现; | REPORT-002 | 全栈开发(待指定) | 漏投/中断可恢复或明确失败;旧任务不可回写;输入/目标结果/策略/产品快照重试不隐式变化。 | 54项报告检查覆盖目标版本冻结、超时重试快照不变、旧v2输入仍v1、损坏快照先于模型失败;产品快照/生产守护未完成,旧29项任务证据保留 | 2026-09-24 | | REPORT-003 | 全栈开发(待指定) | 完整度按发布字段集复算,等级有依据且非审批;null rank/score按状态验证;格式错误不成功,产品/规则更新不改旧报告。 | v2自填支线已实现;本轮58项回归及Flash3例/Pro1例真实样例通过;真实产品/外部查询、生产与业务人工签收待完成 | 2026-09-24 | | REPORT-004 | 全栈开发(待指定) | 个人/企业真实链路按版本展示;未发布无分或等级,100%不等于授信;旧报告不重算;新复评新assessmentId。 | 6.17三栏/局部重试/旧版/权限及生命周期验证;真实产品与外部渠道仍待验收 | 2026-09-28 | -| REPORT-005 | 全栈开发(待指定) | 本人成功报告可导出;金额/理由与历史一致;不重跑模型/泄露身份;中文分页可读,JSON错误不保存成PDF。 | 04—10方案定义导出接口与失败/隐私边界;PDF引擎及中文字体待选型锁定,未生成样本 | 2026-09-24 | -| REPORT-006 | 全栈开发(待指定) | 根据判定及当前可用性开放行动;无银行申请提交;新评估不改历史、无草稿;上下文和返回正确。 | 04—10方案已定义全部按钮去向和条件,尚未注册路由/实施页面 | 2026-09-24 | +| REPORT-005 | 全栈开发(待指定) | 本人成功报告可导出;金额/理由与历史一致;不重跑模型/泄露身份;中文分页可读,JSON错误不保存成PDF。 | 鉴权接口/H5导出已实施,29项PDF+20项HTTP+24项浏览器检查通过;跨浏览器/真机和生产容量待验收,见6.21 | 2026-09-28 | +| REPORT-006 | 全栈开发(待指定) | 根据判定及当前可用性开放行动;无银行申请提交;新评估不改历史、无草稿;上下文和返回正确。 | 27页已注册;38项H5流程/边界检查、Android/微信编译通过,真实产品与平台待验收,见6.20 | 2026-09-28 | 剩余依赖:REPORT-001商业预算/生产额度待DEC-AI;REPORT-003完整报告仍依赖DATA、PRODUCT、DEC-MATCH;DEC-READINESS首版开发策略已发布,人工业务验收待完成。模型真实权限已验证。 @@ -467,17 +510,17 @@ DEC-DEMAND已确认并发布,需求录入/提交/历史子范围已实现; | 任务编号 | 任务 | 范围 | 优先级 | 直接依赖 | 预计人日 | 状态 | | --- | --- | --- | --- | --- | --- | --- | -| CHAT-001 | 会话与消息API | 普通会话创建/列表/消息分页/归属;明确可引用评估上下文且不占用正式assessment_id。 | P1 | AUTH-002、BASE-001 | 1–1.5 | 未开始 | -| CHAT-002 | DeepSeek对话调用 | 上下文裁剪、敏感信息最小化、消息幂等、异步回复与本地配额记录。 | P1 | CHAT-001、REPORT-001、REPORT-002 | 1–2 | 未开始 | -| CHAT-003 | 助手页面接入 | chatId/requestId、历史加载、发送状态、失败重试、由报告进入解释上下文。 | P1 | CHAT-002、REPORT-004 | 1–2 | 未开始 | -| CHAT-004 | 对话异常与额度验收 | 并发消息、重复点击、额度耗尽、供应商超时及失效会话。 | P1 | CHAT-003 | 1–1.5 | 未开始 | +| CHAT-001 | 会话与消息API | 普通会话创建/列表/消息分页/归属;明确可引用评估上下文且不占用正式assessment_id。 | P1 | AUTH-002、BASE-001 | 1–1.5 | 待验收 | +| CHAT-002 | DeepSeek对话调用 | 上下文裁剪、敏感信息最小化、消息幂等、异步回复与本地配额记录。 | P1 | CHAT-001、REPORT-001、REPORT-002 | 1–2 | 待验收 | +| CHAT-003 | 助手页面接入 | chatId/requestId、历史加载、发送状态、失败重试、由报告进入解释上下文。 | P1 | CHAT-002、REPORT-004 | 1–2 | 待验收 | +| CHAT-004 | 对话异常与额度验收 | 并发消息、重复点击、额度耗尽、供应商超时及失效会话。 | P1 | CHAT-003 | 1–1.5 | 开发中 | | 任务编号 | 负责人 | 验收条件 | 证据 | 更新时间 | | --- | --- | --- | --- | --- | -| CHAT-001 | 全栈开发(待指定) | 用户只能读自身会话;评估会话与普通会话分离;重进恢复历史。 | 未验收;无真实业务验收证据 | 2026-09-22 | -| CHAT-002 | 全栈开发(待指定) | 同请求不重复建消息或记本地消耗;错误回复不标成功;不会发送无关证件资料。 | 未验收;无真实业务验收证据 | 2026-09-22 | -| CHAT-003 | 全栈开发(待指定) | 切换会话不串上下文;超时保留可重试消息;重进页面能继续。 | 未验收;无真实业务验收证据 | 2026-09-22 | -| CHAT-004 | 全栈开发(待指定) | 配额并发不超扣;供应商计费不明可对账;仅真实成功回复显示完成。 | 未验收;无真实业务验收证据 | 2026-09-22 | +| CHAT-001 | 全栈开发(待指定) | 用户只能读自身会话;评估会话与普通会话分离;重进恢复历史。 | 本地70项助手及H5联调通过;真实语义/真机待验收,见6.19 | 2026-09-28 | +| CHAT-002 | 全栈开发(待指定) | 同请求不重复建消息或记本地消耗;错误回复不标成功;不会发送无关证件资料。 | 本地70项助手及H5联调通过;真实语义/真机待验收,见6.19 | 2026-09-28 | +| CHAT-003 | 全栈开发(待指定) | 切换会话不串上下文;超时保留可重试消息;重进页面能继续。 | 本地70项助手及H5联调通过;真实语义/真机待验收,见6.19 | 2026-09-28 | +| CHAT-004 | 全栈开发(待指定) | 配额并发不超扣;供应商计费不明可对账;仅真实成功回复显示完成。 | 并发额度/超时/迟到/重试本地通过;供应商真实语义与生产容量待验收,见6.19 | 2026-09-28 | 直接外部/业务阻塞:无;仍须满足前置任务。 @@ -1017,3 +1060,67 @@ REPORT-004三栏页面子项完成本地联调,整体仍开发中。改动repo 后续建议按页面方案推进08上下文AI助手(CHAT模块),再衔接10行动页与09 PDF独立任务。真实产品/人工金标准、外部渠道、微信内H5及真机均仍待验收,不标整体验收完成。 收尾:随机合成账户、3条评估/会话、Token和隔离队列已清理,测试HTTP服务和浏览器会话已关闭;原1会员、2条成功评估/会话、25张表保持,syntheticUsers=0。本轮开始时未发现运行中的analysis:work,清理后已启动正式worker(PID33796),错误日志为空。文本编码、diff检查、63任务一致性与26条路由检查通过;未提交、推送或发布。 + + +### 6.18 2026-09-28 原型04/05还原与单产品AI解释 + +本轮优先实现PRODUCT-004的04、05子范围。页面按原型还原机构头部、状态标签、三栏栏目、绿色推荐依据、橙色不推荐/注意事项、底部双按钮;真实匹配仍使用符合已知条件/条件不符/待核实三态,不展示原型中的匹配百分比、审批概率或虚构银行优势。额度、年化、期限移入产品详情;证据和来源保持可展开查看。 + +| 检查 | 结果与证据 | 验证边界 | +| --- | --- | --- | +| 后端回归 | `php tests/product_explanations.php --worker-stopped`通过51项;`php tests/match_records.php --worker-stopped`通过70项。覆盖鉴权、归属、POST参数、并发幂等、成功缓存、失败三次边界、用量记录、超时回收、迟到结果、快照/游标和删除记录 | 使用随机合成账户与假模型,测试前停止worker,结束自动清理;无迁移/新表 | +| 真实模型 | DeepSeek `deepseek-v4-flash-0731`调用成功,输入911—1087 tokens、输出235—315 tokens,耗时约2.9—4.5秒;保存逐条reasonId/text/evidenceRefs | 共6次真实Flash调用,4次成功、2次因理由顺序被旧校验拒绝;按ID集合校验修复后不符与待核实样例通过。未声称真实机构业务准确性,不记录密钥 | +| 前端主流程 | Chromium,H5 `http://localhost:5173/`;390×844、390×1000、1280×900。已保存解释读取、证据展开、产品详情/申请条件切换、失败重试、刷新保留queued、三态页面和底部操作通过 | Browser plugin不可用,使用Playwright CLI;未做微信内置浏览器、Safari、Android/iOS真机 | +| 故障与安全 | 轮询断网后规则理由仍保留并可手动查询;迟到响应不切回旧栏;下架保留历史参数且禁用资料准备;公共模式不显示AI栏;非法评估ID不发请求;越权不回退公共产品;401回登录;读取已保存结果不发POST | 故障为本地路由注入;未做多设备压力测试 | +| 视觉对照 | 已查看`docs/原型.jpg`原图及04/05放大局部;对照机构头部、绿色/橙色编号、三栏、底部按钮、白底密度五类要素。保存截图于`C:/Users/JUN/AppData/Local/Temp/airz-product-explanation-20260928/` | 原型中的真实银行Logo、92%匹配度、立即申请和咨询AI无已确认数据/接口,因此使用通用图标、状态标签、资料准备/对比入口并在页面说明 | + +本轮新增接口和状态契约见`docs/产品匹配规则开发契约.md`第9节;不新增业务表或数据库迁移。analysis:work已恢复运行。下一步为原型08上下文助手,随后10行动页和09 PDF;真实产品资料与人工金标准提供后再做正式匹配验收。 + + +6.18收尾补记:HBuilderX5.26 Android与微信小程序最终编译通过;H5运行页面身份正确、非空、无框架错误遮罩,最终三态读取流程无console.error/warn,不发POST。首次Android暴露UTS局部函数前向引用限制,调整声明顺序和轮询回调后修复。临时HTTP服务首次未指定public目录导致首页HTML响应,修正启动参数后重跑;早期脚本误用不存在的按钮文案和CLI环境未定义setTimeout,修正定位/等待后通过,不将脚本失败算作业务通过。 + +最终对照检查了机构头部、栏目文字/选中线、理由顺序和编号、字体与行距、底部按钮及桌面容器;原型单页小图不适合按原始像素直接作为可读手机界面,使用390×1000接近纵横比并同时检查390×844。长规则标题缩短重复核验模板,原始依据仍完整可展开。首屏有意差异为演示标记/通用图标、三态替代百分比、真实理由数量、资料准备和对比替代尚未接通的申请/咨询;说明见原型方案第8节。 + +截图:[04手机]()、[05手机]()、[04/05并排]()、[待核实]()。测试脚本flow.js/retry.js/states.js/capture05.js/edges.js/final-capture.js均在同一临时目录;界面已保存输出来自真实Flash,基础评估报告由假模型生成。 + +合成账号及其评估/会话/日志、Token和隔离队列已清理,测试HTTP服务关闭,正式analysis:work恢复(PID50752);数据库仍为1会员、2成功评估/会话、25张表。63项编号/依赖/工时一致且无环、26路由、UTF-8无BOM、链接及diff检查通过;本轮没有执行git提交、推送或发布。 + +### 6.19 2026-09-28 原型08上下文助手实施与验证 + +- 界面按原型恢复机器人问候、快捷问题、聊天气泡和输入栏,新增紧凑上下文卡与历史对话。报告/单产品/对比入口、登录返回及H5 chatId刷新已接通。 +- 后端AssistantChats/Assistant控制器、四组助手API、持久日志任务已实现。普通会话不占正式assessment_id;服务端冻结事实、同键幂等、三次重试、租约恢复、迟到只补用量、六轮历史裁剪及共享每日额度均已接入。API与边界见[助手契约](上下文AI助手开发契约.md)。 +- 经本轮用户授权,停止空闲worker并备份后完成5项增量迁移,复跑0项;备份为后端相邻airz-backups/assistant-context-20260928-154651-271907。逐条对照确认原2份会话/2条日志未改写,原评估保留。数据库仍25表、1会员、2份评估/会话。 + +| 验证 | 结果 | 边界 | +| --- | --- | --- | +| 后端 | 助手70项、产品解释51项、分析任务31项、评估HTTP36项、匹配HTTP/快照70项通过 | 合成账户/假模型;无本轮收费模型调用 | +| 并发及故障 | 双进程发送串行;跨会话仅剩一次额度不会超扣;同键重放、三次重试、租约失效、迟到用量、归属及上下文冲突通过 | 修复MySQL旧快照导致序号竞争,关键查询使用锁定当前读 | +| H5 | Chromium390×844及1280×900;普通/评估/产品/对比、23轮分页、刷新、回执丢失、额度错误、失败重试、跨账号清理、真实密码登录返回通过 | Browser plugin not available,使用现有Playwright CLI;无安装依赖 | +| 编译及视觉 | HBuilderX5.26 Android、微信编译通过;最终页面非空、无框架遮罩,正常流程console.error/warn为0 | 原生端百分比max-width已修正;旧开发服务器未载入新登录代码,重启后复测通过;H5编译器仍提示共享layout既有类型声明警告,不是浏览器运行错误 | +| 清理 | 合成账号、评估、会话、日志、Token及队列已清理,隔离HTTP服务与浏览器关闭 | 截图及无凭据QA脚本保留临时目录,不提交仓库 | + +截图:[普通助手]()、[上下文助手]()、[桌面]()。真实DeepSeek多轮语义、真实产品人工样例、微信内H5/Safari、真机键盘/安全区及生产容量未验收,不能将假模型联调描述成真实回复验收。CHAT-001—003待验收、CHAT-004开发中;原型10及09 PDF仍未开始。保留用户已有改动,未提交、推送或发布。 + +### 6.20 2026-09-28 原型10实施与验证 + +- 新增next-step页、主包白名单路由帮助函数和四个SVG图标;报告/产品/助手/登录入口增量接通。63项编号及依赖保持不变,REPORT-006待验收;无提交、推送或发布。 +- H5 Chromium 390×844、1280×900:主流程14项、边界21项、导航及本机缓存3项,共38项通过。覆盖报告/产品入口、无产品选择、准备刷新、AI上下文往返、个人/企业空白重评、首页清栈、冷启动返回、越权、错误产品、参数、账户切换迟到响应及真实密码登录恢复。正常主流程无业务console.error/warn,无POST或模型请求。 +- 主流程使用临时合成个人/企业成功报告和真实只读API;不符/待核实及跨账户拒绝也来自真实API。不可用、快照不一致、503、无匹配、旧版、未完成、迟到响应采用可控响应注入,未修改正式产品。登录验证单独发送登录POST,不能把只读页面测试说成无任何写入。 +- 最终HBuilderX5.26 Android(17:04:58)及微信小程序(17:05:58)27页编译成功。共享layout既有H5类型警告保留,未做无关重构。真机、微信内H5/Safari、真实产品渠道未验收;08真实多轮语义仍待验收。 +- 测试前确认worker空闲并停止,结束清理全部合成账号/评估/会话/日志/令牌/队列,关闭隔离HTTP和浏览器。恢复1会员、2评估/会话、2日志;原评估161/229会话摘要前后相同。正式worker恢复PID45420,H5最新服务5173(PID51832),新会话须重新检查PID。 +- 证据目录:`C:/Users/JUN/AppData/Local/Temp/airz-next-step-20260928/`,包含无凭据QA脚本与verification.md;脚本中的__QA_FIXTURE__需由新合成数据注入。截图:[行动页手机]()、[材料准备手机]()、[行动页桌面]()。 + +下一步实施REPORT-005 PDF导出;当前无下载按钮或虚假成功提示,不包含银行受理/授信/放款。 + +### 6.21 2026-09-28 PDF导出实施与验证 + +- 后端ReportPdf、Assessments::pdf、MatchRecords::exportSnapshot及report.pdf路由;前端ReportExport组件、report-export.uts下载器与report-route.uts登录白名单。只读本人成功报告,无迁移/新表/收费模型调用。依赖和部署见后端extend/report-pdf/README.md。 +- `php tests/report_pdf.php`29项:精度、零值、最大金额、隐私字段与文本遮蔽、HTML转义、v1、未匹配/零候选、企业、关闭引擎503、真实PDF。样本通过Poppler逐页渲染、pdfplumber中文提取/隐私/页面边界检查,末尾版本说明整体分页,避免只剩免责声明的尾页。 +- `php tests/report_pdf_http.php --worker-stopped`20项真实HTTP:401/404/409 JSON、no-store、合法二进制/MIME/安全文件名、重复下载不改报告与调用日志、不查询当前产品目录、损坏/撤销会话拒绝。合成账号/评估/日志/Token/队列及隔离服务已清理;没有真实模型调用。 +- 浏览器使用Playwright CLI(Browser plugin not available),Chromium390×844/1280×900,24项检查通过:普通流程6项、边界18项。页面身份/非空/无框架浮层、正常流程console.error/warn为空;实际download事件文件可解析。API响应采用合成报告及后端生成的真实PDF注入;错误页、损坏、断网、503、401、离页、账号切换、微信UA提示均验证。不能把受控UI响应检查描述为浏览器完整真实后端联调;真实HTTP另由上项覆盖。真实密码登录回跳本轮未重跑。 +- 最终HBuilderX5.26 Android17:34:03、微信小程序17:36:09编译通过。原生/小程序仅提示普通H5下载,不宣称原生保存可用;微信内H5/Safari/真机、生产并发容量仍未验收。共享layout既有H5类型警告保留。 +- 自动审批曾拒绝一条“创建合成UI账号+启动隔离服务+浏览器”的组合命令,仅返回blocked by policy,未给具体理由;没有重试该组合或规避限制。已恢复worker,并采用无服务器凭据的受控浏览器响应完成UI检查。其他工具路径/定位问题修正后验证通过。 +- 当前数据库1用户、2成功评估/会话、2日志、0待处理;原161/229报告会话摘要与执行前一致。worker PID34324、H5 5173/PID51832已核对运行,后续勿硬编码PID。无提交/推送/发布。 +- 证据目录`C:/Users/JUN/AppData/Local/Temp/airz-report-pdf-20260928/`:personal/enterprise/legacy/unmatched/zero-candidates/long.pdf、http-personal.pdf、browser-report.pdf及对应渲染图;ui-flow.js/ui-edges.js只含不能访问服务器的合成会话标识。截图:[手机报告]()、[桌面报告]();[合成PDF样本]()。 + +REPORT-005待验收。下一步08真实DeepSeek多轮语义、真实产品人工样例与微信内H5/Safari/真机验收;真实模型调用会产生用量,应在具体样例及预算边界明确后执行。 diff --git a/docs/新会话交接.md b/docs/新会话交接.md new file mode 100644 index 0000000..22809f9 --- /dev/null +++ b/docs/新会话交接.md @@ -0,0 +1,102 @@ +# AI融资项目新会话交接 + +记录日期:2026-09-28。本文件为接续入口;详细任务状态以[开发进度](开发进度.md)0.20、6.21节为准,设计以[开发文档](开发文档.md)v1.18、[原型页面方案](原型04-10页面改造与跳转方案.md)v1.7为准。历史章节中的“待开发”应结合最新更新阅读。 + +## 1. 当前停在哪 + +用户要求界面内容尽可能还原`docs/原型.jpg`。原型08已继续实施:界面、持久会话、固定评估/产品上下文、异步回复、分页、原键重试、共享额度、报告/产品/对比入口及登录返回已完成本地联调;关键代码有中文注释。原型10也已完成本地联调;09 PDF普通H5也已实施;下一步为08真实多轮语义与跨平台/真实产品验收。 + +| 内容 | 当前状态 | +| --- | --- | +| 04/05 产品匹配详情 | 原型布局与单产品解释保留;咨询AI已接08;产品对比仍可进入 | +| 06 产品详情 | 公共资料和本次评估冻结快照分开读取 | +| 07 产品对比 | 同次2—3产品、补选/移除/刷新保留;可带选择进入08,PRODUCT-005待验收 | +| 08 上下文AI助手 | CHAT-001—003待验收,CHAT-004开发中;70项助手测试与H5、Android/微信编译通过;真实多轮模型语义/真机未验收 | +| 09 报告 | 三栏及本次报告咨询AI入口完成;REPORT-004整体仍开发中;REPORT-005普通H5导出已本地验证,平台/容量待验收 | +| 10 下一步行动 | REPORT-006待验收;四项行动/登录恢复/状态守卫已接通,38项H5检查及Android/微信编译通过 | + +当前27个注册页面、63个稳定任务编号。未提交/推送/发布;前后端已有改动均保留。 + +## 2. 原型08实现与下一步 + +完整契约见[上下文AI助手开发契约](上下文AI助手开发契约.md)。前端`packages/finance/assistant/assistant.uvue`、`packages/finance/services/assistant.uts`;后端`AssistantChats.php`、v1 `Assistant.php`和`AnalysisWork.php`。旧sendAssistantMessage模拟入口已移除。 + +- 普通会话scene=assistant、assessment_id/analysis_context=NULL。本轮用户明确授权后已执行后端`database/migrate_assistant_context.py --apply --worker-stopped`,新增两列及归属约束共5项,复跑0项。备份`D:/AAdesk/202609/airz-backups/assistant-context-20260928-154651-271907/`,原2份评估会话/2条日志逐条未改写。恢复优先保留可空列、回退助手代码,不能整表覆盖后续记录。 +- GET `/assistant/context`只读预览,GET/POST `/assistant/chats`读取列表/创建,GET `/assistant/chats/:id`恢复并校验URL绑定,GET/POST `/assistant/chats/:id/messages`分页/发送。创建与进入页面均不调用模型,快捷问题只填入文本框。 +- 明确发送创建用户行与ast:调用日志,analysis:work持久消费。每条逻辑消息requestId保持不变;回执丢失同retryAttempt重放,明确失败才手动递增0→1→2。每会话100轮、同时一条待处理;每日创建30会话,调用与评估/单产品解释共享每日额度。 +- 并发序号/幂等/额度必须保持锁定当前读,不能仅依赖用户锁后普通SELECT;测试发现MySQL可重复读旧快照会造成重复序号。 +- 页面每3秒查询、最多60次,可续查;离页清空、Token变化拒绝迟到回包。消息/报告不落本机缓存,H5只保存chatId等ID到URL。登录后只接受白名单助手返回并重新鉴权。 +- 后端默认Flash真实适配已接通,本轮测试使用假模型,未新发收费模型调用;不要把假模型回复当作真实DeepSeek多轮语义验收。 + +原型10及09 PDF已实施;下一步补真实模型/产品与平台验收;并补08真实多轮人工语义、微信内H5/Safari/真机键盘安全区及生产容量验收。供应商与真实产品准备仍可推进,不虚构整体完成率。 + +## 3. 必须延续的业务约定 + +- 不做草稿;重新评估进入空白表单,不覆盖历史评估。 +- fa_user_info一条对应一次评估;fa_ai_chat保存关联报告及匹配结果;fa_ai_chat_log保存消息和调用记录。不新建独立评估/报告/匹配表。 +- Token保存在Redis,fa_user_token已删除。 +- 金额数据库DECIMAL(11,2),单位元;API用元十进制字符串;客户端万元,保留精度,例如123456.78元显示12.345678万元。 +- 产品稳定条件、额度/期限/利率等使用独立字段,地区/补充规则JSON;沿用冻结产品快照,不用当前产品参数覆盖历史。 +- 规则决定eligible/ineligible/unknown,AI只解释;无评分策略则score=null,不使用原型92%、B+或固定三正三反。非候选的正向部分称“已满足条件”。 +- 申请仅限资料准备与引导;不提交银行申请、不声称受理成功。真实产品尚未提供,本地6条上架资料是明确标注的演示产品。 +- DeepSeek走腾讯TokenHub,已配置Flash/Pro;默认Flash。短信、微信/一键登录、外部查询、客服服务商仍待定。 +- 中文交流与关键中文注释;UTF-8无BOM。保留未提交工作,不自行提交/推送/建PR、迁移或覆盖用户改动。凭据只从后端私密配置读取,不在文档、命令输出、日志或客户端复述。 + +## 4. 04/05实现入口和注意点 + +前端:`packages/finance/product/product.uvue`、`packages/finance/services/matches.uts`、`packages/finance/services/compare.uts`。 + +后端:`application/common/library/ProductExplanations.php`、`MatchRecords.php`、`DeepSeekClient.php`、`AnalysisTasks.php`、`application/admin/command/AnalysisWork.php`、`application/api/controller/v1/Assessments.php`、`application/route.php`。 + +- POST `/api/v1/assessments/:id/matches/:productId/explanation`仅接受requestId;返回HTTP200的匹配详情及异步状态,不能把HTTP200理解为模型完成。 +- fa_ai_chat.match_result中单项ai_explanation保存queued/running/completed/failed和逐条解释;首次not_requested。fa_ai_chat_log的`pex:`调用日志作为持久待办,analysis:work在报告队列空闲时消费。 +- 成功缓存、并发点击和同键重放不会重复调用。每评估每产品最多三次尝试,与报告共享每日用户调用预留额度。失败新键可重试;租约失效明确失败,迟到仅补用量。 +- 模型可能重排理由,按reasonId完整集合校验无重复/遗漏/外来项,再恢复规则顺序,不能再用数组位置强制匹配。 +- 更新解释不能使分页失效:游标摘要排除ai_explanation,仍校验其他冻结字段。 +- 前端每三秒读状态、最多六十次,可手动续查;离页停止轮询、清理数据并拒绝迟到回包。UTS Android局部函数不支持任意前向引用,声明顺序须注意。 + +详见[产品匹配规则开发契约](产品匹配规则开发契约.md)第9节及[需求与评估结果数据契约](需求与评估结果数据契约.md)。 + +## 5. 验证与现场状态 + +- 51项单产品解释测试、70项匹配HTTP/快照检查通过。真实Flash共6次调用,4次成功、2次因旧顺序校验失败,修复后不符及待核实样例通过;不是6次均成功。 +- HBuilderX5.26 Android/微信小程序编译通过;H5 Chromium在390×844、390×1000、1280×900验证,正常最终流程无业务console.error/warn。微信内H5、Safari及真机、真实产品人工金标准未验收。 +- 合成测试账号/评估/会话/日志、Token与队列已清理,测试HTTP和浏览器会话已关闭。上次数据库核验为1会员、2成功评估/会话、25张表;原评估161/229未改写。 +- 2026-09-28本轮收尾正式analysis:work已重启加载助手代码,PID45420已恢复运行(原型10测试后);新会话应重新检查进程/任务状态,不能将旧PID视为永久有效。已有模型worker需在代码变更后安全重启。 +- 前后端均有未提交改动;本次已实施原型08及10,不清理既有工作树。开始新一轮修改前先git status并保留用户现有改动。 + +本轮08验证:助手70项、产品解释51项、任务31项、评估HTTP36项、匹配HTTP/快照70项通过;H5 Chromium390×844/1280×900完成发送/刷新/分页/重试/回执丢失/三入口/越权/登录返回验证,Android和微信编译通过。合成数据、令牌、隔离服务、浏览器已清理。截图和无凭据QA脚本在`C:/Users/JUN/AppData/Local/Temp/airz-assistant-20260928/`。共享layout既有H5类型警告保留,正常浏览器运行无业务error/warn。 + +此前04/05测试与截图目录:`C:/Users/JUN/AppData/Local/Temp/airz-product-explanation-20260928/`。其中flow/retry/states/capture05/edges/final-capture脚本和截图可参考,但临时目录可能被系统清理;fixture.json已删除,不假定旧账号仍可登录。产品对比和报告三栏证据分别在airz-compare-20260928、airz-report-tabs-20260928临时目录。 + +原型10最新验证见开发进度6.20:38项H5检查(真实API主流程+边界响应注入)、Android/微信27页编译通过。测试已清理,原161/229报告会话摘要未改变,数据库恢复1用户、2评估/会话、2日志。H5最新5173/PID51832,worker PID45420;新会话先检查当前状态。截图与无凭据脚本在`C:/Users/JUN/AppData/Local/Temp/airz-next-step-20260928/`。 + +原型10代码:`packages/finance/next-step/next-step.uvue`、`services/next-step-route.uts`。只读status/report/matches接口,核对成功归属与快照元数据;eligible且available才开放准备。重新评估按status.type进入空白表单;登录白名单恢复;onHide清空个人数据、generation/token拒绝迟到请求。未修改后端业务或迁移。不要把模拟不可用/旧版响应测试说成真实产品/旧数据验收。 + +原型09 PDF最新见进度0.20/6.21:29项PDF、20项真实HTTP、24项受控浏览器检查通过,最终Android/微信编译通过。引擎Dompdf3.1.6在后端extend/report-pdf独立composer.lock,字体Noto Sans SC含许可与哈希;部署须在该目录composer install,详见其README。后端ReportPdf与report.pdf路由、MatchRecords::exportSnapshot;前端ReportExport组件/report-export.uts,登录report-route白名单。无迁移,无收费模型调用。仅普通H5开放下载,其余端给操作提示;不能把编译通过说成原生下载验收。 + +本轮曾被自动审批拒绝组合UI夹具启动,改以受控响应验证浏览器,不声称完整真实浏览器联调。真实HTTP检查独立通过。全部真实合成账号/Token/队列已清理;原两份报告摘要相同。worker现PID34324,H5仍5173/PID51832;每次重查。PDF/截图证据在`C:/Users/JUN/AppData/Local/Temp/airz-report-pdf-20260928/`。 + +## 6. 环境与验证命令 + +前端目录:`D:/WorkSpace/cyun/ai融资`,uni-app x/Vue3/UTS、HBuilderX5.26 VDOM,无npm构建入口。后端目录:`D:/AAdesk/202609/airz`,FastAdmin/ThinkPHP、PHP7.4、MySQL/Redis。 + +```powershell +# 在对应项目目录执行;后端合成任务测试前先核对并停止全部分析worker,结束清理后恢复。 +& 'D:/Develop/phpstudy_pro/Extensions/php/php7.4.3nts/php.exe' tests/product_explanations.php --worker-stopped +& 'D:/Develop/phpstudy_pro/Extensions/php/php7.4.3nts/php.exe' tests/match_records.php --worker-stopped +& 'D:/Develop/phpstudy_pro/Extensions/php/php7.4.3nts/php.exe' tests/assistant_chats.php --worker-stopped +# --live会真实调用并产生用量,日常回归不加。 +& 'D:/Develop/phpstudy_pro/Extensions/php/php7.4.3nts/php.exe' think analysis:work + +& 'D:/Develop/HBuilderX/cli.exe' launch app-android --project 'D:/WorkSpace/cyun/ai融资' --compile true --continue-on-error false +& 'D:/Develop/HBuilderX/cli.exe' launch mp-weixin --project 'D:/WorkSpace/cyun/ai融资' --compile true --continue-on-error false +``` + +H5已清理旧开发服务器并以最新代码恢复`http://localhost:5173/`,新会话先核对监听。注意HBuilder多次launch可能保留旧端口产物,新增代码未加载时先重启正确服务,不把旧包误判为业务错误。可用Python为`D:/Develop/Python311/python.exe`。已有Playwright CLI使用`npx --no-install @playwright/cli`,从临时QA目录运行避免向项目写入日志;工具可用性按新会话实际环境选择,无需安装全局依赖。 + +本地PHP测试服务需指定`-t D:/AAdesk/202609/airz/public`,否则可能返回首页HTML。UI测试使用随机合成账号,不输出密码/Token;原有真实用户账号无需改动。恢复扫描可能拾取测试任务,仅换Redis队列不足以隔离,故测试前要检查worker。 + +## 7. 新会话可以直接发送 + +> 请先阅读docs/新会话交接.md、开发进度0.20/6.21和原型04-10页面方案,继续原型08真实多轮语义及跨平台验收准备,先核对可执行样例和用量边界。界面尽量还原docs/原型.jpg,关键代码加中文注释;保留已有04/05解释、07对比、08上下文助手、09报告及10行动成果。只做材料准备与引导,不提交银行申请;PDF未完成时不做假下载。先检查工作树与数据库/worker现状,新增迁移仍按具体方案申请授权。 diff --git a/docs/需求与评估结果数据契约.md b/docs/需求与评估结果数据契约.md index d41eb7b..1970c4e 100644 --- a/docs/需求与评估结果数据契约.md +++ b/docs/需求与评估结果数据契约.md @@ -171,7 +171,7 @@ unknown不是建议申请;ineligible不是永久拒绝。展示应为“本次 - 推荐依据 `positiveReasons`、不符条件 `blockingReasons`、待核实/注意事项 `cautions` 分开保存。首页各组最多展示三条;没有证据就不生成,详情可读完整列表。通过部分条件的不适配产品,其positiveReasons不能标成“推荐该产品”。 - 理由 `{reasonId,code,text,evidenceRefs}` 由确定性规则/模板生成,evidenceRefs至少一个且只引用本项证据。失败条件、未知依据全部保存,不能因为只展示三条而丢掉阻断项。产品公共优势不是用户个性化理由。 - 证据 `{evidenceId,ruleId,ruleVersion,kind,fieldRefs,operator,expected,actual,outcome,source,observedAt}` 固定类型、单位和来源。evidenceId在整份报告内唯一且稳定,例如由productId、ruleId和条目序号组成,不能让不同产品的同名规则共用ID。kind=hard/soft,source=self_reported/verified/product_snapshot;expected/actual金额保持元字符串,未知actual=null。规则快照保存requiredSource,复核时能判明证据是否够用。 -- 单项 `aiExplanation={status,text,evidenceRefs}`,status=not_requested/completed/failed;只解释服务端已生成的理由,不能新增规则、伪造优势/风险或改判定。模型内容缺证据、含审批承诺或改写数值时拒绝保存该段,保留规则理由并显示解释暂不可用。不存在“必须每家补足三正三反”的生成要求。 +- 单项 `aiExplanation={status,text,evidenceRefs,reasonExplanations,generatedAt,errorCode,canRetry}`,status=not_requested/queued/running/completed/failed(2026-09-28已实现);reasonExplanations为`{reasonId,text,evidenceRefs}[]`,generatedAt为ISO时间或null,errorCode为稳定错误码或null,canRetry为boolean。taskId/leaseUntil/requestKeys/attempts仅内部保存,不通过DTO外发;只解释服务端已生成的理由,不能新增规则、伪造优势/风险或改判定。模型内容缺证据、含审批承诺或改写数值时拒绝保存该段,保留规则理由并显示解释暂不可用。不存在“必须每家补足三正三反”的生成要求。 证据类型增补:source在事实完全缺失/无法确定来源时允许null,不捏造self_reported/verified;observedAt未知也为null。额外提供requiredSource、reasonCode、valueType及unit,现已映射入正式match_result。not_applicable以product_snapshot作为适用范围依据来源。 diff --git a/packages/account/login/login.uvue b/packages/account/login/login.uvue index 81bf875..93ae245 100644 --- a/packages/account/login/login.uvue +++ b/packages/account/login/login.uvue @@ -27,7 +27,23 @@ import { API_BASE_URL, requestSmsCode, loginWithSms, loginWithPassword } from '@/packages/account/services/auth.uts' import { showAgreementNotice } from '@/services/assessment.uts' import { consumeInitialLaunch } from '@/services/launch.uts' - onLoad(() => { consumeInitialLaunch() }) + import { assistantReturnPath } from '@/services/assistant-return.uts' + import { nextStepRoute } from '@/services/next-step-route.uts' + import { reportRoute } from '@/services/report-route.uts' + let afterLoginUrl = '/pages/home/home' + onLoad((options) => { + consumeInitialLaunch() + if (options?.['resumeAssistant'] == '1') { + const target = assistantReturnPath(options?.['assessmentId'] ?? '', options?.['productIds'] ?? '', options?.['chatId'] ?? '', options?.['from'] ?? '') + if (target.length > 0) afterLoginUrl = target + } else if (options?.['resumeNextStep'] == '1') { + const target = nextStepRoute(options?.['assessmentId'] ?? '', options?.['productId'] ?? '', options?.['section'] ?? 'actions') + if (target.length > 0) afterLoginUrl = target + } else if (options?.['resumeReport'] == '1') { + const target = reportRoute(options?.['assessmentId'] ?? '', options?.['tab'] ?? 'overview') + if (target.length > 0) afterLoginUrl = target + } + }) const { statusStyle, contentStyle, pageStyle } = usePageLayout() const mode = ref('password') const phone = ref('') @@ -58,7 +74,7 @@ if (countdown.value <= 1) { countdown.value = 0; clearInterval(countdownTimer) } else countdown.value -= 1 }, 1000) } - const finishLogin = (_token: string) => { uni.redirectTo({ url: '/pages/home/home' }) } + const finishLogin = (_token: string) => { uni.redirectTo({ url: afterLoginUrl }) } const resendSms = async () => { if (loading.value || countdown.value > 0 || !validPhone()) return if (!agreed.value) { errorMessage.value = '请先阅读并勾选用户协议与隐私政策'; return } diff --git a/packages/finance/assistant/assistant.uvue b/packages/finance/assistant/assistant.uvue index f31c798..a440dfc 100644 --- a/packages/finance/assistant/assistant.uvue +++ b/packages/finance/assistant/assistant.uvue @@ -1,92 +1,228 @@ - - diff --git a/packages/finance/compare/compare.uvue b/packages/finance/compare/compare.uvue index 5289bc1..2f50ee1 100644 --- a/packages/finance/compare/compare.uvue +++ b/packages/finance/compare/compare.uvue @@ -35,6 +35,7 @@ 历史参数保留评估时版本;当前可用状态单独展示。缺失信息不会被推断为零,演示产品仅供功能验证。 + @@ -45,6 +46,7 @@ import AppHeader from '@/components/AppHeader.uvue' import { usePageLayout } from '@/services/layout.uts' import { getSession } from '@/services/api.uts' + import { assistantRoute } from '@/packages/finance/services/assistant.uts' import { MatchDetail, MatchReason, validRecordId, fetchMatchDetailRecord } from '@/packages/finance/services/matches.uts' import { parseCompareIds, saveCompareSelection, compareQuery, sameMatchSnapshot, compareReasonText } from '@/packages/finance/services/compare.uts' type CompareColumn = { id: string, loading: boolean, error: string, data: MatchDetail | null } @@ -120,6 +122,7 @@ uni.redirectTo({ url: '/packages/finance/matches/matches' + compareQuery(assessmentId.value, ids.value) }) } const back = () => { if (getCurrentPages().length > 1) uni.navigateBack(); else toMatches() } + const consult = () => { uni.navigateTo({ url: assistantRoute(assessmentId.value, ids.value, 'compare') }) } const remove = (id: string) => { const next = ids.value.filter((value: string): boolean => value != id) saveCompareSelection(assessmentId.value, next) diff --git a/packages/finance/components/ReportExport.uvue b/packages/finance/components/ReportExport.uvue new file mode 100644 index 0000000..ff77dd5 --- /dev/null +++ b/packages/finance/components/ReportExport.uvue @@ -0,0 +1,42 @@ + + + diff --git a/packages/finance/next-step/next-step.uvue b/packages/finance/next-step/next-step.uvue new file mode 100644 index 0000000..85a906d --- /dev/null +++ b/packages/finance/next-step/next-step.uvue @@ -0,0 +1,178 @@ + + + diff --git a/packages/finance/product/product.uvue b/packages/finance/product/product.uvue index a277dde..67829e0 100644 --- a/packages/finance/product/product.uvue +++ b/packages/finance/product/product.uvue @@ -22,11 +22,11 @@ - {{ assessmentId.length > 0 ? '本次评估 #' + assessmentId : '公共产品资料' }} · 产品版本 v{{ product!.version }}{{ match!.availabilityLabel }},历史参数与结论保留。{{ match!.state != 'eligible' ? '请先核对不符条件或待核实项。' : '当前产品不可用或状态未知,暂不提供准备入口。' }}自填信息未经核验;本页面不承诺额度、放款或获批。返回本次匹配选择评估查看匹配结果 + {{ assessmentId.length > 0 ? '本次评估 #' + assessmentId : '公共产品资料' }} · 产品版本 v{{ product!.version }}{{ match!.availabilityLabel }},历史参数与结论保留。{{ match!.state != 'eligible' ? '请先核对不符条件或待核实项。' : '当前产品不可用或状态未知,暂不提供准备入口。' }}自填信息未经核验;本页面不承诺额度、放款或获批。查看同类产品对比返回本次匹配选择评估查看匹配结果 - - + + @@ -85,6 +86,7 @@ import { getSession } from '@/services/api.uts' import { MatchView, MatchReason, ProductView, fetchMatchDetail, fetchPublicProduct, validRecordId, requestProductExplanation } from '@/packages/finance/services/matches.uts' import { parseCompareIds, compareSelection, saveCompareSelection, compareQuery } from '@/packages/finance/services/compare.uts' + import { assistantRoute } from '@/packages/finance/services/assistant.uts' const { pageStyle, contentStyle, bottomStyle } = usePageLayout() const assessmentId = ref(''); const productId = ref(''); const tab = ref('details') const selectedIds = ref([]); let from = '' @@ -99,6 +101,46 @@ const attentionVisible = computed((): MatchReason[] => attentionExpanded.value ? attention.value : attention.value.slice(0, 3)) const aiPending = computed((): boolean => match.value != null && ['queued','running'].includes(match.value!.aiStatus)) const canPrepare = computed((): boolean => match.value != null && match.value!.state == 'eligible' && match.value!.availability == 'available') + // 缩短重复的规则模板标题;核验限制仍保留在逐条依据和页尾,不改判定含义。 + const reasonTitle = (reason: MatchReason): string => reason.text.replace('(资料尚需核验)。', '').replace('本产品已配置条件', '产品条件') + function stopPoll(): void { if (timer != 0) clearTimeout(timer); timer = 0 } + const current = (request: number, token: string): boolean => visible && generation == request && getSession()?.getString('token') == token + const explanationError = (request: number, token: string, message: string) => { + if (!visible || generation != request) return + if (getSession() == null) { uni.redirectTo({ url: '/packages/account/login/login' }); return } + if (current(request, token)) aiError.value = message + } + let pollAction: () => void = () => {} + function schedulePoll(): void { + stopPoll() + if (!visible || !aiPending.value) return + if (++pollCount > 60) { pollStopped.value = true; return } + timer = setTimeout(() => { timer = 0; pollAction() }, 3000) + } + async function refreshExplanation(): Promise { + if (aiBusy.value || match.value == null) return + const request = generation; const token = getSession()?.getString('token') ?? '' + aiError.value = ''; aiBusy.value = true + try { + const result = await fetchMatchDetail(assessmentId.value, productId.value) + if (current(request, token)) { match.value = result; schedulePoll() } + } catch (err) { explanationError(request, token, err instanceof Error ? err.message : '解释状态读取失败,请重试') + } finally { if (current(request, token)) aiBusy.value = false } + } + pollAction = () => { refreshExplanation() } + const checkExplanation = () => { pollCount = 0; pollStopped.value = false; refreshExplanation() } + const generateExplanation = async () => { + if (aiBusy.value || match.value == null || aiPending.value || match.value!.aiStatus == 'completed') return + const request = generation; const token = getSession()?.getString('token') ?? '' + // 网络结果不确定时保留同一个幂等键,只有收到明确失败状态后才开始新的尝试。 + if (requestKey.length == 0) requestKey = 'explain_' + Date.now().toString() + '_' + Math.random().toString(36).slice(2, 12) + aiBusy.value = true; aiError.value = ''; pollCount = 0; pollStopped.value = false + try { + const result = await requestProductExplanation(assessmentId.value, productId.value, requestKey) + if (current(request, token)) { match.value = result; requestKey = ''; schedulePoll() } + } catch (err) { explanationError(request, token, err instanceof Error ? err.message : 'AI解释请求失败,请重试') + } finally { if (current(request, token)) aiBusy.value = false } + } const load = async () => { stopPoll(); pollCount = 0; pollStopped.value = false; aiError.value = '' const request = ++generation; product.value = null; match.value = null; error.value = ''; expanded.value = false @@ -118,46 +160,18 @@ } catch (err) { if (visible && generation == request) error.value = err instanceof Error ? err.message : '产品读取失败' } finally { if (generation == request) loading.value = false } } + const history = () => { uni.navigateTo({ url: '/packages/finance/archive/archive' }) } + // 仅携带选择ID;助手会重新校验归属并读取冻结事实,进入页面不会调用模型。 + const consult = () => { uni.navigateTo({ url: assistantRoute(assessmentId.value, [productId.value], 'product') }) } + function toMatches(): void { if (assessmentId.value.length > 0) uni.redirectTo({ url: '/packages/finance/matches/matches' + compareQuery(assessmentId.value, selectedIds.value) }); else history() } // 替换当前路由保留栏目、来源与对比选择,刷新后仍停留在同一栏。 const switchTab = (value: string) => { if (value == tab.value) return const query = assessmentId.value.length > 0 ? compareQuery(assessmentId.value, selectedIds.value) + '&' : '?' uni.redirectTo({ url: '/packages/finance/product/product' + query + 'productId=' + productId.value + '&tab=' + value + '&from=' + from }) } - const prepare = () => { if (canPrepare.value) { if (tab.value == 'conditions') toMatches(); else switchTab('conditions') } } - const stopPoll = () => { if (timer != 0) clearTimeout(timer); timer = 0 } - const current = (request: number, token: string): boolean => visible && generation == request && getSession()?.getString('token') == token - const refreshExplanation = async () => { - if (aiBusy.value || match.value == null) return - const request = generation; const token = getSession()?.getString('token') ?? '' - aiError.value = ''; aiBusy.value = true - try { - const result = await fetchMatchDetail(assessmentId.value, productId.value) - if (current(request, token)) { match.value = result; schedulePoll() } - } catch (err) { if (current(request, token)) aiError.value = err instanceof Error ? err.message : '解释状态读取失败,请重试' - } finally { if (current(request, token)) aiBusy.value = false } - } - const schedulePoll = () => { - stopPoll() - if (!visible || !aiPending.value) return - if (++pollCount > 60) { pollStopped.value = true; return } - timer = setTimeout(() => { timer = 0; refreshExplanation() }, 3000) - } - const checkExplanation = () => { pollCount = 0; pollStopped.value = false; refreshExplanation() } - const generateExplanation = async () => { - if (aiBusy.value || match.value == null || aiPending.value || match.value!.aiStatus == 'completed') return - const request = generation; const token = getSession()?.getString('token') ?? '' - // 网络结果不确定时保留同一个幂等键,只有收到明确失败状态后才开始新的尝试。 - if (requestKey.length == 0) requestKey = 'explain_' + Date.now().toString() + '_' + Math.random().toString(36).slice(2, 12) - aiBusy.value = true; aiError.value = ''; pollCount = 0; pollStopped.value = false - try { - const result = await requestProductExplanation(assessmentId.value, productId.value, requestKey) - if (current(request, token)) { match.value = result; requestKey = ''; schedulePoll() } - } catch (err) { if (current(request, token)) aiError.value = err instanceof Error ? err.message : 'AI解释请求失败,请重试' - } finally { if (current(request, token)) aiBusy.value = false } - } - const history = () => { uni.navigateTo({ url: '/packages/finance/archive/archive' }) } - const toMatches = () => { if (assessmentId.value.length > 0) uni.redirectTo({ url: '/packages/finance/matches/matches' + compareQuery(assessmentId.value, selectedIds.value) }); else history() } + // 下一步页重新核对当前可用性,避免沿用产品详情进入时的旧状态。 + const prepare = () => { if (canPrepare.value) uni.navigateTo({ url: '/packages/finance/next-step/next-step?assessmentId=' + assessmentId.value + '&productId=' + productId.value + '§ion=prepare' }) } const back = () => { if (getCurrentPages().length > 1) uni.navigateBack(); else if (from == 'compare') uni.redirectTo({ url: '/packages/finance/compare/compare' + compareQuery(assessmentId.value, selectedIds.value) }); else toMatches() } const openCompare = () => { if (match.value == null) return @@ -218,8 +232,8 @@ .green-number { background-color: #35b38c; } .orange-number { background-color: #f49162; } .reason-content { flex: 1; } - .reason-title { color: #27364c; font-size: 26rpx; line-height: 40rpx; font-weight: 600; } - .reason-detail { color: #7b8594; font-size: 23rpx; line-height: 36rpx; margin-top: 4rpx; } + .reason-title { color: #27364c; font-size: 28rpx; line-height: 42rpx; font-weight: 600; } + .reason-detail { color: #7b8594; font-size: 25rpx; line-height: 39rpx; margin-top: 4rpx; } .evidence-toggle { color: #8596ad; font-size: 21rpx; padding: 8rpx 0; } .evidence-box { background-color: #f5f8fc; border-radius: 8rpx; padding: 8rpx 14rpx 14rpx; margin-top: 4rpx; } .evidence { color: #7f8b9b; font-size: 22rpx; line-height: 36rpx; margin-top: 8rpx; } diff --git a/packages/finance/report/report.uvue b/packages/finance/report/report.uvue index 972cf03..4cc2139 100644 --- a/packages/finance/report/report.uvue +++ b/packages/finance/report/report.uvue @@ -8,6 +8,7 @@ 正在读取已保存报告… 报告暂不可读取{{ error }}前往融资档案 @@ -57,8 +60,10 @@