工程分析报告.md 24 KB

养老院管理系统(KYJ-YangLao)工程分析报告

一、项目概述

1.1 项目基本信息

  • 项目名称: kyj-yanglao-end(养老院管理系统后端)
  • 基础框架: 芋道 RuoYi-Vue-Pro 2.1.0(JDK 8)
  • 构建工具: Maven
  • 主要技术栈: Spring Boot 2.7.18 + MyBatis + MySQL

1.2 项目定位

这是一个针对养老院(长者护理机构)的综合管理系统,涵盖:

  • 长者信息管理
  • 合同管理
  • 账单与费用管理
  • 日常开支管理
  • 员工管理
  • 设备管理
  • 工作流(BPM)
  • 数据报表

二、工程架构

2.1 整体结构(多模块架构)

kyj-yanglao-end/
├── yudao-dependencies/          # 依赖版本管理(BOM)
├── yudao-framework/             # 核心框架层
│   ├── yudao-common/            # 通用工具类
│   ├── yudao-spring-boot-starter-*/ # 各种功能启动器
│   │   ├── biz-data-permission/ # 数据权限
│   │   ├── biz-ip/              # IP地址解析
│   │   ├── biz-tenant/          # 多租户支持
│   │   ├── excel/               # Excel导入导出
│   │   ├── job/                 # 定时任务
│   │   ├── monitor/             # 监控工具
│   │   ├── mq/                  # 消息队列
│   │   ├── mybatis/             # MyBatis增强
│   │   ├── protection/          # 服务保障
│   │   ├── redis/               # Redis缓存
│   │   ├── security/            # Spring Security
│   │   ├── test/                # 测试框架
│   │   ├── web/                 # Web框架
│   │   └── websocket/           # WebSocket
│   └── pom.xml
├── yudao-module-system/         # 系统模块(核心业务)
│   ├── yudao-module-system-api/ # API接口定义
│   ├── yudao-module-system-biz/ # 业务实现
│   └── pom.xml
├── yudao-module-infra/          # 基础设施模块
├── yudao-module-member/         # 会员模块
├── yudao-module-bpm/            # 工作流模块
├── yudao-module-report/         # 报表模块
├── yudao-module-crm/            # CRM模块(可选)
├── yudao-module-erp/            # ERP模块(可选)
├── yudao-module-mall/           # 商城模块(可选)
├── yudao-module-pay/            # 支付模块(可选)
├── yudao-server/                # 主应用程序
│   ├── src/main/java/
│   ├── src/main/resources/
│   ├── Dockerfile
│   └── pom.xml
├── yudao-ui/                    # 前端项目集合
│   ├── yudao-ui-admin-vue3/     # 管理后台(Vue3)
│   ├── yudao-ui-admin-vue2/     # 管理后台(Vue2)
│   ├── yudao-ui-admin-vben/     # 管理后台(Vben)
│   ├── yudao-ui-admin-uniapp/   # 管理后台(UniApp)
│   ├── yudao-ui-mall-uniapp/    # 商城前端(UniApp)
├── script/                      # 脚本文件
│   ├── docker/                  # Docker配置
│   ├── jenkins/                 # Jenkins配置
│   └── shell/                   # 部署脚本
├── sql/                         # 数据库脚本
│   ├── mysql/                   # MySQL脚本
│   ├── oracle/                  # Oracle脚本
│   ├── postgresql/              # PostgreSQL脚本
│   ├── sqlserver/               # SQL Server脚本
│   ├── dm/                      # 达梦数据库脚本
│   └── kingbase/                # 国产数据库脚本
└── pom.xml                      # 根POM文件

2.2 分层架构

┌─────────────────────────────────────────────┐
│         Controller(控制层)                 │
│  - 请求处理、参数验证、响应返回              │
└────────────────┬────────────────────────────┘
                 │
┌─────────────────────────────────────────────┐
│         Service(业务层)                    │
│  - 业务逻辑处理、事务管理                    │
└────────────────┬────────────────────────────┘
                 │
┌─────────────────────────────────────────────┐
│         Mapper(数据访问层)                 │
│  - 数据库操作、SQL执行                      │
└────────────────┬────────────────────────────┘
                 │
┌─────────────────────────────────────────────┐
│         Database(数据库层)                 │
│  - MySQL数据存储                            │
└─────────────────────────────────────────────┘

三、核心模块详解

3.1 yudao-module-system(系统模块)

这是项目的核心业务模块,包含养老院管理的所有主要功能。

3.1.1 模块结构

yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/
├── api/                         # API接口实现
│   ├── order/                   # 订单API
│   │   ├── OrderApi.java        # 接口定义
│   │   └── OrderApiImpl.java     # 实现类(需优化)
│   ├── bpm/                     # 工作流API
│   └── ...
├── controller/                  # 控制层
│   ├── admin/
│   │   ├── biz/                 # 业务相关控制器
│   │   │   ├── ExpenseOrderController.java      # 账单管理
│   │   │   ├── ExpenseController.java           # 费用管理
│   │   │   ├── ElderlyInfoController.java       # 长者信息
│   │   │   ├── ElderlyContractController.java   # 合同管理
│   │   │   ├── DailyExpensesController.java     # 日常开支
│   │   │   ├── RefundSettlementOrderController.java # 退款结算
│   │   │   └── ...
│   │   ├── yk/                  # 养老院相关控制器
│   │   ├── restaurant/          # 餐饮相关控制器
│   │   ├── discount/            # 折扣管理
│   │   └── ...
│   └── ...
├── service/                     # 业务层
│   ├── biz/                     # 业务服务
│   │   ├── ExpenseOrderService.java
│   │   ├── ExpenseOrderServiceImpl.java
│   │   ├── ExpenseService.java
│   │   ├── ExpenseServiceImpl.java
│   │   ├── DailyExpensesService.java
│   │   ├── DailyExpensesServiceImpl.java
│   │   ├── ElderlyInfoService.java
│   │   ├── ElderlyInfoServiceImpl.java
│   │   ├── ElderlyContractService.java
│   │   ├── ElderlyContractServiceImpl.java
│   │   ├── DepositService.java
│   │   ├── DepositServiceImpl.java
│   │   ├── RefundSettlementOrderService.java
│   │   ├── RefundSettlementOrderServiceImpl.java
│   │   ├── PriceChangeRecordServiceImpl.java
│   │   ├── NurseChangeRecordServiceImpl.java
│   │   └── ...
│   ├── yk/                      # 养老院服务
│   ├── restaurant/              # 餐饮服务
│   ├── discount/                # 折扣服务
│   ├── permission/              # 权限服务
│   ├── tenant/                  # 租户服务
│   ├── user/                    # 用户服务
│   ├── sms/                     # 短信服务
│   └── ...
├── dal/                         # 数据访问层
│   ├── dataobject/              # 数据对象
│   │   ├── biz/
│   │   │   ├── ExpenseOrderDO.java
│   │   │   ├── ExpenseOrderItemDO.java
│   │   │   ├── ExpenseDO.java
│   │   │   ├── DailyExpensesDO.java
│   │   │   ├── ElderlyInfoDO.java
│   │   │   ├── ElderlyContractDO.java
│   │   │   ├── DepositRecordDO.java
│   │   │   ├── ElderlyChangeRecordDO.java
│   │   │   ├── ElderlyAskLeaveDO.java
│   │   │   ├── RefundSettlementOrderDO.java
│   │   │   └── ...
│   │   ├── yk/
│   │   ├── restaurant/
│   │   └── ...
│   └── mysql/                   # MyBatis Mapper
│       ├── biz/
│       │   ├── ExpenseOrderMapper.java
│       │   ├── ExpenseOrderItemMapper.java
│       │   ├── ExpenseMapper.java
│       │   ├── DailyExpensesMapper.java
│       │   ├── ElderlyInfoMapper.java
│       │   ├── ExpenseItemMapper.java
│       │   └── ...
│       ├── yk/
│       └── ...
├── enums/                       # 枚举类
│   └── change/
│       └── BusinessConstants.java
├── job/                         # 定时任务
│   └── ElderContractUpdateJob.java
├── util/                        # 工具类
│   ├── BizUtil.java
│   ├── StringUtil.java
│   ├── SignUtil.java
│   ├── SSLClient.java
│   ├── http/
│   │   ├── HttpClientUtil.java
│   │   └── HttpClientResult.java
│   ├── oauth2/
│   ├── device/
│   └── ...
└── resources/
    ├── mapper/                  # MyBatis XML映射文件
    │   ├── ExpenseOrderMapper.xml
    │   ├── ExpenseOrderItemMapper.xml
    │   ├── ExpenseMapper.xml
    │   ├── DailyExpensesMapper.xml
    │   ├── ElderlyInfoMapper.xml
    │   └── ...(共60+个Mapper.xml文件)
    ├── images/                  # 验证码图片
    └── META-INF/

3.1.2 主要业务对象

对象 说明 关键字段
ExpenseOrder 账单 id, elder_id, billing_month, pay_status, payable_amount, actual_amount
ExpenseOrderItem 账单项目 id, expense_order_id, expense_source, total_amount, actual_price, pay_status
Expense 费用 id, elder_id, created_time
ExpenseItem 费用项 id, expense_id, item_category_id, type, amount
DailyExpenses 日常开支 id, elder_id, item_name, amount, round_amount, type
ElderlyInfo 长者信息 id, elder_name, in_status, org_type, tenant_id, bed_id
ElderlyContract 合同 id, elder_id, contract_number, begin_time, expire_time, contract_term
DepositRecord 押金记录 id, elder_id, deposit_amount, refund_amount
ElderlyChangeRecord 长者变更记录 id, elder_id, change_type, change_content
RefundSettlementOrder 退款结算单 id, elder_id, settlement_amount

3.1.3 关键API接口

// OrderApi.java - 订单相关API
public interface OrderApi {
    // 按月获取订单列表
    List<OrderItemRespVO> getListByMonth(Integer orgType, Long tenantId, String billMonth, Integer inStatus);
    
    // 按月获取总计
    OrderItemTotalRespVO getTotalByMonth(Integer orgType, Long tenantId, String billingMonth);
    
    // 获取应收列表(按月)
    List<OrderItemRespVO> getReceivableListByMonth(Integer orgType, Long tenantId, String queryFLag, String billingMonth);
    
    // 获取应收总计(按年)- 【需要优化的方法】
    OrderItemTotalRespVO getOrderReceivableTotal(Integer orgType, Long tenantId, String billingMonth);
}

四、性能问题分析

4.1 OrderApiImpl.getOrderReceivableTotal() 方法的性能问题

问题描述

getOrderReceivableTotal() 方法存在严重的 N+1 查询问题,导致数据库查询次数过多。

问题代码分析

@Override
public OrderItemTotalRespVO getOrderReceivableTotal(Integer orgType, Long tenantId, String billingMonth) {
    OrderItemTotalRespVO orderItemTotalRespVO = new OrderItemTotalRespVO();
    // ...
    
    // 循环12个月,每个月调用一次 getReceivableListByMonth
    for (int i = 0; i < 12; i++) {
        String queryFlag = String.valueOf(i + 1);
        List<OrderItemRespVO> receivableList = getReceivableListByMonth(orgType, tenantId, queryFlag, billingMonth);
        // 处理数据...
    }
    
    return orderItemTotalRespVO;
}

查询链路分析

getOrderReceivableTotal()
  └─ for i=1 to 12:
      └─ getReceivableListByMonth(queryFlag=i, billingMonth)
          └─ getListByMonth(orgType, tenantId, billingMonth, null)
              ├─ orderMapper.selectListByMonth()  // 查询1:订单列表
              ├─ orderItemMapper.selectList()     // 查询2:订单项目
              ├─ itemMapper.selectBatchIds()      // 查询3:费用项
              └─ dailyExpensesMapper.selectBatchIds() // 查询4:日常开支

性能影响

指标
每次调用的数据库查询数 4次
循环次数 12次
总查询数 48次
问题根源 重复查询相同数据,缺乏缓存

4.2 其他潜在性能问题

  1. getTotalByMonth() 方法

    • 调用两次 getListByMonth()(分别查询在住和退住)
    • 每次调用都会重新查询数据库
  2. getListByMonth() 方法

    • 虽然已经优化了批量查询(避免N+1),但仍有改进空间
    • 可以考虑添加缓存机制
  3. ElderlyInfoMapper.selectCountByParam() 方法

    • getTotalByMonth() 中调用4次
    • 可以合并为一次查询

五、数据库设计

5.1 核心表关系图

elderly_info (长者信息)
    ├─ elderly_contract (合同)
    ├─ elderly_expense_order (账单)
    │   └─ elderly_expense_order_item (账单项)
    │       ├─ elderly_expense_item (费用项)
    │       └─ daily_expenses (日常开支)
    ├─ elderly_expense (费用)
    │   └─ elderly_expense_item (费用项)
    ├─ daily_expenses (日常开支)
    ├─ deposit_record (押金)
    ├─ elderly_change_record (变更记录)
    └─ elderly_balance (余额)

5.2 关键表设计

elderly_info(长者信息表)

CREATE TABLE elderly_info (
    id BIGINT PRIMARY KEY,
    elder_name VARCHAR(100),
    elder_sex INT,
    elder_age INT,
    in_status INT,  -- 1: 在住, 2: 退住
    org_type INT,
    tenant_id BIGINT,
    bed_id BIGINT,
    build_id BIGINT,
    nurse_level_name VARCHAR(100),
    address VARCHAR(500),
    created_time DATETIME,
    updated_time DATETIME
);

elderly_expense_order(账单表)

CREATE TABLE elderly_expense_order (
    id BIGINT PRIMARY KEY,
    elder_id BIGINT,
    billing_month VARCHAR(10),  -- 格式: YYYY-MM
    pay_status INT,  -- 0: 未缴费, 1: 已缴费
    payable_amount DECIMAL(10,2),
    actual_amount DECIMAL(10,2),
    arrears_note VARCHAR(500),
    created_time DATETIME,
    updated_time DATETIME,
    tenant_id BIGINT,
    org_type INT
);

elderly_expense_order_item(账单项表)

CREATE TABLE elderly_expense_order_item (
    id BIGINT PRIMARY KEY,
    expense_order_id BIGINT,
    expense_source INT,  -- 1: 月度费用, 2: 日常开支
    source_expense_item_id BIGINT,
    total_amount DECIMAL(10,2),
    actual_price DECIMAL(10,2),
    pay_status INT,  -- 0: 未缴费, 1: 已缴费
    created_time DATETIME,
    updated_time DATETIME
);

六、技术栈详解

6.1 后端技术栈

技术 版本 用途
Spring Boot 2.7.18 应用框架
Spring Security 5.7.x 权限认证
MyBatis 3.5.x ORM框架
MyBatis Plus 3.5.x MyBatis增强
MySQL 5.7+ 关系型数据库
Redis 5.0+ 缓存存储
Lombok 1.18.30 代码生成
MapStruct 1.5.5 对象映射
Flowable 6.7.x 工作流引擎
EasyExcel 3.x Excel处理
Knife4j 3.x API文档

6.2 前端技术栈

技术 说明
Vue 3 现代前端框架
Vue 2 传统前端框架
Vben Admin 企业级后台模板
UniApp 跨平台移动应用

6.3 基础设施

组件 用途
Docker 容器化部署
Jenkins CI/CD流程
MySQL 数据存储
Redis 缓存层
Nginx 反向代理

七、关键业务流程

7.1 账单生成流程

1. 定时任务触发(ElderContractUpdateJob)
   ↓
2. 查询所有有效合同的长者
   ↓
3. 根据合同和费用项生成账单(ExpenseOrder)
   ↓
4. 创建账单项(ExpenseOrderItem)
   ├─ 月度费用项(床位费、护理费、餐费、服务费)
   └─ 日常开支项(点餐、医疗护理、身体护理等)
   ↓
5. 计算应付金额和实付金额
   ↓
6. 保存到数据库

7.2 费用统计流程

getOrderReceivableTotal(orgType, tenantId, billingMonth)
  ↓
循环12个月 (i=1 to 12)
  ├─ getReceivableListByMonth(queryFlag=i, billingMonth)
  │   ├─ 获取该月订单列表
  │   ├─ 获取订单项目
  │   ├─ 获取费用项详情
  │   ├─ 获取日常开支详情
  │   └─ 组装返回数据
  │
  └─ 累加各项金额
      ├─ 床位费
      ├─ 护理费
      ├─ 餐费
      ├─ 服务费
      └─ 调整金额
  ↓
返回年度统计总计

八、开发规范

8.1 包结构规范

cn.iocoder.yudao.module.system
├── api/              # 对外API接口
├── controller/       # HTTP控制层
├── service/          # 业务逻辑层
│   ├── biz/         # 业务服务
│   ├── permission/  # 权限服务
│   ├── tenant/      # 租户服务
│   └── ...
├── dal/              # 数据访问层
│   ├── dataobject/  # 数据对象(DO)
│   └── mysql/       # MyBatis Mapper
├── enums/            # 枚举类
├── job/              # 定时任务
├── util/             # 工具类
└── framework/        # 框架相关

8.2 命名规范

对象类型 后缀 示例
数据对象 DO ExpenseOrderDO
请求对象 ReqVO ExpenseOrderCreateReqVO
响应对象 RespVO ExpenseOrderRespVO
DTO对象 DTO OrderItemRespDTO
服务接口 Service ExpenseOrderService
服务实现 ServiceImpl ExpenseOrderServiceImpl
数据访问 Mapper ExpenseOrderMapper
控制器 Controller ExpenseOrderController

8.3 代码规范

  • 使用 Lombok 简化代码(@Data, @Slf4j等)
  • 使用 MapStruct 进行对象转换
  • 使用 LambdaQueryWrapperX 进行动态SQL构建
  • 遵循单一职责原则
  • 避免在循环中进行数据库查询(N+1问题)
  • 使用批量查询替代单条查询

九、部署架构

9.1 Docker部署

# docker-compose.yml
services:
  mysql:
    image: mysql:5.7
    ports:
      - "3306:3306"
    environment:
      MYSQL_ROOT_PASSWORD: root
  
  redis:
    image: redis:5
    ports:
      - "6379:6379"
  
  yudao-server:
    build: .
    ports:
      - "8080:8080"
    depends_on:
      - mysql
      - redis
    environment:
      SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/yudao
      SPRING_REDIS_HOST: redis

9.2 应用配置

# application.yml
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/yudao
    username: root
    password: root
    driver-class-name: com.mysql.cj.jdbc.Driver
  
  jpa:
    hibernate:
      ddl-auto: validate
  
  redis:
    host: localhost
    port: 6379
    database: 0

mybatis:
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: cn.iocoder.yudao.module.system.dal.dataobject
  configuration:
    map-underscore-to-camel-case: true

十、优化建议

10.1 紧急优化(OrderApiImpl)

优先级: 高

  1. 合并数据库查询

    • 创建 selectListByYear() 方法,一次性查询全年数据
    • 在内存中按月份分组,避免12次循环查询
  2. 实现缓存机制

    • 对月度数据进行缓存
    • 设置合理的缓存过期时间
  3. 优化SQL查询

    • 使用JOIN替代多次查询
    • 添加必要的数据库索引

10.2 中期优化

优先级: 中

  1. 异步处理

    • 使用异步任务处理费用统计
    • 提高API响应速度
  2. 分页处理

    • 对大数据量进行分页
    • 减少内存占用
  3. 索引优化

    • billing_month, elder_id, tenant_id 上添加索引
    • 优化查询性能

10.3 长期优化

优先级: 低

  1. 数据仓库

    • 建立数据仓库进行离线分析
    • 减少在线系统压力
  2. 微服务化

    • 将费用模块独立为微服务
    • 提高系统可扩展性
  3. 消息队列

    • 使用消息队列处理费用更新
    • 提高系统解耦性

十一、关键文件清单

11.1 核心业务文件

文件路径 说明
OrderApiImpl.java 订单API实现(需优化
ExpenseOrderService.java 账单业务接口
ExpenseOrderServiceImpl.java 账单业务实现
ExpenseService.java 费用业务接口
ExpenseServiceImpl.java 费用业务实现
DailyExpensesService.java 日常开支业务接口
DailyExpensesServiceImpl.java 日常开支业务实现
ElderlyInfoService.java 长者信息业务接口
ElderlyInfoServiceImpl.java 长者信息业务实现
ElderlyContractService.java 合同业务接口
ElderlyContractServiceImpl.java 合同业务实现

11.2 数据访问文件

文件路径 说明
ExpenseOrderMapper.java 账单Mapper接口
ExpenseOrderMapper.xml 账单SQL映射(需优化
ExpenseOrderItemMapper.java 账单项Mapper接口
ExpenseOrderItemMapper.xml 账单项SQL映射
ExpenseMapper.java 费用Mapper接口
ExpenseMapper.xml 费用SQL映射
DailyExpensesMapper.java 日常开支Mapper接口
DailyExpensesMapper.xml 日常开支SQL映射
ElderlyInfoMapper.java 长者信息Mapper接口
ElderlyInfoMapper.xml 长者信息SQL映射

11.3 控制器文件

文件路径 说明
ExpenseOrderController.java 账单管理控制器
ExpenseController.java 费用管理控制器
DailyExpensesController.java 日常开支控制器
ElderlyInfoController.java 长者信息控制器
ElderlyContractController.java 合同管理控制器
RefundSettlementOrderController.java 退款结算控制器

十二、常见问题解答

Q1: 系统支持多租户吗?

A: 是的,系统内置多租户支持(yudao-spring-boot-starter-biz-tenant)。每个租户有独立的数据隔离。

Q2: 如何添加新的费用项?

A: 通过 ExpenseItemService 添加新的费用项,然后在账单生成时会自动包含。

Q3: 账单如何生成?

A: 通过定时任务 ElderContractUpdateJob 自动生成,也可以手动触发。

Q4: 系统支持哪些数据库?

A: 支持 MySQL、Oracle、PostgreSQL、SQL Server、达梦、国产数据库等。

Q5: 如何处理退住长者的账单?

A: 系统会根据 in_status 字段区分在住和退住,分别统计。


十三、总结

13.1 项目优势

✅ 基于成熟的开源框架(RuoYi-Vue-Pro) ✅ 完整的多模块架构 ✅ 支持多租户和权限管理 ✅ 包含工作流和报表功能 ✅ 支持多种数据库 ✅ 有完整的前后端分离

13.2 改进方向

⚠️ 需要优化 getOrderReceivableTotal() 方法的性能 ⚠️ 可以添加更多缓存机制 ⚠️ 需要完善错误处理和日志记录 ⚠️ 可以增加更多的单元测试

13.3 建议

  1. 立即行动: 优化 OrderApiImpl.getOrderReceivableTotal() 方法
  2. 短期计划: 添加缓存机制和数据库索引
  3. 中期计划: 实现异步处理和消息队列
  4. 长期规划: 考虑微服务化和数据仓库

文档生成时间: 2025-12-08 文档版本: 1.0 作者: AI Assistant