补贴统计审计字段改造技术方案

为补贴统计列表和当前页面实际使用的异步 XLSX 导出补充备注、创建、审核与终审信息,并把大批量导出的峰值内存控制在固定批次范围内。

方案已审核通过开发与验证完成代码已推送并关联 VWCG-1248目标:store / guoxin_develop

1. 已确认口径

一条实际到账补贴记录 = 列表一行。同一个人不同批次显示多行;同人同批次若出现多条到账记录,视为疑似重复发放,保留多行并记录异常,不静默合并。

2. 数据来源

实际到账真源aizhct_jsgx.yoshop_user_subsidy

使用记录 ID、人员 ID、批次 ID、发放日期以及 money + used_money。只有终审到账数据进入统计。

批次审计真源zhct_jsgx.ydy_subsidy_log

通过 user_subsidy.log_id = subsidy_log.id 获取备注、创建、审核、终审字段。

页面字段表字段
备注ydy_subsidy_log.note
创建人 / 创建时间create_by / create_time
审核人 / 审核时间reviewer / review_time
终审人 / 终审时间final_reviewer / final_review_time

姓名、手机号继续来自 ydy_staff;部门来自 ydy_staff_department + ydy_department,沿用现有数据权限。

3. 查询设计

  1. 从 AI 账户库按到账记录分页查询,不再按人员合并多个批次。
  2. 收集当前页或当前导出批次中的有效 log_id
  3. 一次性查询主库 ydy_subsidy_log 并建立批次映射。
  4. 批量查询人员、部门;禁止逐行查询。
  5. 列表总数改为数据库侧 COUNT(id),删除全量结果加载后在 PHP 中计数的做法。
历史兼容:log_id=0 或批次缺失时,备注、创建人、创建时间降级使用 AI 到账记录;审核和终审字段显示 --。默认时间 2000-01-01 00:00:00 视为空值。

4. 页面与接口

列顺序:序号、补贴日期、部门名称、姓名、手机号、补贴金额、备注、创建人、创建时间、审核人、审核时间、终审人、终审时间。

5. 异步导出与内存门禁

当前真实入口:POST /p/mealOrder/exporttype=6,由 SubsidyReport::statisticExportToFile() 流式生成 XLSX。
固定内存

每批 1000 行,当前批次查询人员、部门和发放批次,每行立即写入 XML,完成后释放数组。

当前批次过滤

按到账记录扫描,只查询和过滤当前 1000 条涉及的人员,避免全量 AI 用户 ID 和超长 IN 条件。

失败清理

调用 abort() 删除临时 XML 和 .tmp 文件。

Sheet 上限

超过 1,048,574 条明细提示缩小日期范围,不截断、不自动拆多 Sheet。

结论:内存复杂度由 O(总行数) 降为 O(1000行当前批次 + 当前映射)。主要剩余风险转为数据库耗时、磁盘空间和 OSS 上传时间。

6. 影响范围

预计修改不修改
SubsidyReport.php
subsidyStatistics.vue
补贴统计专项测试
Apifox PC 响应字段
同步导出接口
ExportMealOrder.php 分发
数据库结构
新增、审核、终审和账户余额逻辑

7. 测试和验收

8. 实现验证结果

开发与本地验证完成。专项 3/3、国信 37/37、数据权限 14/14、真实只读列表、真实 13 列 XLSX 和 Node 14 前端构建均通过。
明细行总行数耗时PHP 峰值内存文件
10,00010,0024.418s2 MiB完整
100,000100,00240.545s2 MiB完整
200,000200,00285.147s2 MiB完整

完整记录见 implementation-verification.md。Apifox 增量契约已准备,真实导入需确认“智慧营养健康餐厅”目标目录。

9. 工时与审核

预计人工工时约 5 小时,包含方案、实现、测试、大批量异步导出验证和提交准备。

审核结论:通过并要求落地  审核人:用户  审核日期:2026-08-19