# 居家上门服务系统 — 可执行实现方案 > 生成日期:2026-05-15 > 基于:V2.0 工程落地增强版 + V2.1 行业经验增强版 + V2.2 边界限制增强版 > 项目状态:全新仓库,从零搭建 --- ## 1. 需求与约束摘要 | 项 | 内容 | |---|---| | **任务类型** | 新接口 / 新能力开发(全新系统) | | **目标** | 实现居家上门服务全链路闭环系统:需求受理 → 评估定级 → 方案制定 → 派单调度 → 上门执行 → 过程监管 → 验收反馈 → 结算归档 | | **硬边界** | Spring Boot / Java 17+、PostgreSQL、Redis、MQTT(通知)、对象存储(文件)、RESTful+action、OpenAPI 3.1、hss_表前缀、Outbox通知、四层状态机、幂等写、前端只传动作不传状态、敏感数据授权脱敏审计 | | **范围** | 全部模块 + delivery 端小程序 | --- ## 2. 代码依据 本项目为全新仓库,无现有后端代码。以下为架构文档依据: | 依据文件 | 路径 | 职责 | |---|---|---| | V2.0 工程落地增强版 | `docs/ architecture/居家上门服务闭环流程文档_V2工程落地增强版.md` | 业务闭环流程、四层状态机、数据模型、调度算法、通知设计、合规安全、结算对账 | | V2.1 行业经验增强版 | `docs/ architecture/居家上门服务闭环流程文档_V2.1_行业经验增强版.md` | 美团三层调度、ETA预测、VRPTW建模、delivery智能助手、运力运营中心、主数据平台、SRE稳定性 | | V2.2 边界限制增强版 | `/home/akoo/居家服务/居家上门服务闭环流程文档_V2.2_边界限制增强版.md` | 12条硬约束、技术栈锁定、DDL边界、接口风格、部署环境、协作边界 | --- ## 3. DDL 依据 当前仓库无 `db/init.sql` 与 `db/update.sql`。以下设计基于 V2.0 文档 4.1 节数据域划分(第 939-958 行),结合 V2.2 第 16.3 节 DDL 边界约束。 | 数据域 | 设计表名(hss_前缀) | 来源 | |---|---|---| | 申请域 | `hss_service_applications` | V2.0 §4.1 | | 用户画像域 | `hss_patient_profiles` | V2.0 §4.1 | | 评估域 | `hss_assessment_tasks`、`hss_assessment_reports` | V2.0 §4.1 | | 异议域 | `hss_objections` | V2.0 §4.2 | | 方案域 | `hss_service_plans`、`hss_service_plan_items`、`hss_plan_versions` | V2.0 §4.1 | | 计划域 | `hss_service_schedules` | V2.0 §4.1 | | 工单域 | `hss_work_orders`、`hss_work_order_items` | V2.0 §4.1 | | 执行域 | `hss_checkins`、`hss_execution_records`、`hss_evidence_files` | V2.0 §4.1 | | 异常域 | `hss_exceptions`、`hss_exception_actions` | V2.0 §4.1 | | 监管域 | `hss_spot_checks`、`hss_violations`、`hss_corrections` | V2.0 §4.1 | | 验收域 | `hss_acceptances`、`hss_complaints` | V2.0 §4.1 | | 结算域 | `hss_settlements`、`hss_settlement_items`、`hss_payments`、`hss_refunds` | V2.0 §4.1 | | 归档域 | `hss_ledgers`、`hss_archive_files` | V2.0 §4.1 | | 通知域 | `hss_notification_outbox`、`hss_notification_receipts` | V2.0 §7.2 | | 审计域 | `hss_audit_logs`、`hss_state_transitions` | V2.0 §3.6、§8.4 | | 合规域 | `hss_consent_records`、`hss_data_access_logs` | V2.0 §8.2 | | 调度域(V2.1扩展) | `hss_service_grids`、`hss_grid_capacity_daily`、`hss_staff_skill_capacity`、`hss_capacity_forecasts`、`hss_capacity_alerts` | V2.1 §15.2.1 | | 主数据域(V2.1扩展) | `hss_md_orgs`、`hss_md_staff`、`hss_md_qualifications`、`hss_md_service_items`、`hss_md_regions`、`hss_md_price_rules` | V2.1 §15.7 | --- ## 4. 改动范围清单 全部为新增文件。 | 路径 | 增/删/改 | 摘要 | |---|---|---| | `pom.xml` | 增 | Maven 构建配置,Spring Boot 3.x + Java 17 | | `src/main/java/com/meizhou/hss/` | 增 | 根包目录 | | `src/main/java/.../common/` | 增 | 公共模块:响应体、异常、工具类、幂等注解、审计切面 | | `src/main/java/.../config/` | 增 | Spring 配置:Security、Redis、MQTT、对象存储、定时任务、OpenAPI | | `src/main/java/.../statemachine/` | 增 | 四层状态机引擎:申请、方案、工单、结算 | | `src/main/java/.../module/application/` | 增 | 申请域:controller/service/repository/entity/dto | | `src/main/java/.../module/assessment/` | 增 | 评估域:controller/service/repository/entity/dto | | `src/main/java/.../module/plan/` | 增 | 方案域:controller/service/repository/entity/dto | | `src/main/java/.../module/schedule/` | 增 | 计划与调度域 | | `src/main/java/.../module/workorder/` | 增 | 工单域 | | `src/main/java/.../module/execution/` | 增 | 执行域:签到、执行记录、证据链 | | `src/main/java/.../module/exception/` | 增 | 异常域:异常上报与处理 | | `src/main/java/.../module/supervision/` | 增 | 监管域:抽查、违规、整改 | | `src/main/java/.../module/acceptance/` | 增 | 验收域:验收、评价、投诉 | | `src/main/java/.../module/settlement/` | 增 | 结算域:结算、支付、退款 | | `src/main/java/.../module/archive/` | 增 | 归档域:台账、归档文件 | | `src/main/java/.../module/notification/` | 增 | 通知域:Outbox 与回执 | | `src/main/java/.../module/audit/` | 增 | 审计域:审计日志、状态流转 | | `src/main/java/.../module/compliance/` | 增 | 合规域:授权同意、数据访问日志 | | `src/main/java/.../module/masterdata/` | 增 | 主数据域:机构、人员、资质、服务项目、区域、价格 | | `src/main/java/.../module/capacity/` | 增 | 运力域:服务网格、容量、预测 | | `src/main/resources/db/migration/` | 增 | Flyway 迁移脚本 | | `src/main/resources/application.yml` | 增 | 主配置 | | `src/test/java/.../` | 增 | 单元测试与集成测试 | | `delivery-miniapp/` | 增 | delivery 端小程序(uni-app) | --- ## 5. 方案概述 ### 5.1 分层架构 ``` ┌──────────────────────────────────────────────┐ │ Controller 层(REST + action-style REST) │ │ - 参数校验(Spring Validation) │ │ - 幂等拦截(Idempotency-Key) │ │ - 权限注解(@PreAuthorize) │ │ - OpenAPI 注解(SpringDoc) │ └──────────────────┬───────────────────────────┘ │ ┌──────────────────▼───────────────────────────┐ │ Service 层(业务编排) │ │ - 状态机调用(不跳过状态检查) │ │ - 事务边界(@Transactional) │ │ - Outbox 写入(同事务) │ │ - 审计日志写入 │ └──────────────────┬───────────────────────────┘ │ ┌──────────────────▼───────────────────────────┐ │ Repository 层(数据访问) │ │ - MyBatis-Plus BaseMapper │ │ - 自定义 SQL(复杂查询/统计) │ │ - 乐观锁 version 字段 │ └──────────────────┬───────────────────────────┘ │ ┌──────────────────▼───────────────────────────┐ │ Domain 层(领域对象) │ │ - Entity(映射表) │ │ - DTO / VO / Request / Response │ │ - 状态枚举 │ │ - 业务异常 │ └──────────────────────────────────────────────┘ ``` ### 5.2 核心数据流 ```text POST /applications → 创建申请(DRAFT) POST /applications/{id}/submit → 提交申请(PENDING_ACCEPTANCE) POST /applications/{id}/accept → 受理通过(PENDING_ASSESSMENT) POST /assessments/{id}/assign → 派发评估(ASSESSING) POST /assessments/{id}/submit → 提交评估(ASSESSMENT_PASSED) POST /plans → 创建方案(PLAN_DRAFT) POST /plans/{id}/submit → 提交签署(PLAN_PENDING_SIGN) POST /plans/{id}/sign → 签署通过(PLAN_EFFECTIVE) POST /schedules/{id}/generate → 生成服务计划 POST /work-orders/{id}/dispatch → 派单(ORDER_ASSIGNED) POST /work-orders/{id}/accept → 接单(ORDER_ACCEPTED) POST /work-orders/{id}/check-in → 签到(ORDER_CHECKED_IN) POST /work-orders/{id}/start → 开始服务(ORDER_IN_SERVICE) POST /execution-records → 逐项记录执行 POST /work-orders/{id}/finish → 完成服务(ORDER_COMPLETED) POST /acceptances → 发起验收(ACCEPTANCE_PENDING) POST /acceptances/{id}/confirm → 验收通过(ACCEPTED) POST /settlements/{id}/generate → 生成结算单 POST /settlements/{id}/approve → 审核通过 POST /settlements/{id}/pay → 支付完成(SETTLEMENT_PAID) POST /settlements/{id}/archive → 归档(ARCHIVED) ``` ### 5.3 异常流 ```text 任何非终态 → POST /{entity}/{id}/cancel → CANCELLED(需原因) 评估中 → POST /assessments/{id}/object → REVIEWING → 维持/重评 方案待签署 → POST /plans/{id}/reject → PLAN_REJECTED → 重新编制 工单已派单 → POST /work-orders/{id}/reassign → 改派 工单服务中 → POST /work-orders/{id}/report-exception → ORDER_EXCEPTION → 协调/改派/关闭 验收拒绝 → POST /acceptances/{id}/reject → 创建问题处理单 结算不通过 → POST /settlements/{id}/return → 退回修改 ``` --- ## 6. 代码级修改说明(核心) ### 6.1 项目初始化 **文件**:`pom.xml`(新增) 当前逻辑:不存在。 拟议改动:创建 Maven 父 POM,管理所有模块依赖。 ```xml 4.0.0 org.springframework.boot spring-boot-starter-parent 3.3.0 com.meizhou hss-home-service 1.0.0-SNAPSHOT HSS Home Service 17 3.5.6 2.5.0 10.11.0 org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-security org.springframework.boot spring-boot-starter-validation org.springframework.boot spring-boot-starter-data-redis com.baomidou mybatis-plus-spring-boot3-starter ${mybatis-plus.version} org.postgresql postgresql org.flywaydb flyway-core org.flywaydb flyway-database-postgresql org.springdoc springdoc-openapi-starter-webmvc-ui ${springdoc.version} org.springframework.boot spring-boot-starter-test test ``` ### 6.2 公共模块 **目录**:`src/main/java/com/meizhou/hss/common/`(新增) #### 6.2.1 统一响应体 **文件**:`ApiResponse.java`(新增) 当前逻辑:不存在。 拟议改动:所有接口统一使用此响应格式。 ```java // 新增 @Data @NoArgsConstructor @AllArgsConstructor public class ApiResponse { private int code; // 200 成功 private String message; private T data; private String requestId; // UUID private long timestamp; // System.currentTimeMillis() public static ApiResponse ok(T data) { ... } public static ApiResponse fail(int code, String message) { ... } } ``` #### 6.2.2 幂等拦截 **文件**:`@Idempotent.java` + `IdempotentAspect.java`(新增) 当前逻辑:不存在。 拟议改动:基于 Redis 实现 request_id 幂等。相同 `requestId + action + entityId` 在 TTL 内重复提交返回首次结果。 ```java // 新增注解 @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface Idempotent { String prefix() default "idempotent"; long ttlSeconds() default 300; } // 新增切面 @Aspect @Component public class IdempotentAspect { @Around("@annotation(idempotent)") public Object around(ProceedingJoinPoint pjp, Idempotent idempotent) { // 从请求头获取 Idempotency-Key // 拼接 key = prefix + ":" + idempotencyKey // Redis SET NX EX,成功则执行,失败则返回缓存结果 } } ``` #### 6.2.3 审计字段基类 **文件**:`BaseEntity.java`(新增) ```java // 新增 - 所有 hss_ 表 Entity 继承此类 @Data public abstract class BaseEntity { @TableId(type = IdType.AUTO) private Long id; private Long tenantId; private Long orgId; private String status; private Integer version; private LocalDateTime createdAt; private LocalDateTime updatedAt; private Long createdBy; private Long updatedBy; @TableLogic private Integer deleted; // 0 正常, 1 已删除 } ``` ### 6.3 状态机引擎 **目录**:`src/main/java/com/meizhou/hss/statemachine/`(新增) #### 文件清单 | 文件 | 职责 | |---|---| | `StateMachine.java` | 通用状态机接口:`transition(entity, action, context) → targetState` | | `StateMachineConfig.java` | 状态转换规则配置(从 YAML/DB 加载) | | `TransitionRule.java` | 单条转换规则:fromStatus + action + role → toStatus + constraints | | `ApplicationStateMachine.java` | 申请状态机实现 | | `PlanStateMachine.java` | 方案状态机实现 | | `WorkOrderStateMachine.java` | 工单状态机实现 | | `SettlementStateMachine.java` | 结算状态机实现 | | `StateTransitionException.java` | 非法状态转换异常 | **当前逻辑**:不存在。 **拟议改动**:基于 V2.0 文档 §3.2~3.5 的状态转换表实现。 ```java // 新增 - TransitionRule public record TransitionRule( String entityType, // application / plan / work_order / settlement String fromStatus, String action, // submit / accept / reject / check-in / finish / approve / ... String requiredRole, // 允许执行此动作的角色 String toStatus, List constraints // 约束条件:如 "hasAssessmentReport"、"amountMatched" ) {} // 新增 - StateMachine 核心方法 public class StateMachine { // 校验转换是否合法 public boolean canTransition(String entityType, String fromStatus, String action, String role); // 执行转换(不通过抛 StateTransitionException) public String transition(String entityType, String fromStatus, String action, String role, Map context); // 记录状态流转到 hss_state_transitions private void recordTransition(...); } ``` 状态转换规则初始化(基于文档 §3.2~3.5,部分示例): ```java // 新增 - 申请状态机规则 rules.add(new TransitionRule("application", "DRAFT", "submit", "APPLICANT", "PENDING_ACCEPTANCE", List.of("materialsComplete"))); rules.add(new TransitionRule("application", "PENDING_ACCEPTANCE", "accept", "RECEPTIONIST", "PENDING_ASSESSMENT", List.of("ageCheck", "qualificationCheck", "duplicateCheck"))); rules.add(new TransitionRule("application", "PENDING_ACCEPTANCE", "return", "RECEPTIONIST", "RETURNED", List.of("returnReasonRequired"))); // ... 等全部规则 ``` ### 6.4 申请域模块 **目录**:`src/main/java/com/meizhou/hss/module/application/` #### 文件清单 | 文件 | 职责 | |---|---| | `entity/ServiceApplicationEntity.java` | 映射 `hss_service_applications` | | `dto/ApplicationCreateRequest.java` | 创建申请请求 DTO | | `dto/ApplicationSubmitRequest.java` | 提交申请请求 DTO | | `dto/ApplicationResponse.java` | 申请响应 DTO | | `dto/ApplicationListQuery.java` | 列表查询参数 | | `repository/ServiceApplicationMapper.java` | MyBatis-Plus Mapper | | `service/ApplicationService.java` | 业务逻辑 | | `service/ApplicationValidationService.java` | 自动校验(材料完整性、资格、重复申请) | | `controller/ApplicationController.java` | REST 接口 | **当前逻辑**:不存在。 **拟议改动**: `ApplicationController.java`: ```java // 新增 @RestController @RequestMapping("/api/hss/applications") @Tag(name = "服务申请") public class ApplicationController { @PostMapping @Idempotent(prefix = "app:create") public ApiResponse create( @Valid @RequestBody ApplicationCreateRequest req) { // Service: 校验 → 创建 DRAFT 状态申请 → 记录状态流转 } @PostMapping("/{id}/submit") @Idempotent(prefix = "app:submit") public ApiResponse submit( @PathVariable Long id, @Valid @RequestBody ApplicationSubmitRequest req) { // Service: 状态机 DRAFT→PENDING_ACCEPTANCE → 写 Outbox 通知受理员 } @PostMapping("/{id}/accept") @Idempotent(prefix = "app:accept") @PreAuthorize("hasRole('RECEPTIONIST')") public ApiResponse accept(@PathVariable Long id) { // Service: 校验(材料+资格+重复)→ 状态机 PENDING_ACCEPTANCE→PENDING_ASSESSMENT } @PostMapping("/{id}/return") @Idempotent(prefix = "app:return") @PreAuthorize("hasRole('RECEPTIONIST')") public ApiResponse returnApplication( @PathVariable Long id, @Valid @RequestBody ReturnRequest req) { // 约束:必须填写退回原因 } @PostMapping("/{id}/cancel") @Idempotent(prefix = "app:cancel") public ApiResponse cancel(@PathVariable Long id) { // 约束:申请人本人或授权家属 } @GetMapping public ApiResponse> list(ApplicationListQuery query) { // 数据范围:按 tenant_id、org_id、角色过滤 } @GetMapping("/{id}") public ApiResponse getById(@PathVariable Long id) { // 脱敏:非授权角色隐藏完整地址、电话 } } ``` **注**:其余模块(评估、方案、调度、工单、执行、异常、监管、验收、结算、归档、通知、审计、合规、主数据、运力)的代码结构遵循相同模式,此处为避免文档过度膨胀,仅输出申请域作为样板。完整代码在实施阶段逐模块编写。 ### 6.5 通知 Outbox 模块 **目录**:`src/main/java/com/meizhou/hss/module/notification/` 关键设计: ```java // 新增 - 通知创建(在业务事务内调用) @Service public class NotificationService { // 与业务在同一事务中写入 Outbox @Transactional public void createNotification(Long entityId, String entityType, String channel, String template, Map params) { NotificationOutboxEntity outbox = new NotificationOutboxEntity(); outbox.setEntityId(entityId); outbox.setChannel(channel); // MQTT / WECHAT / SMS outbox.setStatus("CREATED"); outbox.setRequestId(IdempotencyContext.getRequestId()); outboxMapper.insert(outbox); } } // 新增 - 定时任务:扫描 Outbox 并异步发送 @Component public class NotificationSender { @Scheduled(fixedDelay = 2000) // 每2秒扫描 public void sendPending() { // SELECT * FROM hss_notification_outbox WHERE status='CREATED' LIMIT 100 // 发送 → 更新 status=SENT → 记录 receipt // 失败 → status=FAILED, retry_count+1 } } ``` ### 6.6 审计模块 **目录**:`src/main/java/com/meizhou/hss/module/audit/` ```java // 新增 - AOP 切面自动记录审计 @Aspect @Component public class AuditAspect { @Around("@annotation(auditable)") public Object around(ProceedingJoinPoint pjp, Auditable auditable) { // 记录:操作人、时间、IP、设备、操作类型、业务对象ID、前后值 } } // 新增 - 状态流转记录(状态机内部调用) // 写入 hss_state_transitions: // entity_type, entity_id, from_status, action, to_status, // operator_id, operator_role, reason, request_id, created_at ``` ### 6.7 调度算法模块 **目录**:`src/main/java/com/meizhou/hss/module/schedule/algorithm/` ```java // 新增 - 两阶段调度 @Service public class DispatchAlgorithm { // 阶段1:硬约束过滤 public List hardFilter(List allStaff, WorkOrder order) { return allStaff.stream() .filter(s -> s.getStatus() == StaffStatus.ACTIVE) .filter(s -> s.hasQualification(order.getRequiredSkills())) .filter(s -> s.getRegion().contains(order.getServiceAddress().getRegion())) .filter(s -> !hasTimeConflict(s, order)) .filter(s -> !s.isBlacklisted()) .filter(s -> s.getTodayOrderCount() < s.getMaxDailyOrders()) .toList(); } // 阶段2:软约束评分 public List scoreAndRank(List candidates, WorkOrder order) { // score = distance * 0.25 + skill * 0.25 + workload * 0.20 // + rating * 0.15 + response * 0.10 + familiarity * 0.05 // 返回 Top5,附解释 } } ``` --- ## 7. 接口设计方案(任务类型=1 强制) ### 7.1 核心接口清单 按主链路阶段组织,以下为核心接口设计。 #### 7.1.1 服务申请接口组 **接口1:创建服务申请** | 接口名称 | 创建服务申请 | | -------- | ------------------------------------------------------ | | 接口地址 | `/api/hss/applications` | | 请求方式 | `POST` | | 接口描述 | 服务对象/家属提交服务申请,创建后状态为 DRAFT | | 参数名 | 类型 | 是否必填 | 说明 | | ----------- | ------ | -------- | --------------------------- | | patientId | string | 是 | 服务对象ID | | serviceType | string | 是 | 服务类型枚举:HOME_CARE / REHABILITATION / BATH_ASSIST / ASSESSMENT | | channel | string | 是 | 申请渠道:APP / WECHAT / PHONE / COMMUNITY / HOSPITAL | | contactName | string | 是 | 联系人姓名 | | contactPhone | string | 是 | 联系人电话 | | address | string | 是 | 服务地址 | | regionCode | string | 是 | 区域编码 | | notes | string | 否 | 备注说明 | | attachmentIds | array | 否 | 附件ID列表 | | 字段路径 | 类型 | 示例 | 说明 | | -------- | ------- | -------------- | -------------------- | | code | int | 200 | 状态码 | | success | boolean | true | 是否成功 | | message | string | 申请创建成功 | 响应消息 | | data.id | string | 1001 | 申请ID | | data.status | string | DRAFT | 申请状态 | | data.createdAt | string | 2026-05-15T10:30:00 | 创建时间 | 请求示例: ```json { "patientId": "2001", "serviceType": "HOME_CARE", "channel": "WECHAT", "contactName": "张三", "contactPhone": "138****5678", "address": "梅江区金山街道XX小区3栋201", "regionCode": "441402001", "notes": "老人独居,需要日常护理", "attachmentIds": ["att_001", "att_002"] } ``` 返回示例: ```json { "code": 200, "message": "申请创建成功", "data": { "id": "1001", "status": "DRAFT", "createdAt": "2026-05-15T10:30:00" }, "requestId": "req-uuid-abc123", "timestamp": 1715747400000 } ``` --- **接口2:提交服务申请** | 接口名称 | 提交服务申请 | | -------- | ------------------------------------------------------ | | 接口地址 | `/api/hss/applications/{id}/submit` | | 请求方式 | `POST` | | 接口描述 | 将草稿状态申请提交为待受理,触发自动校验 | | 参数名 | 类型 | 是否必填 | 说明 | | ----------- | ------ | -------- | --------------------------- | | id | string | 是 | 路径参数,申请ID | | 字段路径 | 类型 | 示例 | 说明 | | -------- | ------- | -------------- | -------------------- | | code | int | 200 | 状态码 | | data.status | string | PENDING_ACCEPTANCE | 新状态 | | data.validationResult.passed | boolean | true | 自动校验结果 | --- **接口3:受理通过** | 接口名称 | 受理通过 | | -------- | ------------------------------------------------------ | | 接口地址 | `/api/hss/applications/{id}/accept` | | 请求方式 | `POST` | | 接口描述 | 受理员审核通过,申请进入待评估状态 | | 参数名 | 类型 | 是否必填 | 说明 | | ----------- | ------ | -------- | --------------------------- | | id | string | 是 | 路径参数,申请ID | | reason | string | 否 | 审核备注 | --- **接口4:受理退回** | 接口名称 | 受理退回 | | -------- | ------------------------------------------------------ | | 接口地址 | `/api/hss/applications/{id}/return` | | 请求方式 | `POST` | | 接口描述 | 受理员退回申请,需填写退回原因 | | 参数名 | 类型 | 是否必填 | 说明 | | ----------- | ------ | -------- | --------------------------- | | id | string | 是 | 路径参数 | | reason | string | 是 | 退回原因(必填) | --- #### 7.1.2 工单执行接口组 **接口5:GPS 签到** | 接口名称 | GPS签到 | | -------- | ------------------------------------------------------ | | 接口地址 | `/api/hss/work-orders/{id}/check-in` | | 请求方式 | `POST` | | 接口描述 | 服务人员在服务地址200米内签到,需GPS+照片+对象确认 | | 参数名 | 类型 | 是否必填 | 说明 | | ----------- | ------ | -------- | --------------------------- | | id | string | 是 | 工单ID | | latitude | number | 是 | 纬度 | | longitude | number | 是 | 经度 | | photoFileId | string | 是 | 现场照片文件ID | | patientConfirmed | boolean | 是 | 服务对象是否确认 | | patientSignatureId | string | 否 | 对象签名文件ID | | 字段路径 | 类型 | 示例 | 说明 | | -------- | ------- | -------------- | -------------------- | | code | int | 200 | 状态码 | | data.status | string | ORDER_CHECKED_IN | 新状态 | | data.distance | number | 85.5 | 签到位置距服务地址距离(米) | | data.checkinTime | string | 2026-05-15T09:05:00 | 签到时间 | 请求示例: ```json { "latitude": 24.2878, "longitude": 116.1271, "photoFileId": "file_checkin_001", "patientConfirmed": true, "patientSignatureId": "sig_001" } ``` 返回示例: ```json { "code": 200, "message": "签到成功", "data": { "id": "5001", "status": "ORDER_CHECKED_IN", "distance": 85.5, "checkinTime": "2026-05-15T09:05:00" }, "requestId": "req-uuid-def456", "timestamp": 1715747700000 } ``` --- **接口6:服务完成提交** | 接口名称 | 服务完成提交 | | -------- | ------------------------------------------------------ | | 接口地址 | `/api/hss/work-orders/{id}/finish` | | 请求方式 | `POST` | | 接口描述 | 服务人员完成所有必做项目后提交,工单进入已完成状态 | | 参数名 | 类型 | 是否必填 | 说明 | | ----------- | ------ | -------- | --------------------------- | | id | string | 是 | 工单ID | | executionRecords | array | 是 | 项目执行记录列表 | | executionRecords[].planItemId | string | 是 | 方案项目ID | | executionRecords[].status | string | 是 | COMPLETED / PARTIAL / NOT_COMPLETED / SKIPPED / USER_REFUSED | | executionRecords[].actualStartTime | string | 是 | 实际开始时间 | | executionRecords[].actualEndTime | string | 是 | 实际结束时间 | | executionRecords[].evidenceFileIds | array | 否 | 证据文件ID列表 | | executionRecords[].notes | string | 否 | 执行备注 | | signOffLatitude | number | 是 | 签退纬度 | | signOffLongitude | number | 是 | 签退经度 | | serviceSummary | string | 否 | 服务总结 | --- #### 7.1.3 结算接口组 **接口7:生成结算单** | 接口名称 | 生成结算单 | | -------- | ------------------------------------------------------ | | 接口地址 | `/api/hss/settlements/generate` | | 请求方式 | `POST` | | 接口描述 | 基于已验收工单生成结算单,自动汇总金额与抵扣 | | 参数名 | 类型 | 是否必填 | 说明 | | ----------- | ------ | -------- | --------------------------- | | workOrderIds | array | 是 | 已验收工单ID列表 | | periodStart | string | 是 | 结算周期开始日期 | | periodEnd | string | 是 | 结算周期结束日期 | | 字段路径 | 类型 | 示例 | 说明 | | -------- | ------- | -------------- | -------------------- | | data.id | string | 7001 | 结算单ID | | data.totalAmount | number | 1200.00 | 总金额 | | data.insuranceDeduction | number | 800.00 | 长护险抵扣 | | data.selfPayAmount | number | 400.00 | 自费金额 | | data.items | array | [...] | 结算明细 | --- ### 7.2 接口契约约定 - 所有写接口必须带 `Idempotency-Key` 请求头 - 所有分页接口参数:`page`(默认1)、`size`(默认20,最大100)、`sort`(如 `createdAt,desc`) - 状态动作接口路径格式:`POST /api/hss/{resource}/{id}/{action}` - 资源 CRUD:`GET/POST/PUT/DELETE /api/hss/{resource}` 和 `/{id}` - 统一错误响应: ```json { "code": 40001, "message": "参数校验失败", "details": [ {"field": "contactPhone", "message": "联系电话格式不正确"} ], "requestId": "req-uuid-err123" } ``` ### 7.3 错误码规划 | 错误码范围 | 含义 | |---|---| | 200 | 成功 | | 40001-40099 | 参数校验错误 | | 40101-40199 | 认证/授权错误 | | 40301-40399 | 权限不足 | | 40401-40499 | 资源不存在 | | 40901-40999 | 状态冲突(非法状态转换) | | 40910-40919 | 幂等冲突(重复提交) | | 42201-42299 | 业务规则校验失败 | | 50001-50099 | 服务器内部错误 | | 50301-50399 | 依赖服务不可用 | --- ## 8. 数据库与迁移计划 ### 8.1 DDL 变更明细 迁移脚本位于 `src/main/resources/db/migration/`,采用 Flyway 管理。 #### V1__baseline.sql(初始基线) 核心表结构(部分示例): ```sql -- ========================================== -- 基线迁移 V1:创建居家服务核心业务表 -- ========================================== -- 1. 申请域 CREATE TABLE hss_service_applications ( id BIGSERIAL PRIMARY KEY, tenant_id BIGINT NOT NULL, org_id BIGINT NOT NULL, patient_id BIGINT NOT NULL, service_type VARCHAR(32) NOT NULL, -- HOME_CARE / REHABILITATION / BATH_ASSIST / ASSESSMENT channel VARCHAR(32) NOT NULL, -- APP / WECHAT / PHONE / COMMUNITY / HOSPITAL contact_name VARCHAR(64) NOT NULL, contact_phone VARCHAR(20) NOT NULL, address TEXT NOT NULL, region_code VARCHAR(20) NOT NULL, status VARCHAR(32) NOT NULL DEFAULT 'DRAFT', notes TEXT, version INTEGER NOT NULL DEFAULT 0, created_at TIMESTAMP NOT NULL DEFAULT NOW(), updated_at TIMESTAMP NOT NULL DEFAULT NOW(), created_by BIGINT, updated_by BIGINT, deleted SMALLINT NOT NULL DEFAULT 0 ); CREATE INDEX idx_hss_app_status ON hss_service_applications(status); CREATE INDEX idx_hss_app_patient ON hss_service_applications(patient_id); CREATE INDEX idx_hss_app_created ON hss_service_applications(created_at); -- 2. 评估域 CREATE TABLE hss_assessment_tasks ( id BIGSERIAL PRIMARY KEY, tenant_id BIGINT NOT NULL, org_id BIGINT NOT NULL, application_id BIGINT NOT NULL REFERENCES hss_service_applications(id), assessor_id BIGINT, status VARCHAR(32) NOT NULL DEFAULT 'PENDING_ASSIGNMENT', -- 评估结果快照 care_level VARCHAR(16), -- LEVEL_1 ~ LEVEL_5 risk_level VARCHAR(16), -- LOW / MEDIUM / HIGH / CRITICAL report_content JSONB, version INTEGER NOT NULL DEFAULT 0, created_at TIMESTAMP NOT NULL DEFAULT NOW(), updated_at TIMESTAMP NOT NULL DEFAULT NOW(), created_by BIGINT, updated_by BIGINT, deleted SMALLINT NOT NULL DEFAULT 0 ); CREATE INDEX idx_hss_at_status ON hss_assessment_tasks(status); CREATE INDEX idx_hss_at_app ON hss_assessment_tasks(application_id); CREATE INDEX idx_hss_at_assessor ON hss_assessment_tasks(assessor_id); CREATE TABLE hss_assessment_reports ( id BIGSERIAL PRIMARY KEY, task_id BIGINT NOT NULL REFERENCES hss_assessment_tasks(id), version INTEGER NOT NULL DEFAULT 1, content JSONB NOT NULL, -- 评估指标详情 conclusion TEXT, created_at TIMESTAMP NOT NULL DEFAULT NOW(), created_by BIGINT ); -- 3. 方案域 CREATE TABLE hss_service_plans ( id BIGSERIAL PRIMARY KEY, tenant_id BIGINT NOT NULL, org_id BIGINT NOT NULL, application_id BIGINT NOT NULL, assessment_task_id BIGINT NOT NULL, status VARCHAR(32) NOT NULL DEFAULT 'PLAN_DRAFT', version_number INTEGER NOT NULL DEFAULT 1, total_amount DECIMAL(12,2), -- 方案总金额 insurance_deduction DECIMAL(12,2), -- 长护险抵扣 self_pay_amount DECIMAL(12,2), -- 自费金额 signed_at TIMESTAMP, signed_by BIGINT, effective_at TIMESTAMP, terminated_at TIMESTAMP, version INTEGER NOT NULL DEFAULT 0, created_at TIMESTAMP NOT NULL DEFAULT NOW(), updated_at TIMESTAMP NOT NULL DEFAULT NOW(), created_by BIGINT, updated_by BIGINT, deleted SMALLINT NOT NULL DEFAULT 0 ); CREATE TABLE hss_service_plan_items ( id BIGSERIAL PRIMARY KEY, plan_id BIGINT NOT NULL REFERENCES hss_service_plans(id), service_item_id BIGINT NOT NULL, -- 引用主数据服务项目 item_name VARCHAR(128) NOT NULL, -- 版本化快照 unit_price DECIMAL(10,2) NOT NULL, -- 版本化快照 frequency INTEGER NOT NULL, -- 服务频次 standard_duration INTEGER, -- 标准服务时长(分钟) created_at TIMESTAMP NOT NULL DEFAULT NOW() ); CREATE TABLE hss_plan_versions ( id BIGSERIAL PRIMARY KEY, plan_id BIGINT NOT NULL, version_number INTEGER NOT NULL, snapshot_data JSONB NOT NULL, -- 完整方案快照 change_reason TEXT, created_at TIMESTAMP NOT NULL DEFAULT NOW(), created_by BIGINT ); -- 4. 服务计划域 CREATE TABLE hss_service_schedules ( id BIGSERIAL PRIMARY KEY, tenant_id BIGINT NOT NULL, plan_id BIGINT NOT NULL REFERENCES hss_service_plans(id), scheduled_date DATE NOT NULL, time_window_start TIME, -- 预约时间窗开始 time_window_end TIME, -- 预约时间窗结束 status VARCHAR(32) NOT NULL DEFAULT 'SCHEDULED', version INTEGER NOT NULL DEFAULT 0, created_at TIMESTAMP NOT NULL DEFAULT NOW(), updated_at TIMESTAMP NOT NULL DEFAULT NOW() ); CREATE INDEX idx_hss_ss_date ON hss_service_schedules(scheduled_date); CREATE INDEX idx_hss_ss_plan ON hss_service_schedules(plan_id); -- 5. 工单域 CREATE TABLE hss_work_orders ( id BIGSERIAL PRIMARY KEY, tenant_id BIGINT NOT NULL, org_id BIGINT NOT NULL, schedule_id BIGINT REFERENCES hss_service_schedules(id), plan_id BIGINT NOT NULL, patient_id BIGINT NOT NULL, staff_id BIGINT, status VARCHAR(32) NOT NULL DEFAULT 'ORDER_CREATED', service_date DATE NOT NULL, scheduled_start TIME, scheduled_end TIME, risk_level VARCHAR(16), is_high_risk BOOLEAN DEFAULT FALSE, version INTEGER NOT NULL DEFAULT 0, created_at TIMESTAMP NOT NULL DEFAULT NOW(), updated_at TIMESTAMP NOT NULL DEFAULT NOW(), created_by BIGINT, updated_by BIGINT, deleted SMALLINT NOT NULL DEFAULT 0 ); CREATE INDEX idx_hss_wo_status ON hss_work_orders(status); CREATE INDEX idx_hss_wo_staff ON hss_work_orders(staff_id); CREATE INDEX idx_hss_wo_date ON hss_work_orders(service_date); CREATE INDEX idx_hss_wo_patient ON hss_work_orders(patient_id); CREATE TABLE hss_work_order_items ( id BIGSERIAL PRIMARY KEY, work_order_id BIGINT NOT NULL REFERENCES hss_work_orders(id), plan_item_id BIGINT NOT NULL, item_name VARCHAR(128) NOT NULL, unit_price DECIMAL(10,2) NOT NULL, required BOOLEAN DEFAULT TRUE, -- 是否必做 status VARCHAR(32) DEFAULT 'PENDING', -- COMPLETED/PARTIAL/NOT_COMPLETED/SKIPPED/USER_REFUSED evidence_required BOOLEAN DEFAULT FALSE, created_at TIMESTAMP NOT NULL DEFAULT NOW() ); -- 6. 执行域 CREATE TABLE hss_checkins ( id BIGSERIAL PRIMARY KEY, work_order_id BIGINT NOT NULL REFERENCES hss_work_orders(id), checkin_type VARCHAR(16) NOT NULL, -- CHECKIN / CHECKOUT latitude DECIMAL(10,7) NOT NULL, longitude DECIMAL(10,7) NOT NULL, distance_meters INTEGER, -- 距目标地址距离 photo_file_id VARCHAR(64), patient_confirmed BOOLEAN, patient_signature_id VARCHAR(64), created_at TIMESTAMP NOT NULL DEFAULT NOW(), created_by BIGINT ); CREATE TABLE hss_execution_records ( id BIGSERIAL PRIMARY KEY, work_order_id BIGINT NOT NULL, work_order_item_id BIGINT NOT NULL, status VARCHAR(32) NOT NULL, -- COMPLETED/PARTIAL/NOT_COMPLETED/SKIPPED/USER_REFUSED actual_start TIMESTAMP, actual_end TIMESTAMP, notes TEXT, created_at TIMESTAMP NOT NULL DEFAULT NOW(), created_by BIGINT ); CREATE TABLE hss_evidence_files ( id BIGSERIAL PRIMARY KEY, entity_type VARCHAR(32) NOT NULL, -- CHECKIN / EXECUTION / EXCEPTION / ACCEPTANCE entity_id BIGINT NOT NULL, file_type VARCHAR(16) NOT NULL, -- PHOTO / VIDEO / AUDIO file_key VARCHAR(256) NOT NULL, -- 对象存储 key file_size BIGINT, created_at TIMESTAMP NOT NULL DEFAULT NOW(), created_by BIGINT ); -- 7. 异常域 CREATE TABLE hss_exceptions ( id BIGSERIAL PRIMARY KEY, work_order_id BIGINT NOT NULL REFERENCES hss_work_orders(id), exception_type VARCHAR(32) NOT NULL, -- PATIENT_ABSENT / PATIENT_REFUSE / WRONG_ADDRESS / ... description TEXT NOT NULL, evidence_file_ids TEXT, -- JSON 数组 status VARCHAR(32) NOT NULL DEFAULT 'REPORTED', handled_by BIGINT, resolution TEXT, created_at TIMESTAMP NOT NULL DEFAULT NOW(), created_by BIGINT ); -- 8. 验收域 CREATE TABLE hss_acceptances ( id BIGSERIAL PRIMARY KEY, work_order_id BIGINT NOT NULL REFERENCES hss_work_orders(id), status VARCHAR(32) NOT NULL DEFAULT 'ACCEPTANCE_PENDING', result VARCHAR(16), -- ACCEPTED / REJECTED rating SMALLINT, -- 1-5 星 tags TEXT, -- JSON 标签数组 comment TEXT, rejected_reason TEXT, created_at TIMESTAMP NOT NULL DEFAULT NOW(), created_by BIGINT ); -- 9. 结算域 CREATE TABLE hss_settlements ( id BIGSERIAL PRIMARY KEY, tenant_id BIGINT NOT NULL, org_id BIGINT NOT NULL, patient_id BIGINT NOT NULL, status VARCHAR(32) NOT NULL DEFAULT 'SETTLEMENT_READY', period_start DATE NOT NULL, period_end DATE NOT NULL, total_amount DECIMAL(12,2), insurance_deduction DECIMAL(12,2), self_pay_amount DECIMAL(12,2), paid_at TIMESTAMP, payment_channel VARCHAR(32), payment_transaction_id VARCHAR(64), version INTEGER NOT NULL DEFAULT 0, created_at TIMESTAMP NOT NULL DEFAULT NOW(), updated_at TIMESTAMP NOT NULL DEFAULT NOW(), created_by BIGINT, updated_by BIGINT, deleted SMALLINT NOT NULL DEFAULT 0 ); CREATE TABLE hss_settlement_items ( id BIGSERIAL PRIMARY KEY, settlement_id BIGINT NOT NULL REFERENCES hss_settlements(id), work_order_id BIGINT NOT NULL, execution_record_id BIGINT, item_name VARCHAR(128), unit_price DECIMAL(10,2), actual_amount DECIMAL(10,2), deduction DECIMAL(10,2), self_pay DECIMAL(10,2), status VARCHAR(32) ); -- 10. 通知域 CREATE TABLE hss_notification_outbox ( id BIGSERIAL PRIMARY KEY, entity_type VARCHAR(32) NOT NULL, entity_id BIGINT NOT NULL, channel VARCHAR(16) NOT NULL, -- MQTT / WECHAT / SMS template_code VARCHAR(64), params JSONB, recipient_id BIGINT, status VARCHAR(16) NOT NULL DEFAULT 'CREATED', retry_count INTEGER DEFAULT 0, max_retries INTEGER DEFAULT 3, next_retry_at TIMESTAMP, request_id VARCHAR(64), created_at TIMESTAMP NOT NULL DEFAULT NOW() ); CREATE INDEX idx_hss_nf_status ON hss_notification_outbox(status, next_retry_at); CREATE TABLE hss_notification_receipts ( id BIGSERIAL PRIMARY KEY, outbox_id BIGINT NOT NULL, status VARCHAR(16) NOT NULL, -- SENT / DELIVERED / READ / CONFIRMED / FAILED / EXPIRED sent_at TIMESTAMP, delivered_at TIMESTAMP, read_at TIMESTAMP, error_message TEXT, created_at TIMESTAMP NOT NULL DEFAULT NOW() ); -- 11. 审计域 CREATE TABLE hss_state_transitions ( id BIGSERIAL PRIMARY KEY, entity_type VARCHAR(32) NOT NULL, -- application / plan / work_order / settlement entity_id BIGINT NOT NULL, from_status VARCHAR(32), action VARCHAR(32) NOT NULL, to_status VARCHAR(32) NOT NULL, operator_id BIGINT, operator_role VARCHAR(32), reason TEXT, request_id VARCHAR(64), created_at TIMESTAMP NOT NULL DEFAULT NOW() ); CREATE INDEX idx_hss_st_entity ON hss_state_transitions(entity_type, entity_id); CREATE INDEX idx_hss_st_request ON hss_state_transitions(request_id); CREATE TABLE hss_audit_logs ( id BIGSERIAL PRIMARY KEY, entity_type VARCHAR(32), entity_id BIGINT, action VARCHAR(32) NOT NULL, operator_id BIGINT, operator_name VARCHAR(64), operator_role VARCHAR(32), client_ip VARCHAR(45), device_info VARCHAR(256), detail JSONB, is_sensitive BOOLEAN DEFAULT FALSE, created_at TIMESTAMP NOT NULL DEFAULT NOW() ); CREATE INDEX idx_hss_al_entity ON hss_audit_logs(entity_type, entity_id); CREATE INDEX idx_hss_al_operator ON hss_audit_logs(operator_id); CREATE INDEX idx_hss_al_time ON hss_audit_logs(created_at); -- 12. 合规域 CREATE TABLE hss_consent_records ( id BIGSERIAL PRIMARY KEY, patient_id BIGINT NOT NULL, consent_type VARCHAR(32) NOT NULL, -- GPS / PHOTO / HEALTH / AUDIO_VIDEO consent_status VARCHAR(16) NOT NULL, -- GRANTED / REVOKED / EXPIRED granted_at TIMESTAMP, revoked_at TIMESTAMP, expires_at TIMESTAMP, created_by BIGINT, created_at TIMESTAMP NOT NULL DEFAULT NOW() ); CREATE TABLE hss_data_access_logs ( id BIGSERIAL PRIMARY KEY, operator_id BIGINT NOT NULL, data_type VARCHAR(32) NOT NULL, -- PERSONAL / HEALTH / LOCATION / FINANCIAL entity_type VARCHAR(32), entity_id BIGINT, access_action VARCHAR(16) NOT NULL, -- VIEW / EXPORT / DOWNLOAD client_ip VARCHAR(45), reason TEXT, created_at TIMESTAMP NOT NULL DEFAULT NOW() ); -- 唯一约束:幂等键 CREATE UNIQUE INDEX uk_hss_st_request ON hss_state_transitions(request_id, entity_type, entity_id); ``` ### 8.2 执行顺序与窗口建议 | 阶段 | 脚本 | 内容 | 建议窗口 | |---|---|---|---| | 1 | V1__baseline.sql | 全部核心表创建 | 首次部署(停机窗口 10min) | | 2 | V2__seed_master_data.sql | 主数据初始化(区域、服务项目、资质字典) | 紧随 V1 | | 3 | V3__add_indexes.sql | 性能索引补充 | 在线(CREATE INDEX CONCURRENTLY) | | 后续 | V4+ | 增量变更 | 按需,遵循 flyway 版本号 | ### 8.3 回滚策略 - 每次迁移对应一个 `U` 版本回滚脚本(如 `U1__baseline_rollback.sql`) - 回滚原则:非生产环境可直接 DROP;生产环境采用 `migrate down + data restore` - 关键变更必须备份受影响数据:`CREATE TABLE xxx_backup AS SELECT * FROM xxx WHERE ...` - 禁止 `DROP COLUMN` 直接执行:先标记废弃 → 观察一个版本 → 再删除 --- ## 9. 接口契约与兼容性 ### 9.1 兼容性说明 | 方面 | 策略 | |---|---| | 账号/登录 | 兼容现有平台 JWT Token 格式 | | 角色/权限 | 新增居家服务角色(受理员、评估员、方案制定员、调度员、服务人员、监管员、结算员),不影响现有角色 | | 机构/用户 | 复用现有 org_id / user_id 体系 | | 文件上传 | 复用现有对象存储接口,居家服务文件单独 folder | | 业务表 | 全新 `hss_` 前缀,不影响现有业务表 | ### 9.2 版本管理 - API 路径不加版本号,通过 Header `Accept-Version` 管理 - 破坏性变更走新接口 + 旧接口保留一个版本后废弃 --- ## 10. 自测与回归 ### 10.1 单元测试范围 | 测试对象 | 覆盖内容 | |---|---| | 状态机 | 所有合法转换、非法转换拦截、重复提交幂等 | | 校验服务 | 年龄校验、资格校验、重复申请校验 | | 调度算法 | 硬约束过滤逻辑、软约束评分计算、Top5排序 | | 结算计算 | 金额汇总、抵扣计算、部分完成折算 | ### 10.2 集成测试范围 | 测试场景 | 验证点 | |---|---| | 主链路 | 申请→评估→方案→工单→执行→验收→结算→归档 全流程 | | 异常链路 | 退回、异议、拒签、改派、异常上报、拒绝验收、结算退回 | | 通知链路 | Outbox 写入→定时发送→回执记录 | | 权限链路 | 角色隔离、数据范围过滤、字段脱敏 | | 并发场景 | 同 request_id 重复提交、派单并发冲突 | ### 10.3 关键回归场景 - 状态机规则变更后,所有上游调用方不受影响(规则集中管理) - 结算公式变更后,历史结算单金额不变(版本化快照) - 服务项目价格调整后,已签署方案不受影响(版本冻结) --- ## 11. 工程目录结构总览 ``` hss-home-service/ ├── pom.xml ├── src/ │ ├── main/ │ │ ├── java/com/meizhou/hss/ │ │ │ ├── HssApplication.java # Spring Boot 启动类 │ │ │ ├── common/ │ │ │ │ ├── ApiResponse.java # 统一响应 │ │ │ │ ├── BaseEntity.java # 审计字段基类 │ │ │ │ ├── ErrorCode.java # 错误码枚举 │ │ │ │ ├── BusinessException.java # 业务异常 │ │ │ │ ├── Idempotent.java # 幂等注解 │ │ │ │ ├── IdempotentAspect.java # 幂等切面 │ │ │ │ ├── Auditable.java # 审计注解 │ │ │ │ └── AuditAspect.java # 审计切面 │ │ │ ├── config/ │ │ │ │ ├── SecurityConfig.java │ │ │ │ ├── RedisConfig.java │ │ │ │ ├── MqttConfig.java │ │ │ │ ├── ObjectStorageConfig.java │ │ │ │ ├── SchedulerConfig.java │ │ │ │ ├── OpenApiConfig.java │ │ │ │ └── MyBatisPlusConfig.java │ │ │ ├── statemachine/ │ │ │ │ ├── StateMachine.java │ │ │ │ ├── TransitionRule.java │ │ │ │ ├── StateTransitionException.java │ │ │ │ ├── ApplicationStateMachine.java │ │ │ │ ├── PlanStateMachine.java │ │ │ │ ├── WorkOrderStateMachine.java │ │ │ │ └── SettlementStateMachine.java │ │ │ └── module/ │ │ │ ├── application/ │ │ │ │ ├── controller/ApplicationController.java │ │ │ │ ├── service/ApplicationService.java │ │ │ │ ├── service/ApplicationValidationService.java │ │ │ │ ├── repository/ServiceApplicationMapper.java │ │ │ │ ├── entity/ServiceApplicationEntity.java │ │ │ │ └── dto/{CreateRequest,SubmitRequest,Response,ListQuery}.java │ │ │ ├── assessment/ │ │ │ │ ├── controller/AssessmentController.java │ │ │ │ ├── service/AssessmentService.java │ │ │ │ ├── repository/{AssessmentTaskMapper,AssessmentReportMapper}.java │ │ │ │ ├── entity/{AssessmentTaskEntity,AssessmentReportEntity}.java │ │ │ │ └── dto/{...}.java │ │ │ ├── plan/ │ │ │ │ └── ... (同模式) │ │ │ ├── schedule/ │ │ │ │ ├── controller/ScheduleController.java │ │ │ │ ├── service/ScheduleService.java │ │ │ │ ├── service/DispatchService.java │ │ │ │ ├── algorithm/DispatchAlgorithm.java │ │ │ │ ├── algorithm/HardConstraintFilter.java │ │ │ │ ├── algorithm/SoftScoringRanker.java │ │ │ │ └── ... │ │ │ ├── workorder/ │ │ │ ├── execution/ │ │ │ ├── exception/ │ │ │ ├── supervision/ │ │ │ ├── acceptance/ │ │ │ ├── settlement/ │ │ │ ├── archive/ │ │ │ ├── notification/ │ │ │ │ ├── service/NotificationService.java │ │ │ │ ├── sender/NotificationSender.java │ │ │ │ ├── sender/MqttSender.java │ │ │ │ ├── sender/WechatSender.java │ │ │ │ └── sender/SmsSender.java │ │ │ ├── audit/ │ │ │ ├── compliance/ │ │ │ ├── masterdata/ │ │ │ └── capacity/ │ │ └── resources/ │ │ ├── application.yml │ │ ├── application-dev.yml │ │ ├── application-test.yml │ │ ├── application-prod.yml │ │ └── db/migration/ │ │ ├── V1__baseline.sql │ │ ├── V2__seed_master_data.sql │ │ └── V3__add_indexes.sql │ └── test/java/com/meizhou/hss/ │ ├── statemachine/ │ │ ├── ApplicationStateMachineTest.java │ │ ├── PlanStateMachineTest.java │ │ ├── WorkOrderStateMachineTest.java │ │ └── SettlementStateMachineTest.java │ ├── module/ │ │ ├── application/ApplicationControllerTest.java │ │ ├── workorder/WorkOrderIntegrationTest.java │ │ └── settlement/SettlementCalculationTest.java │ └── algorithm/DispatchAlgorithmTest.java └── delivery-miniapp/ ├── pages/delivery/ │ ├── login/ │ ├── index/ # 工作台 │ ├── orders/ # 工单列表 │ ├── order-detail/ # 工单详情 │ ├── accept/ # 接单确认 │ ├── checkin/ # GPS签到 │ ├── execute/ # 服务执行 │ ├── exception/ # 异常上报 │ ├── finish/ # 签退完成 │ ├── offline-sync/ # 离线补传 │ ├── messages/ # 通知消息 │ └── profile/ # 我的资质 └── ... ``` --- ## 12. 实施优先级与分批计划 ### 第一批(MVP 核心链路)- 预计 4~6 周 1. 项目初始化:pom.xml、application.yml、启动类 2. 公共模块:ApiResponse、BaseEntity、异常、幂等、审计切面 3. 数据库基线:V1__baseline.sql(全部核心表) 4. 状态机:四层状态机 + 状态流转记录 5. 申请域:创建、提交、受理通过/退回、取消 6. 评估域:派发评估、签到、提交报告、异议 7. 方案域:创建、编辑、提交签署、签署/拒签、版本管理 8. 计划域:服务计划生成 9. 工单域:工单创建、派单、接单/拒单 10. 执行域:签到、逐项执行记录、完成 11. 验收域:验收确认/拒绝、评价 12. 结算域:生成结算单、审核、支付确认、归档 13. 通知域:Outbox 写入 + 定时发送 14. 审计域:状态流转记录 + 审计日志 ### 第二批(增强能力)- 预计 3~4 周 1. 调度算法:硬约束过滤 + 软约束评分 + Top5推荐 2. 监管域:抽查计划、违规记录、整改跟踪 3. 合规域:授权同意、敏感数据访问审计 4. 主数据域:机构、人员、资质、服务项目、区域、价格 5. 异常域:异常上报、处理动作、紧急事件 6. delivery 端小程序开发 ### 第三批(智能化与运营)- 后续迭代 1. 运力域:服务网格、容量预测 2. ETA 预测 3. 调度算法优化(局部搜索/OR-Tools) 4. 数据看板和质量分析 5. 人员绩效结算 --- ## 13. 短 Prompt ```txt 基于 /home/akoo/居家服务/IMPLEMENTATION_PLAN.md 实现 MVP 第一批(项目初始化 + 公共模块 + 数据库基线 + 状态机 + 申请域 + 评估域)。 技术栈:Spring Boot 3.3 + Java 17 + MyBatis-Plus + PostgreSQL + Flyway。 - 严格遵循 hss_ 表前缀和审计字段规范 - 前端只传动作不传目标状态 - 所有写接口带 Idempotency-Key - 通知走 Outbox 模式 - 输出 Flyway V1 迁移脚本 + Java 代码 ```