12 KiB
12 KiB
模块导航与拆分规范
四阶段拆分已落地:am.py 保留命令及 WSGI 兼容入口,应用工厂和业务代码位于 logistics_chat/,页面样式与脚本位于 static/。本文描述当前结构及后续结构调整约定。
先定位,再阅读
从 AGENTS.md 选择文件,以函数、常量、接口为锚点,搜索后只读取相关实现和调用方。模块移动时更新索引,不保存易失效的行号。默认遵守 Git 忽略规则,排除附件、数据库、日志、备份、虚拟环境和工作草稿。
rg --files
rg -n -F 'calc_freight' logistics_chat/pricing.py
rg -n -F '/api/human/' logistics_chat/routes static/js examples
rg -n '^(def |class | def )' scripts tests -g '*.py'
PowerShell 下把目录和 -g '*.py' 分开传给 rg。报价字典可能整行很长,搜索时加 --max-columns 200 --max-columns-preview,避免输出整份数据。
当前模块索引
| 业务范围 | 实际文件与搜索锚点 | 联动位置 |
|---|---|---|
| 应用入口与配置 | am.py:main、延迟访问的 app;logistics_chat/__init__.py:create_app;config.py:default_config、get_setting;runtime.py:serve_app |
start.bat、.env.example |
| Jenkins 灰度部署 | Jenkinsfile、Dockerfile;deploy/gray_config.py:GrayConfig;publish-gray.sh、activate-gray.sh、prepare-gray-tls.sh、renew-gray-tls.sh |
部署指南;独立持久化数据、证书和回环端口;wsgi.py 提供容器内路径 |
| 请求钩子 | logistics_chat/hooks.py:rate_limit、no_cache_html |
工厂注册钩子;限流状态在 app.extensions['rate_hits'] |
| SQLite 与维护 | logistics_chat/db.py:connect、close_connections、init_db、backup_db、save_message、last_user_question、load_context |
维护 CLI 在 scripts/;旧会话自动清理仍未启用 |
| 历史接口 | logistics_chat/history_service.py:new_chat、get_history、get_messages、del_history、clear_all;对应 routes/history.py |
static/js/chat.js:ensureConv、loadHistory、openConversation |
| 知识检索 | logistics_chat/knowledge.py:knowledge_list、search_knowledge |
knowledge.md 与代码同步,程序不读取该文档 |
| 运费与附加费 | logistics_chat/pricing.py:RATES、parse_shipping_intent、dims_to_cm、pick_rate、calc_freight、freight_reply、calc_warehouse_card、detect_surcharge、check_island |
logistics_chat/rates_extra.py 为唯一扩展数据源,根目录同名文件仅兼容转发 |
| 运单轨迹 | logistics_chat/tracking.py:extract_tracking_no、build_track、CARD_PREFIX、card_to_text |
static/js/chat.js:fillTrackCard、addTrackCard;模拟节点时间取当前时刻,回归对照需固定时钟 |
| AI 与 SSE | logistics_chat/chat_service.py:create_chat_stream、sse;ai_client.py:post_completion、compress_answer、gen_followups |
routes/chat.py:stream_chat;客户端 doSend、renderError、renderFollowups |
| 人工会话 | logistics_chat/human_service.py:human_*;对应 routes/human.py |
输入状态在 app.extensions['human_typing'];客户 startHumanPoll;客服 loadQueue、poll、sendReply |
| 附件 | logistics_chat/file_service.py:upload_file、cleanup_uploads;routes/files.py:uploaded_file |
扩展名/大小/目录由配置提供;客户端 addMsg,客服端 appendMsg |
| 登录、统计、订单、留言、导出 | logistics_chat/business_service.py:admin_login、admin_stats、my_orders、add_ticket、list_tickets、export_chat |
routes/admin.py、routes/business.py;登录页 static/js/admin_login.js |
| 页面 | templates/index.html、templates/admin.html、templates/admin_login.html |
先加载共享 static/css/theme.css,再加载对应 chat、admin、admin_login 的 CSS/JS;保留全局事件入口 |
| 回归 | tests/test_rules.py、test_storage.py、test_api.py、test_config.py、test_deployment.py、test_gray_config.py、test_gray_activation.py、test_startup.py、test_maintenance_scripts.py、test_frontend.py;tests/frontend/admin.test.cjs |
Linux 回退模拟基础设施、实际操作临时文件;模型、数据库及上传隔离;Node 验证异步交互 |
除标明的根目录文件外,表内缩写的 Python 文件均相对 logistics_chat/。
当前文件布局
am.py # CLI;显式请求 am.app 时创建默认 WSGI 应用
rates_extra.py # 旧导入路径的兼容转发
logistics_chat/
├── __init__.py # create_app 与显式运行时初始化
├── config.py # 根目录 .env、环境变量、稳定根路径、服务/资源配置
├── db.py # 连接、schema、历史持久化、备份
├── knowledge.py # 知识与关键词检索
├── pricing.py # 运费规则、解析、换算、附加费说明
├── rates_extra.py # 扩展报价数据
├── tracking.py # 单号识别、模拟轨迹、卡片协议
├── ai_client.py # 模型 HTTP、压缩与追问
├── chat_service.py # 问答编排与 SSE 帧
├── history_service.py # 历史会话 CRUD
├── human_service.py # 人工状态与消息
├── business_service.py # 反馈、统计、登录、订单、留言、CSV
├── file_service.py # 附件校验、保存、清理
├── hooks.py # 限流及 HTML/SSE 缓存头
├── runtime.py # Waitress / Flask 启动
└── routes/
├── __init__.py # Blueprint 注册
├── chat.py
├── history.py
├── human.py
├── admin.py
├── business.py
├── files.py
└── pages.py
templates/ # HTML/Jinja 及原有事件属性
static/css/ # theme.css 共享令牌;chat/admin/admin_login 页面样式
static/js/ # chat.js、admin.js、admin_login.js,经典脚本
scripts/ # 可独立运行的维护 CLI
tests/ # 按业务模块组织的回归
模块边界与依赖方向
- 路由只解析请求并包装响应;服务组织业务;规则模块提供确定性计算。依赖方向为
routes → services → rules / db / ai_client,下层不导入路由或根入口。 db.py统一连接、schema 和历史持久化。人工与管理业务的 SQL 放在所属服务,HTTP 路由不执行 SQL。请求及流式请求结束时关闭连接,未提交事务回滚。init_db包括客服账号、订单与留言表,首次启动只建空表;不内置账号。重复初始化保留已有数据,业务测试从真实初始化结果插入夹具,不另建缺失表。- 所有模型 HTTP 经
ai_client.post_completion。保留流式问答(5, 90)、压缩(5, 30)、追问(5, 15)三组连接/读取超时;不能因共用客户端而合并期限。流结束或取消时释放 HTTP 响应。 - 模块导入不建库、不备份、不清理附件、不访问模型。
create_app默认显式初始化运行目录、数据库、备份与旧附件清理;INITIALIZE_RUNTIME=False可禁止这些动作,此时调用方负责提供已有 schema。访问兼容入口am.app视为显式创建应用。 config.ROOT_DIR指向仓库根目录,模板/静态目录显式提供给 Flask。数据库、上传、备份、日志使用配置中的绝对路径,避免包文件移动改变数据位置。default_config用python-dotenv读取根目录.env,不修改os.environ;只读取已支持的DEEPSEEK_API_KEY,不展开${...}。显式工厂配置优先于进程环境(含空值),再使用文件值。配置在应用创建时确定,修改后重启;真实.env不纳入 Git。- 限流、输入状态由应用实例持有,不能每请求重置或跨测试应用共享。维护 CLI 和纯规则可用标准库加载,包入口延迟导入 Web 依赖。
- 单文件围绕一个职责;超过约 300–400 行时检查职责,而非按行数机械拆分。报价数据保持单一来源;兼容转发不复制字典。页面脚本按页面保留既有执行顺序和全局函数,不擅自改为 ES Modules。
- 配色、字体基线和通用控件放在
theme.css,页面布局放在对应 CSS。客户页通过body.dark覆盖主题令牌;新增可翻译文案加入chat.js的I18N,静态文案用data-i18n。调整样式后检查桌面、390px 窄屏、侧栏、聊天卡片和客服空/活动状态。 - 客户附件预览由
clearAttachment管理,轨迹展开由fillTrackCard管理。客服drafts按sid保存草稿,发送成功后只清理已确认发送的内容;常用回复仅填入草稿。renderList只在展示数据变化时重绘。 - 客服工作台默认只展示会话列表和全高聊天区;统计使用原生
details收在「数据概览」。setSessionTab切换接待/排队列表,setChatView与showSessionList控制 720px 及以下的整屏导航,不结束当前会话。setToolsOpen控制默认关闭的服务资料:1200px 以上为侧栏,较窄屏为抽屉;列表入口让未选会话的手机用户也能查看留言。
后续结构调整顺序
| 阶段 | 范围 | 验收要求 |
|---|---|---|
| 1. 纯规则 | 知识、报价、运费、运单识别 | 边界结果与迁移前一致;固定时钟比较模拟轨迹;导入无运行数据副作用 |
| 2. 数据访问 | 配置、SQLite、备份、附件 | 临时目录验证 schema 兼容、事务、保留/清理时机和跨目录 CLI |
| 3. 服务/路由 | 模型、聊天、人工、应用工厂、Blueprint | URL/方法/状态/JSON/SSE 不变;保留限流、HTML/SSE 缓存头及根入口 |
| 4. 前端 | 模板与 CSS/JS | 仅迁移时对照原资源内容;主动改版时验证语法、资源 URL、加载顺序、响应式和客户/客服页交互 |
每阶段完成相关验证再推进依赖阶段。鉴权、缺表和计费的业务修复单独说明,避免在结构调整中顺带改行为。
必须保留的接口与数据约定
- SSE 字段为
t、e、card、replace、suggest、d,保留流式输出、停止、异常及中断保存。 chat_service.create_chat_stream在识别运单号时忽略[图片]/uploads/...和[文件]/uploads/...路径,避免附件文件名中的时间戳误触发查询;存储与请求仍保留原始附件标记和 URL。- 历史卡片以
__CARD__{json}保存;原 SQLite 表、字段、角色值和历史记录继续可读。 - 人工申请使用
conv_id,返回session_id,后续用sid。状态为waiting/active/closed,消息方向为customer/agent。 - 计费档位、单位换算和舍入保持原样。
calc_freight.total仅含基础运费;附加费尚未统一并入。知识文档与knowledge_list同步维护。 - 上传 URL 保留
/uploads/,默认 10MB,扩展名配置保持不变。原附件保留本地、继续忽略,目录迁移不另建一份数据。 - 后台鉴权和会话隔离仍不完整,轨迹为模拟数据。Linux 公网验收用 Nginx 全站密码隔离访问,不代表已修复面向客户开放所需的应用权限。
验证与维护
先按 README 安装项目依赖。Windows 使用 .\.venv\Scripts\python.exe -m pytest -v 或同解释器的 -m unittest discover -s tests -v;Linux/macOS 使用 .venv/bin/python。业务测试依赖 Flask,不能用未安装依赖的全局 Python 运行整套测试。模型请求全部模拟,不代表真实 DeepSeek 联调。
路径、函数或资产移动后同步更新根 AGENTS.md、本文、知识资料和 README 目录树。仅改导航时检查路径、符号、命令;改业务时补充相关成功和失败分支,前端改动检查实际页面。