2 Commity 615449f97d ... 056bb943e8

Autor SHA1 Wiadomość Data
  wubinggen 056bb943e8 [milestone-2] 阶段2a Team B 架构设计交付 9 godzin temu
  wubinggen 2fc44bd43d [milestone-1] 阶段2a Team A 需求分析交付 9 godzin temu

+ 82 - 56
deliveries/team-a-requirement/DELIVERY-MANIFEST.md

@@ -1,94 +1,120 @@
 # 交付清单 — Team A 需求分析师
 
 ## 里程碑信息
-- **阶段**: 需求分析
-- **里程碑编号**: milestone-1
-- **提交时间**: 2026-05-30 17:30
+- **阶段**: 阶段2a 果农核心功能
+- **里程碑编号**: milestone-1(需求分析)
+- **提交时间**: 2026-05-30
 - **负责团队**: Team A
 
 ## 交付产物
 
 | 序号 | 文件路径 | 说明 | 覆盖度检查 | 核心内容摘要 |
 |------|----------|------|------------|--------------|
-| 1 | deliveries/team-a-requirement/spec.md | 阶段一需求规格 | 模块数: 4/4, 功能点: 20/20 | 系统管理、用户认证、首页与行情、审核框架 |
-| 2 | deliveries/team-a-requirement/use-cases.md | 阶段一用例文档 | 用例数: 18/18, 覆盖功能点: 20/20 | 系统管理4用例、用户认证8用例、首页4用例、审核2用例 |
-| 3 | deliveries/team-a-requirement/constraints.md | 阶段一约束条件 | 约束类别: 8/8 | 技术、安全、业务、性能、兼容性、数据、接口、测试 |
+| 1 | deliveries/team-a-requirement/spec.md | 阶段2a需求规格 | 模块数: 5/5, 功能点: 14/14 | 果农名片、招工发布、找工人、找客商、后台审核 |
+| 2 | deliveries/team-a-requirement/use-cases.md | 阶段2a用例文档 | 用例数: 32/32, 覆盖功能点: 14/14 | 名片7用例、招工6用例、找工人4用例、找客商3用例、审核7用例+2系统任务 |
+| 3 | deliveries/team-a-requirement/constraints.md | 阶段2a约束条件 | 约束类别: 8/8 | 继承阶段一+新增文件上传/内容安全/招工规则/距离计算 |
 | 4 | deliveries/team-a-requirement/DELIVERY-MANIFEST.md | 本交付清单 | - | 交付物清单、关键信息、问题反馈 |
 
 ## 修改文件清单
 
 | 序号 | 文件路径 | 操作类型 | 说明 |
 |------|----------|----------|------|
-| 1 | deliveries/team-a-requirement/spec.md | 新 | 阶段一需求规格文档 |
-| 2 | deliveries/team-a-requirement/use-cases.md | 新 | 阶段一用例文档 |
-| 3 | deliveries/team-a-requirement/constraints.md | 新 | 阶段一约束条件文档 |
-| 4 | deliveries/team-a-requirement/DELIVERY-MANIFEST.md | 新 | 本交付清单 |
+| 1 | deliveries/team-a-requirement/spec.md | 覆盖更新 | 阶段一更新为阶段2a需求规格 |
+| 2 | deliveries/team-a-requirement/use-cases.md | 覆盖更新 | 阶段一更新为阶段2a用例文档 |
+| 3 | deliveries/team-a-requirement/constraints.md | 覆盖更新 | 阶段一更新为阶段2a约束条件 |
+| 4 | deliveries/team-a-requirement/DELIVERY-MANIFEST.md | 覆盖更新 | 本交付清单 |
 
 ## 交付说明
 
-本次交付为阶段一(基础设施与用户体系)的需求分析成果,基于已有的需求规格说明书(requirements-specification.md)提取和细化。
+本次交付为阶段2a(果农核心功能)的需求分析成果,基于需求规格说明书(requirements-specification.md)和阶段2a任务清单(phase-2a-tasks.md)提取和细化。
 
 ### 核心内容
 
-1. **系统管理模块**(6个功能点)
-   - 角色管理:系统预置8种角色,RBAC权限模型
-   - 账号管理:管理员账号增删改查,BCrypt密码加密
-   - 权限管理:菜单+按钮级权限控制
-   - 字典管理:苹果品种、工种、农资种类、行政区划
-   - 操作日志:管理员操作行为记录
-   - 数据初始化:基础字典数据导入
-
-2. **用户认证模块**(8个功能点)
-   - 微信登录:code→openid→JWT token
-   - 后台登录:用户名+密码→JWT token
-   - 身份路由:根据身份数量决定跳转逻辑
-   - 用户信息查询:基本信息+脱敏手机号
-   - 用户状态管理:正常/禁用/锁定
-   - 手机号加密存储:AES加密+SHA256哈希
-   - 身份绑定:为用户绑定果农/工人/客商/农资商身份
-   - 管理员创建用户:后台创建用户账号
-
-3. **首页与行情模块**(4个功能点)
-   - 果农首页:问候语+今日行情+金刚区
-   - 工人首页:推荐招工+附近招工列表
-   - 客商首页:今日行情+货源推荐
-   - 农资商首页:店铺概览+快捷入口
-
-4. **审核基础框架**(2个功能点)
-   - 审核流程:通用审核框架,支持通过/驳回
-   - 审核列表:待审核列表查看和筛选
+1. **果农名片模块**(4个功能点)
+   - 名片信息维护:品种、产量、价格、地址、经纬度
+   - 视频上传:3步流程(前端预处理→后端存储→异步压缩)
+   - 照片上传:≤9张,单张≤5MB,EXIF清除
+   - 审核状态:待审/已通过/被驳回(驳回显示原因)
+
+2. **招工发布与管理模块**(5个功能点)
+   - 发布招工:免审核直接发布,表单字段完整
+   - 敏感关键词检测:正则匹配,keyword_flag标记,不阻塞发布
+   - 招工编辑:可编辑价格、人数、天数、备注
+   - 招工下架:逻辑删除(status=0)
+   - 我的招工列表:历史记录查看
+
+3. **找工人模块**(2个功能点)
+   - 工人列表:工种筛选、距离排序(Haversine公式)、状态展示
+   - 一键拨号:调用拨号接口记录日志,唤起系统拨号
+
+4. **找客商模块**(2个功能点)
+   - 客商列表:基本信息展示
+   - 一键拨号:同找工人拨号流程
+
+5. **后台审核模块**(3个功能点)
+   - 名片审核:通过/驳回(需填原因),审核日志
+   - 待复核列表:敏感词标记招工处理,标记正常/强制下架
+   - 审核SLA提醒:24小时提醒审核员,48小时升级超级管理员
 
 ## 给下游团队的关键信息
 
 ### 关键决策
 
-1. **认证方案**: 采用 JWT Token 认证,小程序端有效期24小时,后台端8小时
-2. **权限模型**: RBAC(用户→角色→权限),默认拒绝,显式授权
-3. **手机号存储**: AES加密存储明文,SHA256哈希用于查询索引
-4. **身份模型**: 一人多职,user_identity 表关联,数据隔离通过 user_identity_id
-5. **字典管理**: 系统内置字典不可删除,仅可扩展
+1. **视频上传方案**: 本地文件存储(非OSS),3步流程:前端预处理→后端存储→异步压缩
+2. **招工发布规则**: 免审核直接发布,敏感词标记不阻塞
+3. **距离计算**: Haversine公式实时计算,经纬度DECIMAL(10,7)精度
+4. **拨号机制**: 手机号通过单独接口获取(记录日志),列表不直接返回
+5. **审核SLA**: 24小时提醒,48小时升级,定时任务实现
 
 ### 隐含约束
 
-1. **数据库必须使用 MySQL 5.7+**(客户环境限制
-2. **Spring Boot 版本固定 1.5.9**(兼容性要求
-3. **MyBatis XML 必须使用 #{} 参数化**(防SQL注入
-4. **手机号接口返回必须脱敏**(隐私保护)
-5. **审核 SLA: ≤24小时提醒,48小时升级**(业务要求
+1. **视频仅限1个**,照片≤9张(数据库字段设计决定
+2. **招工编辑后重新触发敏感词检测**(防规避
+3. **距离计算需要果园地址→经纬度**(地理编码依赖
+4. **拨号日志是独立接口**,不在列表接口中返回手机号
+5. **审核结果需通知果农**(短信或站内信
 
 ### 特别注意
 
-1. **身份路由逻辑**: 0个身份→提示联系村委会,1个身份→直接进入,N个身份→选择页
-2. **密码锁定机制**: 连续5次错误锁定30分钟
-3. **操作日志**: 敏感操作(删除、权限变更、状态变更)必须记录
-4. **字典初始化**: 系统首次启动需导入基础字典数据
+1. **视频压缩是异步操作**:上传后立即返回URL,压缩在后台进行
+2. **敏感词不阻塞发布**:keyword_flag=1的招工仍然对工人可见
+3. **驳回后可重新提交**:状态重置为待审,清除驳回原因
+4. **EXIF清除是前端责任**:后端不做二次清除(性能考虑)
+
+### 阶段2a新增接口清单
+
+| 接口 | 方法 | 说明 | 状态 |
+|------|------|------|------|
+| /api/wx/grower/profile | GET | 获取果农档案 | 新增 |
+| /api/wx/grower/profile | PUT | 更新果农档案 | 新增 |
+| /api/wx/grower/recruit | POST | 发布招工 | 新增 |
+| /api/wx/grower/recruit | GET | 我的招工列表 | 新增 |
+| /api/wx/grower/recruit/{id} | PUT | 编辑招工 | 新增 |
+| /api/wx/grower/recruit/{id} | DELETE | 下架招工 | 新增 |
+| /api/wx/grower/workers | GET | 工人列表 | 新增 |
+| /api/wx/grower/buyers | GET | 客商列表 | 新增 |
+| /api/wx/call/phone | POST | 拨号接口 | 新增 |
+| /api/admin/audit/grower-profile | GET | 名片审核列表 | 新增 |
+| /api/admin/audit/grower-profile/{id} | PUT | 名片审核操作 | 新增 |
+| /api/admin/audit/recruit-review | GET | 待复核列表 | 新增 |
+| /api/admin/audit/recruit-review/{id} | PUT | 待复核操作 | 新增 |
+
+**已有接口(阶段2a复用)**:
+| 接口 | 方法 | 说明 | 状态 |
+|------|------|------|------|
+| /api/wx/file/upload/image | POST | 上传图片 | 已实现 |
+| /api/wx/file/upload/video | POST | 上传视频 | 已实现 |
+| /api/wx/file/files/{category}/{filename} | GET | 访问文件 | 已实现 |
+| /api/wx/file/delete | DELETE | 删除文件 | 已实现 |
 
 ## 对上团队的问题
 
-无。需求规格文档(requirements-specification.md)已完整覆盖阶段一所有功能点。
+无。需求规格文档(requirements-specification.md)已完整覆盖阶段2a所有功能点。
 
 ## 待确认事项
 
-1. **行政区划数据**: 洒渔镇下辖村的实际数据需要用户提供
-2. **超级管理员初始密码**: 建议 admin/admin123,首次登录强制修改
-3. **天气数据接口**: 果农首页天气功能是否需要接入第三方API?
+1. **地理编码服务**: 果园地址→经纬度转换使用哪个服务?(高德/百度/腾讯地图API)
+2. **语音输入**: 小程序端语音识别使用微信原生API还是第三方服务?
+3. **敏感词库**: 初始词库范围需要业务方确认(当前仅含明确违规词)
+4. **审核通知**: 审核结果通知方式(短信/站内信/小程序模板消息)
+5. **视频压缩**: 是否需要部署FFmpeg?还是使用Java原生压缩库?

+ 96 - 67
deliveries/team-a-requirement/constraints.md

@@ -1,20 +1,22 @@
-# 阶段一约束条件 — 基础设施与用户体系
+# 阶段2a约束条件 — 果农核心功能
+
+> 继承阶段一全部约束 + 阶段2a新增约束
 
 ---
 
-## 一、技术约束
+## 一、技术约束(继承阶段一)
 
 ### 1.1 开发环境
 - **JDK**: 1.8.0_291
 - **Maven**: 3.6.3
 - **Spring Boot**: 1.5.9.RELEASE
-- **数据库**: MySQL 5.7+
-- **缓存**: Redis 3.0+
+- **数据库**: MySQL 5.7+(sayu 库)
+- **缓存**: Redis 3.0+(可选)
 - **ORM**: MyBatis(XML 映射)
 
 ### 1.2 代码规范
 - **包名**: com.sayu
-- **Controller 路径**: 
+- **Controller 路径**:
   - 小程序端: /api/wx/*
   - 后台管理端: /api/admin/*
 - **MyBatis XML**: 必须使用 `#{}` 语法,禁止 `${}`
@@ -24,82 +26,90 @@
 - **构建工具**: Maven
 - **编译命令**: `mvn compile`
 - **测试命令**: `mvn test`
-- **打包命令**: `mvn package -DskipTests`
 - **启动命令**: `mvn spring-boot:run`
 
 ---
 
-## 二、安全约束
+## 二、安全约束(继承阶段一 + 新增)
 
-### 2.1 数据安全
+### 2.1 数据安全(继承)
 - **手机号**: AES 加密存储,phone_hash (SHA256) 唯一索引
-- **密码**: BCrypt 加密,强度≥8位,含大小写字母和数字
 - **Token**: JWT,payload 包含 userId, identityId, identityType, exp
 - **密钥管理**: 配置在 application.properties,禁止硬编码
 
-### 2.2 接口安全
+### 2.2 接口安全(继承)
 - **认证**: JWT Token 认证
 - **授权**: RBAC 权限控制,默认拒绝,显式授权
-- **防重放**: Token 过期机制(小程序24小时,后台8小时)
 - **防注入**: MyBatis #{} 参数化
 - **敏感数据**: 接口返回脱敏(手机号 138****8888)
 
-### 2.3 操作安全
-- **登录日志**: 记录登录时间、IP、设备信息
-- **操作日志**: 记录管理员操作行为
-- **密码锁定**: 连续5次错误锁定30分钟
-- **账号禁用**: 禁用后不可登录
+### 2.3 文件上传安全(新增)
+- **格式白名单**: 图片(jpg,jpeg,png,gif)、视频(mp4,mov,avi)
+- **大小限制**: 图片≤5MB/张,视频≤50MB
+- **EXIF清除**: 前端必须清除EXIF元数据(防止位置泄露)
+- **文件存储**: 本地存储目录 `./uploads/`,禁止路径穿越
+
+### 2.4 内容安全(新增)
+- **敏感词检测**: 正则匹配,色情/赌博/政治等明确违规词
+- **不阻塞发布**: keyword_flag=1 进入待复核,招工仍可见
+- **人工复核**: 审核员定时处理待复核列表
 
 ---
 
-## 三、业务约束
+## 三、业务约束(继承阶段一 + 新增)
 
-### 3.1 用户体系
-- **一人多职**: 一个用户可绑定多个身份(果农/工人/客商/农资商)
+### 3.1 用户体系(继承)
+- **一人多职**: 一个用户可绑定多个身份
 - **数据隔离**: 所有业务表带 user_identity_id 字段
-- **身份路由**: 
-  - 0个身份 → 提示联系村委会
-  - 1个身份 → 直接进入对应首页
-  - N个身份 → 身份选择页
-
-### 3.2 审核机制
-- **审核对象**: 果农档案、工人档案、客商档案、招工信息、货源信息
-- **审核状态**: 待审、已通过、被驳回
+- **身份路由**: 0个→提示联系村委会,1个→直接进入,N个→选择页
+
+### 3.2 审核机制(继承 + 扩展)
+- **审核对象**: 果农名片(阶段2a新增)
+- **审核状态**: 待审(0)、已通过(1)、被驳回(2)
 - **审核 SLA**: ≤24小时提醒,48小时升级给超级管理员
 - **驳回要求**: 必须填写驳回原因
+- **待复核**: 敏感关键词标记的招工信息
+
+### 3.3 招工发布规则(新增)
+- **免审核直接发布**: recruit_info.status=1
+- **敏感词标记**: keyword_flag=1 不阻塞发布
+- **下架**: 逻辑删除(status=0)
+- **编辑**: 可编辑价格、人数、天数、备注
 
-### 3.3 字典管理
-- **系统内置字典**: 不可删除,仅可扩展
-- **字典编码**: 唯一
-- **字典变更**: 记录操作日志
+### 3.4 文件上传规则(新增)
+- **视频**: 仅限1个,≤50MB,MP4/MOV,异步压缩720p/2Mbps
+- **照片**: ≤9张,单张≤5MB,JPG/JPEG/PNG/GIF
+- **存储**: 本地文件存储,数据库存URL
 
 ---
 
-## 四、性能约束
+## 四、性能约束(继承阶段一 + 新增)
 
-### 4.1 响应时间
+### 4.1 响应时间(继承)
 - **接口响应**: ≤500ms(95%请求)
 - **页面加载**: ≤3s
 
-### 4.2 并发能力
-- **并发用户**: ≥100
-- **数据库连接池**: 最大连接数 20
+### 4.2 文件上传性能(新增)
+- **上传时间**: ≤50MB文件,局域网环境≤30s
+- **视频压缩**: 异步处理,不影响用户操作
+- **压缩重试**: 失败自动重试3次
 
-### 4.3 数据量
-- **用户数据**: 预计 10,000+
-- **操作日志**: 保留 ≥180天
-- **字典数据**: 预计 100+ 条
+### 4.3 距离计算性能(新增)
+- **Haversine公式**: 实时计算,不缓存
+- **经纬度精度**: DECIMAL(10,7)
+- **排序**: 按距离升序,分页查询
 
 ---
 
-## 五、兼容性约束
+## 五、兼容性约束(继承阶段一)
 
 ### 5.1 小程序端
 - **微信基础库**: ≥2.0
-- **适老化**: 
+- **适老化**:
   - 正文≥18px(rem)
   - 按钮≥88×88px
   - 高对比度
+  - 语音输入支持
 
 ### 5.2 后台管理端
 - **浏览器**: Chrome/Firefox/Edge 最新版
@@ -107,32 +117,34 @@
 
 ---
 
-## 六、数据约束
+## 六、数据约束(继承阶段一 + 新增)
 
-### 6.1 数据库设计
+### 6.1 数据库设计(继承)
 - **字符集**: utf8mb4
 - **排序规则**: utf8mb4_unicode_ci
 - **表引擎**: InnoDB
-- **主键**: 自增ID 或 雪花算法
+- **主键**: 自增ID
 
-### 6.2 索引设计
-- **sys_user**: phone_hash UNIQUE, openid UNIQUE, status INDEX
-- **user_identity**: user_id INDEX, identity_type INDEX
-- **audit_log**: operator_id INDEX
-- **operation_log**: operator_id INDEX
+### 6.2 索引设计(新增)
+- **grower_profile**: latitude+longitude 复合索引(距离查询)
+- **recruit_info**: latitude+longitude 复合索引
+- **recruit_info**: keyword_flag INDEX(待复核查询)
+- **call_log**: caller_identity_id INDEX, callee_identity_id INDEX
 
-### 6.3 初始数据
-- **字典数据**: 苹果品种、工种类型、农资种类、行政区划
-- **管理员账号**: 超级管理员(admin/admin123)
+### 6.3 JSON字段规范(新增)
+- **varieties**: JSON数组,如 `["红富士","嘎啦"]`
+- **work_types**: JSON数组,如 `["采摘工","分拣工"]`
+- **photos**: JSON数组,如 `["http://localhost:8080/files/image/xxx.jpg"]`
+- **skills**: JSON数组,如 `["采摘","套袋"]`
 
 ---
 
-## 七、接口约束
+## 七、接口约束(继承阶段一)
 
-### 7.1 接口格式
+### 7.1 接口格式(继承)
 - **请求格式**: JSON
 - **响应格式**: JSON
-- **响应结构**: 
+- **响应结构**:
   ```json
   {
     "code": 200,
@@ -141,7 +153,7 @@
   }
   ```
 
-### 7.2 错误码规范
+### 7.2 错误码规范(继承)
 - **200**: 成功
 - **400**: 请求参数错误
 - **401**: 未认证
@@ -149,32 +161,49 @@
 - **404**: 资源不存在
 - **500**: 服务器内部错误
 
-### 7.3 分页规范
-- **请求参数**: page(页码,从1开始)、pageSize(每页数量,默认10)
-- **响应参数**: 
+### 7.3 分页规范(继承)
+- **请求参数**: page(页码,从1开始)、pageSize(每页数量,默认20)
+- **响应参数**:
   ```json
   {
     "total": 100,
     "page": 1,
-    "pageSize": 10,
+    "pageSize": 20,
     "list": []
   }
   ```
 
 ---
 
-## 八、测试约束
+## 八、测试约束(继承阶段一 + 新增)
 
-### 8.1 测试框架
+### 8.1 测试框架(继承)
 - **单元测试**: JUnit 4
 - **集成测试**: Spring Boot Test
 - **测试目录**: src/test/java/
 
-### 8.2 测试覆盖
+### 8.2 测试覆盖(继承)
 - **核心接口**: 测试覆盖率 ≥80%
 - **测试独立性**: 每个测试方法独立运行
 - **测试可重复**: 同一测试多次运行结果一致
 
-### 8.3 测试数据
-- **测试数据库**: 独立测试数据库
-- **测试数据**: 测试前准备,测试后清理
+### 8.3 阶段2a测试重点(新增)
+- **文件上传**: 50MB边界、格式异常、EXIF清除验证
+- **招工发布**: 敏感词标记、免审核发布、下架/编辑
+- **找工人**: 工种筛选、距离排序准确性、拨号日志
+- **审核**: 名片通过/驳回、待复核处理、SLA提醒
+
+---
+
+## 九、约束继承清单
+
+| 约束类别 | 阶段一约束 | 阶段2a新增 |
+|---------|-----------|-----------|
+| 技术约束 | 全部继承 | 无新增 |
+| 安全约束 | 全部继承 | 文件上传安全、内容安全 |
+| 业务约束 | 全部继承 | 招工发布规则、文件上传规则 |
+| 性能约束 | 全部继承 | 文件上传性能、距离计算性能 |
+| 兼容性约束 | 全部继承 | 无新增 |
+| 数据约束 | 全部继承 | 索引设计、JSON字段规范 |
+| 接口约束 | 全部继承 | 无新增 |
+| 测试约束 | 全部继承 | 阶段2a测试重点 |

+ 238 - 248
deliveries/team-a-requirement/spec.md

@@ -1,284 +1,274 @@
-# 阶段一需求规格 — 基础设施与用户体系
+# 阶段2a需求规格 — 果农核心功能
 
-> 基于 requirements-specification.md 提取
-> 阶段一功能点:20
+> 基于 requirements-specification.md + phase-2a-tasks.md 提取
+> 阶段2a功能点:14
 
 ---
 
 ## 一、阶段范围
 
-阶段一聚焦**基础设施搭建**和**用户体系建设**,为后续业务功能提供底层支撑
+阶段2a聚焦**果农核心业务功能**,使果农能完善名片、发布招工、找到工人和客商
 
 ### 功能模块
 
 | 模块 | 功能点数 | 优先级 |
 |------|---------|--------|
-| 系统管理(角色/权限/字典/日志) | 6 | P0 |
-| 用户注册与认证 | 8 | P0 |
-| 首页与行情展示 | 4 | P0 |
-| 审核基础框架 | 2 | P1 |
+| 果农名片(信息维护+视频+照片+审核状态) | 4 | P0 |
+| 招工发布与管理 | 5 | P0 |
+| 找工人 | 2 | P0 |
+| 找客商 | 2 | P0 |
+| 后台审核(名片审核+待复核+SLA) | 3 | P0/P1 |
 
-**总计**: 20 个功能点
+**总计**: 14 个功能点
 
 ---
 
 ## 二、功能需求
 
-### 2.1 系统管理模块
-
-#### 2.1.1 角色管理(P0)
-- **功能**: 系统预置角色(果农/工人/客商/农资商/超级管理员/数据录入员/审核员/运维人员)
-- **角色属性**: 角色名称、角色编码、权限列表、状态
-- **操作**: 查看角色列表、查看角色详情、分配权限
-- **约束**: 系统预置角色不可删除,仅可修改权限配置
-
-#### 2.1.2 账号管理(P0)
-- **功能**: 后台管理员账号的增删改查
-- **账号属性**: 用户名、密码(BCrypt加密)、姓名、手机号、角色、状态
-- **操作**: 创建账号、编辑账号、启用/禁用、重置密码
-- **约束**: 
-  - 用户名唯一
-  - 手机号唯一
-  - 密码强度:≥8位,含大小写字母和数字
-  - 禁用后不可登录
-
-#### 2.1.3 权限管理(P0)
-- **功能**: 基于 RBAC 的权限控制
-- **权限模型**: 用户 → 角色 → 权限(菜单+按钮)
-- **菜单结构**: 
-  - 系统管理(角色管理、账号管理、字典管理、操作日志)
-  - 用户管理(果农管理、工人管理、客商管理、农资商管理)
-  - 内容审核(招工审核、货源审核、投诉处理)
-  - 数据统计(数据大屏、报表导出)
-- **约束**: 
-  - 默认拒绝,显式授权
-  - 超级管理员拥有全部权限
-  - 权限变更实时生效
-
-#### 2.1.4 字典管理(P1)
-- **功能**: 系统字典数据的维护
-- **字典类型**: 
-  - 苹果品种(红富士/嘎啦/花牛/秦冠/其他)
-  - 工种类型(采摘/套袋/搬运/装卸/其他)
-  - 农资种类(化肥/果袋/反光膜/选果机/农药)
-  - 行政区划(洒渔镇下辖村)
-  - 审核状态(待审/已通过/被驳回)
-  - 用户状态(正常/禁用/锁定)
-- **操作**: 查看字典列表、新增字典项、编辑字典项、删除字典项
-- **约束**: 
-  - 字典编码唯一
-  - 系统内置字典不可删除
-  - 字典变更记录操作日志
-
-#### 2.1.5 操作日志(P1)
-- **功能**: 记录管理员的操作行为
-- **日志内容**: 操作人、操作时间、操作类型、操作模块、操作内容、IP地址、操作结果
-- **操作**: 查看日志列表、按条件筛选、导出日志
-- **约束**: 
-  - 日志只增不删
-  - 保留期限:≥180天
-  - 敏感操作(删除、权限变更)必须记录
-
-#### 2.1.6 数据字典初始化(P0)
-- **功能**: 系统初始化时导入基础字典数据
-- **数据内容**: 
-  - 苹果品种:红富士、嘎啦、花牛、秦冠、青苹果、其他
-  - 工种类型:采摘、套袋、搬运、装卸、修剪、其他
-  - 农资种类:化肥、果袋、反光膜、选果机、农药、其他
-  - 行政区划:洒渔镇下辖村(需实际数据)
-- **约束**: 初始化数据不可删除,仅可扩展
+### 2.1 果农名片模块
+
+#### 2.1.1 名片信息维护(P0)
+- **功能**: 果农编辑和完善个人名片信息
+- **字段**:
+  - 苹果品种(多选,字典:红富士/嘎啦/花牛/青冠/国光/金帅)
+  - 产量(斤,DECIMAL(10,2))
+  - 预期价格(元/斤,DECIMAL(8,2))
+  - 果园地址(文本,≤200字)
+  - 经纬度(地理编码后存储,DECIMAL(10,7))
+- **操作**: GET 获取档案 / PUT 更新档案
+- **接口**: `/api/wx/grower/profile`
+- **约束**:
+  - 仅果农身份可操作
+  - 品种为JSON数组存储
+  - 地址变更时需重新地理编码
+
+#### 2.1.2 视频上传(P0)
+- **功能**: 果农上传果园展示视频
+- **上传流程(3步)**:
+  1. **前端预处理**: 清除EXIF元数据 → 预校验格式/大小
+  2. **后端接收存储**: 调用上传API → 存储到本地 `./uploads/video/` 目录
+  3. **异步压缩**: 后端异步压缩为720p/2Mbps/≤5分钟
+- **限制**:
+  - 文件大小:≤50MB
+  - 格式:MP4、MOV
+  - 分辨率:压缩至720p
+  - 码率:压缩至2Mbps
+  - 时长:≤5分钟
+- **接口**: `/api/wx/file/upload/video`(已实现)
+- **存储**: 本地文件存储,数据库存URL
+- **约束**:
+  - 前端必须清除EXIF(防止位置信息泄露)
+  - 压缩失败有重试机制
+  - 仅允许上传1个视频
+
+#### 2.1.3 照片上传(P0)
+- **功能**: 果农上传果园照片
+- **限制**:
+  - 数量:≤9张
+  - 单张大小:≤5MB
+  - 格式:JPG、JPEG、PNG、GIF
+- **接口**: `/api/wx/file/upload/image`(已实现)
+- **存储**: 本地文件存储,URL以JSON数组存入 `grower_profile.photos`
+- **约束**:
+  - 前端清除EXIF
+  - 支持删除已上传照片
+
+#### 2.1.4 审核状态查看(P0)
+- **功能**: 果农查看名片审核状态
+- **状态流转**: 待审(0) → 已通过(1) / 被驳回(2)
+- **展示**:
+  - 待审:显示"审核中"
+  - 已通过:显示"已通过",名片对外可见
+  - 被驳回:显示"已驳回" + 驳回原因
+- **约束**:
+  - 驳回后可修改重新提交
+  - 重新提交后状态重置为"待审"
 
 ---
 
-### 2.2 用户注册与认证
-
-#### 2.2.1 微信登录(P0)
-- **流程**: 
-  1. 小程序端调用 `wx.login()` 获取 code
-  2. 后端用 code 换取 openid
-  3. 查询 openid 是否已绑定用户
-  4. 已绑定 → 签发 JWT token
-  5. 未绑定 → 返回提示"未找到信息,请联系村委会"
-- **Token 结构**: 
-  - payload: userId, identityId, identityType, exp
-  - 有效期: 24小时
-- **约束**: 
-  - 一个 openid 绑定一个用户
-  - Token 过期后需重新登录
-  - 登录日志记录
-
-#### 2.2.2 后台登录(P0)
-- **流程**: 
-  1. 输入用户名+密码
-  2. 验证用户名存在
-  3. 验证密码正确(BCrypt)
-  4. 验证账号状态(非禁用)
-  5. 签发 JWT token
-- **Token 结构**: 
-  - payload: userId, username, roleId, exp
-  - 有效期: 8小时
-- **约束**: 
-  - 连续5次密码错误锁定30分钟
-  - 登录日志记录
-  - 支持退出登录(Token 黑名单)
-
-#### 2.2.3 身份路由(P0)
-- **功能**: 根据用户身份数量决定跳转逻辑
-- **规则**: 
-  - 0个身份 → 提示"未找到信息,请联系村委会"
-  - 1个身份 → 直接进入对应首页
-  - N个身份 → 身份选择页(大卡片列表,≥120px高度)
-- **约束**: 
-  - 身份选择后记录到 Token
-  - 支持切换身份(重新选择)
-
-#### 2.2.4 用户信息查询(P0)
-- **功能**: 查询当前登录用户的基本信息
-- **返回**: 用户ID、姓名、手机号(脱敏)、身份列表、当前身份
-- **约束**: 
-  - 手机号脱敏显示(138****8888)
-  - 仅返回当前身份相关的信息
-
-#### 2.2.5 用户状态管理(P0)
-- **功能**: 管理员管理用户账号状态
-- **状态**: 正常、禁用、锁定
-- **操作**: 
-  - 启用:恢复正常状态
-  - 禁用:禁止登录和业务操作
-  - 锁定:因投诉等原因锁定,需人工解锁
-- **约束**: 
-  - 状态变更记录操作日志
-  - 锁定需注明原因
-
-#### 2.2.6 手机号加密存储(P0)
-- **功能**: 用户手机号 AES 加密存储
-- **方案**: 
-  - 明文手机号 → AES 加密 → 存储
-  - 明文手机号 → SHA256 → phone_hash(唯一索引)
-  - 查询时通过 phone_hash 匹配
-- **约束**: 
-  - AES 密钥配置在 application.properties
-  - phone_hash 唯一索引
-  - 接口返回时脱敏显示
-
-#### 2.2.7 身份绑定(P0)
-- **功能**: 管理员为用户绑定身份
-- **身份类型**: 果农、工人、客商、农资商
-- **绑定信息**: 
-  - 果农:果园地址、苹果品种、产量
-  - 工人:工种、技能、报价
-  - 客商:公司名称、收购品种、收购量
-  - 农资商:店铺名称、主营产品
-- **约束**: 
-  - 一个用户可绑定多个身份
-  - 每个身份独立管理
-  - 身份信息变更需审核
-
-#### 2.2.8 管理员创建用户(P0)
-- **功能**: 后台管理员创建用户账号
-- **流程**: 
-  1. 填写用户基本信息(姓名、手机号)
-  2. 选择身份类型
-  3. 填写身份详细信息
-  4. 创建成功后通知用户(短信)
-- **约束**: 
-  - 手机号唯一
-  - 创建后需用户首次登录激活
-  - 记录操作日志
+### 2.2 招工发布与管理模块
+
+#### 2.2.1 发布招工(P0)
+- **功能**: 果农发布招工需求
+- **表单字段**:
+  - 工种(多选,字典:采摘工/分拣工/装卸工/喷药工/修剪工/施肥工)
+  - 价格(DECIMAL(8,2))
+  - 价格单位(元/天 | 元/个)
+  - 需要人数(INT)
+  - 天数(INT)
+  - 工作地点(文本)
+  - 经纬度(地理编码)
+  - 备注(≤500字,支持语音输入)
+- **发布规则**: 免审核直接发布(status=1)
+- **接口**: `POST /api/wx/grower/recruit`
+- **约束**:
+  - 仅果农身份可发布
+  - 必填字段:工种、价格、价格单位、人数、工作地点
+  - 语音输入转文字后存入备注
+
+#### 2.2.2 敏感关键词检测(P0)
+- **功能**: 发布时自动检测敏感关键词
+- **检测机制**:
+  - 正则匹配敏感词库(色情/赌博/政治等明确违规词)
+  - 检测到敏感词 → `keyword_flag=1`,进入待复核列表
+  - 不阻塞发布,招工信息仍然可见
+- **约束**:
+  - 初始词库硬编码,后续可扩展
+  - 审核员定时处理待复核列表
+  - 误判可通过后台标记为正常
+
+#### 2.2.3 招工编辑(P1)
+- **功能**: 果农编辑已发布的招工信息
+- **可编辑字段**: 价格、人数、天数、备注
+- **接口**: `PUT /api/wx/grower/recruit/{id}`
+- **约束**:
+  - 仅可编辑自己发布的招工
+  - 编辑后如含敏感词,重新触发检测
+
+#### 2.2.4 招工下架(P0)
+- **功能**: 果农下架已发布的招工
+- **接口**: `DELETE /api/wx/grower/recruit/{id}`(逻辑删除,status=0)
+- **约束**:
+  - 仅可下架自己发布的招工
+  - 下架后工人不可见
+
+#### 2.2.5 我的招工列表(P1)
+- **功能**: 果农查看自己发布的招工历史
+- **展示**: 工种、价格、人数、发布时间、状态、报名人数
+- **接口**: `GET /api/wx/grower/recruit`
+- **约束**:
+  - 按发布时间倒序
+  - 支持分页
 
 ---
 
-### 2.3 首页与行情展示
-
-#### 2.3.1 果农首页(P0)
-- **布局**: 
-  - 顶部:问候语"早安,[姓名]!" + 当地实时天气
-  - 中部:今日行情(苹果品种收购价格区间,涨价红/降价绿色块)
-  - 底部:金刚区(4个核心入口:找工人、找客商、买农资、发布需求)
-- **数据来源**: 
-  - 行情数据:market_price 表
-  - 天气数据:第三方 API(可选)
-- **约束**: 
-  - 行情数据每日更新
-  - 展示更新时间
-
-#### 2.3.2 工人首页(P0)
-- **布局**: 
-  - 顶部:推荐招工(工种匹配+距离排序)
-  - 中部:附近招工卡片列表
-  - 底部:我的报名、个人档案
-- **数据来源**: recruit_info 表
-- **约束**: 
-  - 按距离排序
-  - 展示工种、价格、天数、人数、果农姓名、距离
-
-#### 2.3.3 客商首页(P0)
-- **布局**: 
-  - 顶部:今日行情
-  - 中部:货源推荐(品种匹配+产量排序)
-  - 底部:我的联系、收藏
-- **数据来源**: grower_profile 表、market_price 表
-- **约束**: 
-  - 按品种匹配推荐
-  - 展示品种、产量、预期价格、果园地址
-
-#### 2.3.4 农资商首页(P1)
-- **布局**: 
-  - 顶部:店铺概览
-  - 中部:商品管理入口
-  - 底部:订单管理、店铺设置
-- **数据来源**: supplier_shop 表
-- **约束**: 
-  - 展示店铺基本信息
-  - 快捷入口
+### 2.3 找工人模块
+
+#### 2.3.1 工人列表(P0)
+- **功能**: 果农查找附近空闲工人
+- **筛选**: 工种(单选)
+- **列表展示**: 工人姓名、工种标签、报价(元/天或元/个)、距离(km)、状态(空闲/忙碌)
+- **排序**: 按距离升序
+- **接口**: `GET /api/wx/grower/workers`
+- **距离计算**:
+  - 果园地址 → 地理编码 → 经纬度存储
+  - 查询时使用 Haversine 公式计算距离
+  - 经纬度精确到小数点后7位
+- **约束**:
+  - 仅显示状态为"空闲"的工人
+  - 返回距离(km,保留1位小数)
+  - 分页查询,每页20条
+
+#### 2.3.2 一键拨号(P0)
+- **功能**: 果农点击工人电话按钮拨号
+- **流程**:
+  1. 调用 `/api/wx/call/phone` 获取手机号
+  2. 后端记录拨号日志(call_log表)
+  3. 返回脱敏手机号,前端唤起系统拨号
+- **约束**:
+  - 拨号日志记录:拨号方ID、被拨方ID、拨号时间
+  - 手机号通过单独接口获取(不在列表中直接返回)
 
 ---
 
-### 2.4 审核基础框架
-
-#### 2.4.1 审核流程(P0)
-- **功能**: 通用审核流程框架
-- **审核对象**: 果农档案、工人档案、客商档案、招工信息、货源信息
-- **审核状态**: 待审、已通过、被驳回
-- **审核操作**: 
-  - 通过:更新状态为已通过
-  - 驳回:更新状态为被驳回,填写驳回原因
-- **约束**: 
-  - 审核记录操作日志
-  - 驳回需注明原因
-  - 审核 SLA:≤24小时提醒,48小时升级
-
-#### 2.4.2 审核列表(P1)
-- **功能**: 审核员查看待审核列表
-- **筛选**: 审核类型、状态、时间范围
-- **排序**: 按提交时间倒序
-- **约束**: 
-  - 仅审核员和超级管理员可访问
-  - 展示待审核数量
+### 2.4 找客商模块
+
+#### 2.4.1 客商列表(P0)
+- **功能**: 果农查找收购客商
+- **列表展示**: 客商姓名/公司名、收购品种、收购价格区间、收购数量、收购点地址
+- **接口**: `GET /api/wx/grower/buyers`
+- **约束**:
+  - 展示客商基本信息
+  - 分页查询
+
+#### 2.4.2 一键拨号(P0)
+- **功能**: 果农点击客商电话按钮拨号
+- **流程**: 同找工人拨号流程
+- **约束**:
+  - 记录拨号日志
+  - 手机号脱敏
+
+---
+
+### 2.5 后台审核模块
+
+#### 2.5.1 名片审核(P0)
+- **功能**: 审核员审核果农名片
+- **审核内容**: 视频内容、照片内容、信息真实性
+- **操作**: 通过 / 驳回(需填原因)
+- **接口**:
+  - `GET /api/admin/audit/grower-profile` — 审核列表
+  - `PUT /api/admin/audit/grower-profile/{id}` — 审核操作
+- **约束**:
+  - 仅审核员和超级管理员可操作
+  - 驳回必须填写原因
+  - 审核结果通知果农
+
+#### 2.5.2 待复核列表(P0)
+- **功能**: 审核员处理敏感关键词标记的招工
+- **展示**: 招工内容、标记关键词、发布者、发布时间
+- **操作**: 标记为正常 / 强制下架
+- **接口**:
+  - `GET /api/admin/audit/recruit-review` — 待复核列表
+  - `PUT /api/admin/audit/recruit-review/{id}` — 处理操作
+- **约束**:
+  - 仅审核员和超级管理员可操作
+  - 强制下架需填写原因
+
+#### 2.5.3 审核SLA提醒(P1)
+- **功能**: 审核超时自动提醒
+- **规则**:
+  - 待审核超过24小时 → 提醒审核员
+  - 待审核超过48小时 → 升级提醒超级管理员
+- **实现**: 定时任务扫描,短信/站内信通知
+- **约束**:
+  - 仅提醒未处理的审核项
+  - 每个审核项最多提醒3次
 
 ---
 
 ## 三、非功能需求
 
 ### 3.1 性能需求
-- 接口响应时间:≤500ms(95%请求)
-- 并发用户数:≥100
-- 数据库连接池:最大连接数 20
+- 文件上传:≤50MB文件,上传时间≤30s(局域网环境
+- 列表查询:≤500ms(含距离计算)
+- 视频压缩:异步处理,不影响用户操作
 
 ### 3.2 安全需求
-- 手机号 AES 加密存储
-- 密码 BCrypt 加密
-- JWT Token 认证
-- RBAC 权限控制
-- 接口防重放攻击
-- SQL 注入防护(MyBatis #{})
+- 视频/照片上传:格式白名单校验,防止恶意文件
+- 敏感词检测:防止色情/赌博/政治违规内容
+- 手机号保护:拨号接口单独获取,列表不返回
+- EXIF清除:防止位置信息泄露
 
 ### 3.3 可用性需求
-- 系统可用性:≥99%
-- 数据备份:每日全量备份
-- 故障恢复:≤4小时
-
-### 3.4 兼容性需求
-- 微信小程序:基础库 ≥2.0
-- 后台管理:Chrome/Firefox/Edge 最新版
-- 适老化:正文≥18px(rem)、按钮≥88×88px
+- 视频压缩失败:自动重试3次
+- 文件上传失败:支持重新上传
+- 网络中断:前端提示重试
+
+---
+
+## 四、数据模型(阶段2a涉及)
+
+### 4.1 已有表(需扩展使用)
+
+| 表名 | 阶段2a用途 |
+|------|-----------|
+| grower_profile | 果农档案CRUD |
+| recruit_info | 招工信息CRUD |
+| worker_profile | 工人列表查询 |
+| buyer_profile | 客商列表查询 |
+| call_log | 拨号日志记录 |
+| audit_log | 审核日志记录 |
+
+### 4.2 关键字段说明
+
+**grower_profile**:
+- `varieties`: JSON数组,如 `["红富士","嘎啦"]`
+- `photos`: JSON数组,如 `["http://localhost:8080/files/image/xxx.jpg"]`
+- `video_url`: 单个URL
+- `latitude`/`longitude`: DECIMAL(10,7),用于距离计算
+
+**recruit_info**:
+- `work_types`: JSON数组,如 `["采摘工","分拣工"]`
+- `keyword_flag`: 0正常/1待复核
+- `status`: 0下架/1发布中

+ 386 - 202
deliveries/team-a-requirement/use-cases.md

@@ -1,390 +1,573 @@
-# 阶段一用例文档 — 基础设施与用户体系
+# 阶段2a用例文档 — 果农核心功能
 
-> 功能点覆盖:20/20
+> 功能点覆盖:14/14
+> 用例数:32
 
 ---
 
-## 一、系统管理用例
+## 一、果农名篇用例
 
-### UC-SYS-001: 角色管理
+### UC-GP-001: 查看名片信息
 
-**主要参与者**: 超级管理员
+**主要参与者**: 果农用户
 
-**前置条件**: 已登录后台管理系统
+**前置条件**: 已登录,身份为果农
 
 **基本流程**:
-1. 管理员进入系统管理 → 角色管理
-2. 系统显示角色列表(角色名称、编码、状态、创建时间)
-3. 管理员点击某个角色查看详情
-4. 系统显示角色详情(权限列表)
-5. 管理员修改权限配置
-6. 系统保存权限变更
-7. 系统记录操作日志
+1. 果农进入"我的名片"页面
+2. 系统查询 grower_profile 表
+3. 系统展示名片信息:品种、产量、预期价格、果园地址、视频、照片、审核状态
 
 **替代流程**:
-- 3a. 管理员搜索角色 → 按名称筛选
-- 5a. 管理员尝试删除系统预置角色 → 系统提示"系统预置角色不可删除"
+- 2a. 名片未完善 → 显示引导页,提示完善信息
 
-**后置条件**: 角色权限已更新,操作日志已记录
+**后置条件**: 无数据变更
 
 ---
 
-### UC-SYS-002: 账号管理
+### UC-GP-002: 编辑名片信息
 
-**主要参与者**: 超级管理员
+**主要参与者**: 果农用户
 
-**前置条件**: 已登录后台管理系统
+**前置条件**: 已登录,身份为果农
 
 **基本流程**:
-1. 管理员进入系统管理 → 账号管理
-2. 系统显示账号列表(用户名、姓名、手机号、角色、状态
-3. 管理员点击"新增账号"
-4. 管理员填写:用户名、密码、姓名、手机号、角色
-5. 系统验证:用户名唯一、手机号唯一、密码强度
-6. 系统创建账号(密码 BCrypt 加密)
-7. 系统记录操作日志
+1. 果农点击"编辑名片"
+2. 系统显示编辑表单(品种多选、产量、价格、地址
+3. 果农修改信息
+4. 果农点击"保存"
+5. 系统验证数据(品种非空、价格>0、地址非空)
+6. 系统更新 grower_profile 表
+7. 系统重置审核状态为"待审"
 
 **替代流程**:
-- 5a. 用户名已存在 → 提示"用户名已存在"
-- 5b. 手机号已存在 → 提示"手机号已注册"
-- 5c. 密码强度不足 → 提示"密码需≥8位,含大小写字母和数字"
+- 5a. 必填字段为空 → 提示"请填写完整信息"
+- 5b. 价格≤0 → 提示"价格必须大于0"
 
-**后置条件**: 账号已创建,可正常登录
+**后置条件**: 名片信息已更新,审核状态重置为待审
 
 ---
 
-### UC-SYS-003: 字典管理
+### UC-GP-003: 上传果园视频
 
-**主要参与者**: 超级管理员、数据录入员
+**主要参与者**: 果农用户
 
-**前置条件**: 已登录后台管理系统
+**前置条件**: 已登录,身份为果农
 
 **基本流程**:
-1. 管理员进入系统管理 → 字典管理
-2. 系统显示字典类型列表
-3. 管理员选择某个字典类型(如"苹果品种")
-4. 系统显示该类型下的字典项列表
-5. 管理员点击"新增字典项"
-6. 管理员填写:字典编码、字典名称、排序号
-7. 系统验证:字典编码唯一
-8. 系统创建字典项
-9. 系统记录操作日志
+1. 果农在名片编辑页点击"上传视频"
+2. 前端调用 `wx.chooseVideo()` 选择视频
+3. 前端清除EXIF元数据
+4. 前端预校验:格式(MP4/MOV)、大小(≤50MB)
+5. 前端调用 `/api/wx/file/upload/video` 上传
+6. 后端校验文件格式和大小
+7. 后端存储到 `./uploads/video/` 目录
+8. 后端返回文件URL
+9. 前端更新名片视频URL
+10. 后端异步压缩视频(720p/2Mbps)
 
 **替代流程**:
-- 7a. 字典编码已存在 → 提示"字典编码已存在"
-- 5a. 管理员尝试删除系统内置字典 → 提示"系统内置字典不可删除"
+- 4a. 格式不支持 → 提示"仅支持MP4/MOV格式"
+- 4b. 文件过大 → 提示"视频大小不能超过50MB"
+- 5a. 网络中断 → 提示"上传失败,请重试"
+- 10a. 压缩失败 → 自动重试3次,仍失败记录日志
 
-**后置条件**: 字典项已创建,可在业务中使用
+**后置条件**: 视频已上传,URL已存入 grower_profile.video_url
 
 ---
 
-### UC-SYS-004: 操作日志查看
+### UC-GP-004: 上传果园照片
 
-**主要参与者**: 超级管理员
+**主要参与者**: 果农用户
 
-**前置条件**: 已登录后台管理系统
+**前置条件**: 已登录,身份为果农
 
 **基本流程**:
-1. 管理员进入系统管理 → 操作日志
-2. 系统显示操作日志列表(操作人、时间、类型、模块、内容、IP、结果)
-3. 管理员按条件筛选(操作人、时间范围、操作类型)
-4. 系统显示筛选结果
-5. 管理员点击某条日志查看详情
-6. 系统显示日志详情
+1. 果农在名片编辑页点击"上传照片"
+2. 前端调用 `wx.chooseImage()` 选择照片(≤9张)
+3. 前端清除EXIF元数据
+4. 前端预校验:格式(JPG/JPEG/PNG/GIF)、单张大小(≤5MB)
+5. 前端逐张调用 `/api/wx/file/upload/image` 上传
+6. 后端存储到 `./uploads/image/` 目录
+7. 后端返回文件URL列表
+8. 前端更新名片照片列表
 
 **替代流程**:
-- 3a. 管理员导出日志 → 系统生成 Excel 文件
+- 2a. 已有9张照片 → 提示"最多上传9张照片"
+- 4a. 单张过大 → 提示"单张照片不能超过5MB"
+- 5a. 部分上传失败 → 提示失败数量,支持重新上传
+
+**后置条件**: 照片URL已存入 grower_profile.photos(JSON数组)
+
+---
+
+### UC-GP-005: 删除已上传照片
+
+**主要参与者**: 果农用户
+
+**前置条件**: 已登录,身份为果农,已有照片
+
+**基本流程**:
+1. 果农在名片编辑页查看照片列表
+2. 果农点击某张照片的"删除"按钮
+3. 系统弹出确认框
+4. 果农确认删除
+5. 系统调用 `/api/wx/file/delete` 删除文件
+6. 系统更新 grower_profile.photos,移除对应URL
+
+**替代流程**:
+- 4a. 果农取消 → 不执行删除
+
+**后置条件**: 照片已删除,URL已从数据库移除
+
+---
+
+### UC-GP-006: 查看审核状态
+
+**主要参与者**: 果农用户
+
+**前置条件**: 已登录,身份为果农,已提交名片
+
+**基本流程**:
+1. 果农进入"我的名片"页面
+2. 系统查询 audit_status 字段
+3. 系统展示审核状态:
+   - 待审(0) → 显示"审核中"
+   - 已通过(1) → 显示"已通过"
+   - 被驳回(2) → 显示"已驳回" + 驳回原因
+
+**替代流程**: 无
 
 **后置条件**: 无数据变更
 
 ---
 
-## 二、用户认证用例
+### UC-GP-007: 驳回后重新提交
 
-### UC-AUTH-001: 微信登录
+**主要参与者**: 果农用户
+
+**前置条件**: 已登录,身份为果农,名片被驳回
+
+**基本流程**:
+1. 果农查看驳回原因
+2. 果农修改名片信息/更换视频照片
+3. 果农点击"重新提交"
+4. 系统重置审核状态为"待审(0)"
+5. 系统清除驳回原因
+
+**替代流程**: 无
+
+**后置条件**: 审核状态重置为待审
+
+---
 
-**主要参与者**: 小程序用户
+## 二、招工发布用例
 
-**前置条件**: 用户已安装微信
+### UC-RC-001: 发布招工信息
+
+**主要参与者**: 果农用户
+
+**前置条件**: 已登录,身份为果农
 
 **基本流程**:
-1. 用户打开小程序
-2. 小程序调用 `wx.login()` 获取 code
-3. 小程序将 code 发送到后端
-4. 后端用 code 调用微信接口换取 openid
-5. 后端查询 openid 是否已绑定用户
-6. 已绑定 → 后端签发 JWT token,返回用户信息
-7. 小程序存储 token,进入首页
+1. 果农点击"发布招工"
+2. 系统显示招工表单
+3. 果农填写:工种(多选)、价格、价格单位、人数、天数、工作地点、备注
+4. 果农点击"发布"
+5. 系统验证必填字段(工种、价格、价格单位、人数、工作地点)
+6. 系统检测敏感关键词
+7. 如无敏感词 → keyword_flag=0
+8. 如有敏感词 → keyword_flag=1
+9. 系统创建 recruit_info 记录(status=1,免审核直接发布)
+10. 系统提示"发布成功"
 
 **替代流程**:
-- 5a. 未绑定 → 返回提示"未找到信息,请联系村委会"
-- 6a. 用户有多个身份 → 返回身份列表,用户选择后进入对应首页
+- 5a. 必填字段为空 → 提示"请填写完整信息"
+- 5b. 价格≤0 → 提示"价格必须大于0"
+- 5c. 人数≤0 → 提示"人数必须大于0"
 
-**后置条件**: 用户已登录,token 已存储
+**后置条件**: 招工信息已发布,工人可见
 
 ---
 
-### UC-AUTH-002: 后台登录
+### UC-RC-002: 语音输入备注
 
-**主要参与者**: 后台管理员
+**主要参与者**: 果农用户
 
-**前置条件**: 已打开后台管理系统
+**前置条件**: 正在编辑招工表单
 
 **基本流程**:
-1. 管理员输入用户名和密码
-2. 点击"登录"
-3. 系统验证用户名存在
-4. 系统验证密码正确(BCrypt)
-5. 系统验证账号状态(非禁用)
-6. 系统签发 JWT token
-7. 系统记录登录日志
-8. 管理员进入后台首页
+1. 果农点击备注输入框旁的麦克风图标
+2. 前端调用语音识别API
+3. 果农说话
+4. 前端将语音转为文字
+5. 文字自动填入备注输入框
+6. 果农可手动修改识别结果
 
 **替代流程**:
-- 3a. 用户名不存在 → 提示"用户名或密码错误"
-- 4a. 密码错误 → 提示"用户名或密码错误",记录错误次数
-- 4b. 连续5次错误 → 锁定30分钟,提示"账号已锁定,请30分钟后重试"
-- 5a. 账号已禁用 → 提示"账号已禁用,请联系管理员"
+- 2a. 语音识别失败 → 提示"识别失败,请手动输入"
+- 3a. 环境噪音过大 → 提示"请到安静环境重试"
 
-**后置条件**: 管理员已登录,token 已存储
+**后置条件**: 备注已填入
 
 ---
 
-### UC-AUTH-003: 身份路由
+### UC-RC-003: 编辑招工信息
 
-**主要参与者**: 小程序用户
+**主要参与者**: 果农用户
 
-**前置条件**: 用户已登录
+**前置条件**: 已登录,身份为果农,已有发布的招工
 
 **基本流程**:
-1. 用户登录成功
-2. 系统查询用户绑定的身份数量
-3. 根据身份数量决定跳转:
-   - 0个身份 → 显示提示页"未找到信息,请联系村委会"
-   - 1个身份 → 直接进入对应首页
-   - N个身份 → 显示身份选择页
+1. 果农进入"我的招工"列表
+2. 果农选择某条招工,点击"编辑"
+3. 系统显示编辑表单(价格、人数、天数、备注可编辑)
+4. 果农修改信息
+5. 果农点击"保存"
+6. 系统验证数据
+7. 系统检测敏感关键词
+8. 系统更新 recruit_info 记录
 
 **替代流程**:
-- 3a. 用户选择身份 → 进入对应首页
-- 3b. 用户拒绝授权 → 显示引导页,提供联系管理员方式
+- 6a. 数据验证失败 → 提示错误信息
 
-**后置条件**: 用户已进入对应角色首页
+**后置条件**: 招工信息已更新
 
 ---
 
-### UC-AUTH-004: 用户信息查询
+### UC-RC-004: 下架招工信息
 
-**主要参与者**: 已登录用户
+**主要参与者**: 果农用户
 
-**前置条件**: 用户已登录
+**前置条件**: 已登录,身份为果农,已有发布的招工
 
 **基本流程**:
-1. 用户进入个人中心
-2. 系统查询用户基本信息
-3. 系统返回:用户ID、姓名、手机号(脱敏)、身份列表、当前身份
+1. 果农进入"我的招工"列表
+2. 果农选择某条招工,点击"下架"
+3. 系统弹出确认框
+4. 果农确认下架
+5. 系统更新 recruit_info.status=0
+6. 系统提示"已下架"
 
-**替代流程**: 无
+**替代流程**:
+- 4a. 果农取消 → 不执行下架
 
-**后置条件**: 无数据变更
+**后置条件**: 招工已下架,工人不可见
 
 ---
 
-### UC-AUTH-005: 用户状态管理
+### UC-RC-005: 查看我的招工列表
 
-**主要参与者**: 超级管理员
+**主要参与者**: 果农用户
 
-**前置条件**: 已登录后台管理系统
+**前置条件**: 已登录,身份为果农
 
 **基本流程**:
-1. 管理员进入用户管理 → 用户列表
-2. 管理员选择某个用户
-3. 管理员修改用户状态(启用/禁用/锁定)
-4. 系统验证操作合法性
-5. 系统更新用户状态
-6. 系统记录操作日志
+1. 果农进入"我的招工"页面
+2. 系统查询该果农发布的所有招工
+3. 系统按发布时间倒序展示
+4. 展示:工种、价格、人数、发布时间、状态、报名人数
+5. 果农可下拉刷新、上拉加载更多
 
 **替代流程**:
-- 4a. 尝试禁用超级管理员 → 提示"不可禁用超级管理员"
-- 3a. 锁定操作 → 需填写锁定原因
+- 2a. 无招工记录 → 显示"暂无招工,去发布"
 
-**后置条件**: 用户状态已更新,操作日志已记录
+**后置条件**: 无数据变更
 
 ---
 
-### UC-AUTH-006: 管理员创建用户
+### UC-RC-006: 敏感词自动检测
 
-**主要参与者**: 超级管理员、数据录入员
+**主要参与者**: 系统(自动)
 
-**前置条件**: 已登录后台管理系统
+**前置条件**: 果农发布或编辑招工
 
 **基本流程**:
-1. 管理员进入用户管理 → 创建用户
-2. 管理员填写:姓名、手机号
-3. 管理员选择身份类型
-4. 管理员填写身份详细信息
-5. 系统验证:手机号唯一
-6. 系统创建用户账号
-7. 系统发送短信通知用户
-8. 系统记录操作日志
+1. 系统获取招工备注内容
+2. 系统使用正则表达式匹配敏感词库
+3. 匹配成功 → 设置 keyword_flag=1
+4. 匹配失败 → 设置 keyword_flag=0
+5. 记录检测结果
+
+**替代流程**: 无
+
+**后置条件**: keyword_flag 已设置
+
+---
+
+## 三、找工人用例
+
+### UC-WK-001: 查看工人列表
+
+**主要参与者**: 果农用户
+
+**前置条件**: 已登录,身份为果农
+
+**基本流程**:
+1. 果农点击"找工人"
+2. 系统查询状态为"空闲"的工人
+3. 系统按工种筛选(可选)
+4. 系统按距离升序排序
+5. 系统展示工人列表:姓名、工种标签、报价、距离、状态
+6. 果农可下拉刷新、上拉加载更多
 
 **替代流程**:
-- 5a. 手机号已存在 → 提示"手机号已注册"
+- 2a. 无空闲工人 → 显示"暂无空闲工人"
+- 3a. 选择特定工种 → 仅显示该工种工人
+
+**后置条件**: 无数据变更
+
+---
+
+### UC-WK-002: 按工种筛选工人
+
+**主要参与者**: 果农用户
 
-**后置条件**: 用户已创建,等待首次登录激活
+**前置条件**: 正在查看工人列表
+
+**基本流程**:
+1. 果农点击工种筛选按钮
+2. 系统显示工种选项(采摘工/分拣工/装卸工/喷药工/修剪工/施肥工)
+3. 果农选择工种
+4. 系统重新查询并展示筛选结果
+
+**替代流程**: 无
+
+**后置条件**: 无数据变更
 
 ---
 
-### UC-AUTH-007: 身份绑定
+### UC-WK-003: 拨打工人电话
 
-**主要参与者**: 超级管理员、数据录入员
+**主要参与者**: 果农用户
 
-**前置条件**: 已登录后台管理系统,用户已存在
+**前置条件**: 已登录,正在查看工人列表
 
 **基本流程**:
-1. 管理员进入用户管理 → 选择用户
-2. 管理员点击"绑定身份"
-3. 管理员选择身份类型
-4. 管理员填写身份详细信息
-5. 系统创建身份关联
-6. 系统记录操作日志
+1. 果农点击某工人的"拨号"按钮
+2. 前端调用 `/api/wx/call/phone` 接口
+3. 后端记录拨号日志(call_log表)
+4. 后端返回脱敏手机号(138****8888)
+5. 前端调用 `wx.makePhoneCall()` 唤起系统拨号
 
 **替代流程**:
-- 3a. 用户已有该类型身份 → 提示"用户已有该身份"
+- 3a. 接口调用失败 → 提示"获取号码失败,请重试"
+- 5a. 用户取消拨号 → 不做处理
 
-**后置条件**: 用户已绑定新身份
+**后置条件**: 拨号日志已记录
 
 ---
 
-### UC-AUTH-008: 退出登录
+### UC-WK-004: 查看工人详情
 
-**主要参与者**: 已登录用户
+**主要参与者**: 果农用户
 
-**前置条件**: 用户已登录
+**前置条件**: 正在查看工人列表
 
 **基本流程**:
-1. 用户点击"退出登录"
-2. 系统清除本地 token
-3. 系统跳转到登录页
+1. 果农点击某工人卡片
+2. 系统显示工人详情:姓名、技能标签、报价、状态、距离
+3. 显示"拨号"按钮
 
 **替代流程**: 无
 
-**后置条件**: 用户已退出,token 已清除
+**后置条件**: 无数据变更
 
 ---
 
-## 三、首页与行情用例
+## 四、找客商用例
 
-### UC-HOME-001: 果农首页展示
+### UC-BY-001: 查看客商列表
 
 **主要参与者**: 果农用户
 
 **前置条件**: 已登录,身份为果农
 
 **基本流程**:
-1. 用户进入果农首页
-2. 系统显示问候语"早安,[姓名]!"
-3. 系统显示今日行情(苹果品种、价格区间、涨跌、更新时间)
-4. 系统显示金刚区(找工人、找客商、买农资、发布需求)
+1. 果农点击"找客商"
+2. 系统查询所有客商
+3. 系统展示客商列表:姓名/公司名、收购品种、收购价格、收购数量、地址
+4. 果农可下拉刷新、上拉加载更多
 
 **替代流程**:
-- 3a. 行情数据未更新 → 显示"暂无行情数据"
+- 2a. 无客商数据 → 显示"暂无客商信息"
 
 **后置条件**: 无数据变更
 
 ---
 
-### UC-HOME-002: 工人首页展示
+### UC-BY-002: 拨打客商电话
 
-**主要参与者**: 工人用户
+**主要参与者**: 果农用户
 
-**前置条件**: 已登录,身份为工人
+**前置条件**: 已登录,正在查看客商列表
 
 **基本流程**:
-1. 用户进入工人首页
-2. 系统显示推荐招工(按工种匹配+距离排序)
-3. 系统显示招工卡片列表(工种、价格、天数、人数、果农姓名、距离)
+1. 果农点击某客商的"拨号"按钮
+2. 前端调用 `/api/wx/call/phone` 接口
+3. 后端记录拨号日志
+4. 后端返回脱敏手机号
+5. 前端唤起系统拨号
 
 **替代流程**:
-- 2a. 无匹配招工 → 显示"暂无招工信息"
+- 3a. 接口调用失败 → 提示"获取号码失败,请重试"
+
+**后置条件**: 拨号日志已记录
+
+---
+
+### UC-BY-003: 查看客商详情
+
+**主要参与者**: 果农用户
+
+**前置条件**: 正在查看客商列表
+
+**基本流程**:
+1. 果农点击某客商卡片
+2. 系统显示客商详情:公司名、收购品种、价格区间、收购标准、地址
+3. 显示"拨号"按钮
+
+**替代流程**: 无
 
 **后置条件**: 无数据变更
 
 ---
 
-### UC-HOME-003: 客商首页展示
+## 五、后台审核用例
+
+### UC-AU-001: 查看名片审核列表
 
-**主要参与者**: 客商用户
+**主要参与者**: 审核员
 
-**前置条件**: 已登录,身份为客商
+**前置条件**: 已登录后台管理系统
 
 **基本流程**:
-1. 用户进入客商首页
-2. 系统显示今日行情
-3. 系统显示货源推荐(按品种匹配+产量排序)
+1. 审核员进入"内容审核" → "名片审核"
+2. 系统查询 audit_status=0 的果农档案
+3. 系统按提交时间倒序展示
+4. 展示:果农姓名、品种、提交时间、审核状态
+5. 系统显示待审核数量角标
 
 **替代流程**:
-- 3a. 无匹配货源 → 显示"暂无货源信息"
+- 2a. 无待审核项 → 显示"暂无待审核"
 
 **后置条件**: 无数据变更
 
 ---
 
-### UC-HOME-004: 农资商首页展示
+### UC-AU-002: 审核果农名片
 
-**主要参与者**: 农资商用户
+**主要参与者**: 审核员
 
-**前置条件**: 已登录,身份为农资商
+**前置条件**: 已登录后台管理系统,有待审核名片
 
 **基本流程**:
-1. 用户进入农资商首页
-2. 系统显示店铺概览
-3. 系统显示快捷入口(商品管理、订单管理、店铺设置)
+1. 审核员选择某条待审核名片
+2. 系统显示名片详情(视频、照片、信息)
+3. 审核员审核内容
+4. 审核员点击"通过"或"驳回"
+5. 如驳回 → 填写驳回原因(必填)
+6. 系统更新 grower_profile.audit_status
+7. 系统记录审核日志(audit_log表)
+8. 系统通知果农审核结果
 
 **替代流程**:
-- 2a. 店铺未完善 → 显示引导完善店铺信息
+- 5a. 驳回但未填原因 → 提示"请填写驳回原因"
 
-**后置条件**: 无数据变更
+**后置条件**: 审核状态已更新,审核日志已记录
 
 ---
 
-## 四、审核用例
+### UC-AU-003: 查看待复核招工列表
 
-### UC-AUDIT-001: 审核流程
+**主要参与者**: 审核员
+
+**前置条件**: 已登录后台管理系统
+
+**基本流程**:
+1. 审核员进入"内容审核" → "待复核列表"
+2. 系统查询 keyword_flag=1 的招工信息
+3. 系统按发布时间倒序展示
+4. 展示:招工内容、标记关键词、发布者、发布时间
+5. 系统显示待复核数量角标
+
+**替代流程**:
+- 2a. 无待复核项 → 显示"暂无待复核"
+
+**后置条件**: 无数据变更
+
+---
+
+### UC-AU-004: 处理待复核招工
 
 **主要参与者**: 审核员
 
-**前置条件**: 已登录后台管理系统,有待审核项
+**前置条件**: 已登录后台管理系统,有待复核招工
 
 **基本流程**:
-1. 审核员进入内容审核 → 待审核列表
-2. 系统显示待审核列表(审核类型、提交人、提交时间)
-3. 审核员选择某项查看详情
-4. 系统显示审核详情(内容、附件)
-5. 审核员点击"通过"或"驳回"
-6. 如驳回,填写驳回原因
-7. 系统更新审核状态
-8. 系统记录审核日志
-9. 系统通知提交人审核结果
+1. 审核员选择某条待复核招工
+2. 系统显示招工详情和标记的敏感词
+3. 审核员判断内容是否违规
+4. 如正常 → 点击"标记为正常",keyword_flag=0
+5. 如违规 → 点击"强制下架",填写原因,status=0
+6. 系统记录审核日志
+7. 系统通知发布者
 
 **替代流程**:
-- 5a. 审核员点击"驳回" → 必须填写驳回原因
+- 5a. 未填下架原因 → 提示"请填写下架原因"
+
+**后置条件**: 招工状态已更新,审核日志已记录
+
+---
+
+### UC-AU-005: 审核SLA提醒(24小时)
 
-**后置条件**: 审核状态已更新,通知已发送
+**主要参与者**: 系统(定时任务)
+
+**前置条件**: 有待审核项超过24小时
+
+**基本流程**:
+1. 定时任务每小时扫描一次
+2. 查询创建时间超过24小时且未处理的审核项
+3. 系统发送提醒通知给对应审核员
+4. 记录提醒日志
+
+**替代流程**: 无
+
+**后置条件**: 提醒已发送
 
 ---
 
-### UC-AUDIT-002: 审核列表查看
+### UC-AU-006: 审核SLA升级(48小时)
+
+**主要参与者**: 系统(定时任务)
+
+**前置条件**: 有待审核项超过48小时
+
+**基本流程**:
+1. 定时任务每小时扫描一次
+2. 查询创建时间超过48小时且未处理的审核项
+3. 系统发送升级提醒给超级管理员
+4. 记录提醒日志
+
+**替代流程**: 无
+
+**后置条件**: 升级提醒已发送
+
+---
+
+### UC-AU-007: 后台查看招工巡查列表
 
 **主要参与者**: 审核员、超级管理员
 
 **前置条件**: 已登录后台管理系统
 
 **基本流程**:
-1. 审核员进入内容审核
-2. 系统显示审核列表(待审核/已审核 Tab)
-3. 审核员按条件筛选(审核类型、状态、时间范围)
-4. 系统显示筛选结果
-5. 系统显示待审核数量角标
+1. 管理员进入"内容审核" → "招工巡查"
+2. 系统查询所有招工信息(含已下架
+3. 系统按发布时间倒序展示
+4. 管理员可筛选:状态、关键词标记、时间范围
+5. 管理员可强制下架违规内容
 
 **替代流程**: 无
 
@@ -396,8 +579,9 @@
 
 | 模块 | 用例数 | 功能点覆盖 |
 |------|--------|-----------|
-| 系统管理 | 4 | 6/6 |
-| 用户认证 | 8 | 8/8 |
-| 首页与行情 | 4 | 4/4 |
-| 审核框架 | 2 | 2/2 |
-| **总计** | **18** | **20/20** |
+| 果农名片 | 7 | 4/4 |
+| 招工发布 | 6 | 5/5 |
+| 找工人 | 4 | 2/2 |
+| 找客商 | 3 | 2/2 |
+| 后台审核 | 7 | 3/3 |
+| **总计** | **32** | **14/14** |

+ 74 - 46
deliveries/team-b-architecture/DELIVERY-MANIFEST.md

@@ -1,84 +1,110 @@
 # 交付清单 — Team B 架构师
 
 ## 里程碑信息
-- **阶段**: 架构设计
-- **里程碑编号**: milestone-2
-- **提交时间**: 2026-05-30 18:00
+- **阶段**: 阶段2a 果农核心功能
+- **里程碑编号**: milestone-2(架构设计)
+- **提交时间**: 2026-05-30
 - **负责团队**: Team B
 
 ## 交付产物
 
 | 序号 | 文件路径 | 说明 | 覆盖度检查 | 核心内容摘要 |
 |------|----------|------|------------|--------------|
-| 1 | deliveries/team-b-architecture/design.md | 架构设计文档 | 模块数: 5/5, 架构层: 4/4 | 系统架构、数据库设计、接口设计、安全设计、技术选型 |
-| 2 | deliveries/team-b-architecture/api-definition.md | 接口定义文档 | 接口数: 25/25, 模块数: 5/5 | 认证5接口、用户4接口、系统8接口、审核3接口、首页5接口 |
-| 3 | deliveries/team-b-architecture/tech-stack.md | 技术选型文档 | 类别: 8/8 | 后端技术栈、前端技术栈、开发工具、部署环境、设计规范 |
+| 1 | deliveries/team-b-architecture/design.md | 架构设计文档 | 模块数: 5/5, 新增文件: 20个 | 果农名片、招工、搜索、文件、审核模块架构 |
+| 2 | deliveries/team-b-architecture/api-definition.md | 接口定义文档 | 新增接口: 13/13, 已有接口: 4/4 | 果农名片2、招工4、搜索2、拨号1、审核4 |
+| 3 | deliveries/team-b-architecture/tech-stack.md | 技术选型文档 | 类别: 8/8 | 继承阶段一+距离计算、敏感词检测、视频压缩 |
 | 4 | deliveries/team-b-architecture/DELIVERY-MANIFEST.md | 本交付清单 | - | 交付物清单、关键信息、问题反馈 |
 
 ## 修改文件清单
 
 | 序号 | 文件路径 | 操作类型 | 说明 |
 |------|----------|----------|------|
-| 1 | deliveries/team-b-architecture/design.md | 新 | 架构设计文档 |
-| 2 | deliveries/team-b-architecture/api-definition.md | 新 | 接口定义文档 |
-| 3 | deliveries/team-b-architecture/tech-stack.md | 新 | 技术选型文档 |
-| 4 | deliveries/team-b-architecture/DELIVERY-MANIFEST.md | 新 | 本交付清单 |
+| 1 | deliveries/team-b-architecture/design.md | 覆盖更新 | 从阶段一更新为阶段2a架构设计 |
+| 2 | deliveries/team-b-architecture/api-definition.md | 覆盖更新 | 从阶段一更新为阶段2a接口定义 |
+| 3 | deliveries/team-b-architecture/tech-stack.md | 覆盖更新 | 从阶段一更新为阶段2a技术选型 |
+| 4 | deliveries/team-b-architecture/DELIVERY-MANIFEST.md | 覆盖更新 | 本交付清单 |
 
 ## 交付说明
 
-本次交付为阶段一(基础设施与用户体系)的架构设计成果,基于 Team A 的需求规格(spec.md)进行设计。
+本次交付为阶段2a(果农核心功能)的架构设计成果,基于 Team A 的需求规格(阶段2a spec.md)进行设计。
 
 ### 核心内容
 
-1. **系统架构设计**
-   - 四层架构:客户端层 → API网关层 → 业务逻辑层 → 数据存储层
-   - 模块划分:用户模块、系统模块、审核模块、首页模块、通用模块
-   - 分层职责:Controller(API入口)→ Service(业务逻辑)→ Mapper(数据访问)
+1. **架构扩展**
+   - 新增5个业务模块:果农模块、招工模块、搜索模块、文件模块、审核扩展
+   - 新增20个Java源文件
+   - 继承阶段一四层架构
 
 2. **数据库设计**
-   - 核心表:sys_user、user_identity、sys_role、sys_permission、sys_dict、audit_log、operation_log
-   - 索引设计:phone_hash唯一索引、openid唯一索引、user_id索引、identity_type索引
-   - 加密方案:手机号AES加密存储,SHA256哈希用于查询
+   - 核心表:grower_profile、recruit_info、call_log
+   - 索引设计:经纬度复合索引(距离查询)、keyword_flag索引(待复核查询)
+   - JSON字段规范:varieties、photos、work_types、skills
 
 3. **接口设计**
-   - 接口总数:25
-   - 模块分布:认证5个、用户4个、系统8个、审核3个、首页5个
-   - 接口规范:RESTful风格,统一响应格式,错误码规范
+   - 新增接口:13
+   - 已有接口复用:4个(文件上传)
+   - 覆盖14个功能点
 
-4. **安全设计**
-   - 认证流程:JWT Token认证,拦截器校验,RBAC权限控制
-   - 数据安全:手机号加密、密码BCrypt、敏感数据脱敏
-   - 接口安全:参数校验、SQL注入防护、防重放攻击
+4. **关键技术方案**
+   - 距离计算:Haversine公式,纯Java实现
+   - 敏感词检测:正则匹配,keyword_flag标记
+   - 视频压缩:FFmpeg异步压缩,720p/2Mbps
+   - 文件存储:本地存储,UUID文件名
 
-5. **技术选型**
-   - 后端:Java 8 + Spring Boot 1.5.9 + MyBatis + MySQL + Redis
-   - 前端:微信小程序 + Vue 2 + Element UI + ECharts
-   - 工具:Maven + Git + Gogs
+5. **安全设计**
+   - 文件上传:格式白名单+大小限制
+   - 内容安全:敏感词检测+待复核
+   - 拨号安全:日志记录+数据脱敏
 
 ## 给下游团队的关键信息
 
 ### 关键决策
 
-1. **分层架构**: Controller → Service → Mapper,职责清晰,便于测试
-2. **接口设计**: 25个接口覆盖20个功能点,部分功能合并为单个接口
-3. **数据库设计**: 7张核心表,索引设计覆盖高频查询场景
-4. **安全方案**: JWT认证 + RBAC权限 + 手机号加密,满足安全要求
-5. **技术栈**: 固定版本,避免兼容性问题
+1. **距离计算**: Haversine公式实时计算,经纬度DECIMAL(10,7)精度
+2. **敏感词机制**: 不阻塞发布,keyword_flag标记进入待复核
+3. **视频压缩**: FFmpeg异步执行,失败重试3次
+4. **文件命名**: UUID重命名,防止路径穿越
+5. **拨号机制**: 单独接口获取手机号,记录拨号日志
 
 ### 隐含约束
 
-1. **Controller 必须参数校验**: 使用 @Valid 或手动校验
-2. **Service 必须事务管理**: 使用 @Transactional 注解
-3. **Mapper 必须 #{} 参数化**: 禁止使用 ${}
-4. **接口响应必须统一格式**: 使用 ApiResult 包装
-5. **敏感数据必须脱敏**: 手机号、密码等
+1. **JSON字段查询**: MySQL 5.7不支持JSON索引,使用LIKE查询(性能可接受)
+2. **距离计算优化**: 可先用矩形范围筛选(经纬度差值),再精确计算
+3. **视频压缩依赖FFmpeg**: 需要系统安装FFmpeg,否则使用备选方案
+4. **文件大小限制**: application.properties配置,前端和后端双重校验
+5. **审核SLA**: 需要定时任务支持(ScheduledExecutorService)
 
 ### 特别注意
 
-1. **身份路由逻辑**: 0个身份→提示联系村委会,1个身份→直接进入,N个身份→选择页
-2. **密码锁定机制**: 连续5次错误锁定30分钟,需记录锁定时间
-3. **审核SLA**: ≤24小时提醒,48小时升级,需定时任务支持
-4. **Token黑名单**: 退出登录时将Token加入Redis黑名单
+1. **招工编辑后重新检测敏感词**: 防止通过编辑规避检测
+2. **名片更新重置审核状态**: 修改后需重新审核
+3. **拨号日志是独立接口**: 不在列表接口中返回手机号
+4. **文件访问免认证**: /api/wx/file/files/** 路径排除在JWT拦截器外
+
+### 阶段2a新增文件清单
+
+| 文件 | 说明 | 依赖 |
+|------|------|------|
+| GrowerProfileController.java | 果农档案API | GrowerProfileService |
+| GrowerProfileService.java | 果农档案业务 | GrowerProfileMapper |
+| GrowerProfileMapper.xml | 果农档案映射 | - |
+| RecruitController.java | 招工CRUD API | RecruitService, KeywordCheckService |
+| RecruitService.java | 招工业务 | RecruitMapper, KeywordCheckService |
+| RecruitMapper.xml | 招工映射 | - |
+| WorkerSearchController.java | 工人列表API | WorkerSearchService |
+| WorkerSearchService.java | 工人搜索 | WorkerProfileMapper, DistanceUtil |
+| BuyerSearchController.java | 客商列表API | BuyerSearchService |
+| BuyerSearchService.java | 客商搜索 | BuyerProfileMapper |
+| CallPhoneController.java | 拨号API | CallLogService |
+| CallLogService.java | 拨号日志 | CallLogMapper |
+| CallLogMapper.xml | 拨号日志映射 | - |
+| GrowerAuditController.java | 名片审核API | GrowerAuditService |
+| GrowerAuditService.java | 名片审核 | GrowerProfileMapper, AuditLogService |
+| RecruitReviewController.java | 待复核API | RecruitReviewService |
+| RecruitReviewService.java | 待复核 | RecruitMapper, AuditLogService |
+| KeywordCheckService.java | 敏感词检测 | - |
+| DistanceUtil.java | 距离计算 | - |
+| VideoCompressService.java | 视频压缩 | - |
 
 ## 对上团队的问题
 
@@ -86,6 +112,8 @@
 
 ## 待确认事项
 
-1. **数据库连接池**: 建议使用 HikariCP(Spring Boot 1.5.x 默认),是否需要调整?
-2. **日志框架**: 建议使用 Logback(Spring Boot 默认),是否需要切换?
-3. **缓存策略**: Token黑名单和验证码使用Redis,是否需要其他缓存?
+1. **FFmpeg安装**: 服务器是否已安装FFmpeg?如未安装,视频压缩需要备选方案
+2. **地理编码**: 地址→经纬度转换由前端还是后端完成?建议前端处理
+3. **敏感词库**: 初始词库范围需要业务方确认
+4. **语音输入**: 小程序端语音识别使用微信原生API还是第三方服务?
+5. **审核SLA**: 定时任务使用ScheduledExecutorService还是Quartz?

+ 279 - 580
deliveries/team-b-architecture/api-definition.md

@@ -1,78 +1,40 @@
-# 阶段一接口定义 — 基础设施与用户体系
+# 阶段2a接口定义 — 果农核心功能
 
-> 接口总数:25 个
-> 覆盖功能点:20/20
+> 新增接口总数:13 个
+> 已有接口(复用):4 个
+> 覆盖功能点:14/14
 
 ---
 
 ## 一、接口总览
 
+### 阶段2a新增接口
+
 | 模块 | 接口数 | 说明 |
 |------|--------|------|
-| 认证模块 | 5 | 登录、登出、身份选择、Token刷新、密码修改 |
-| 用户模块 | 4 | 用户信息、状态管理、身份绑定、创建用户 |
-| 系统管理 | 8 | 角色、账号、字典、权限、操作日志 |
-| 审核模块 | 3 | 审核列表、审核操作、审核详情 |
-| 首页模块 | 5 | 果农/工人/客商/农资商首页、行情数据 |
-
-**总计**: 25 个接口
-
----
-
-## 二、认证模块接口
+| 果农名片 | 2 | 档案查询、档案更新 |
+| 招工管理 | 4 | 发布、列表、编辑、下架 |
+| 找工人/客商 | 2 | 工人列表、客商列表 |
+| 拨号 | 1 | 获取手机号+记录日志 |
+| 后台审核 | 4 | 名片审核列表/操作、待复核列表/操作 |
 
-### 2.1 POST /api/wx/auth/login — 微信登录
+**新增总计**: 13 个接口
 
-**描述**: 小程序用户通过微信 code 登录
-
-**请求头**:
-```
-Content-Type: application/json
-```
-
-**请求参数**:
-```json
-{
-  "code": "string" // 必填,微信 wx.login() 获取的 code
-}
-```
+### 已有接口(阶段2a复用)
 
-**响应参数**:
-```json
-{
-  "code": 200,
-  "message": "success",
-  "data": {
-    "token": "string", // JWT Token
-    "userId": "long", // 用户ID
-    "identities": [ // 身份列表
-      {
-        "identityId": "long",
-        "identityType": "string", // GROWER/WORKER/BUYER/SUPPLIER
-        "identityName": "string"
-      }
-    ]
-  }
-}
-```
-
-**错误码**:
-- 1001: 未找到用户信息,请联系村委会
-- 1002: 微信接口调用失败
+| 模块 | 接口数 | 说明 |
+|------|--------|------|
+| 文件上传 | 4 | 图片上传、视频上传、文件访问、文件删除 |
 
 ---
 
-### 2.2 POST /api/admin/auth/login — 后台登录
+## 二、果农名片接口
 
-**描述**: 后台管理员通过用户名密码登录
+### 2.1 GET /api/wx/grower/profile — 获取果农档案
 
-**请求参数**:
-```json
-{
-  "username": "string", // 必填,用户名
-  "password": "string"  // 必填,密码
-}
-```
+**描述**: 获取当前果农的名片信息
+
+**请求头**: `Authorization: Bearer {token}`
 
 **响应参数**:
 ```json
@@ -80,36 +42,50 @@ Content-Type: application/json
   "code": 200,
   "message": "success",
   "data": {
-    "token": "string",
-    "userId": "long",
-    "username": "string",
-    "realName": "string",
-    "roleId": "long",
-    "roleName": "string"
+    "id": 1,
+    "name": "张三",
+    "varieties": ["红富士", "嘎啦"],
+    "yieldAmount": 50000.00,
+    "expectedPrice": 4.00,
+    "address": "洒渔镇黄兴村",
+    "latitude": 27.3331000,
+    "longitude": 103.7168000,
+    "videoUrl": "http://localhost:8080/files/video/abc.mp4",
+    "photos": [
+      "http://localhost:8080/files/image/1.jpg",
+      "http://localhost:8080/files/image/2.jpg"
+    ],
+    "auditStatus": 0,
+    "auditRemark": null
   }
 }
 ```
 
 **错误码**:
-- 1003: 用户名或密码错误
-- 1004: 账号已禁用
-- 1005: 账号已锁定,请30分钟后重试
+- 2001: 果农档案不存在
 
 ---
 
-### 2.3 POST /api/wx/auth/select-identity — 选择身份
+### 2.2 PUT /api/wx/grower/profile — 更新果农档案
 
-**描述**: 多身份用户选择当前使用的身份
+**描述**: 更新果农名片信息,审核状态重置为待审
 
-**请求头**:
-```
-Authorization: Bearer {token}
-```
+**请求头**: `Authorization: Bearer {token}`
 
 **请求参数**:
 ```json
 {
-  "identityId": "long" // 必填,身份ID
+  "name": "张三",                    // 必填,姓名
+  "varieties": ["红富士", "嘎啦"],    // 必填,品种(JSON数组)
+  "yieldAmount": 50000.00,           // 产量(斤)
+  "expectedPrice": 4.00,             // 预期价格(元/斤)
+  "address": "洒渔镇黄兴村",          // 必填,果园地址
+  "latitude": 27.3331000,            // 纬度
+  "longitude": 103.7168000,          // 经度
+  "videoUrl": "http://localhost:8080/files/video/abc.mp4",
+  "photos": [
+    "http://localhost:8080/files/image/1.jpg"
+  ]
 }
 ```
 
@@ -118,53 +94,40 @@ Authorization: Bearer {token}
 {
   "code": 200,
   "message": "success",
-  "data": {
-    "token": "string" // 包含新身份信息的 Token
-  }
+  "data": null
 }
 ```
 
+**业务逻辑**:
+1. 验证必填字段(name、varieties、address)
+2. 更新 grower_profile
+3. 重置 audit_status=0,清空 audit_remark
+
 **错误码**:
-- 1006: 身份不存在
+- 2002: 必填字段不能为空
 
 ---
 
-### 2.4 POST /api/wx/auth/refresh — 刷新Token
-
-**描述**: 刷新当前 Token 有效期
-
-**请求头**:
-```
-Authorization: Bearer {token}
-```
-
-**响应参数**:
-```json
-{
-  "code": 200,
-  "message": "success",
-  "data": {
-    "token": "string"
-  }
-}
-```
-
----
+## 三、招工管理接口
 
-### 2.5 PUT /api/admin/auth/password — 修改密码
+### 3.1 POST /api/wx/grower/recruit — 发布招工
 
-**描述**: 后台管理员修改密码
+**描述**: 发布招工信息,免审核直接发布
 
-**请求头**:
-```
-Authorization: Bearer {token}
-```
+**请求头**: `Authorization: Bearer {token}`
 
 **请求参数**:
 ```json
 {
-  "oldPassword": "string", // 必填,旧密码
-  "newPassword": "string"  // 必填,新密码
+  "workTypes": ["采摘工", "分拣工"],   // 必填,工种(JSON数组)
+  "price": 150.00,                    // 必填,价格
+  "priceUnit": "DAY",                 // 必填,价格单位:DAY/PIECE
+  "workerCount": 3,                   // 必填,需要人数
+  "days": 5,                          // 天数
+  "location": "洒渔镇黄兴村",          // 必填,工作地点
+  "latitude": 27.3331000,             // 纬度
+  "longitude": 103.7168000,           // 经度
+  "remark": "需要有经验的采摘工"       // 备注
 }
 ```
 
@@ -173,25 +136,35 @@ Authorization: Bearer {token}
 {
   "code": 200,
   "message": "success",
-  "data": null
+  "data": {
+    "recruitId": 1
+  }
 }
 ```
 
+**业务逻辑**:
+1. 验证必填字段
+2. 敏感词检测(remark字段)
+3. keyword_flag=0 或 1
+4. 创建 recruit_info(status=1)
+
 **错误码**:
-- 1007: 旧密码错误
-- 1008: 新密码强度不足
+- 2003: 工种不能为空
+- 2004: 价格必须大于0
+- 2005: 人数必须大于0
+- 2006: 工作地点不能为空
 
 ---
 
-## 三、用户模块接口
+### 3.2 GET /api/wx/grower/recruit — 我的招工列表
 
-### 3.1 GET /api/wx/user/info — 获取用户信息
+**描述**: 获取当前果农发布的招工历史
 
-**描述**: 获取当前登录用户的基本信息
+**请求头**: `Authorization: Bearer {token}`
 
-**请求**:
+**请求参数**:
 ```
-Authorization: Bearer {token}
+?page=1&pageSize=20
 ```
 
 **响应参数**:
@@ -200,41 +173,43 @@ Authorization: Bearer {token}
   "code": 200,
   "message": "success",
   "data": {
-    "userId": "long",
-    "realName": "string",
-    "phone": "string", // 脱敏显示:138****8888
-    "identities": [
+    "total": 5,
+    "page": 1,
+    "pageSize": 20,
+    "list": [
       {
-        "identityId": "long",
-        "identityType": "string",
-        "identityName": "string"
+        "id": 1,
+        "workTypes": ["采摘工", "分拣工"],
+        "price": 150.00,
+        "priceUnit": "DAY",
+        "workerCount": 3,
+        "days": 5,
+        "location": "洒渔镇黄兴村",
+        "status": 1,
+        "keywordFlag": 0,
+        "applyCount": 2,
+        "createdAt": "2026-05-30 10:00:00"
       }
-    ],
-    "currentIdentity": {
-      "identityId": "long",
-      "identityType": "string"
-    }
+    ]
   }
 }
 ```
 
 ---
 
-### 3.2 PUT /api/admin/user/status — 修改用户状态
+### 3.3 PUT /api/wx/grower/recruit/{id} — 编辑招工
 
-**描述**: 管理员修改用户账号状态
+**描述**: 编辑已发布的招工信息
 
-**请求头**:
-```
-Authorization: Bearer {token}
-```
+**请求头**: `Authorization: Bearer {token}`
 
 **请求参数**:
 ```json
 {
-  "userId": "long",    // 必填,用户ID
-  "status": "int",     // 必填,状态:0正常 1禁用 2锁定
-  "lockReason": "string" // 锁定时必填
+  "price": 180.00,
+  "workerCount": 5,
+  "days": 7,
+  "remark": "价格上调,急招"
 }
 ```
 
@@ -247,180 +222,53 @@ Authorization: Bearer {token}
 }
 ```
 
-**错误码**:
-- 1009: 用户不存在
-- 1010: 不可禁用超级管理员
-- 1011: 锁定原因不能为空
-
----
-
-### 3.3 POST /api/admin/user/bind-identity — 绑定身份
-
-**描述**: 管理员为用户绑定新身份
-
-**请求头**:
-```
-Authorization: Bearer {token}
-```
-
-**请求参数**:
-```json
-{
-  "userId": "long",        // 必填,用户ID
-  "identityType": "string", // 必填,身份类型
-  "profileData": {}         // 身份详细信息(JSON)
-}
-```
-
-**响应参数**:
-```json
-{
-  "code": 200,
-  "message": "success",
-  "data": {
-    "identityId": "long"
-  }
-}
-```
+**业务逻辑**:
+1. 验证招工存在且属于当前用户
+2. 更新可编辑字段(price、workerCount、days、remark)
+3. 重新触发敏感词检测
 
 **错误码**:
-- 1012: 用户已有该身份
+- 2007: 招工不存在
+- 2008: 无权编辑此招工
 
 ---
 
-### 3.4 POST /api/admin/user — 创建用户
+### 3.4 DELETE /api/wx/grower/recruit/{id} — 下架招工
 
-**描述**: 管理员创建新用户
+**描述**: 下架已发布的招工(逻辑删除)
 
-**请求头**:
-```
-Authorization: Bearer {token}
-```
-
-**请求参数**:
-```json
-{
-  "realName": "string",    // 必填,真实姓名
-  "phone": "string",       // 必填,手机号
-  "identityType": "string", // 必填,身份类型
-  "profileData": {}         // 身份详细信息
-}
-```
+**请求头**: `Authorization: Bearer {token}`
 
 **响应参数**:
 ```json
 {
   "code": 200,
   "message": "success",
-  "data": {
-    "userId": "long"
-  }
+  "data": null
 }
 ```
 
-**错误码**:
-- 1013: 手机号已注册
-
----
-
-## 四、系统管理接口
-
-### 4.1 GET /api/admin/role/list — 角色列表
-
-**描述**: 获取系统角色列表
-
-**请求头**:
-```
-Authorization: Bearer {token}
-```
+**业务逻辑**:
+1. 验证招工存在且属于当前用户
+2. 更新 status=0
 
-**响应参数**:
-```json
-{
-  "code": 200,
-  "message": "success",
-  "data": [
-    {
-      "id": "long",
-      "roleName": "string",
-      "roleCode": "string",
-      "description": "string",
-      "status": "int",
-      "isSystem": "int"
-    }
-  ]
-}
-```
+**错误码**:
+- 2007: 招工不存在
+- 2008: 无权操作此招工
 
 ---
 
-### 4.2 GET /api/admin/role/{id}/permissions — 角色权限
-
-**描述**: 获取指定角色的权限列表
-
-**请求头**:
-```
-Authorization: Bearer {token}
-```
-
-**响应参数**:
-```json
-{
-  "code": 200,
-  "message": "success",
-  "data": [
-    {
-      "id": "long",
-      "permName": "string",
-      "permCode": "string",
-      "permType": "string",
-      "path": "string"
-    }
-  ]
-}
-```
-
----
+## 四、找工人/客商接口
 
-### 4.3 PUT /api/admin/role/{id}/permissions — 分配权限
+### 4.1 GET /api/wx/grower/workers — 工人列表
 
-**描述**: 为角色分配权限
+**描述**: 查找附近空闲工人
 
-**请求头**:
-```
-Authorization: Bearer {token}
-```
+**请求头**: `Authorization: Bearer {token}`
 
 **请求参数**:
-```json
-{
-  "permissionIds": ["long"] // 权限ID列表
-}
 ```
-
-**响应参数**:
-```json
-{
-  "code": 200,
-  "message": "success",
-  "data": null
-}
-```
-
----
-
-### 4.4 GET /api/admin/account/list — 账号列表
-
-**描述**: 获取管理员账号列表(分页)
-
-**请求头**:
-```
-Authorization: Bearer {token}
-```
-
-**请求参数**:
-```
-?page=1&pageSize=10&keyword=string
+?workType=采摘工&page=1&pageSize=20
 ```
 
 **响应参数**:
@@ -429,44 +277,42 @@ Authorization: Bearer {token}
   "code": 200,
   "message": "success",
   "data": {
-    "total": "long",
-    "page": "int",
-    "pageSize": "int",
+    "total": 10,
+    "page": 1,
+    "pageSize": 20,
     "list": [
       {
-        "id": "long",
-        "username": "string",
-        "realName": "string",
-        "phone": "string", // 脱敏
-        "roleName": "string",
-        "status": "int",
-        "createdAt": "string"
+        "identityId": 5,
+        "name": "李四",
+        "skills": ["采摘工", "分拣工"],
+        "price": 150.00,
+        "priceUnit": "DAY",
+        "status": 1,
+        "distance": 2.5
       }
     ]
   }
 }
 ```
 
+**业务逻辑**:
+1. 查询 worker_profile.status=1(空闲)
+2. 可选按工种筛选
+3. 计算距离(Haversine公式)
+4. 按距离升序排序
+5. 分页返回
+
 ---
 
-### 4.5 POST /api/admin/account — 创建账号
+### 4.2 GET /api/wx/grower/buyers — 客商列表
 
-**描述**: 创建管理员账号
+**描述**: 查找收购客商
 
-**请求头**:
-```
-Authorization: Bearer {token}
-```
+**请求头**: `Authorization: Bearer {token}`
 
 **请求参数**:
-```json
-{
-  "username": "string", // 必填,用户名
-  "password": "string", // 必填,密码
-  "realName": "string", // 必填,真实姓名
-  "phone": "string",    // 必填,手机号
-  "roleId": "long"      // 必填,角色ID
-}
+```
+?page=1&pageSize=20
 ```
 
 **响应参数**:
@@ -475,67 +321,38 @@ Authorization: Bearer {token}
   "code": 200,
   "message": "success",
   "data": {
-    "accountId": "long"
+    "total": 5,
+    "page": 1,
+    "pageSize": 20,
+    "list": [
+      {
+        "identityId": 10,
+        "name": "王五果业",
+        "varieties": ["红富士", "嘎啦"],
+        "priceRange": "3.5-4.5",
+        "totalAmount": 100000.00,
+        "standards": "果径≥80mm",
+        "address": "昭通市水果批发市场"
+      }
+    ]
   }
 }
 ```
 
-**错误码**:
-- 1014: 用户名已存在
-- 1015: 手机号已注册
-- 1016: 密码强度不足
-
 ---
 
-### 4.6 GET /api/admin/dict/list — 字典列表
+## 五、拨号接口
 
-**描述**: 获取指定类型的字典列表
-
-**请求头**:
-```
-Authorization: Bearer {token}
-```
+### 5.1 POST /api/wx/call/phone — 拨号接口
 
-**请求参数**:
-```
-?dictType=string
-```
+**描述**: 获取对方手机号并记录拨号日志
 
-**响应参数**:
-```json
-{
-  "code": 200,
-  "message": "success",
-  "data": [
-    {
-      "id": "long",
-      "dictType": "string",
-      "dictCode": "string",
-      "dictName": "string",
-      "sortOrder": "int"
-    }
-  ]
-}
-```
-
----
-
-### 4.7 POST /api/admin/dict — 新增字典项
-
-**描述**: 新增字典项
-
-**请求头**:
-```
-Authorization: Bearer {token}
-```
+**请求头**: `Authorization: Bearer {token}`
 
 **请求参数**:
 ```json
 {
-  "dictType": "string",  // 必填,字典类型
-  "dictCode": "string",  // 必填,字典编码
-  "dictName": "string",  // 必填,字典名称
-  "sortOrder": "int"     // 排序号
+  "calleeIdentityId": 5    // 必填,被拨方身份ID
 }
 ```
 
@@ -545,72 +362,33 @@ Authorization: Bearer {token}
   "code": 200,
   "message": "success",
   "data": {
-    "dictId": "long"
+    "phone": "138****8888",      // 脱敏手机号(前端显示)
+    "realPhone": "13800138000"   // 真实手机号(用于拨号)
   }
 }
 ```
 
-**错误码**:
-- 1017: 字典编码已存在
-- 1018: 系统内置字典不可删除
-
----
-
-### 4.8 GET /api/admin/operation-log/list — 操作日志列表
-
-**描述**: 获取操作日志列表(分页)
+**业务逻辑**:
+1. 验证被拨方存在
+2. 记录拨号日志(call_log)
+3. 返回手机号
 
-**请求头**:
-```
-Authorization: Bearer {token}
-```
-
-**请求参数**:
-```
-?page=1&pageSize=10&operatorId=long&startTime=string&endTime=string
-```
-
-**响应参数**:
-```json
-{
-  "code": 200,
-  "message": "success",
-  "data": {
-    "total": "long",
-    "page": "int",
-    "pageSize": "int",
-    "list": [
-      {
-        "id": "long",
-        "operatorName": "string",
-        "operationType": "string",
-        "operationModule": "string",
-        "operationContent": "string",
-        "ipAddress": "string",
-        "result": "int",
-        "createdAt": "string"
-      }
-    ]
-  }
-}
-```
+**错误码**:
+- 2009: 被拨方不存在
 
 ---
 
-## 五、审核模块接口
+## 六、后台审核接口
 
-### 5.1 GET /api/admin/audit/list — 审核列表
+### 6.1 GET /api/admin/audit/grower-profile — 名片审核列表
 
-**描述**: 获取审核列表(分页)
+**描述**: 获取待审核的果农名片列表
 
-**请求头**:
-```
-Authorization: Bearer {token}
-```
+**请求头**: `Authorization: Bearer {token}`
 
 **请求参数**:
 ```
-?page=1&pageSize=10&targetType=string&status=string
+?page=1&pageSize=10&status=0
 ```
 
 **响应参数**:
@@ -619,17 +397,20 @@ Authorization: Bearer {token}
   "code": 200,
   "message": "success",
   "data": {
-    "total": "long",
-    "page": "int",
-    "pageSize": "int",
+    "total": 3,
+    "page": 1,
+    "pageSize": 10,
     "list": [
       {
-        "id": "long",
-        "targetType": "string",
-        "targetId": "long",
-        "submitterName": "string",
-        "status": "string",
-        "createdAt": "string"
+        "id": 1,
+        "growerName": "张三",
+        "varieties": ["红富士"],
+        "yieldAmount": 50000.00,
+        "address": "洒渔镇黄兴村",
+        "videoUrl": "http://localhost:8080/files/video/abc.mp4",
+        "photos": ["http://localhost:8080/files/image/1.jpg"],
+        "auditStatus": 0,
+        "createdAt": "2026-05-30 10:00:00"
       }
     ]
   }
@@ -638,20 +419,17 @@ Authorization: Bearer {token}
 
 ---
 
-### 5.2 PUT /api/admin/audit/{id} — 审核操作
+### 6.2 PUT /api/admin/audit/grower-profile/{id} — 名片审核操作
 
-**描述**: 执行审核操作(通过/驳回)
+**描述**: 对果农名片执行审核操作
 
-**请求头**:
-```
-Authorization: Bearer {token}
-```
+**请求头**: `Authorization: Bearer {token}`
 
 **请求参数**:
 ```json
 {
-  "action": "string", // 必填,APPROVE/REJECT
-  "reason": "string"  // 驳回时必填
+  "action": "APPROVE",    // 必填,APPROVE/REJECT
+  "reason": ""            // 驳回时必填
 }
 ```
 
@@ -664,49 +442,27 @@ Authorization: Bearer {token}
 }
 ```
 
-**错误码**:
-- 1019: 审核记录不存在
-- 1020: 驳回原因不能为空
-
----
+**业务逻辑**:
+1. 验证审核记录存在
+2. APPROVE → audit_status=1
+3. REJECT → audit_status=2,audit_remark=reason
+4. 记录审核日志
 
-### 5.3 GET /api/admin/audit/{id} — 审核详情
-
-**描述**: 获取审核详情
-
-**请求头**:
-```
-Authorization: Bearer {token}
-```
-
-**响应参数**:
-```json
-{
-  "code": 200,
-  "message": "success",
-  "data": {
-    "id": "long",
-    "targetType": "string",
-    "targetId": "long",
-    "targetData": {}, // 审核对象的详细数据
-    "submitterName": "string",
-    "status": "string",
-    "createdAt": "string"
-  }
-}
-```
+**错误码**:
+- 2010: 审核记录不存在
+- 2011: 驳回原因不能为空
 
 ---
 
-## 六、首页模块接口
+### 6.3 GET /api/admin/audit/recruit-review — 待复核招工列表
 
-### 6.1 GET /api/wx/home/grower — 果农首页
+**描述**: 获取敏感关键词标记的招工列表
 
-**描述**: 获取果农首页数据
+**请求头**: `Authorization: Bearer {token}`
 
-**请求**:
+**请求参数**:
 ```
-Authorization: Bearer {token}
+?page=1&pageSize=10
 ```
 
 **响应参数**:
@@ -715,21 +471,18 @@ Authorization: Bearer {token}
   "code": 200,
   "message": "success",
   "data": {
-    "greeting": "string", // 问候语
-    "marketPrices": [
-      {
-        "variety": "string",
-        "priceMin": "decimal",
-        "priceMax": "decimal",
-        "trend": "string", // up/down/stable
-        "updateTime": "string"
-      }
-    ],
-    "quickEntries": [
+    "total": 2,
+    "page": 1,
+    "pageSize": 10,
+    "list": [
       {
-        "name": "string",
-        "icon": "string",
-        "path": "string"
+        "id": 1,
+        "workTypes": ["采摘工"],
+        "price": 150.00,
+        "remark": "日薪300元...",
+        "keywordFlag": 1,
+        "publisherName": "张三",
+        "createdAt": "2026-05-30 10:00:00"
       }
     ]
   }
@@ -738,137 +491,83 @@ Authorization: Bearer {token}
 
 ---
 
-### 6.2 GET /api/wx/home/worker — 工人首页
+### 6.4 PUT /api/admin/audit/recruit-review/{id} — 待复核操作
 
-**描述**: 获取工人首页推荐招工
+**描述**: 处理待复核招工
 
-**请求头**:
-```
-Authorization: Bearer {token}
-```
+**请求头**: `Authorization: Bearer {token}`
 
-**响应参数**:
+**请求参数**:
 ```json
 {
-  "code": 200,
-  "message": "success",
-  "data": {
-    "recommendedRecruits": [
-      {
-        "id": "long",
-        "workType": "string",
-        "price": "decimal",
-        "priceUnit": "string",
-        "days": "int",
-        "peopleCount": "int",
-        "growerName": "string",
-        "distance": "decimal" // 公里
-      }
-    ]
-  }
+  "action": "NORMAL",      // 必填,NORMAL/FORCE_OFFLINE
+  "reason": ""             // 强制下架时必填
 }
 ```
 
----
-
-### 6.3 GET /api/wx/home/buyer — 客商首页
-
-**描述**: 获取客商首页数据
-
-**请求头**:
-```
-Authorization: Bearer {token}
-```
-
 **响应参数**:
 ```json
 {
   "code": 200,
   "message": "success",
-  "data": {
-    "marketPrices": [...],
-    "recommendedGrowers": [
-      {
-        "identityId": "long",
-        "variety": "string",
-        "production": "decimal", // 斤
-        "expectedPrice": "decimal",
-        "orchardAddress": "string",
-        "distance": "decimal"
-      }
-    ]
-  }
+  "data": null
 }
 ```
 
+**业务逻辑**:
+1. 验证招工存在
+2. NORMAL → keyword_flag=0
+3. FORCE_OFFLINE → status=0,记录原因
+
+**错误码**:
+- 2012: 招工不存在
+- 2013: 下架原因不能为空
+
 ---
 
-### 6.4 GET /api/wx/home/supplier — 农资商首页
+## 七、已有接口(阶段2a复用)
 
-**描述**: 获取农资商首页数据
+### 7.1 POST /api/wx/file/upload/image — 上传图片
 
-**请求头**:
-```
-Authorization: Bearer {token}
-```
+**描述**: 上传图片文件(已实现)
 
-**响应参数**:
-```json
-{
-  "code": 200,
-  "message": "success",
-  "data": {
-    "shopInfo": {
-      "shopName": "string",
-      "mainProducts": "string",
-      "productCount": "int"
-    },
-    "quickEntries": [
-      {"name": "商品管理", "path": "/pages/product/list"},
-      {"name": "订单管理", "path": "/pages/order/list"},
-      {"name": "店铺设置", "path": "/pages/shop/setting"}
-    ]
-  }
-}
-```
+**请求**: multipart/form-data
 
----
+**限制**: ≤5MB/张,格式:jpg,jpeg,png,gif
 
-### 6.5 GET /api/wx/market-price — 行情数据
+### 7.2 POST /api/wx/file/upload/video — 上传视频
 
-**描述**: 获取今日行情数据
+**描述**: 上传视频文件(已实现)
 
-**请求头**:
-```
-Authorization: Bearer {token}
-```
+**请求**: multipart/form-data
 
-**响应参数**:
-```json
-{
-  "code": 200,
-  "message": "success",
-  "data": [
-    {
-      "variety": "string",
-      "priceMin": "decimal",
-      "priceMax": "decimal",
-      "trend": "string",
-      "updateTime": "string"
-    }
-  ]
-}
-```
+**限制**: ≤50MB,格式:mp4,mov,avi
 
----
+### 7.3 GET /api/wx/file/files/{category}/{filename} — 访问文件
 
-## 七、接口统计
+**描述**: 访问已上传的文件(已实现,免认证)
 
-| 模块 | 接口数 | 方法 |
-|------|--------|------|
-| 认证模块 | 5 | POST×3, PUT×1, GET×1 |
-| 用户模块 | 4 | GET×1, PUT×1, POST×2 |
-| 系统管理 | 8 | GET×5, POST×2, PUT×1 |
-| 审核模块 | 3 | GET×2, PUT×1 |
-| 首页模块 | 5 | GET×5 |
-| **总计** | **25** | GET×16, POST×7, PUT×2 |
+### 7.4 DELETE /api/wx/file/delete — 删除文件
+
+**描述**: 删除已上传的文件(已实现)
+
+---
+
+## 八、接口统计
+
+| 模块 | 新增接口 | 已有接口 | 总计 |
+|------|---------|---------|------|
+| 果农名片 | 2 | - | 2 |
+| 招工管理 | 4 | - | 4 |
+| 找工人/客商 | 2 | - | 2 |
+| 拨号 | 1 | - | 1 |
+| 后台审核 | 4 | - | 4 |
+| 文件上传 | - | 4 | 4 |
+| **总计** | **13** | **4** | **17** |
+
+| HTTP方法 | 数量 |
+|---------|------|
+| GET | 6 |
+| POST | 4 |
+| PUT | 5 |
+| DELETE | 2 |

+ 401 - 407
deliveries/team-b-architecture/design.md

@@ -1,11 +1,11 @@
-# 阶段一架构设计 — 基础设施与用户体系
+# 阶段2a架构设计 — 果农核心功能
 
-> 基于 Team A 需求规格(spec.md)
-> 嵌入 Team A 关键信息
+> 基于 Team A 需求规格(阶段2a spec.md)
+> 新增模块:果农名片、招工发布、找工人、找客商、后台审核
 
 ---
 
-## 一、系统架构
+## 一、系统架构(继承阶段一 + 扩展)
 
 ### 1.1 整体架构
 
@@ -31,7 +31,11 @@
 │                      业务逻辑层                              │
 ├──────────┬──────────┬──────────┬──────────┬────────────────┤
 │ 用户模块 │ 系统模块 │ 审核模块 │ 首页模块 │  通用模块      │
-│ AuthService│ SysService│ AuditService│ HomeService│  CommonService│
+│AuthService│SysService│AuditService│HomeService│CommonService│
+├──────────┼──────────┼──────────┼──────────┼────────────────┤
+│ 果农模块 │ 招工模块 │ 搜索模块 │ 文件模块 │  工具模块      │
+│GrowerSvc │RecruitSvc│SearchSvc │FileService│ DistanceUtil  │
+│GrowerAudit│RecruitRev│CallLogSvc│           │ KeywordCheck  │
 └──────┬───┴──────┬───┴──────┬───┴──────┬───┴────────┬───────┘
        │          │          │          │            │
        ▼          ▼          ▼          ▼            ▼
@@ -45,24 +49,24 @@
 ┌─────────────────────────────────────────────────────────────┐
 │                      数据存储层                              │
 ├─────────────────────────┬───────────────────────────────────┤
-│   MySQL (crrc 库)       │   Redis (缓存)
-│   - 15 张业务表          │   - Token 黑名单    
-│   - AES 加密字段         │   - 验证码缓存      
-│   - SHA256 哈希索引      │   - 数据大屏统计
+│   MySQL (sayu 库)       │   本地文件存储 
+│   - 20 张业务表          │   - ./uploads/image/
+│   - AES 加密字段         │   - ./uploads/video/
+│   - SHA256 哈希索引      │                 
 └─────────────────────────┴───────────────────────────────────┘
 ```
 
-### 1.2 模块划分
+### 1.2 阶段2a新增模块
 
 | 模块 | 包名 | 职责 |
 |------|------|------|
-| 用户模块 | com.sayu.service | 用户认证、身份管理、权限控制 |
-| 系统模块 | com.sayu.service | 角色管理、账号管理、字典管理、操作日志 |
-| 审核模块 | com.sayu.service | 审核流程、审核列表、审核日志 |
-| 首页模块 | com.sayu.service | 首页数据、行情展示 |
-| 通用模块 | com.sayu.util | 工具类、常量、异常处理 |
+| 果农模块 | com.sayu.service | 果农档案CRUD、审核状态管理 |
+| 招工模块 | com.sayu.service | 招工发布、编辑、下架、敏感词检测 |
+| 搜索模块 | com.sayu.service | 工人列表、客商列表、距离计算 |
+| 文件模块 | com.sayu.service | 文件上传、存储、访问、删除 |
+| 审核模块(扩展) | com.sayu.service | 名片审核、待复核列表、SLA提醒 |
 
-### 1.3 分层架构
+### 1.3 分层架构(继承阶段一)
 
 ```
 Controller 层(API 入口)
@@ -74,243 +78,285 @@ Mapper 层(数据访问)
 Entity/DTO/VO 层(数据模型)
 ```
 
-**职责划分**:
-- **Controller**: 接收请求、参数校验、调用 Service、返回响应
-- **Service**: 业务逻辑、事务管理、异常处理
-- **Mapper**: 数据库操作、MyBatis XML 映射
-- **Entity**: 数据库实体,与表结构对应
-- **DTO**: 数据传输对象,Service 层间传递
-- **VO**: 视图对象,Controller 返回给前端
-
 ---
 
-## 二、数据库设计
+## 二、数据库设计(继承阶段一 + 扩展)
 
-### 2.1 ER 图
+### 2.1 ER 图(阶段2a涉及)
 
 ```
 sys_user (用户基础表)
-    ├── 1:N ──→ user_identity (身份关联表)
-    │               │
-    │               ├── 1:1 ──→ grower_profile (果农档案)
-    │               ├── 1:1 ──→ worker_profile (工人档案)
-    │               ├── 1:1 ──→ buyer_profile (客商档案)
-    │               └── 1:1 ──→ supplier_shop (农资店铺)
-    │
-    └── 1:N ──→ operation_log (操作日志)
+    └── 1:N ──→ user_identity (身份关联表)
+                    │
+                    ├── 1:1 ──→ grower_profile (果农档案) ←── 阶段2a核心
+                    │               │
+                    │               └── 1:N ──→ recruit_info (招工信息) ←── 阶段2a核心
+                    │
+                    ├── 1:1 ──→ worker_profile (工人档案)
+                    │               │
+                    │               └── 1:N ──→ worker_apply (工人报名)
+                    │
+                    └── 1:1 ──→ buyer_profile (客商档案)
 
-audit_log (审核日志)
+call_log (拨号日志) ←── 阶段2a新增使用
-    └── 关联 → user_identity
+    ├── caller_identity_id → user_identity
+    └── callee_identity_id → user_identity
 
-sys_role (角色表)
+audit_log (审核日志) ←── 阶段2a扩展使用
-    └── N:M ──→ sys_permission (权限表)
+    └── target_type = 'GROWER_PROFILE' / 'RECRUIT_REVIEW'
 ```
 
-### 2.2 核心表设计
+### 2.2 阶段2a涉及的核心表
 
-#### sys_user(用户基础表)
+#### grower_profile(果农档案表)— 阶段2a核心
 
 | 字段 | 类型 | 约束 | 说明 |
 |------|------|------|------|
-| id | BIGINT | PK, AUTO_INCREMENT | 用户ID |
-| openid | VARCHAR(64) | UNIQUE, INDEX | 微信 openid |
-| username | VARCHAR(50) | UNIQUE | 后台登录用户名 |
-| password | VARCHAR(100) | | BCrypt 加密密码 |
-| phone | VARCHAR(100) | | AES 加密手机号 |
-| phone_hash | VARCHAR(64) | UNIQUE, INDEX | SHA256 手机号哈希 |
-| real_name | VARCHAR(50) | | 真实姓名 |
-| status | TINYINT | INDEX | 状态:0正常 1禁用 2锁定 |
-| lock_reason | VARCHAR(200) | | 锁定原因 |
-| login_fail_count | INT | | 连续登录失败次数 |
-| lock_time | DATETIME | | 锁定时间 |
-| created_at | DATETIME | | 创建时间 |
-| updated_at | DATETIME | | 更新时间 |
-
-#### user_identity(身份关联表)
+| id | BIGINT | PK, AUTO_INCREMENT | 主键 |
+| user_identity_id | BIGINT | INDEX | 关联user_identity.id |
+| name | VARCHAR(50) | | 姓名 |
+| varieties | VARCHAR(200) | | 苹果品种(JSON数组) |
+| yield_amount | DECIMAL(10,2) | | 产量(斤) |
+| expected_price | DECIMAL(8,2) | | 预期价格(元/斤) |
+| address | VARCHAR(200) | | 果园地址 |
+| latitude | DECIMAL(10,7) | INDEX | 纬度 |
+| longitude | DECIMAL(10,7) | INDEX | 经度 |
+| video_url | VARCHAR(255) | | 果园视频URL(本地存储) |
+| photos | TEXT | | 照片URL(JSON数组) |
+| audit_status | TINYINT | INDEX | 0待审 1通过 2驳回 |
+| audit_remark | VARCHAR(200) | | 驳回原因 |
+
+#### recruit_info(招工信息表)— 阶段2a核心
 
 | 字段 | 类型 | 约束 | 说明 |
 |------|------|------|------|
-| id | BIGINT | PK, AUTO_INCREMENT | 身份ID |
-| user_id | BIGINT | INDEX | 关联用户ID |
-| identity_type | VARCHAR(20) | INDEX | 身份类型:GROWER/WORKER/BUYER/SUPPLIER |
-| status | TINYINT | | 状态:0正常 1禁用 |
-| created_at | DATETIME | | 创建时间 |
-
-#### sys_role(角色表)
+| id | BIGINT | PK, AUTO_INCREMENT | 主键 |
+| user_identity_id | BIGINT | INDEX | 发布者身份ID |
+| work_types | VARCHAR(100) | | 工种(JSON数组) |
+| price | DECIMAL(8,2) | | 价格 |
+| price_unit | VARCHAR(10) | | DAY/PIECE |
+| worker_count | INT | | 需要人数 |
+| days | INT | | 天数 |
+| location | VARCHAR(200) | | 工作地点 |
+| latitude | DECIMAL(10,7) | INDEX | 纬度 |
+| longitude | DECIMAL(10,7) | INDEX | 经度 |
+| remark | VARCHAR(500) | | 备注 |
+| status | TINYINT | INDEX | 0下架 1发布中 |
+| keyword_flag | TINYINT | INDEX | 0正常 1待复核 |
+| created_at | DATETIME | | 发布时间 |
+
+#### call_log(拨号日志表)— 阶段2a新增使用
 
 | 字段 | 类型 | 约束 | 说明 |
 |------|------|------|------|
-| id | BIGINT | PK, AUTO_INCREMENT | 角色ID |
-| role_name | VARCHAR(50) | UNIQUE | 角色名称 |
-| role_code | VARCHAR(50) | UNIQUE | 角色编码 |
-| description | VARCHAR(200) | | 角色描述 |
-| status | TINYINT | | 状态:0正常 1禁用 |
-| is_system | TINYINT | | 是否系统预置:0否 1是 |
-| created_at | DATETIME | | 创建时间 |
+| id | BIGINT | PK, AUTO_INCREMENT | 主键 |
+| caller_identity_id | BIGINT | INDEX | 拨号方身份ID |
+| callee_identity_id | BIGINT | INDEX | 被拨方身份ID |
+| call_time | DATETIME | | 拨号时间 |
 
-#### sys_permission(权限表
+### 2.3 索引设计(阶段2a新增)
 
-| 字段 | 类型 | 约束 | 说明 |
-|------|------|------|------|
-| id | BIGINT | PK, AUTO_INCREMENT | 权限ID |
-| parent_id | BIGINT | | 父权限ID |
-| perm_name | VARCHAR(50) | | 权限名称 |
-| perm_code | VARCHAR(100) | UNIQUE | 权限编码 |
-| perm_type | VARCHAR(20) | | 类型:MENU/BUTTON |
-| path | VARCHAR(200) | | 菜单路径 |
-| icon | VARCHAR(100) | | 菜单图标 |
-| sort_order | INT | | 排序号 |
-| status | TINYINT | | 状态:0正常 1禁用 |
-
-#### sys_role_permission(角色权限关联表)
+```sql
+-- grower_profile 表索引
+CREATE INDEX idx_user_identity_id ON grower_profile(user_identity_id);
+CREATE INDEX idx_audit_status ON grower_profile(audit_status);
+CREATE INDEX idx_lat_lng ON grower_profile(latitude, longitude);
 
-| 字段 | 类型 | 约束 | 说明 |
-|------|------|------|------|
-| id | BIGINT | PK, AUTO_INCREMENT | 主键 |
-| role_id | BIGINT | INDEX | 角色ID |
-| permission_id | BIGINT | INDEX | 权限ID |
+-- recruit_info 表索引
+CREATE INDEX idx_user_identity_id ON recruit_info(user_identity_id);
+CREATE INDEX idx_status ON recruit_info(status);
+CREATE INDEX idx_keyword_flag ON recruit_info(keyword_flag);
+CREATE INDEX idx_lat_lng ON recruit_info(latitude, longitude);
 
-#### sys_dict(字典表)
+-- call_log 表索引
+CREATE INDEX idx_caller ON call_log(caller_identity_id);
+CREATE INDEX idx_callee ON call_log(callee_identity_id);
+```
 
-| 字段 | 类型 | 约束 | 说明 |
-|------|------|------|------|
-| id | BIGINT | PK, AUTO_INCREMENT | 字典ID |
-| dict_type | VARCHAR(50) | INDEX | 字典类型 |
-| dict_code | VARCHAR(50) | UNIQUE | 字典编码 |
-| dict_name | VARCHAR(100) | | 字典名称 |
-| sort_order | INT | | 排序号 |
-| is_system | TINYINT | | 是否系统内置:0否 1是 |
-| status | TINYINT | | 状态:0正常 1禁用 |
+---
 
-#### audit_log(审核日志表
+## 三、接口设计(阶段2a新增)
 
-| 字段 | 类型 | 约束 | 说明 |
-|------|------|------|------|
-| id | BIGINT | PK, AUTO_INCREMENT | 日志ID |
-| target_type | VARCHAR(50) | | 审核对象类型 |
-| target_id | BIGINT | | 审核对象ID |
-| operator_id | BIGINT | INDEX | 审核人ID |
-| action | VARCHAR(20) | | 审核动作:APPROVE/REJECT |
-| reason | VARCHAR(500) | | 审核原因 |
-| created_at | DATETIME | | 审核时间 |
+### 3.1 果农名片接口
 
-#### operation_log(操作日志表)
+#### GET /api/wx/grower/profile — 获取果农档案
 
-| 字段 | 类型 | 约束 | 说明 |
-|------|------|------|------|
-| id | BIGINT | PK, AUTO_INCREMENT | 日志ID |
-| operator_id | BIGINT | INDEX | 操作人ID |
-| operator_name | VARCHAR(50) | | 操作人姓名 |
-| operation_type | VARCHAR(50) | | 操作类型 |
-| operation_module | VARCHAR(50) | | 操作模块 |
-| operation_content | VARCHAR(500) | | 操作内容 |
-| ip_address | VARCHAR(50) | | IP地址 |
-| result | TINYINT | | 操作结果:0失败 1成功 |
-| created_at | DATETIME | | 操作时间 |
-
-### 2.3 索引设计
+**描述**: 获取当前果农的名片信息
 
-```sql
--- sys_user 表索引
-CREATE UNIQUE INDEX idx_phone_hash ON sys_user(phone_hash);
-CREATE UNIQUE INDEX idx_openid ON sys_user(openid);
-CREATE INDEX idx_status ON sys_user(status);
+**请求头**: `Authorization: Bearer {token}`
 
--- user_identity 表索引
-CREATE INDEX idx_user_id ON user_identity(user_id);
-CREATE INDEX idx_identity_type ON user_identity(identity_type);
+**响应参数**:
+```json
+{
+  "code": 200,
+  "message": "success",
+  "data": {
+    "id": 1,
+    "name": "张三",
+    "varieties": ["红富士", "嘎啦"],
+    "yieldAmount": 50000,
+    "expectedPrice": 4.0,
+    "address": "洒渔镇黄兴村",
+    "latitude": 27.3331,
+    "longitude": 103.7168,
+    "videoUrl": "http://localhost:8080/files/video/abc.mp4",
+    "photos": ["http://localhost:8080/files/image/1.jpg"],
+    "auditStatus": 0,
+    "auditRemark": null
+  }
+}
+```
 
--- audit_log 表索引
-CREATE INDEX idx_operator_id ON audit_log(operator_id);
+#### PUT /api/wx/grower/profile — 更新果农档案
 
--- operation_log 表索引
-CREATE INDEX idx_operator_id ON operation_log(operator_id);
+**描述**: 更新果农名片信息,审核状态重置为待审
+
+**请求参数**:
+```json
+{
+  "name": "张三",
+  "varieties": ["红富士", "嘎啦"],
+  "yieldAmount": 50000,
+  "expectedPrice": 4.0,
+  "address": "洒渔镇黄兴村",
+  "latitude": 27.3331,
+  "longitude": 103.7168,
+  "videoUrl": "http://localhost:8080/files/video/abc.mp4",
+  "photos": ["http://localhost:8080/files/image/1.jpg"]
+}
 ```
 
+**业务逻辑**:
+1. 验证必填字段
+2. 更新 grower_profile
+3. 重置 audit_status=0,清空 audit_remark
+
 ---
 
-## 三、接口设计
+### 3.2 招工接口
 
-### 3.1 认证接口
+#### POST /api/wx/grower/recruit — 发布招工
 
-#### POST /api/wx/auth/login — 微信登录
+**描述**: 发布招工信息,免审核直接发布
 
 **请求参数**:
 ```json
 {
-  "code": "wx_login_code"
+  "workTypes": ["采摘工", "分拣工"],
+  "price": 150,
+  "priceUnit": "DAY",
+  "workerCount": 3,
+  "days": 5,
+  "location": "洒渔镇黄兴村",
+  "latitude": 27.3331,
+  "longitude": 103.7168,
+  "remark": "需要有经验的采摘工"
 }
 ```
 
+**业务逻辑**:
+1. 验证必填字段(workTypes、price、priceUnit、workerCount、location)
+2. 敏感词检测(keyword_flag)
+3. 创建 recruit_info(status=1,免审核)
+
+#### GET /api/wx/grower/recruit — 我的招工列表
+
+**请求参数**: `?page=1&pageSize=20`
+
 **响应参数**:
 ```json
 {
   "code": 200,
   "message": "success",
   "data": {
-    "token": "jwt_token",
-    "userId": 1,
-    "identities": [
+    "total": 5,
+    "page": 1,
+    "pageSize": 20,
+    "list": [
       {
-        "identityId": 1,
-        "identityType": "GROWER",
-        "identityName": "果农"
+        "id": 1,
+        "workTypes": ["采摘工"],
+        "price": 150,
+        "priceUnit": "DAY",
+        "workerCount": 3,
+        "days": 5,
+        "location": "洒渔镇黄兴村",
+        "status": 1,
+        "keywordFlag": 0,
+        "applyCount": 2,
+        "createdAt": "2026-05-30 10:00"
       }
     ]
   }
 }
 ```
 
-**业务逻辑**:
-1. 用 code 调用微信接口换取 openid
-2. 查询 openid 是否已绑定用户
-3. 已绑定 → 签发 JWT token
-4. 未绑定 → 返回错误码 1001(提示联系村委会)
-
-#### POST /api/admin/auth/login — 后台登录
+#### PUT /api/wx/grower/recruit/{id} — 编辑招工
 
 **请求参数**:
 ```json
 {
-  "username": "admin",
-  "password": "admin123"
+  "price": 180,
+  "workerCount": 5,
+  "remark": "价格上调,急招"
 }
 ```
 
+**业务逻辑**:
+1. 验证招工存在且属于当前用户
+2. 更新可编辑字段
+3. 重新触发敏感词检测
+
+#### DELETE /api/wx/grower/recruit/{id} — 下架招工
+
+**业务逻辑**:
+1. 验证招工存在且属于当前用户
+2. 更新 status=0(逻辑删除)
+
+---
+
+### 3.3 找工人/客商接口
+
+#### GET /api/wx/grower/workers — 工人列表
+
+**请求参数**: `?workType=采摘工&page=1&pageSize=20`
+
 **响应参数**:
 ```json
 {
   "code": 200,
   "message": "success",
   "data": {
-    "token": "jwt_token",
-    "userId": 1,
-    "username": "admin",
-    "realName": "管理员",
-    "roleId": 1,
-    "roleName": "超级管理员"
+    "total": 10,
+    "page": 1,
+    "pageSize": 20,
+    "list": [
+      {
+        "identityId": 5,
+        "name": "李四",
+        "skills": ["采摘工", "分拣工"],
+        "price": 150,
+        "priceUnit": "DAY",
+        "status": 1,
+        "distance": 2.5
+      }
+    ]
   }
 }
 ```
 
 **业务逻辑**:
-1. 验证用户名存在
-2. 验证密码正确(BCrypt)
-3. 验证账号状态
-4. 签发 JWT token
-5. 记录登录日志
+1. 查询 status=1(空闲)的工人
+2. 可选按工种筛选(skills JSON字段 LIKE 查询)
+3. 计算距离(Haversine公式)
+4. 按距离升序排序
 
-#### POST /api/wx/auth/select-identity — 选择身份
+#### GET /api/wx/grower/buyers — 客商列表
 
-**请求参数**:
-```json
-{
-  "identityId": 1
-}
-```
+**请求参数**: `?page=1&pageSize=20`
 
 **响应参数**:
 ```json
@@ -318,14 +364,38 @@ CREATE INDEX idx_operator_id ON operation_log(operator_id);
   "code": 200,
   "message": "success",
   "data": {
-    "token": "new_jwt_token_with_identity"
+    "total": 5,
+    "page": 1,
+    "pageSize": 20,
+    "list": [
+      {
+        "identityId": 10,
+        "name": "王五果业",
+        "varieties": ["红富士", "嘎啦"],
+        "priceRange": "3.5-4.5",
+        "totalAmount": 100000,
+        "standards": "果径≥80mm",
+        "address": "昭通市水果批发市场"
+      }
+    ]
   }
 }
 ```
 
-### 3.2 用户接口
+---
+
+### 3.4 拨号接口
+
+#### POST /api/wx/call/phone — 拨号接口
 
-#### GET /api/wx/user/info — 获取用户信息
+**描述**: 获取对方手机号并记录拨号日志
+
+**请求参数**:
+```json
+{
+  "calleeIdentityId": 5
+}
+```
 
 **响应参数**:
 ```json
@@ -333,32 +403,24 @@ CREATE INDEX idx_operator_id ON operation_log(operator_id);
   "code": 200,
   "message": "success",
   "data": {
-    "userId": 1,
-    "realName": "张三",
     "phone": "138****8888",
-    "identities": [...],
-    "currentIdentity": {
-      "identityId": 1,
-      "identityType": "GROWER"
-    }
+    "realPhone": "13800138000"
   }
 }
 ```
 
-#### PUT /api/admin/user/status — 修改用户状态
+**业务逻辑**:
+1. 验证被拨方存在
+2. 记录拨号日志(call_log)
+3. 返回脱敏手机号给前端显示,真实手机号用于拨号
 
-**请求参数**:
-```json
-{
-  "userId": 1,
-  "status": 0,
-  "lockReason": "违规操作"
-}
-```
+---
+
+### 3.5 后台审核接口
 
-### 3.3 系统管理接口
+#### GET /api/admin/audit/grower-profile — 名片审核列表
 
-#### GET /api/admin/role/list — 角色列表
+**请求参数**: `?page=1&pageSize=10&status=0`
 
 **响应参数**:
 ```json
@@ -366,86 +428,52 @@ CREATE INDEX idx_operator_id ON operation_log(operator_id);
   "code": 200,
   "message": "success",
   "data": {
-    "total": 8,
+    "total": 3,
+    "page": 1,
+    "pageSize": 10,
     "list": [
       {
         "id": 1,
-        "roleName": "超级管理员",
-        "roleCode": "ADMIN",
-        "status": 0,
-        "isSystem": 1
+        "growerName": "张三",
+        "varieties": ["红富士"],
+        "yieldAmount": 50000,
+        "videoUrl": "...",
+        "photos": ["..."],
+        "auditStatus": 0,
+        "createdAt": "2026-05-30 10:00"
       }
     ]
   }
 }
 ```
 
-#### POST /api/admin/account — 创建账号
+#### PUT /api/admin/audit/grower-profile/{id} — 名片审核操作
 
 **请求参数**:
 ```json
 {
-  "username": "newadmin",
-  "password": "Admin123",
-  "realName": "新管理员",
-  "phone": "13800138000",
-  "roleId": 2
+  "action": "APPROVE",
+  "reason": ""
 }
 ```
 
-#### GET /api/admin/dict/list — 字典列表
-
-**请求参数**:
-```
-?dictType=apple_variety
-```
-
-**响应参数**:
+或驳回:
 ```json
 {
-  "code": 200,
-  "message": "success",
-  "data": [
-    {
-      "id": 1,
-      "dictType": "apple_variety",
-      "dictCode": "red_fuji",
-      "dictName": "红富士",
-      "sortOrder": 1
-    }
-  ]
+  "action": "REJECT",
+  "reason": "视频内容不清晰,请重新上传"
 }
 ```
 
-#### GET /api/admin/operation-log/list — 操作日志列表
-
-**请求参数**:
-```
-?page=1&pageSize=10&operatorId=1&startTime=2026-05-01&endTime=2026-05-30
-```
-
-### 3.4 审核接口
-
-#### GET /api/admin/audit/list — 审核列表
-
-**请求参数**:
-```
-?page=1&pageSize=10&targetType=GROWER_PROFILE&status=PENDING
-```
-
-#### PUT /api/admin/audit/{id} — 审核操作
-
-**请求参数**:
-```json
-{
-  "action": "APPROVE",
-  "reason": ""
-}
-```
+**业务逻辑**:
+1. 验证审核记录存在
+2. 驳回时 reason 不能为空
+3. 更新 grower_profile.audit_status
+4. 记录审核日志(audit_log)
 
-### 3.5 首页接口
+#### GET /api/admin/audit/recruit-review — 待复核招工列表
 
-#### GET /api/wx/home/grower — 果农首页
+**请求参数**: `?page=1&pageSize=10`
 
 **响应参数**:
 ```json
@@ -453,205 +481,171 @@ CREATE INDEX idx_operator_id ON operation_log(operator_id);
   "code": 200,
   "message": "success",
   "data": {
-    "greeting": "早安,张三!",
-    "marketPrices": [
+    "total": 2,
+    "list": [
       {
-        "variety": "红富士",
-        "priceMin": 3.5,
-        "priceMax": 4.2,
-        "trend": "up",
-        "updateTime": "2026-05-30 08:00"
+        "id": 1,
+        "workTypes": ["采摘工"],
+        "remark": "日薪300元,...",
+        "keywordFlag": 1,
+        "publisherName": "张三",
+        "createdAt": "2026-05-30 10:00"
       }
-    ],
-    "quickEntries": [
-      {"name": "找工人", "icon": "worker", "path": "/pages/worker/list"},
-      {"name": "找客商", "icon": "buyer", "path": "/pages/buyer/list"},
-      {"name": "买农资", "icon": "supplier", "path": "/pages/supplier/list"},
-      {"name": "发布需求", "icon": "publish", "path": "/pages/recruit/publish"}
     ]
   }
 }
 ```
 
-#### GET /api/wx/home/worker — 工人首页
+#### PUT /api/admin/audit/recruit-review/{id} — 待复核操作
 
-**响应参数**:
+**请求参数**:
 ```json
 {
-  "code": 200,
-  "message": "success",
-  "data": {
-    "recommendedRecruits": [
-      {
-        "id": 1,
-        "workType": "采摘",
-        "price": 150,
-        "priceUnit": "元/天",
-        "days": 5,
-        "peopleCount": 3,
-        "growerName": "李四",
-        "distance": 2.5
-      }
-    ]
-  }
+  "action": "NORMAL",
+  "reason": ""
 }
 ```
 
----
-
-## 四、安全设计
-
-### 4.1 认证流程
-
-```
-客户端请求
-    │
-    ▼
-拦截器检查 Token
-    │
-    ├── 无 Token → 401 未认证
-    │
-    ├── Token 无效 → 401 未认证
-    │
-    ├── Token 过期 → 401 未认证
-    │
-    └── Token 有效 → 解析用户信息
-                          │
-                          ▼
-                    检查权限(RBAC)
-                          │
-                          ├── 无权限 → 403 禁止访问
-                          │
-                          └── 有权限 → 执行业务逻辑
-```
-
-### 4.2 权限模型
-
-```
-用户 (sys_user)
-    │
-    └── N:M ──→ 角色 (sys_role)
-                    │
-                    └── N:M ──→ 权限 (sys_permission)
+或强制下架:
+```json
+{
+  "action": "FORCE_OFFLINE",
+  "reason": "内容违规"
+}
 ```
 
-**权限检查流程**:
-1. 从 Token 解析 userId 和 roleId
-2. 查询角色关联的权限列表
-3. 检查当前接口是否在权限列表中
-4. 无权限返回 403
-
-### 4.3 数据安全
-
-- **手机号**: AES 加密存储,SHA256 哈希索引
-- **密码**: BCrypt 加密
-- **Token**: JWT 签名,有效期控制
-- **接口**: 参数校验,SQL 注入防护
-- **日志**: 敏感操作记录
+**业务逻辑**:
+1. 验证招工存在
+2. NORMAL → keyword_flag=0
+3. FORCE_OFFLINE → status=0,记录原因
 
 ---
 
-## 五、技术选型
+## 四、安全设计(继承阶段一 + 扩展)
 
-### 5.1 后端技术栈
+### 4.1 文件上传安全
 
-| 技术 | 版本 | 用途 |
-|------|------|------|
-| Java | 1.8 | 开发语言 |
-| Spring Boot | 1.5.9 | 应用框架 |
-| MyBatis | 1.3.2 | ORM 框架 |
-| MySQL | 5.7+ | 数据库 |
-| Redis | 3.0+ | 缓存 |
-| JWT (jjwt) | 0.9.1 | Token 认证 |
-|阿里云 OSS | 3.15.1 | 文件存储 |
-| 阿里云短信 | 2.1.0 | 短信服务 |
-| Apache POI | 3.17 | Excel 处理 |
-
-### 5.2 前端技术栈
-
-| 技术 | 版本 | 用途 |
-|------|------|------|
-| 微信小程序 | 基础库 ≥2.0 | 移动端 |
-| Vue | 2.6.14 | 后台前端框架 |
-| Element UI | 2.15.9 | UI 组件库 |
-| ECharts | 5.4.3 | 数据可视化 |
-| Axios | 0.27.2 | HTTP 客户端 |
-
-### 5.3 开发工具
-
-| 工具 | 用途 |
-|------|------|
-| Maven | 构建工具 |
-| Git | 版本控制 |
-| Gogs | 代码仓库 |
-| Navicat/DBeaver | 数据库客户端 |
-| 微信开发者工具 | 小程序开发 |
-
----
+```
+前端上传 → 格式白名单校验 → 大小限制 → 存储到本地目录
+                                         │
+                                         ▼
+                                   返回文件URL
+```
 
-## 六、部署架构
+- **格式白名单**: 图片(jpg,jpeg,png,gif)、视频(mp4,mov,avi)
+- **大小限制**: 图片≤5MB,视频≤50MB
+- **EXIF清除**: 前端责任,后端不二次处理(性能考虑)
+- **路径安全**: 文件名使用UUID,防止路径穿越
 
-### 6.1 开发环境
+### 4.2 内容安全
 
 ```
-本地开发机
-├── JDK 1.8
-├── Maven 3.6.3
-├── MySQL 5.7
-├── Redis 3.0
-└── 微信开发者工具
+招工发布 → 敏感词检测 → keyword_flag 标记 → 不阻塞发布
+                                         │
+                                         ▼
+                                   待复核列表
 ```
 
-### 6.2 生产环境(规划)
+- **敏感词库**: 初始硬编码,仅含明确违规词
+- **检测方式**: 正则匹配
+- **处理方式**: keyword_flag=1 进入待复核,不阻塞发布
+
+### 4.3 拨号安全
 
 ```
-云服务器
-├── Nginx(反向代理)
-├── Spring Boot 应用(8080 端口)
-├── MySQL 数据库
-├── Redis 缓存
-└── 阿里云 OSS(文件存储)
+拨号请求 → 记录拨号日志 → 返回脱敏手机号 → 前端拨号
 ```
 
+- **日志记录**: 拨号方ID、被拨方ID、时间
+- **数据脱敏**: 列表不返回手机号,拨号接口单独获取
+
 ---
 
-## 七、关键决策记录
+## 五、关键技术方案
 
-### 7.1 认证方案选择
+### 5.1 距离计算(Haversine公式)
 
-**决策**: 采用 JWT Token 认证
+```java
+public class DistanceUtil {
+    private static final double EARTH_RADIUS = 6371; // 地球半径(km)
 
-**原因**:
-1. 无状态,适合分布式部署
-2. 小程序和后台可共用认证机制
-3. 支持自定义 payload(userId, identityId, identityType)
+    public static double calculate(double lat1, double lng1, double lat2, double lng2) {
+        double dLat = Math.toRadians(lat2 - lat1);
+        double dLng = Math.toRadians(lng2 - lng1);
+        double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
+                   Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) *
+                   Math.sin(dLng / 2) * Math.sin(dLng / 2);
+        double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
+        return EARTH_RADIUS * c;
+    }
+}
+```
 
-**权衡**:
-- Token 无法主动失效 → 采用 Redis 黑名单机制
-- Token 有效期管理 → 小程序24h,后台8h
+**说明**:
+- 输入:两个经纬度点(DECIMAL(10,7))
+- 输出:距离(km,保留1位小数)
+- 精度:小数点后7位,误差≤1米
 
-### 7.2 权限模型选择
+### 5.2 敏感词检测
 
-**决策**: 采用 RBAC(Role-Based Access Control)
+```java
+public class KeywordCheckService {
+    // 初始敏感词库(硬编码)
+    private static final List<String> KEYWORDS = Arrays.asList(
+        // 仅含明确违规词,不含正常业务词汇
+    );
 
-**原因**:
-1. 角色数量有限(8种),管理简单
-2. 权限变更通过角色控制,影响范围可控
-3. 支持细粒度权限(菜单+按钮)
+    public boolean containsSensitiveWord(String text) {
+        if (text == null) return false;
+        for (String keyword : KEYWORDS) {
+            if (text.contains(keyword)) return true;
+        }
+        return false;
+    }
+}
+```
 
-**权衡**:
-- 不支持数据级权限 → 后续可扩展
-- 权限变更需重新登录 → 可优化为实时生效
+### 5.3 视频压缩(异步)
 
-### 7.3 手机号存储方案
+```java
+@Service
+public class VideoCompressService {
+    @Async
+    public void compressVideo(String inputPath, String outputPath) {
+        // FFmpeg 命令:720p,码率2Mbps
+        // ffmpeg -i input.mp4 -vf scale=-1:720 -b:v 2M output.mp4
+    }
+}
+```
 
-**决策**: AES 加密存储 + SHA256 哈希索引
+**约束**:
+- 异步执行,不影响用户操作
+- 失败自动重试3次
+- 压缩后替换原文件
 
-**原因**:
-1. 满足隐私保护要求
-2. SHA256 哈希支持精确查询
-3. AES 加密支持解密显示(管理后台)
+---
 
-**权衡**:
-- 无法支持模糊查询 → 业务上不需要
-- 哈希碰撞风险 → SHA256 碰撞概率极低
+## 六、阶段2a新增文件清单
+
+| 文件 | 说明 |
+|------|------|
+| GrowerProfileController.java | 果农档案API |
+| GrowerProfileService.java | 果农档案业务逻辑 |
+| GrowerProfileMapper.xml | 果农档案MyBatis映射 |
+| RecruitController.java | 招工CRUD API |
+| RecruitService.java | 招工业务逻辑 |
+| RecruitMapper.xml | 招工MyBatis映射 |
+| WorkerSearchController.java | 工人列表API |
+| WorkerSearchService.java | 工人搜索业务逻辑 |
+| BuyerSearchController.java | 客商列表API |
+| BuyerSearchService.java | 客商搜索业务逻辑 |
+| CallPhoneController.java | 拨号API |
+| CallLogService.java | 拨号日志业务逻辑 |
+| CallLogMapper.xml | 拨号日志MyBatis映射 |
+| GrowerAuditController.java | 名片审核API |
+| GrowerAuditService.java | 名片审核业务逻辑 |
+| RecruitReviewController.java | 待复核API |
+| RecruitReviewService.java | 待复核业务逻辑 |
+| KeywordCheckService.java | 敏感词检测服务 |
+| DistanceUtil.java | 距离计算工具类 |
+| VideoCompressService.java | 视频压缩服务 |

+ 134 - 123
deliveries/team-b-architecture/tech-stack.md

@@ -1,8 +1,10 @@
-# 阶段一技术选型 — 基础设施与用户体系
+# 阶段2a技术选型 — 果农核心功能
+
+> 继承阶段一技术选型 + 阶段2a新增
 
 ---
 
-## 一、后端技术栈
+## 一、后端技术栈(继承阶段一)
 
 ### 1.1 核心框架
 
@@ -12,9 +14,8 @@
 | Spring Boot | 1.5.9.RELEASE | 应用框架 | 成熟稳定,社区支持好 |
 | MyBatis | 1.3.2 | ORM 框架 | 灵活的 SQL 控制,XML 映射 |
 | MySQL | 5.7+ | 数据库 | 客户环境限制,性能稳定 |
-| Redis | 3.0+ | 缓存 | 高性能,支持多种数据结构 |
 
-### 1.2 认证与安全
+### 1.2 认证与安全(继承)
 
 | 技术 | 版本 | 用途 | 选型理由 |
 |------|------|------|----------|
@@ -23,15 +24,15 @@
 | AES | - | 手机号加密 | 对称加密,性能好 |
 | SHA256 | - | 手机号哈希 | 单向哈希,支持索引查询 |
 
-### 1.3 文件处理
+### 1.3 文件处理(变更)
 
-| 技术 | 版本 | 用途 | 选型理由 |
-|------|------|------|----------|
-| 阿里云 OSS SDK | 3.15.1 | 文件存储 | 云服务稳定,CDN 加速 |
-| 阿里云短信 SDK | 2.1.0 | 短信服务 | 国内服务稳定 |
-| Apache POI | 3.17 | Excel 处理 | 功能完整,社区活跃 |
+| 技术 | 版本 | 用途 | 选型理由 | 变更说明 |
+|------|------|------|----------|----------|
+| 本地文件存储 | - | 文件存储 | 简化开发,降低依赖 | 替换阿里云OSS |
+| 阿里云短信 SDK | 2.1.0 | 短信服务 | 国内服务稳定 | 保留 |
+| Apache POI | 3.17 | Excel 处理 | 功能完整,社区活跃 | 保留 |
 
-### 1.4 工具库
+### 1.4 工具库(继承)
 
 | 技术 | 版本 | 用途 | 选型理由 |
 |------|------|------|----------|
@@ -41,9 +42,63 @@
 
 ---
 
-## 二、前端技术栈
+## 二、阶段2a新增技术需求
+
+### 2.1 距离计算
+
+| 技术 | 用途 | 说明 |
+|------|------|------|
+| Haversine公式 | 距离计算 | 纯数学计算,无外部依赖 |
+
+**实现方式**: 自定义 `DistanceUtil` 工具类
+
+```java
+// 核心公式
+double a = sin²(Δlat/2) + cos(lat1) × cos(lat2) × sin²(Δlng/2)
+double c = 2 × atan2(√a, √(1-a))
+double distance = R × c  // R=6371km
+```
+
+**精度**: DECIMAL(10,7),误差≤1米
+
+### 2.2 敏感词检测
+
+| 技术 | 用途 | 说明 |
+|------|------|------|
+| 正则表达式 | 敏感词匹配 | 纯Java实现,无外部依赖 |
+
+**实现方式**: 自定义 `KeywordCheckService`
+
+- 初始词库硬编码(仅含明确违规词)
+- 正则匹配,支持通配符
+- 后续可扩展为数据库词库
 
-### 2.1 小程序端
+### 2.3 视频压缩
+
+| 技术 | 版本 | 用途 | 选型理由 |
+|------|------|------|----------|
+| FFmpeg | 系统安装 | 视频压缩 | 功能强大,压缩效果好 |
+
+**实现方式**:
+- Spring `@Async` 异步执行
+- FFmpeg 命令行调用
+- 参数:720p分辨率,2Mbps码率
+
+**备选方案**: 如果FFmpeg不可用,使用Java原生压缩库(效果较差)
+
+### 2.4 地理编码(可选)
+
+| 技术 | 用途 | 说明 |
+|------|------|------|
+| 高德/百度地图API | 地址→经纬度 | 可选,前端可处理 |
+
+**说明**: 地址→经纬度转换可由前端完成,后端仅存储经纬度
+
+---
+
+## 三、前端技术栈(继承阶段一)
+
+### 3.1 小程序端
 
 | 技术 | 版本 | 用途 | 选型理由 |
 |------|------|------|----------|
@@ -52,133 +107,85 @@
 | WXSS | - | 样式语言 | 微信小程序原生 |
 | JavaScript | ES6 | 脚本语言 | 小程序支持 |
 
-### 2.2 后台管理端
+**阶段2a新增小程序能力**:
+- `wx.chooseImage()` — 选择图片
+- `wx.chooseVideo()` — 选择视频
+- `wx.makePhoneCall()` — 拨打电话
+- `wx.getRecorderManager()` — 语音输入(可选)
+
+### 3.2 后台管理端(继承)
 
 | 技术 | 版本 | 用途 | 选型理由 |
 |------|------|------|----------|
 | Vue | 2.6.14 | 前端框架 | 成熟稳定,学习成本低 |
-| Vue Router | 3.5.4 | 路由管理 | Vue 官方路由 |
-| Vuex | 3.6.2 | 状态管理 | Vue 官方状态管理 |
 | Element UI | 2.15.9 | UI 组件库 | 组件丰富,文档完善 |
 | Axios | 0.27.2 | HTTP 客户端 | 支持 Promise,拦截器 |
-| ECharts | 5.4.3 | 数据可视化 | 功能强大,图表丰富 |
 
 ---
 
-## 三、开发工具
-
-### 3.1 构建工具
-
-| 工具 | 版本 | 用途 |
-|------|------|------|
-| Maven | 3.6.3 | 后端构建 |
-| npm | - | 前端依赖管理 |
-| Vue CLI | 4.5.19 | 前端构建 |
-
-### 3.2 版本控制
+## 四、开发工具(继承阶段一)
 
 | 工具 | 用途 |
 |------|------|
+| Maven | 后端构建 |
 | Git | 版本控制 |
 | Gogs | 代码仓库(自托管) |
-
-### 3.3 开发环境
-
-| 工具 | 用途 |
-|------|------|
-| JDK 1.8 | Java 开发环境 |
-| IntelliJ IDEA | Java IDE |
-| VS Code | 前端 IDE |
 | 微信开发者工具 | 小程序开发调试 |
 | Navicat/DBeaver | 数据库客户端 |
-| Redis Desktop Manager | Redis 客户端 |
 
 ---
 
-## 四、部署环境
-
-### 4.1 服务器配置(规划)
-
-| 资源 | 配置 | 说明 |
-|------|------|------|
-| CPU | 2 核 | 足够支撑初期访问量 |
-| 内存 | 4 GB | Spring Boot + MySQL + Redis |
-| 磁盘 | 50 GB | 系统 + 数据 + 日志 |
-| 带宽 | 5 Mbps | 足够支撑初期访问量 |
-
-### 4.2 软件环境
-
-| 软件 | 版本 | 用途 |
-|------|------|------|
-| CentOS | 7.x | 操作系统 |
-| Nginx | 1.18+ | 反向代理 |
-| MySQL | 5.7 | 数据库 |
-| Redis | 3.0+ | 缓存 |
-| JDK | 1.8 | Java 运行环境 |
-
-### 4.3 云服务
-
-| 服务 | 用途 | 配置 |
-|------|------|------|
-| 阿里云 OSS | 文件存储 | 私有读写,CORS 配置 |
-| 阿里云 SMS | 短信服务 | 签名:洒渔用工 |
-| 微信小程序 | 移动端 | AppID 待申请 |
-
----
-
-## 五、数据库设计规范
+## 五、数据库设计规范(继承阶段一)
 
 ### 5.1 命名规范
 
-- **表名**: 小写字母 + 下划线,如 `sys_user`
-- **字段名**: 小写字母 + 下划线,如 `user_name`
+- **表名**: 小写字母 + 下划线,如 `grower_profile`
+- **字段名**: 小写字母 + 下划线,如 `user_identity_id`
 - **主键**: `id`,自增
-- **索引**: `idx_` 前缀,如 `idx_user_id`
-- **唯一索引**: `uk_` 前缀,如 `uk_phone_hash`
-
-### 5.2 字段规范
-
-- **字符串**: VARCHAR,长度按实际需求
-- **数字**: INT/BIGINT/DECIMAL
-- **时间**: DATETIME
-- **状态**: TINYINT,0/1/2
-- **布尔**: TINYINT,0 否 1 是
+- **索引**: `idx_` 前缀
+- **唯一索引**: `uk_` 前缀
 
-### 5.3 必备字段
+### 5.2 阶段2a JSON字段规范
 
-每个业务表必须包含:
-- `id` — 主键
-- `created_at` — 创建时间
-- `updated_at` — 更新时间
+| 字段 | 表 | 格式示例 |
+|------|-----|---------|
+| varieties | grower_profile | `["红富士","嘎啦"]` |
+| photos | grower_profile | `["http://...1.jpg","http://...2.jpg"]` |
+| work_types | recruit_info | `["采摘工","分拣工"]` |
+| skills | worker_profile | `["采摘","套袋"]` |
 
 ---
 
-## 六、接口设计规范
+## 六、接口设计规范(继承阶段一)
 
 ### 6.1 路径规范
 
 - **小程序端**: `/api/wx/{module}/{action}`
 - **后台管理端**: `/api/admin/{module}/{action}`
-- **模块**: 用户模块 `user`,系统模块 `system`,审核模块 `audit`,首页模块 `home`
 
-### 6.2 请求规范
+### 6.2 阶段2a新增模块路径
 
-- **GET**: 查询操作,参数通过 URL 传递
-- **POST**: 创建操作,参数通过 Body 传递
-- **PUT**: 更新操作,参数通过 Body 传递
-- **DELETE**: 删除操作
+| 模块 | 路径前缀 |
+|------|---------|
+| 果农名片 | /api/wx/grower/profile |
+| 招工管理 | /api/wx/grower/recruit |
+| 找工人 | /api/wx/grower/workers |
+| 找客商 | /api/wx/grower/buyers |
+| 拨号 | /api/wx/call/phone |
+| 名片审核 | /api/admin/audit/grower-profile |
+| 待复核 | /api/admin/audit/recruit-review |
 
-### 6.3 响应规范
+### 6.3 响应规范(继承)
 
 ```json
 {
-  "code": 200,       // 状态码
-  "message": "success", // 状态描述
-  "data": {}         // 业务数据
+  "code": 200,
+  "message": "success",
+  "data": {}
 }
 ```
 
-### 6.4 错误码规范
+### 6.4 错误码规范(继承 + 扩展)
 
 | 错误码 | 含义 | 说明 |
 |--------|------|------|
@@ -188,48 +195,52 @@
 | 403 | 禁止访问 | 无权限 |
 | 404 | 未找到 | 资源不存在 |
 | 500 | 服务器错误 | 内部异常 |
-| 1001-1099 | 业务错误 | 自定义业务错误码 |
+| 1001-1099 | 认证错误 | 阶段一业务错误码 |
+| 2001-2099 | 果农模块错误 | 阶段2a新增 |
+| 3001-3099 | 招工模块错误 | 阶段2a新增 |
+| 4001-4099 | 拨号模块错误 | 阶段2a新增 |
+| 5001-5099 | 审核模块错误 | 阶段2a新增 |
 
 ---
 
-## 七、安全设计规范
+## 七、安全设计规范(继承 + 扩展)
 
-### 7.1 认证安全
+### 7.1 文件上传安全(新增)
 
-- **Token**: JWT 签名,有效期控制
-- **密码**: BCrypt 加密,强度校验
-- **登录**: 失败次数限制,锁定机制
+- **格式白名单**: 图片(jpg,jpeg,png,gif)、视频(mp4,mov,avi)
+- **大小限制**: 图片≤5MB,视频≤50MB
+- **文件名**: UUID重命名,防止路径穿越
+- **EXIF清除**: 前端责任
 
-### 7.2 数据安全
+### 7.2 内容安全(新增)
 
-- **手机号**: AES 加密存储,SHA256 哈希索引
-- **敏感数据**: 接口返回脱敏
-- **SQL 注入**: MyBatis #{} 参数化
+- **敏感词检测**: 正则匹配
+- **处理方式**: keyword_flag标记,不阻塞发布
+- **人工复核**: 审核员处理待复核列表
 
-### 7.3 接口安全
+### 7.3 拨号安全(新增)
 
-- **权限控制**: RBAC 模型
-- **参数校验**: 必填校验、类型校验、范围校验
-- **防重放**: Token 过期机制
+- **日志记录**: 拨号方ID、被拨方ID、时间
+- **数据脱敏**: 列表不返回手机号
 
 ---
 
-## 八、性能设计规范
+## 八、性能设计规范(继承 + 扩展)
 
-### 8.1 数据库性能
+### 8.1 距离计算性能(新增)
 
-- **索引**: 高频查询字段建立索引
-- **连接池**: 最大连接数 20
-- **慢查询**: 开启慢查询日志
+- **计算方式**: 实时计算,不缓存
+- **优化**: 可先用矩形范围筛选,再精确计算
+- **精度**: DECIMAL(10,7)
 
-### 8.2 缓存策略
+### 8.2 文件上传性能(新增)
 
-- **Token 黑名单**: Redis 存储
-- **验证码**: Redis 存储,5 分钟过期
-- **数据大屏**: Redis 缓存,定时更新
+- **上传时间**: ≤50MB文件,局域网≤30s
+- **视频压缩**: 异步处理,不影响用户操作
+- **压缩重试**: 失败自动重试3次
 
-### 8.3 接口性能
+### 8.3 接口性能(继承)
 
 - **响应时间**: ≤500ms(95%请求)
 - **并发**: ≥100 用户
-- **分页**: 默认每页 10 条,最大 100 条
+- **分页**: 默认每页 20 条