feat: initial import (exclude templates and runtime temp files)

This commit is contained in:
237899745
2026-02-27 15:21:15 +08:00
commit 0951732c7a
33 changed files with 11698 additions and 0 deletions

294
app/README.md Normal file
View File

@@ -0,0 +1,294 @@
# 喜报处理 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 小时过期。