# Phase 5: 联调与集成(W5-W6) > **目标:** 前后端联调跑通完整流程,配置规则种子数据,确保全链路畅通。 > **周期:** 第 5 ~ 6 周 > **任务数:** 2 个 > **可并行:** 联调和种子数据可由不同人并行 > **前置依赖:** Phase 3 + Phase 4 --- ## 本阶段交付物 | 交付物 | 说明 | |---|---| | 完整流程跑通 | 从创建任务到同步成功的端到端流程 | | 规则种子数据 | 差旅报销制度 + 6 条核心规则 + 城市等级标准 | --- ## 任务清单 ### Task 5.1: 前后端联调 **负责人:** 全员参与 **预计工时:** 3-4 天 **前置依赖:** Phase 3 + Phase 4 **Files:** - Modify: 多个前后端文件(修复联调问题) - [ ] **Step 1: 启动前后端全栈环境** ```bash # 启动基础设施 docker-compose up -d # 启动后端 cd backend alembic upgrade head uvicorn app.main:app --reload --port 8000 # 启动前端 cd frontend npm run dev ``` 确认: - PostgreSQL 可连接:`psql -h localhost -U postgres -d x_financial` - Redis 可连接:`redis-cli ping` - MinIO 可访问:http://localhost:9001 - 后端健康检查:http://localhost:8000/health - 前端可访问:http://localhost:5173 - [ ] **Step 2: 跑通完整报销流程(10 步)** 按开发文档 3.1 节的完整流程: **步骤 1 - 创建任务** 1. 访问首页 http://localhost:5173 2. 在输入框输入"我要报这次北京出差的费用" 3. 点击提交 4. 验证:任务创建成功,跳转到上传页 **步骤 2 - 上传票据** 1. 选择票据类型:增值税发票 2. 上传模拟发票文件(可用任意 PDF/PNG) 3. 选择票据类型:火车票 4. 上传模拟火车票文件 5. 验证:文件列表显示 2 个文件 **步骤 3 - 启动 Agent 识别** 1. 点击"开始识别" 2. 等待 Agent 处理(观察后端日志) 3. 验证:跳转到草稿页,显示识别结果 **步骤 4 - 查看报销草稿** 1. 确认费用明细已自动填充 2. 检查金额、商户、日期等字段 3. 验证:可编辑字段能修改 **步骤 5 - 执行预审** 1. 点击"执行预审" 2. 等待规则引擎执行 3. 验证:跳转到预审结果页 **步骤 6 - 查看预审结果** 1. 检查总体结论 2. 查看风险项(如有) 3. 查看缺件项(如有) 4. 验证:规则命中详情展示正确 **步骤 7 - 补件(如需要)** 1. 点击"一键补件" 2. 在补件页上传缺失附件 3. 提交补件 4. 验证:跳转回预审页,重新预审 **步骤 8 - 确认提交** 1. 确认报销单摘要 2. 点击"确认提交" 3. 等待同步状态更新 4. 验证:同步状态变为 success **步骤 9 - 查看审计日志** 1. 访问审计日志页 2. 按任务ID筛选 3. 验证:所有操作步骤都有记录 **步骤 10 - 查看后端 Swagger** 1. 访问 http://localhost:8000/docs 2. 验证所有 API 文档正确 - [ ] **Step 3: 修复联调过程中发现的问题** 常见问题检查清单: - [ ] API 响应格式前后端一致(字段名、嵌套结构) - [ ] 日期格式统一(ISO 8601) - [ ] 金额精度(Decimal vs Number) - [ ] 错误处理(前端能正确显示后端错误信息) - [ ] 文件上传大小限制(前端 + 后端 + MinIO) - [ ] 跨域配置正确 - [ ] 路由跳转正常 - [ ] Loading 状态显示 - [ ] 空状态展示 - [ ] **Step 4: 压力测试关键接口** - `POST /tasks` 创建 100 个任务 - `GET /tasks` 列表查询响应时间 < 500ms - `POST /tasks/{id}/documents` 上传 10 个文件 - `POST /tasks/{id}/agent/run` Agent 执行时间 < 30s - [ ] **Step 5: Commit** ```bash git add . git commit -m "fix: 前后端联调修复(完整流程跑通)" ``` --- ### Task 5.2: 规则配置与种子数据 **负责人:** 全栈/Agent 工程师 **预计工时:** 2 天 **前置依赖:** Phase 2(规则引擎) **可并行于:** Task 5.1 **Files:** - Create: `backend/alembic/seed/expense_policies.sql` - Create: `backend/alembic/seed/expense_rules.sql` - Create: `backend/alembic/seed/city_levels.sql` - Create: `backend/alembic/seed/hotel_limits.sql` - Create: `backend/scripts/seed_data.py` - [ ] **Step 1: 编写城市等级数据** `backend/alembic/seed/city_levels.sql`: 按典型企业标准配置: - **一线城市**:北京、上海、广州、深圳 - **二线城市**:杭州、南京、成都、武汉、重庆、天津、苏州、西安 - **三线城市**:其他城市 ```sql CREATE TABLE IF NOT EXISTS city_level ( city_name VARCHAR(50) PRIMARY KEY, level VARCHAR(10) NOT NULL -- tier1 / tier2 / tier3 ); INSERT INTO city_level (city_name, level) VALUES ('北京', 'tier1'), ('上海', 'tier1'), ('广州', 'tier1'), ('深圳', 'tier1'), ('杭州', 'tier2'), ('南京', 'tier2'), ('成都', 'tier2'), ('武汉', 'tier2'), ('重庆', 'tier2'), ('天津', 'tier2'), ('苏州', 'tier2'), ('西安', 'tier2'); ``` - [ ] **Step 2: 编写住宿标准数据** `backend/alembic/seed/hotel_limits.sql`: ```sql CREATE TABLE IF NOT EXISTS hotel_limit ( city_level VARCHAR(10) NOT NULL, job_level VARCHAR(20) NOT NULL, -- manager / senior / staff limit_per_night DECIMAL(10,2) NOT NULL, PRIMARY KEY (city_level, job_level) ); INSERT INTO hotel_limit (city_level, job_level, limit_per_night) VALUES ('tier1', 'manager', 800.00), ('tier1', 'senior', 600.00), ('tier1', 'staff', 500.00), ('tier2', 'manager', 600.00), ('tier2', 'senior', 450.00), ('tier2', 'staff', 350.00), ('tier3', 'manager', 500.00), ('tier3', 'senior', 350.00), ('tier3', 'staff', 300.00); ``` - [ ] **Step 3: 编写规则种子数据** `backend/alembic/seed/expense_rules.sql` — 预置开发文档 7.2 节的 3 条示例规则 + MVP 需要的 6 条核心规则: 1. `TRAVEL_HOTEL_LIMIT` — 住宿费标准校验(severity: medium, action: require_explanation) 2. `HOTEL_BILL_REQUIRED` — 住宿费必须上传酒店流水(severity: medium, action: require_attachment) 3. `DUPLICATE_INVOICE_CHECK` — 重复发票检查(severity: blocked, action: block) 4. `REQUIRED_FIELDS_CHECK` — 必填字段校验(severity: medium, action: warn) 5. `AMOUNT_ABNORMAL_CHECK` — 金额异常检查(severity: high, action: require_explanation) 6. `DATE_VALIDITY_CHECK` — 日期合理性校验(severity: low, action: warn) 7. `EXPENSE_TYPE_MATCH_CHECK` — 费用类型匹配校验(severity: low, action: warn) 8. `INVOICE_TITLE_CHECK` — 发票抬头校验(severity: high, action: require_explanation) 9. `TRIP_PERIOD_MATCH_CHECK` — 出差期间匹配校验(severity: medium, action: warn) 每条规则包含完整的 condition_json、action、severity、message_template、policy_ref。 - [ ] **Step 4: 编写数据初始化脚本** `backend/scripts/seed_data.py` — 一键初始化所有种子数据: ```python """初始化种子数据""" import asyncio from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession from app.core.config import settings # ... 读取 SQL 文件并执行 async def main(): engine = create_async_engine(settings.DATABASE_URL) async with engine.begin() as conn: # 按顺序执行 seed SQL for sql_file in ['city_levels.sql', 'hotel_limits.sql', 'expense_rules.sql']: with open(f'alembic/seed/{sql_file}') as f: await conn.execute(f.read()) print("Seed data loaded successfully!") if __name__ == "__main__": asyncio.run(main()) ``` - [ ] **Step 5: 验证种子数据** Run: `cd backend && python scripts/seed_data.py` 验证: - 城市等级表有数据 - 住宿标准表有数据 - 规则表有 9 条规则且全部 enabled - [ ] **Step 6: Commit** ```bash git add backend/ git commit -m "feat: 添加差旅报销制度和规则种子数据" ``` --- ## 本阶段完成检查 - [ ] 完整报销流程(创建→上传→识别→草稿→预审→补件→提交→同步)端到端跑通 - [ ] 前后端 API 格式一致,无字段不匹配 - [ ] 错误场景有正确提示(上传失败、OCR 失败、同步失败) - [ ] 种子数据加载成功,规则引擎使用种子数据执行预审 - [ ] Swagger 文档 http://localhost:8000/docs 可访问 - [ ] 审计日志记录了完整操作链路