feat: 增加反馈消息闭环相关功能及文件

新增反馈目标登录白名单、账户切换守卫、待确认反馈存储、缓存生命周期管理,补充相关文档及截图,完善消息跳转逻辑
This commit is contained in:
hujun
2026-10-05 20:11:24 +08:00
parent 6b16d4fd55
commit 1723363b7e
154 changed files with 16407 additions and 114 deletions
+83 -5
View File
@@ -1,6 +1,84 @@
# AI 融资平台开发进度
基线日期:2026-09-22。文档版本:1.43。最新FAQ服务端导入与隔离HTTP联调见0.52节,积分页面恢复及隔离联调见0.51节,真实读取见0.50节,积分协议与隔离开发检查见0.49节,后端基础和规则设计历史见0.48/0.47节;此前章节保留阶段记录。技术方案和接口说明见[开发文档](./开发文档.md)。本台账现有63项任务、27页面,编号与开发文档保持一致。
基线日期:2026-09-22。文档版本:1.52。反馈与消息后端生产发布见0.62节,反馈与消息配套发布准备见0.61节,最新反馈恢复与消息组合检查见0.60节,反馈回复与站内消息联动见0.59节,会员反馈原键恢复见0.58节,小程序既有发布状态及后台反馈处理见0.57节,首页隔离回归见0.56节,后端发布见0.55节;此前章节保留阶段记录。技术方案和接口说明见[开发文档](./开发文档.md),发布材料见[反馈消息发布清单](./反馈消息发布清单.md)。本台账现有63项任务、27页面,编号与开发文档保持一致。
### 0.62 2026-10-05 反馈与消息后端生产发布
在维护窗口内通过宝塔 Playwright 完成 `111.230.144.231:3306/airz` 的反馈结构迁移和后端发布。完整私密备份为 `/root/airz-feedback-release-20261005-114514`;迁移补齐 `fa_feedback.request_id/reply/handled_by/handled_at` 及唯一索引 `uk_user_feedback_request(user_id,request_id)`,迁移后预检为 `missingFields=[]`、`indexExists=true`、`duplicateGroups=0`、`changeCount=0`。迁移行摘要备份为 `/root/airz-feedback-release-20261005-114514/migration/feedback-20261005-115239-3e7a68c4.json`。
按精确清单发布 7 个后端文件,发布包 SHA-256 为 `597A2BC55D8877FCA5EFC205C1B0761D14B0B1E614196DD7C1C1FF7B8775D4B3`;线上文件哈希一致,PHP 7.4 lint 通过,权限为 `644 root:root`。`php-fpm-74`、`redis`、`airz-analysis` 已恢复 active,Redis 认证后分析队列为0,worker 无 warning/error 日志。只读烟测通过首页200、匿名消息/产品/积分401、后台反馈入口登录页和 `/.env=404`;未创建真实反馈或回复,临时发布物已清理。
本轮只发布后端,小程序端由用户自行发行;未提交、未推送、未创建 PR。回滚仅恢复代码并保留迁移后的反馈、回复、审计和通知数据,不整表恢复。首页、积分、FAQ种子及供应商依赖不属于本批次。
### 0.61 2026-10-05 反馈与消息配套发布准备
新增[反馈与消息发布清单](./反馈消息发布清单.md),整理0.57—0.59的前后端精确文件、明确排除项、数据库只读预检、迁移授权前置、推荐发布顺序、兼容性矩阵和保留业务数据的回滚边界。清单明确 `fa_feedback` 的 `request_id/reply/handled_by/handled_at` 与 `uk_user_feedback_request`,以及 `fa_user_message` 的 `uk_user_message_event` 必须先预检;缺失时不得凭“源码无新增DDL”跳过结构核对,正式 `--apply` 需另行授权、备份和停写条件。
本轮已在明确生产目标 `111.230.144.231:3306/airz` 执行只读预检:`fa_user_message` 唯一索引存在且重复事件组为0;`fa_feedback` 缺少四列及 `uk_user_feedback_request`,重复请求组为0,`changeCount=5`、`applied=false`。现网只读基线 `/api/v1/home=200`、匿名消息/产品/积分为401、敏感路径为404;本地7个后端文件已通过PHP/JS语法检查并生成限定包。缺失结构阻断代码发布,未执行迁移、后端部署、前端发行、正式验收、提交或推送;需单独取得生产维护授权、停写/worker空闲确认和完整备份后才能执行5项DDL。小程序端由用户自行发行,实际发布仍须将后端与六个前端文件作为同一兼容批次安排。当前工作树其他未提交/未跟踪改动保持原样,首页、积分、FAQ种子及供应商依赖不纳入本批次。
### 0.60 2026-10-04 反馈原键恢复与消息组合开发检查
新增后端 `tests/feedback_recovery_notifications.php`,以显式隔离 bootstrap 检查原键重放返回最新处理状态、同键冲突、通知目标归属、分类分页、已读水位、修订不重复通知/不重置已读、另一会员隔离及删除目标不可用;常规夹具事务回滚,七张相关表原有行保持。首次运行发现新测试将 `nextBeforeId` 误当作下一条消息编号,已按既有“本页末条编号、下一页 id<beforeId”契约修正断言,未修改业务实现。最终组合24项、通知专项43项、反馈67项,共134项通过,三文件PHP7.4 lint通过,模型调用0。
Chrome Playwright手机390×844/桌面1280×900补充42项组合检查、38次受控接口请求通过:系统/活动/服务分类、服务分类20+3分页和503重试、快照外新通知保持未读、第一页之外反馈目标、通知跳转同时恢复原键、刷新不自动POST、手动原键确认与最新回复、旧弹窗/已读动作、跨账户迟到分页/401/成功回执及原会员重新鉴权恢复。pageerror=0,2条console仅刻意503/401,无未处理外部请求、框架遮罩或横溢,截图已视觉核对。Browser plugin not available,使用已有缓存Playwright,无新增依赖。全部浏览器API由合成响应提供,本轮不新增真实HTTP/浏览器联调证据;修订通知的真实去重/已读保持由后端隔离测试验证。
全新ROOT `C:/Users/JUN/AppData/Local/Temp/airz-feedback-combo-1791117356770/`,本机MySQL8.0.44仅监听127.0.0.1:3309,随机库 `airz_product_test_1791117356770` 从5.7结构schema初始化26表,显式配置关闭模型、不加载正式.env,不连接正式3306/线上数据库,不启动worker或Redis/PHP HTTP服务。本轮不是MySQL5.7环境验证。测试库已DROP,MySQL正常关闭,浏览器存储清空并关闭,3309/8097/6398无监听;5173原预览保留。证据为ROOT内 `verification.json`、`ui-result.json`、`cleanup-result.json`、`combo-pending-mobile.png` 和 `combo-confirmed-desktop.png`,历史私密ROOT未改、未复用。自动审批以 `blocked by policy` 拒绝本轮文件清理命令,未重试或绕过;本ROOT及初始化失败目录 `C:/Users/JUN/AppData/Local/Temp/airz-feedback-combo-1791117251852/` 的mysql-data/runtime/工具文件和本轮生成日志暂保留,不整体共享或直接启动其中bootstrap,后续另建隔离环境。
本轮仅新增测试和记录,无前端业务源码、接口/DDL或发布变化,不重复平台编译,沿用0.59编译记录。未正式验收、提交/推送或部署,63任务/27页面及SUPPORT-002、MSG正式验收状态保持。下一步优先准备0.57—0.59配套发布的文件清单、顺序、兼容性与回滚检查,取得新授权后才发布;积分规则/原表迁移、真实产品及私有附件/短信/数据/人工客服依赖按既有决策推进。
### 0.59 2026-10-04 反馈回复与站内消息通知联动
`FeedbackEditor` 保存有效 `resolved/closed` 非空回复时,在反馈与安全审计的同一事务内插入服务通知。事件唯一键为 `(user_id,feedback_replied,feedback_id)`,每条反馈最多一条;重复保存、修订及关闭不重复通知、不重置已读。处理中、空回复、匿名或已删除会员不通知,不自动回补未修改的历史记录。消息正文不复制反馈或回复;通知写入失败以 `FEEDBACK_NOTIFICATION_UNAVAILABLE` 回滚反馈和审计,审计失败也无残留通知。复用既有表及唯一索引,无DDL。
消息详情新增 `kind:feedback,feedbackId`,同时核对消息和反馈归属,删除/归属改变返回目标不可用。前端仅生成帮助页白名单路由,独立读取单条反馈并核对回执编号,第一页之外的旧记录也能查看最新回复。新增关联反馈卡、局部失败重试和登录后原目标回跳;离页清理回复,换账户清除目标,迟到响应/401、旧弹窗确认、旧列表点击和全部已读操作不能跨账户回填或跳转。
隔离后端通知专项43项、反馈67项、处理32项,共142项通过;覆盖双PHP进程竞争、通知/审计触发器故障回滚、本人目标、删除/归属变化、去重及已读水位。Chrome Playwright手机390×844/桌面1280×900页面48项、51请求通过(46真实隔离后端、5受控坏目标/详情故障),含完整真实密码登录回跳、实际Token撤销401和跨账户迟到响应。pageerror=0,3条console仅刻意503/404/401;页面身份、非空、无框架遮罩、交互及截图视觉检查通过,无横溢。Browser plugin not available,使用已有缓存Playwright,不新增依赖。HBuilderX5.26 Android 19:38:59、微信19:39:40编译成功,27页面。
新建ROOT `C:/Users/JUN/AppData/Local/Temp/airz-feedback-notify-1791113938987/`,MySQL `127.0.0.1:3309/airz_product_test_1791113938987` 从schema初始化26表,独立Redis6398/DB15及PHP8097;未加载正式.env、未连接正式3306/线上、无模型或worker调用。测试库已DROP、两名合成会员全部Token已清除,三服务停止且3309/8097/6398无监听,5173预览保留。自动审批以 `blocked by policy` 拒绝删除本ROOT的 `fixture.json/runtime/mysql-data`,未重试或绕过,私密文件保留,禁止直接复用或整体共享。安全证据为 `ui-result.json/verification.json/cleanup-db-result.json/cleanup-result.json` 和 `feedback-reply-mobile.png/feedback-reply-desktop.png`。
仅开发检查,未正式验收、提交/推送或发布。最新后端仍为0.55,用户此前发布的小程序不含本轮源码。反馈目标为新增契约,旧前端无法解析,需将本轮及0.57/0.58前后端配套安排发布;不沿用历史授权。SUPPORT-002、MSG系列正式验收及私有附件/客服供应商依赖保持原状态。
### 0.58 2026-10-04 会员反馈原键恢复
帮助页在发送前按会员保存并回读 `{requestId, content}`,键为 `airz:v1:user:<userId>:content.feedback.pending`。仅保存已准备发送且结果尚未确认的命令,不保存普通草稿、Token、反馈列表或回复。刷新、离页重进和浏览器进程重启后恢复原键/原文,锁定原内容并显示“确认上次提交”,不自动POST;反馈列表读取失败仍可原键确认。退出、401及账户切换清理其余会员私有缓存,保留这条恢复例外,必须重新鉴权为原会员才可查看或确认。
POST成功回执必须包含相同 `requestId`,完整解析后比较本机原命令再清理,迟到回执不能清新命令或回填另一账户。网络/401/服务故障/冲突/坏回执保留原键;只有明确的参数或附件拒绝才清键并保留可编辑原文。存储写入、读取或清理失败及损坏记录阻止新提交,并提供重新读取状态;针对H5同步读取吞异常返回空值,先核对键是否存在,清理后以键不存在确认。后端DTO新增 `requestId:string|null`,历史记录保持null,同键重放返回原记录的当前处理状态;复用既有列和唯一索引,无新增DDL。
检查通过:后端反馈67项;Chrome Playwright手机390×844/桌面1280×900主流程72项、进程重启/存储故障补充21项,共93项页面开发检查、29次反馈POST。真实入库后丢回执、离页/刷新、实际撤销Token触发401及通过真实 `saveSession` 重新建立合成会话、主动退出、换账户、迟到旧回执、错误/缺少requestId、坏回复、确定422拒绝、比较清理和存储抛错/静默失败均覆盖。重新登录未覆盖完整真实登录表单。两批pageerror均0,13条console日志仅对应刻意网络/401/422/503故障;无横溢或框架错误遮罩,最终手机/桌面截图已视觉核对。Browser插件未提供,使用已有缓存Playwright,无新增依赖。HBuilderX 5.26最终Android 19:14:42、微信19:16:09编译成功,均27页面。
只操作本轮新建 `127.0.0.1:3309/airz_product_test_1791111261424`(26张表)、PHP8097及独立Redis6398/DB15,未加载正式.env、未连接正式3306/线上、无模型/worker调用。测试库已DROP、两枚Token已清除,MySQL/Redis正常关闭、PHP停止,3309/8097/6398无监听;H5预览5173保留。自动审批以 `blocked by policy` 拒绝删除本轮 `fixture.json/browser-profile/runtime/mysql-data`,未重试或绕过,私密文件保留、禁止直接复用或整体共享。安全回执、截图与精确ROOT见[交接](新会话交接.md)最新节。
本轮仅本地开发检查,不做正式验收或发布。用户已发布的是此前小程序版本,本轮新增前端仍未发行;后端最近发布仍为0.55,本轮回执及0.57后台增强未部署。新前端依赖后端 `requestId` 回执,须后端先或配套发布,否则旧后端即使已保存反馈,前端仍保持待确认。下一开发项建议反馈回复与消息通知联动;积分业务规则、私有附件和客服供应商依赖另行处理。
### 0.57 2026-10-04 小程序已发布,继续反馈处理开发
用户确认小程序端已发布,版本号和具体渠道未提供;此状态更新不代表 H5 已发行或正式验收完成。后端仍以0.55发布记录为准,以下新增反馈处理源码尚未部署。
后台反馈表单新增 CSRF 与 `row[expectedVersion]`。版本由原始处理快照生成 SHA-256,锁内比较,旧页面返回 `FEEDBACK_VERSION_CONFLICT`,不会覆盖新回复;冲突时保留输入并提示复制草稿、重新打开核对。保存时重新检查管理员正常状态和当前处理权限,反馈变更及成功审计在同一事务内完成,审计失败回滚回复。审计仅保留反馈编号、状态、版本及安全错误枚举,原文、回复、Token和未知字段不落盘;同状态同回复不改处理人、不重复成功审计。页面补标题,并修复窄屏弹窗 Bootstrap 负边距造成的15px横向溢出。复用现有表及权限,无新DDL或角色绑定。
隔离检查:反馈服务65项、处理事务/审计失败/双PHP进程竞争32项、真实HTTP25项(13请求)、既有角色权限HTTP227项(158请求)、重试审计纯90项、模型配置审计20项、权限定义97项通过,9个PHP文件lint和反馈JS语法通过。Browser plugin not available,使用缓存Playwright完成22项真实隔离页面检查,1280×900/390×844,冲突在表单内持续显示且保留输入→重新打开最新回复→保存通过;控制台error/warn均0,截图无横溢。只操作新随机隔离库、临时PHP/运行目录,模型关闭、无worker/正式数据库调用;非正式业务验收。测试账户/反馈/日志清空,隔离库删除,PHP/MySQL正常停止,3309/8097/8098无监听。自动审批以blocked by policy拒绝删除剩余本轮数据目录/runtime/会话文件,未绕过,证据与精确路径见交接本轮节。
### 0.55 2026-10-04 后端发布
按用户授权将后端发布至 `https://airz.hqling.cloud`,线上目录 `/www/wwwroot/xctai.cn`,API 前缀 `/api/v1`。本轮只发布后端,不发布前端,不执行数据库迁移、积分表迁移或正式业务验收。发布包实际部署 3716 个文件,SHA-256 为 `9A39A29E77D43EEF5DA2CE5E1217FB24B4E1DBCDF97E7E266C7FDF7E55E5FEFB`;PyMySQL 临时依赖仅用于部署过程,完成后已清理。
部署阶段 `stage → prepare → deploy → resume → verify → cleanup` 全部成功:prepare 确认 26 张表且 worker 已停止,deploy 返回 `DEPLOYED files=3716`,resume 返回 `worker=active`,cleanup 归档至 `/root/airz-backend-20261004`。verify 与本机只读烟测均确认首页 200、匿名消息/产品/积分 401、`.env` 与 `.git/config` 404;未调用收费模型、未修改线上业务数据。前端尚未重新发行,真机、多设备、真实模型和正式验收仍待后续安排。
### 0.54 2026-10-04 反馈与消息适配层响应契约增强
反馈帮助页完成提交回执回填、处理时间优先显示和详情读取;反馈服务对状态、编号、文本、时间、分页和数组项做严格校验。消息服务补齐分类、编号、快照/游标、列表项、详情关联目标、已读回执和快照一致性校验,关联跳转只允许报告与评估白名单路由。首页聚合和 FAQ 页面沿用当前账户/页面代次守卫,避免迟到响应污染新状态。
本轮首次 Android 编译暴露反馈列表 `map` 回调的 UTS/Kotlin 类型推断错误,已改为先显式转换并校验 `UTSJSONObject[]` 后再映射。HBuilderX 5.26 Android 与微信小程序(27 页面)最终编译通过,`git diff --check` 通过。未执行隔离数据库回归、线上部署、前端发行、真机或正式验收;当前仍保留未提交改动。
### 0.53 2026-10-04 首页聚合 BASE-004 开发
后端新增只读 `GET /api/v1/home` 首页聚合,匿名请求返回公开课程、文章和空横幅;有效登录凭据只附加当前会员的评估状态摘要与未读数。评估摘要按会员、`assessment` 场景和未删除记录读取,草稿不计入总数,排队中的任务显示“排队中”;聚合不读取或下发输入资料、报告、匹配正文和消息私密字段。前端首页已接入严格响应解析,移除硬编码评估数量,并对聚合失败保留公开内容和真实消息数的局部降级。
后端 `tests/home_catalog.php` 已补充匿名契约及登录隔离回归夹具,覆盖草稿过滤、本人未读数、最新排队状态和敏感字段不泄露;测试事务回滚且不调用模型或 worker。PHP 7.4 lint、前端 Web/微信小程序/Android 编译和 `git diff --check` 已通过。由于当前本机隔离 MySQL `127.0.0.1:3309` 未监听,数据库回归尚未执行;只检测到独立 MySQL 3306,未连接或修改正式库。下一步先恢复明确的隔离数据库与 bootstrap 后重跑回归;暂不部署、发行或开展验收。
### 0.56 2026-10-04 首页聚合隔离数据库回归完成
新建临时 MySQL 8 实例,仅监听 `127.0.0.1:3309`,使用随机库 `airz_product_test_20261004123000` 从 `database/schema.sql` 初始化 26 张表;PHP bootstrap 显式覆盖隔离数据库、关闭 DeepSeek 和调试。`tests/home_catalog.php` 回归结果为 `checks=8`、`modelCalls=0`、`writes=0`、`rollback=true`,覆盖匿名契约、公开内容推荐、草稿过滤、当前会员评估/未读数隔离、排队状态和敏感字段不泄露。测试后临时 MySQL 已停止,3309 无监听;正式 3306、线上数据库和业务数据未连接或修改。PHP 7.4 lint 与 `git diff --check` 通过。临时目录清理由本机策略拦截,未影响工作区或正式服务,后续按精确路径处理。
### 0.52 2026-10-03 FAQ 服务端导入与隔离 HTTP 联调
@@ -640,14 +718,14 @@ P0 表示核心流程、安全、首发外部能力或发布门槛;P1 表示
| BASE-001 | 接口契约与字段字典 | 定义版本路由、响应、错误、分页、ID、金额、时间及接口状态;确认前后端字段映射。 | P0 | 无 | 0.5–1 | 开发中 |
| BASE-002 | 统一请求与认证适配 | 统一共享/账户请求;后端识别 Bearer;解析业务失败和401;限定 CORS;记录 requestId。 | P0 | BASE-001 | 1–1.5 | 开发中 |
| BASE-003 | 环境与用户缓存隔离 | 开发/测试/生产配置;生产禁用 mock;会话等账户缓存按不可变 userId 隔离;未提交表单只存当前流程内存。 | P0 | BASE-002 | 1–1.5 | 开发中 |
| BASE-004 | 首页和联调骨架 | 首页接入聚合数据、加载/空态/失败重试及登录回跳;建立接口冒烟入口。 | P1 | BASE-002、BASE-003 | 0.5–1 | 未开始 |
| BASE-004 | 首页和联调骨架 | 首页接入聚合数据、加载/空态/失败重试及登录回跳;建立接口冒烟入口。 | P1 | BASE-002、BASE-003 | 0.5–1 | 待验收 |
| 任务编号 | 负责人 | 验收条件 | 证据 | 更新时间 |
| --- | --- | --- | --- | --- |
| BASE-001 | 全栈开发(待指定) | 接口样例可同时被 PHP 和 UTS 解析;区分占位接口与后端现有实现。 | 已实施子集和验证见第0节;完整任务未验收 | 2026-09-22 |
| BASE-002 | 全栈开发(待指定) | HTTP 200 中业务失败不判成功;过期 Token 清会话;普通业务按所有者鉴权。 | 已实施子集和验证见第0节;完整任务未验收 | 2026-09-22 |
| BASE-003 | 全栈开发(待指定) | 切换账户无串数据;旧草稿键清理且不恢复;退出清理敏感缓存和临时填写内容。 | 已实施子集和验证见第0节;完整任务未验收 | 2026-09-22 |
| BASE-004 | 全栈开发(待指定) | 深链接与刷新正确恢复;首页无硬编码账户数据;真实未读数后续由 MSG 接入。 | 未验收;无真实业务验收证据 | 2026-09-22 |
| BASE-004 | 全栈开发(待指定) | 深链接与刷新正确恢复;首页无硬编码账户数据;真实未读数由 MSG 聚合接口接入。 | 源码完成见0.53;隔离数据库回归未运行,未做业务验收 | 2026-10-04 |
DEC-DEMAND已确认并发布,需求录入/提交/历史子范围已实现;其他既有前置任务不变。
@@ -891,7 +969,7 @@ DEC-DEMAND已确认并发布,需求录入/提交/历史子范围已实现;
| 任务编号 | 负责人 | 验收条件 | 证据 | 更新时间 |
| --- | --- | --- | --- | --- |
| SUPPORT-001 | 全栈开发(待指定) | 具有可测试坐席和离线处理渠道;确认SDK/隐私及首发支持范围。 | 未验收;无真实业务验收证据 | 2026-09-22 |
| SUPPORT-002 | 全栈开发(待指定) | 反馈可提交到后台并回复;仅当前用户可查;附件无越权。 | 未验收;无真实业务验收证据 | 2026-09-22 |
| SUPPORT-002 | 全栈开发(待指定) | 反馈可提交到后台并回复;仅当前用户可查;附件无越权。 | 文字闭环、0.57事务审计、0.58原键恢复和0.59通知/本人回复跳转开发检查通过;新增源码未配套发布,私有附件与正式验收待后续 | 2026-10-04 |
| SUPPORT-003 | 全栈开发(待指定) | 真实到达人工坐席;不由前端伪造用户身份;离线可留言并有处理路径。 | 未验收;无真实业务验收证据 | 2026-09-22 |
| SUPPORT-004 | 全栈开发(待指定) | 会话无跨账户泄漏;客户可获回复;供应商不支持项准确提示。 | 未验收;无真实业务验收证据 | 2026-09-22 |
@@ -937,7 +1015,7 @@ DEC-DEMAND已确认并发布,需求录入/提交/历史子范围已实现;
直接阻塞:RELEASE-003 → EXT-DEPLOY。
任务状态计数(仅用于核对台账):未开始 33 项;开发中 12 项;待联调 0 项;待验收 1 项;已完成 0 项;阻塞 14 项。这些计数不换算为项目完成率。
任务状态计数(仅用于核对台账):未开始 32 项;开发中 12 项;待联调 0 项;待验收 2 项;已完成 0 项;阻塞 14 项。这些计数不换算为项目完成率。
## 5. 外部依赖、业务决策与阻塞传播