# 喜报处理 Web 按 `config/xibao_logic.json` 解析接龙文本,批量生成喜报图片并下载。 ## 项目情况(2026-02-24) - 线上域名:`https://zc.workyai.cn` - Nginx 转发:`zc.workyai.cn -> 127.0.0.1:8787` - 运行服务:`xibao-web.service` - 代码目录:`/opt/xibao-web/app` - Python 环境:`/opt/xibao-web/venv` ## 当前能力 - 根据 `#接龙` 文本逐行解析。 - 支持一条文本拆分多个产品(如同一行里的定期 + 理财)。 - 支持别名映射(如 `中心所 -> 潇水南路`、`营江路所 -> 营江路`)。 - 只保留 13 个白名单网点,不在名单内自动跳过。 - 保险默认期交(`page_3`),若未写明年限会要求选择 `3年交 / 5年交`。 - 仅“微信提现12万”这类未写明确期限的记录,按活期场景处理,默认不生成。 - 金额识别支持阿拉伯数字和常见中文写法。 - 中文金额口语兼容:`十万`、`两万五`、`一万二`、`两万五千`、`二点五万`。 - 金额统一按现有规则向下取整到 `N万`(例如 `2.5万 -> 2万`、`7.8万 -> 7万`)。 - 去重策略:有序号时优先按“序号+行内产品序位+行内容指纹”去重;无序号时回退 `branch+amount+type`(历史去重 + 本次输入去重)。 - 每条数据生成独立 PPT,并按其 `page_x` 只导出对应页 PNG。 - 多张 PNG 前端逐图下载(无需解压)。 - 每天 00:00 自动清理 `output/` 下历史截图任务。 - 支持手工强制清理截图(与 00:00 自动清理同逻辑)。 - 支持复盘日志(手工标记识别错/生成错、自动记录解析跳过与异常)。 - 标记识别错/生成错时支持填写备注(前端弹窗输入)。 - 支持“已标识错误”列表查看、编辑、删除。 - 手动“修正并生成”成功后,会自动清除同原始行的活跃标识(转为已解决)。 - 重复记录支持直接预览与下载(若历史图片仍存在)。 - 生成时可查看实时进度(解析、生成PPT、转PDF、导图、收尾)。 - 刷新页面后可查看历史记录并继续标注(支持历史图预览/下载)。 - 生成阶段支持低配模式:默认单任务单并发(同一时刻只允许一个生成任务)。 - 生成策略支持“页面模板缓存”(默认):多条生成时先按 `page_x` 预构建单页模板,单线程落盘以降低峰值内存。 - 生成完成后启用内存回收(`gc.collect + malloc_trim`,可配置开关)。 - 字体保护不变:仍按 run 级别替换文本,仅改数字/状态/网点目标 run,不改字体样式与字号。 - 预览图按顺序逐张加载(前面的先加载),避免大批量并发请求导致预览异常。 - 图片下载接口支持限速(默认 `300KB/s`),可在 `performance.image_delivery.max_kbps` 调整。 - 跳过明细支持“屏蔽”单条(屏蔽后不再展示,清空历史时一并清空屏蔽)。 ## 最近修复 - 修复“识别正确但生成网点变成潇水南路”的问题。 - 原因是模板不同页面的网点文本框索引不一致,旧逻辑固定 `shape_index=3`。 - 现逻辑会优先定位包含“营业所”的文本段再替换,避免错位替换。 - 修复中文金额 `amount_not_found`(例如 `蚣坝揽收十万现金定期一年`)。 - 新增中文金额解析后,补充了兼容保护,避免把单独“万/亿”误识别成 `0万`。 - 状态识别增强:支持“关键词中间夹金额/文本”的句式(如 `揽收十万现金`、`揽收16万礼金`、`微信17万提现`、`商户20万提现`、`揽收20万商户`)。 - 理财页文案调整为 `两三年期理财`,并在生成时对标题文本关闭自动换行,避免多字后折行。 ## 技术实现 - PPT 文本替换:`python-pptx` - PPT 转 PDF、PDF 按页转 PNG:优先本机 `libreoffice + pdftoppm`,无本机环境时回退 Docker `minidocks/libreoffice` - 生成链路:`解析 -> 页面模板缓存(可配置) -> 生成PPT(默认单线程) -> 批量转PDF -> PDF导图(默认单线程)` - 前端迁移策略:主页面已直接接入 Vue(`static/js/main.js`),不再依赖 legacy 保底脚本。 - Vue 运行时采用本地静态文件:`static/vendor/vue.global.prod.js`(由 `npm run sync:vue` 同步)。 默认会在启动时后台预热转换镜像;若已完成部署初始化,首次生成通常不会再等待拉取镜像。 ## 目录 - `server.py`: 后端(标准库 HTTP API + 生成逻辑) - `api_get_routes.py`: GET 接口路由分发(从 `server.py` 抽离) - `api_post_routes.py`: POST 接口路由分发(从 `server.py` 抽离) - `services/workflows.py`: 解析/生成/修正业务流程服务层 - `services/post_ops.py`: 标识/历史/清理等通用 POST 业务服务层 - `repositories/history_repository.py`: 历史读写仓储层 - `static/index.html`: 前端页面 - `static/app.js`: 前端加载入口(仅负责加载脚本) - `static/js/core/state.js`: 前端共享状态与常量 - `static/js/main.js`: 主前端脚本(Vue + 业务逻辑) - `static/vendor/vue.global.prod.js`: 本地 Vue 运行时 - `static/styles.css`: 页面样式 - `config/xibao_logic.json`: 处理规则配置 - `data/generated_history.json`: 去重历史 - `data/manual_rules.json`: 手工规则 - `data/review_logs/review_YYYY-MM-DD.jsonl`: 当日复盘日志 - `output/`: 生成输出目录(每次任务图片) - `tests/`: 自动化单元测试 - `scripts/smoke_api.sh`: 接口烟雾测试脚本 - `package.json`: 前端工具脚本(`lint/test/smoke/sync:vue`) - `Makefile`: 一键检查入口(`make check`) - `app.js`: 历史遗留文件,不参与线上页面加载 ## 启动与运维 ### 本地直接启动 ```bash cd /opt/xibao-web/app /opt/xibao-web/venv/bin/python server.py --host 127.0.0.1 --port 8787 ``` 可选参数: - `--prewarm-blocking`: 启动前阻塞预热镜像(确保服务起来后镜像一定可用) - `--skip-prewarm`: 跳过启动时预热 ### 开发检查(推荐) ```bash cd /opt/xibao-web/app # 1) 语法/静态检查 make lint # 2) 单元测试 make test # 3) 线上接口烟雾回归(默认 zc.workyai.cn) make smoke # 一键全跑 make check ``` 前端工具脚本: ```bash # 同步本地 Vue 运行时到 static/vendor npm run sync:vue ``` ### systemd(线上) ```bash systemctl status xibao-web.service systemctl restart xibao-web.service journalctl -u xibao-web.service -n 200 --no-pager ``` ### Nginx(线上) ```bash cat /etc/nginx/sites-available/zc.workyai.cn nginx -t systemctl reload nginx ``` ## API(核心) - `GET /api/config`: 获取配置摘要 - `POST /api/parse`: 仅解析预览 - `POST /api/generate`: 解析 + 生成 + 返回图片下载地址 - `GET /api/download/{token}`: 下载单张图片 - `GET /api/progress/{token}`: 查询本次生成进度 - `POST /api/output/clear`: 强制清理输出目录截图/任务文件 - `GET /api/history/view?limit=500`: 获取可预览/下载的历史记录视图 - `POST /api/log/mark`: 标记识别错误/生成错误到复盘日志(支持 `note` 备注) - `GET /api/issues?status=active|resolved|all&limit=500`: 查看标识列表 - `POST /api/issues/update`: 修改标识(类型/原始行/备注) - `POST /api/issues/delete`: 删除标识 - `GET /api/log/today`: 查看今日日志 - `POST /api/history/clear`: 清空历史 ## 微信机器人接入(新增) 项目内置桥接脚本:`wechat_bot_bridge.py`,用于把微信消息接入到本项目: - 拉取微信新消息:`/message/HttpSyncMsg` - 识别指令后调用: - `POST /api/parse` - `POST /api/generate` - 将结果回发微信: - 文本:`/message/SendTextMessage` - 图片:`/message/SendImageNewMessage` ### 快速启动 ```bash cd /root/zc.workyai.cn/app python3 wechat_bot_bridge.py \ --wechat-base-url http://127.0.0.1:18238 \ --wechat-session-file /root/WeChatPadPro_test_20260227/webui/.session.json \ --xibao-base-url https://zc.workyai.cn ``` 可选参数: - `--wechat-auth-key`:直接指定 authKey(不走 session 文件) - `--allow-from wxid_a,wxid_b`:仅处理白名单发送者 - `--max-images 3`:每次最多回发几张图 - `--dry-run`:只打印,不实际回消息 - `--once`:只轮询一次(调试用) ### 微信指令 - `/喜报 帮助` - `/喜报 解析 + 文本` - `/喜报 生成 + 文本` - `跳过N`(例如 `跳过3` / `跳过(3)`,当天自动跳过前 N 条序号内容) - `跳过0`(取消当天自动跳过) - `反馈+序号+说明`(记录到复盘/问题列表) - 直接发送包含 `#接龙` 的文本也会触发生成 说明: - 仅处理私聊文本消息(不处理群聊)。 - 跳过/屏蔽项不单独发送通知,识别与过滤完全使用本项目现有逻辑。 - 每日按 `--daily-cleanup-time` 自动清空输出图片与历史记录(不会清空反馈记录)。 ## 常用排查命令 ```bash # 1) 服务是否存活 systemctl status xibao-web.service ss -lntp | rg ':8787' # 2) 配置是否正常 curl -sS http://127.0.0.1:8787/api/config # 3) 单条解析复现 curl -sS -X POST http://127.0.0.1:8787/api/parse \ -H 'Content-Type: application/json' \ --data '{"raw_text":"2、 蚣坝揽收十万现金定期一年"}' # 4) 查看复盘日志(识别错/生成错/skip/异常) tail -n 200 /opt/xibao-web/app/data/review_logs/review_$(date +%F).jsonl # 5) 查看活跃标识 curl -sS 'http://127.0.0.1:8787/api/issues?status=active&limit=200' # 6) 查看手工规则(是否有误命中) cat /opt/xibao-web/app/data/manual_rules.json # 7) 查看历史去重(为什么没新生成) cat /opt/xibao-web/app/data/generated_history.json ``` ## 故障排除指南 ### 问题 1:识别正确,但图片里网点不对(例如固定变成“潇水南路”) - 先确认 `api/parse` 输出的 `branch` 是否正确。 - 若解析正确但图错,重点检查模板页网点文本是否包含“营业所”字样。 - 当前替换逻辑按“营业所”文本段定位;模板若不含该标记,可能回退到配置索引。 - 模板调整后建议先用一条数据做小流量验证。 ### 问题 2:`amount_not_found` - 先用 `api/parse` 复现并看 `skipped` 原因。 - 已支持常见中文金额:`十万`、`两万五`、`一万二`、`二点五万`。 - 若仍失败,先看原文是否存在金额信息,再检查是否被特殊格式拆断。 ### 问题 3:点“生成”后没有新图 - 查看返回里的 `duplicate_records` 和 `summary.duplicate`。 - 常见原因是去重命中(有序号时按序号键,无序号时按 `branch+amount+type`)。 - 需要重生成可清历史后再生成:`POST /api/history/clear`。 ### 问题 4:日志里出现 `demand_deposit_not_generate` - 这是预期策略:只出现活期类关键词且未写明确期限时默认不生成。 - 解决方式是补上产品期限或类型(例如“存一年”“理财”“保险5年交”)。 ### 问题 5:转换失败(Docker 镜像拉取/转换异常) - 先执行 `docker info` 确认 Docker 可用。 - 执行 `docker pull minidocks/libreoffice` 预热镜像。 - 查看服务日志:`journalctl -u xibao-web.service -n 300 --no-pager`。 ### 问题 6:需要回溯某次“识别错/生成错” - 进入 `data/review_logs/review_YYYY-MM-DD.jsonl` 查 `manual_mark`。 - 字段 `mark_type` 区分识别错/生成错,`source_line` 是原句,`note` 是备注。 - 结合同文件内的 `parse_skip`、`manual_correction_apply` 可还原完整过程。 ### 问题 7:标识想改备注或删掉 - 页面“已标识错误”面板可直接编辑或删除。 - 或调用接口: - `POST /api/issues/update`(按 `id` 修改) - `POST /api/issues/delete`(按 `id` 删除) ## /api/generate 示例 ```json { "raw_text": "#接龙\n1、营江路张三30万存一年\n2、潇水南路保险2万", "insurance_year": "5", "template_file": "/opt/xibao-web/templates/黄金三十天喜报模版(余额、保险、理财)(1).pptx", "output_dir": "/opt/xibao-web/app/output", "save_history": true } ``` ## 注意 - 需要本机 Docker 可用(`docker info` 正常)。 - 当前下载 token 默认 1 小时过期。