eight
2024-08-06 bcce8e5364bbbff564ab546235bef1444dfa79d7
birthday to datetime type
已添加14个文件
已修改1个文件
1195 ■■■■■ 文件已修改
jh-module-ecg/jh-module-ecg-api/pom.xml 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jh-module-ecg/jh-module-ecg-api/src/main/java/cn/lihu/jh/module/ecg/enums/ErrorCodeConstants.java 165 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jh-module-ecg/jh-module-ecg-biz/pom.xml 124 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jh-module-ecg/jh-module-ecg-biz/src/main/java/cn/lihu/jh/module/ecg/controller/admin/appointment/AppointmentController.java 95 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jh-module-ecg/jh-module-ecg-biz/src/main/java/cn/lihu/jh/module/ecg/controller/admin/appointment/vo/AppointmentPageReqVO.java 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jh-module-ecg/jh-module-ecg-biz/src/main/java/cn/lihu/jh/module/ecg/controller/admin/appointment/vo/AppointmentRespVO.java 95 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jh-module-ecg/jh-module-ecg-biz/src/main/java/cn/lihu/jh/module/ecg/controller/admin/appointment/vo/AppointmentSaveReqVO.java 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jh-module-ecg/jh-module-ecg-biz/src/main/java/cn/lihu/jh/module/ecg/dal/dataobject/appointment/AppointmentDO.java 119 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jh-module-ecg/jh-module-ecg-biz/src/main/java/cn/lihu/jh/module/ecg/dal/mysql/appointment/AppointmentMapper.java 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jh-module-ecg/jh-module-ecg-biz/src/main/java/cn/lihu/jh/module/ecg/service/appointment/AppointmentService.java 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jh-module-ecg/jh-module-ecg-biz/src/main/java/cn/lihu/jh/module/ecg/service/appointment/AppointmentServiceImpl.java 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jh-module-ecg/jh-module-ecg-biz/src/main/resources/mapper/appointment/AppointmentMapper.xml 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jh-module-ecg/jh-module-ecg-biz/src/test/java/cn/lihu/jh/module/ecg/service/appointment/AppointmentServiceImplTest.java 202 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
jh-module-ecg/pom.xml 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sql/mysql/jh.sql 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
jh-module-ecg/jh-module-ecg-api/pom.xml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <groupId>cn.lihu</groupId>
        <artifactId>jh-module-ecg</artifactId>
        <version>${revision}</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>jh-module-ecg-api</artifactId>
    <packaging>jar</packaging>
    <name>${project.artifactId}</name>
    <description>
        ecg æ¨¡å— API,暴露给其它模块调用
    </description>
    <dependencies>
        <dependency>
            <groupId>cn.lihu</groupId>
            <artifactId>jh-common</artifactId>
        </dependency>
        <!-- å‚数校验 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>
</project>
jh-module-ecg/jh-module-ecg-api/src/main/java/cn/lihu/jh/module/ecg/enums/ErrorCodeConstants.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,165 @@
package cn.lihu.jh.module.system.enums;
import cn.lihu.jh.framework.common.exception.ErrorCode;
/**
 * System é”™è¯¯ç æžšä¸¾ç±»
 *
 * system ç³»ç»Ÿï¼Œä½¿ç”¨ 1-002-000-000 æ®µ
 */
public interface ErrorCodeConstants {
    // ========== AUTH æ¨¡å— 1-002-000-000 ==========
    ErrorCode AUTH_LOGIN_BAD_CREDENTIALS = new ErrorCode(1_002_000_000, "登录失败,账号密码不正确");
    ErrorCode AUTH_LOGIN_USER_DISABLED = new ErrorCode(1_002_000_001, "登录失败,账号被禁用");
    ErrorCode AUTH_LOGIN_CAPTCHA_CODE_ERROR = new ErrorCode(1_002_000_004, "验证码不正确,原因:{}");
    ErrorCode AUTH_THIRD_LOGIN_NOT_BIND = new ErrorCode(1_002_000_005, "未绑定账号,需要进行绑定");
    ErrorCode AUTH_MOBILE_NOT_EXISTS = new ErrorCode(1_002_000_007, "手机号不存在");
    // ========== èœå•模块 1-002-001-000 ==========
    ErrorCode MENU_NAME_DUPLICATE = new ErrorCode(1_002_001_000, "已经存在该名字的菜单");
    ErrorCode MENU_PARENT_NOT_EXISTS = new ErrorCode(1_002_001_001, "父菜单不存在");
    ErrorCode MENU_PARENT_ERROR = new ErrorCode(1_002_001_002, "不能设置自己为父菜单");
    ErrorCode MENU_NOT_EXISTS = new ErrorCode(1_002_001_003, "菜单不存在");
    ErrorCode MENU_EXISTS_CHILDREN = new ErrorCode(1_002_001_004, "存在子菜单,无法删除");
    ErrorCode MENU_PARENT_NOT_DIR_OR_MENU = new ErrorCode(1_002_001_005, "父菜单的类型必须是目录或者菜单");
    // ========== è§’色模块 1-002-002-000 ==========
    ErrorCode ROLE_NOT_EXISTS = new ErrorCode(1_002_002_000, "角色不存在");
    ErrorCode ROLE_NAME_DUPLICATE = new ErrorCode(1_002_002_001, "已经存在名为【{}】的角色");
    ErrorCode ROLE_CODE_DUPLICATE = new ErrorCode(1_002_002_002, "已经存在编码为【{}】的角色");
    ErrorCode ROLE_CAN_NOT_UPDATE_SYSTEM_TYPE_ROLE = new ErrorCode(1_002_002_003, "不能操作类型为系统内置的角色");
    ErrorCode ROLE_IS_DISABLE = new ErrorCode(1_002_002_004, "名字为【{}】的角色已被禁用");
    ErrorCode ROLE_ADMIN_CODE_ERROR = new ErrorCode(1_002_002_005, "编码【{}】不能使用");
    // ========== ç”¨æˆ·æ¨¡å— 1-002-003-000 ==========
    ErrorCode USER_USERNAME_EXISTS = new ErrorCode(1_002_003_000, "用户账号已经存在");
    ErrorCode USER_MOBILE_EXISTS = new ErrorCode(1_002_003_001, "手机号已经存在");
    ErrorCode USER_EMAIL_EXISTS = new ErrorCode(1_002_003_002, "邮箱已经存在");
    ErrorCode USER_NOT_EXISTS = new ErrorCode(1_002_003_003, "用户不存在");
    ErrorCode USER_IMPORT_LIST_IS_EMPTY = new ErrorCode(1_002_003_004, "导入用户数据不能为空!");
    ErrorCode USER_PASSWORD_FAILED = new ErrorCode(1_002_003_005, "用户密码校验失败");
    ErrorCode USER_IS_DISABLE = new ErrorCode(1_002_003_006, "名字为【{}】的用户已被禁用");
    ErrorCode USER_COUNT_MAX = new ErrorCode(1_002_003_008, "创建用户失败,原因:超过租户最大租户配额({})!");
    ErrorCode USER_IMPORT_INIT_PASSWORD = new ErrorCode(1_002_003_009, "初始密码不能为空");
    // ========== éƒ¨é—¨æ¨¡å— 1-002-004-000 ==========
    ErrorCode DEPT_NAME_DUPLICATE = new ErrorCode(1_002_004_000, "已经存在该名字的部门");
    ErrorCode DEPT_PARENT_NOT_EXITS = new ErrorCode(1_002_004_001,"父级部门不存在");
    ErrorCode DEPT_NOT_FOUND = new ErrorCode(1_002_004_002, "当前部门不存在");
    ErrorCode DEPT_EXITS_CHILDREN = new ErrorCode(1_002_004_003, "存在子部门,无法删除");
    ErrorCode DEPT_PARENT_ERROR = new ErrorCode(1_002_004_004, "不能设置自己为父部门");
    ErrorCode DEPT_NOT_ENABLE = new ErrorCode(1_002_004_006, "部门({})不处于开启状态,不允许选择");
    ErrorCode DEPT_PARENT_IS_CHILD = new ErrorCode(1_002_004_007, "不能设置自己的子部门为父部门");
    // ========== å²—位模块 1-002-005-000 ==========
    ErrorCode POST_NOT_FOUND = new ErrorCode(1_002_005_000, "当前岗位不存在");
    ErrorCode POST_NOT_ENABLE = new ErrorCode(1_002_005_001, "岗位({}) ä¸å¤„于开启状态,不允许选择");
    ErrorCode POST_NAME_DUPLICATE = new ErrorCode(1_002_005_002, "已经存在该名字的岗位");
    ErrorCode POST_CODE_DUPLICATE = new ErrorCode(1_002_005_003, "已经存在该标识的岗位");
    // ========== å­—典类型 1-002-006-000 ==========
    ErrorCode DICT_TYPE_NOT_EXISTS = new ErrorCode(1_002_006_001, "当前字典类型不存在");
    ErrorCode DICT_TYPE_NOT_ENABLE = new ErrorCode(1_002_006_002, "字典类型不处于开启状态,不允许选择");
    ErrorCode DICT_TYPE_NAME_DUPLICATE = new ErrorCode(1_002_006_003, "已经存在该名字的字典类型");
    ErrorCode DICT_TYPE_TYPE_DUPLICATE = new ErrorCode(1_002_006_004, "已经存在该类型的字典类型");
    ErrorCode DICT_TYPE_HAS_CHILDREN = new ErrorCode(1_002_006_005, "无法删除,该字典类型还有字典数据");
    // ========== å­—典数据 1-002-007-000 ==========
    ErrorCode DICT_DATA_NOT_EXISTS = new ErrorCode(1_002_007_001, "当前字典数据不存在");
    ErrorCode DICT_DATA_NOT_ENABLE = new ErrorCode(1_002_007_002, "字典数据({})不处于开启状态,不允许选择");
    ErrorCode DICT_DATA_VALUE_DUPLICATE = new ErrorCode(1_002_007_003, "已经存在该值的字典数据");
    // ========== é€šçŸ¥å…¬å‘Š 1-002-008-000 ==========
    ErrorCode NOTICE_NOT_FOUND = new ErrorCode(1_002_008_001, "当前通知公告不存在");
    // ========== çŸ­ä¿¡æ¸ é“ 1-002-011-000 ==========
    ErrorCode SMS_CHANNEL_NOT_EXISTS = new ErrorCode(1_002_011_000, "短信渠道不存在");
    ErrorCode SMS_CHANNEL_DISABLE = new ErrorCode(1_002_011_001, "短信渠道不处于开启状态,不允许选择");
    ErrorCode SMS_CHANNEL_HAS_CHILDREN = new ErrorCode(1_002_011_002, "无法删除,该短信渠道还有短信模板");
    // ========== çŸ­ä¿¡æ¨¡æ¿ 1-002-012-000 ==========
    ErrorCode SMS_TEMPLATE_NOT_EXISTS = new ErrorCode(1_002_012_000, "短信模板不存在");
    ErrorCode SMS_TEMPLATE_CODE_DUPLICATE = new ErrorCode(1_002_012_001, "已经存在编码为【{}】的短信模板");
    ErrorCode SMS_TEMPLATE_API_ERROR = new ErrorCode(1_002_012_002, "短信 API æ¨¡æ¿è°ƒç”¨å¤±è´¥ï¼ŒåŽŸå› æ˜¯ï¼š{}");
    ErrorCode SMS_TEMPLATE_API_AUDIT_CHECKING = new ErrorCode(1_002_012_003, "短信 API æ¨¡ç‰ˆæ— æ³•使用,原因:审批中");
    ErrorCode SMS_TEMPLATE_API_AUDIT_FAIL = new ErrorCode(1_002_012_004, "短信 API æ¨¡ç‰ˆæ— æ³•使用,原因:审批不通过,{}");
    ErrorCode SMS_TEMPLATE_API_NOT_FOUND = new ErrorCode(1_002_012_005, "短信 API æ¨¡ç‰ˆæ— æ³•使用,原因:模版不存在");
    // ========== çŸ­ä¿¡å‘送 1-002-013-000 ==========
    ErrorCode SMS_SEND_MOBILE_NOT_EXISTS = new ErrorCode(1_002_013_000, "手机号不存在");
    ErrorCode SMS_SEND_MOBILE_TEMPLATE_PARAM_MISS = new ErrorCode(1_002_013_001, "模板参数({})缺失");
    ErrorCode SMS_SEND_TEMPLATE_NOT_EXISTS = new ErrorCode(1_002_013_002, "短信模板不存在");
    // ========== çŸ­ä¿¡éªŒè¯ç  1-002-014-000 ==========
    ErrorCode SMS_CODE_NOT_FOUND = new ErrorCode(1_002_014_000, "验证码不存在");
    ErrorCode SMS_CODE_EXPIRED = new ErrorCode(1_002_014_001, "验证码已过期");
    ErrorCode SMS_CODE_USED = new ErrorCode(1_002_014_002, "验证码已使用");
    ErrorCode SMS_CODE_EXCEED_SEND_MAXIMUM_QUANTITY_PER_DAY = new ErrorCode(1_002_014_004, "超过每日短信发送数量");
    ErrorCode SMS_CODE_SEND_TOO_FAST = new ErrorCode(1_002_014_005, "短信发送过于频繁");
    // ========== ç§Ÿæˆ·ä¿¡æ¯ 1-002-015-000 ==========
    ErrorCode TENANT_NOT_EXISTS = new ErrorCode(1_002_015_000, "租户不存在");
    ErrorCode TENANT_DISABLE = new ErrorCode(1_002_015_001, "名字为【{}】的租户已被禁用");
    ErrorCode TENANT_EXPIRE = new ErrorCode(1_002_015_002, "名字为【{}】的租户已过期");
    ErrorCode TENANT_CAN_NOT_UPDATE_SYSTEM = new ErrorCode(1_002_015_003, "系统租户不能进行修改、删除等操作!");
    ErrorCode TENANT_NAME_DUPLICATE = new ErrorCode(1_002_015_004, "名字为【{}】的租户已存在");
    ErrorCode TENANT_WEBSITE_DUPLICATE = new ErrorCode(1_002_015_005, "域名为【{}】的租户已存在");
    // ========== ç§Ÿæˆ·å¥—餐 1-002-016-000 ==========
    ErrorCode TENANT_PACKAGE_NOT_EXISTS = new ErrorCode(1_002_016_000, "租户套餐不存在");
    ErrorCode TENANT_PACKAGE_USED = new ErrorCode(1_002_016_001, "租户正在使用该套餐,请给租户重新设置套餐后再尝试删除");
    ErrorCode TENANT_PACKAGE_DISABLE = new ErrorCode(1_002_016_002, "名字为【{}】的租户套餐已被禁用");
    // ========== ç¤¾äº¤ç”¨æˆ· 1-002-018-000 ==========
    ErrorCode SOCIAL_USER_AUTH_FAILURE = new ErrorCode(1_002_018_000, "社交授权失败,原因是:{}");
    ErrorCode SOCIAL_USER_NOT_FOUND = new ErrorCode(1_002_018_001, "社交授权失败,找不到对应的用户");
    ErrorCode SOCIAL_CLIENT_WEIXIN_MINI_APP_PHONE_CODE_ERROR = new ErrorCode(1_002_018_200, "获得手机号失败");
    ErrorCode SOCIAL_CLIENT_WEIXIN_MINI_APP_QRCODE_ERROR = new ErrorCode(1_002_018_201, "获得小程序码失败");
    ErrorCode SOCIAL_CLIENT_WEIXIN_MINI_APP_SUBSCRIBE_TEMPLATE_ERROR = new ErrorCode(1_002_018_202, "获得小程序订阅消息模版失败");
    ErrorCode SOCIAL_CLIENT_WEIXIN_MINI_APP_SUBSCRIBE_MESSAGE_ERROR = new ErrorCode(1_002_018_203, "发送小程序订阅消息失败");
    ErrorCode SOCIAL_CLIENT_NOT_EXISTS = new ErrorCode(1_002_018_210, "社交客户端不存在");
    ErrorCode SOCIAL_CLIENT_UNIQUE = new ErrorCode(1_002_018_211, "社交客户端已存在配置");
    // ========== OAuth2 å®¢æˆ·ç«¯ 1-002-020-000 =========
    ErrorCode OAUTH2_CLIENT_NOT_EXISTS = new ErrorCode(1_002_020_000, "OAuth2 å®¢æˆ·ç«¯ä¸å­˜åœ¨");
    ErrorCode OAUTH2_CLIENT_EXISTS = new ErrorCode(1_002_020_001, "OAuth2 å®¢æˆ·ç«¯ç¼–号已存在");
    ErrorCode OAUTH2_CLIENT_DISABLE = new ErrorCode(1_002_020_002, "OAuth2 å®¢æˆ·ç«¯å·²ç¦ç”¨");
    ErrorCode OAUTH2_CLIENT_AUTHORIZED_GRANT_TYPE_NOT_EXISTS = new ErrorCode(1_002_020_003, "不支持该授权类型");
    ErrorCode OAUTH2_CLIENT_SCOPE_OVER = new ErrorCode(1_002_020_004, "授权范围过大");
    ErrorCode OAUTH2_CLIENT_REDIRECT_URI_NOT_MATCH = new ErrorCode(1_002_020_005, "无效 redirect_uri: {}");
    ErrorCode OAUTH2_CLIENT_CLIENT_SECRET_ERROR = new ErrorCode(1_002_020_006, "无效 client_secret: {}");
    // ========== OAuth2 æŽˆæƒ 1-002-021-000 =========
    ErrorCode OAUTH2_GRANT_CLIENT_ID_MISMATCH = new ErrorCode(1_002_021_000, "client_id ä¸åŒ¹é…");
    ErrorCode OAUTH2_GRANT_REDIRECT_URI_MISMATCH = new ErrorCode(1_002_021_001, "redirect_uri ä¸åŒ¹é…");
    ErrorCode OAUTH2_GRANT_STATE_MISMATCH = new ErrorCode(1_002_021_002, "state ä¸åŒ¹é…");
    // ========== OAuth2 æŽˆæƒ 1-002-022-000 =========
    ErrorCode OAUTH2_CODE_NOT_EXISTS = new ErrorCode(1_002_022_000, "code ä¸å­˜åœ¨");
    ErrorCode OAUTH2_CODE_EXPIRE = new ErrorCode(1_002_022_001, "code å·²è¿‡æœŸ");
    // ========== é‚®ç®±è´¦å· 1-002-023-000 ==========
    ErrorCode MAIL_ACCOUNT_NOT_EXISTS = new ErrorCode(1_002_023_000, "邮箱账号不存在");
    ErrorCode MAIL_ACCOUNT_RELATE_TEMPLATE_EXISTS = new ErrorCode(1_002_023_001, "无法删除,该邮箱账号还有邮件模板");
    // ========== é‚®ä»¶æ¨¡ç‰ˆ 1-002-024-000 ==========
    ErrorCode MAIL_TEMPLATE_NOT_EXISTS = new ErrorCode(1_002_024_000, "邮件模版不存在");
    ErrorCode MAIL_TEMPLATE_CODE_EXISTS = new ErrorCode(1_002_024_001, "邮件模版 code({}) å·²å­˜åœ¨");
    // ========== é‚®ä»¶å‘送 1-002-025-000 ==========
    ErrorCode MAIL_SEND_TEMPLATE_PARAM_MISS = new ErrorCode(1_002_025_000, "模板参数({})缺失");
    ErrorCode MAIL_SEND_MAIL_NOT_EXISTS = new ErrorCode(1_002_025_001, "邮箱不存在");
    // ========== ç«™å†…信模版 1-002-026-000 ==========
    ErrorCode NOTIFY_TEMPLATE_NOT_EXISTS = new ErrorCode(1_002_026_000, "站内信模版不存在");
    ErrorCode NOTIFY_TEMPLATE_CODE_DUPLICATE = new ErrorCode(1_002_026_001, "已经存在编码为【{}】的站内信模板");
    // ========== ç«™å†…信模版 1-002-027-000 ==========
    // ========== ç«™å†…信发送 1-002-028-000 ==========
    ErrorCode NOTIFY_SEND_TEMPLATE_PARAM_MISS = new ErrorCode(1_002_028_000, "模板参数({})缺失");
}
jh-module-ecg/jh-module-ecg-biz/pom.xml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,124 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <groupId>cn.lihu</groupId>
        <artifactId>jh-module-ecg</artifactId>
        <version>${revision}</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>jh-module-ecg-biz</artifactId>
    <packaging>jar</packaging>
    <name>${project.artifactId}</name>
    <description>
        ecg æ¨¡å—下
    </description>
    <dependencies>
        <dependency>
            <groupId>cn.lihu</groupId>
            <artifactId>jh-module-ecg-api</artifactId>
            <version>${revision}</version>
        </dependency>
        <dependency>
            <groupId>cn.lihu</groupId>
            <artifactId>jh-module-infra-api</artifactId>
            <version>${revision}</version>
        </dependency>
        <!-- ä¸šåŠ¡ç»„ä»¶ -->
        <dependency>
            <groupId>cn.lihu</groupId>
            <artifactId>jh-spring-boot-starter-biz-data-permission</artifactId>
        </dependency>
        <dependency>
            <groupId>cn.lihu</groupId>
            <artifactId>jh-spring-boot-starter-biz-tenant</artifactId>
        </dependency>
        <dependency>
            <groupId>cn.lihu</groupId>
            <artifactId>jh-spring-boot-starter-biz-ip</artifactId>
        </dependency>
        <!-- Web ç›¸å…³ -->
        <dependency>
            <groupId>cn.lihu</groupId>
            <artifactId>jh-spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>
        <!-- DB ç›¸å…³ -->
        <dependency>
            <groupId>cn.lihu</groupId>
            <artifactId>jh-spring-boot-starter-mybatis</artifactId>
        </dependency>
        <dependency>
            <groupId>cn.lihu</groupId>
            <artifactId>jh-spring-boot-starter-redis</artifactId>
        </dependency>
        <!-- Job å®šæ—¶ä»»åŠ¡ç›¸å…³ -->
        <dependency>
            <groupId>cn.lihu</groupId>
            <artifactId>jh-spring-boot-starter-job</artifactId>
        </dependency>
        <!-- æ¶ˆæ¯é˜Ÿåˆ—相关 -->
        <dependency>
            <groupId>cn.lihu</groupId>
            <artifactId>jh-spring-boot-starter-mq</artifactId>
        </dependency>
        <!-- å·¥å…·ç±»ç›¸å…³ -->
        <dependency>
            <groupId>cn.lihu</groupId>
            <artifactId>jh-spring-boot-starter-excel</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-mail</artifactId>
        </dependency>
        <!-- ä¸‰æ–¹äº‘服务相关 -->
        <dependency>
            <groupId>com.xingyuv</groupId>
            <artifactId>spring-boot-starter-justauth</artifactId> <!-- ç¤¾äº¤ç™»é™†ï¼ˆä¾‹å¦‚说,个人微信、企业微信等等) -->
        </dependency>
        <dependency>
            <groupId>com.github.binarywang</groupId>
            <artifactId>wx-java-mp-spring-boot-starter</artifactId> <!-- å¾®ä¿¡ç™»å½•(公众号) -->
        </dependency>
        <dependency>
            <groupId>com.github.binarywang</groupId>
            <artifactId>wx-java-miniapp-spring-boot-starter</artifactId>  <!-- å¾®ä¿¡ç™»å½•(小程序) -->
        </dependency>
        <dependency>
            <groupId>com.aliyun</groupId>
            <artifactId>aliyun-java-sdk-core</artifactId> <!-- çŸ­ä¿¡ï¼ˆé˜¿é‡Œäº‘) -->
        </dependency>
        <dependency>
            <groupId>com.aliyun</groupId>
            <artifactId>aliyun-java-sdk-dysmsapi</artifactId> <!-- çŸ­ä¿¡ï¼ˆé˜¿é‡Œäº‘) -->
        </dependency>
        <dependency>
            <groupId>com.tencentcloudapi</groupId>
            <artifactId>tencentcloud-sdk-java-sms</artifactId> <!-- çŸ­ä¿¡ï¼ˆè…¾è®¯äº‘) -->
        </dependency>
        <dependency>
            <groupId>com.xingyuv</groupId>
            <artifactId>spring-boot-starter-captcha-plus</artifactId> <!-- éªŒè¯ç ï¼Œä¸€èˆ¬ç”¨äºŽç™»å½•使用 -->
        </dependency>
    </dependencies>
</project>
jh-module-ecg/jh-module-ecg-biz/src/main/java/cn/lihu/jh/module/ecg/controller/admin/appointment/AppointmentController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,95 @@
package cn.lihu.jh.module.ecg.controller.admin.appointment;
import org.springframework.web.bind.annotation.*;
import jakarta.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.security.access.prepost.PreAuthorize;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Operation;
import jakarta.validation.constraints.*;
import jakarta.validation.*;
import jakarta.servlet.http.*;
import java.util.*;
import java.io.IOException;
import cn.lihu.jh.framework.common.pojo.PageParam;
import cn.lihu.jh.framework.common.pojo.PageResult;
import cn.lihu.jh.framework.common.pojo.CommonResult;
import cn.lihu.jh.framework.common.util.object.BeanUtils;
import static cn.lihu.jh.framework.common.pojo.CommonResult.success;
import cn.lihu.jh.framework.excel.core.util.ExcelUtils;
import cn.lihu.jh.framework.apilog.core.annotation.ApiAccessLog;
import static cn.lihu.jh.framework.apilog.core.enums.OperateTypeEnum.*;
import cn.lihu.jh.module.ecg.controller.admin.appointment.vo.*;
import cn.lihu.jh.module.ecg.dal.dataobject.appointment.AppointmentDO;
import cn.lihu.jh.module.ecg.service.appointment.AppointmentService;
@Tag(name = "管理后台 - é¢„约")
@RestController
@RequestMapping("/ecg/appointment")
@Validated
public class AppointmentController {
    @Resource
    private AppointmentService appointmentService;
    @PostMapping("/create")
    @Operation(summary = "创建预约")
    @PreAuthorize("@ss.hasPermission('ecg:appointment:create')")
    public CommonResult<Integer> createAppointment(@Valid @RequestBody AppointmentSaveReqVO createReqVO) {
        return success(appointmentService.createAppointment(createReqVO));
    }
    @PutMapping("/update")
    @Operation(summary = "更新预约")
    @PreAuthorize("@ss.hasPermission('ecg:appointment:update')")
    public CommonResult<Boolean> updateAppointment(@Valid @RequestBody AppointmentSaveReqVO updateReqVO) {
        appointmentService.updateAppointment(updateReqVO);
        return success(true);
    }
    @DeleteMapping("/delete")
    @Operation(summary = "删除预约")
    @Parameter(name = "id", description = "编号", required = true)
    @PreAuthorize("@ss.hasPermission('ecg:appointment:delete')")
    public CommonResult<Boolean> deleteAppointment(@RequestParam("id") Integer id) {
        appointmentService.deleteAppointment(id);
        return success(true);
    }
    @GetMapping("/get")
    @Operation(summary = "获得预约")
    @Parameter(name = "id", description = "编号", required = true, example = "1024")
    @PreAuthorize("@ss.hasPermission('ecg:appointment:query')")
    public CommonResult<AppointmentRespVO> getAppointment(@RequestParam("id") Integer id) {
        AppointmentDO appointment = appointmentService.getAppointment(id);
        return success(BeanUtils.toBean(appointment, AppointmentRespVO.class));
    }
    @GetMapping("/page")
    @Operation(summary = "获得预约分页")
    @PreAuthorize("@ss.hasPermission('ecg:appointment:query')")
    public CommonResult<PageResult<AppointmentRespVO>> getAppointmentPage(@Valid AppointmentPageReqVO pageReqVO) {
        PageResult<AppointmentDO> pageResult = appointmentService.getAppointmentPage(pageReqVO);
        return success(BeanUtils.toBean(pageResult, AppointmentRespVO.class));
    }
    @GetMapping("/export-excel")
    @Operation(summary = "导出预约 Excel")
    @PreAuthorize("@ss.hasPermission('ecg:appointment:export')")
    @ApiAccessLog(operateType = EXPORT)
    public void exportAppointmentExcel(@Valid AppointmentPageReqVO pageReqVO,
              HttpServletResponse response) throws IOException {
        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        List<AppointmentDO> list = appointmentService.getAppointmentPage(pageReqVO).getList();
        // å¯¼å‡º Excel
        ExcelUtils.write(response, "预约.xls", "数据", AppointmentRespVO.class,
                        BeanUtils.toBean(list, AppointmentRespVO.class));
    }
}
jh-module-ecg/jh-module-ecg-biz/src/main/java/cn/lihu/jh/module/ecg/controller/admin/appointment/vo/AppointmentPageReqVO.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,76 @@
package cn.lihu.jh.module.ecg.controller.admin.appointment.vo;
import lombok.*;
import java.util.*;
import io.swagger.v3.oas.annotations.media.Schema;
import cn.lihu.jh.framework.common.pojo.PageParam;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static cn.lihu.jh.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - é¢„约分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class AppointmentPageReqVO extends PageParam {
    @Schema(description = "患者编号", example = "29034")
    private String patId;
    @Schema(description = "患者姓名", example = "赵六")
    private String patName;
    @Schema(description = "患者性别")
    private Boolean patGender;
    @Schema(description = "患者生日")
    private LocalDate patBirthday;
    @Schema(description = "患者手机")
    private String patMobile;
    @Schema(description = "患者电话")
    private String patPhone;
    @Schema(description = "身份证号", example = "798")
    private String patIdentityId;
    @Schema(description = "患者地址")
    private String patAddr;
    @Schema(description = "患者所在科室代码")
    private String patDeptCode;
    @Schema(description = "患者所在科室名称")
    private String patDeptDesc;
    @Schema(description = "患者所在病区代码")
    private String patWardCode;
    @Schema(description = "患者所在病区名称")
    private String patWardDesc;
    @Schema(description = "床号")
    private String patBedNo;
    @Schema(description = "预约编号", example = "27849")
    private String bookId;
    @Schema(description = "预约检查时间段")
    private LocalDateTime bookPeriodStart;
    @Schema(description = "预约检查时间段")
    private LocalDateTime bookPeriodEnd;
    @Schema(description = "预约发生时间")
    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
    private LocalDateTime[] bookTime;
    @Schema(description = "预约检查类型", example = "2")
    private Boolean bookCheckType;
    @Schema(description = "预约来源:X系统、护士手动预约")
    private String bookSrc;
}
jh-module-ecg/jh-module-ecg-biz/src/main/java/cn/lihu/jh/module/ecg/controller/admin/appointment/vo/AppointmentRespVO.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,95 @@
package cn.lihu.jh.module.ecg.controller.admin.appointment.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.util.*;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import com.alibaba.excel.annotation.*;
import cn.lihu.jh.framework.excel.core.annotations.DictFormat;
import cn.lihu.jh.framework.excel.core.convert.DictConvert;
@Schema(description = "管理后台 - é¢„约 Response VO")
@Data
@ExcelIgnoreUnannotated
public class AppointmentRespVO {
    @Schema(description = "患者编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "29034")
    @ExcelProperty("患者编号")
    private String patId;
    @Schema(description = "患者姓名", requiredMode = Schema.RequiredMode.REQUIRED, example = "赵六")
    @ExcelProperty("患者姓名")
    private String patName;
    @Schema(description = "患者性别", requiredMode = Schema.RequiredMode.REQUIRED)
    @ExcelProperty(value = "患者性别", converter = DictConvert.class)
    @DictFormat("system_user_sex") // TODO ä»£ç ä¼˜åŒ–:建议设置到对应的 DictTypeConstants æžšä¸¾ç±»ä¸­
    private Boolean patGender;
    @Schema(description = "患者生日")
    @ExcelProperty("患者生日")
    private LocalDate patBirthday;
    @Schema(description = "患者手机")
    @ExcelProperty("患者手机")
    private String patMobile;
    @Schema(description = "患者电话")
    @ExcelProperty("患者电话")
    private String patPhone;
    @Schema(description = "身份证号", example = "798")
    @ExcelProperty("身份证号")
    private String patIdentityId;
    @Schema(description = "患者地址")
    @ExcelProperty("患者地址")
    private String patAddr;
    @Schema(description = "患者所在科室代码")
    @ExcelProperty("患者所在科室代码")
    private String patDeptCode;
    @Schema(description = "患者所在科室名称")
    @ExcelProperty("患者所在科室名称")
    private String patDeptDesc;
    @Schema(description = "患者所在病区代码")
    @ExcelProperty("患者所在病区代码")
    private String patWardCode;
    @Schema(description = "患者所在病区名称")
    @ExcelProperty("患者所在病区名称")
    private String patWardDesc;
    @Schema(description = "床号")
    @ExcelProperty("床号")
    private String patBedNo;
    @Schema(description = "预约编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "27849")
    @ExcelProperty("预约编号")
    private String bookId;
    @Schema(description = "预约检查时间段", requiredMode = Schema.RequiredMode.REQUIRED)
    @ExcelProperty("预约检查时间段")
    private LocalDateTime bookPeriodStart;
    @Schema(description = "预约检查时间段", requiredMode = Schema.RequiredMode.REQUIRED)
    @ExcelProperty("预约检查时间段")
    private LocalDateTime bookPeriodEnd;
    @Schema(description = "预约发生时间", requiredMode = Schema.RequiredMode.REQUIRED)
    @ExcelProperty("预约发生时间")
    private LocalDateTime bookTime;
    @Schema(description = "预约检查类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
    @ExcelProperty(value = "预约检查类型", converter = DictConvert.class)
    @DictFormat("ecg_check_type") // TODO ä»£ç ä¼˜åŒ–:建议设置到对应的 DictTypeConstants æžšä¸¾ç±»ä¸­
    private Boolean bookCheckType;
    @Schema(description = "预约来源:X系统、护士手动预约", requiredMode = Schema.RequiredMode.REQUIRED)
    @ExcelProperty("预约来源:X系统、护士手动预约")
    private String bookSrc;
}
jh-module-ecg/jh-module-ecg-biz/src/main/java/cn/lihu/jh/module/ecg/controller/admin/appointment/vo/AppointmentSaveReqVO.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,76 @@
package cn.lihu.jh.module.ecg.controller.admin.appointment.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.util.*;
import jakarta.validation.constraints.*;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - é¢„约新增/修改 Request VO")
@Data
public class AppointmentSaveReqVO {
    @Schema(description = "患者编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "29034")
    @NotEmpty(message = "患者编号不能为空")
    private String patId;
    @Schema(description = "患者姓名", requiredMode = Schema.RequiredMode.REQUIRED, example = "赵六")
    @NotEmpty(message = "患者姓名不能为空")
    private String patName;
    @Schema(description = "患者性别", requiredMode = Schema.RequiredMode.REQUIRED)
    @NotNull(message = "患者性别不能为空")
    private Boolean patGender;
    @Schema(description = "患者生日")
    private LocalDate patBirthday;
    @Schema(description = "患者手机")
    private String patMobile;
    @Schema(description = "患者电话")
    private String patPhone;
    @Schema(description = "身份证号", example = "798")
    private String patIdentityId;
    @Schema(description = "患者地址")
    private String patAddr;
    @Schema(description = "患者所在科室代码")
    private String patDeptCode;
    @Schema(description = "患者所在科室名称")
    private String patDeptDesc;
    @Schema(description = "患者所在病区代码")
    private String patWardCode;
    @Schema(description = "患者所在病区名称")
    private String patWardDesc;
    @Schema(description = "床号")
    private String patBedNo;
    @Schema(description = "预约编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "27849")
    @NotEmpty(message = "预约编号不能为空")
    private String bookId;
    @Schema(description = "预约检查时间段", requiredMode = Schema.RequiredMode.REQUIRED)
    @NotNull(message = "预约检查时间段不能为空")
    private LocalDateTime bookPeriodStart;
    @Schema(description = "预约检查时间段", requiredMode = Schema.RequiredMode.REQUIRED)
    @NotNull(message = "预约检查时间段不能为空")
    private LocalDateTime bookPeriodEnd;
    @Schema(description = "预约发生时间", requiredMode = Schema.RequiredMode.REQUIRED)
    @NotNull(message = "预约发生时间不能为空")
    private LocalDateTime bookTime;
    @Schema(description = "预约检查类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
    @NotNull(message = "预约检查类型不能为空")
    private Boolean bookCheckType;
}
jh-module-ecg/jh-module-ecg-biz/src/main/java/cn/lihu/jh/module/ecg/dal/dataobject/appointment/AppointmentDO.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,119 @@
package cn.lihu.jh.module.ecg.dal.dataobject.appointment;
import lombok.*;
import java.util.*;
import java.time.LocalDateTime;
import java.time.LocalDateTime;
import java.time.LocalDateTime;
import java.time.LocalDateTime;
import java.time.LocalDateTime;
import java.time.LocalDateTime;
import com.baomidou.mybatisplus.annotation.*;
import cn.lihu.jh.framework.mybatis.core.dataobject.BaseDO;
/**
 * é¢„约 DO
 *
 * @author é©¬å‰‘æ³¢
 */
@TableName("appointment")
@KeySequence("appointment_seq") // ç”¨äºŽ Oracle、PostgreSQL、Kingbase、DB2、H2 æ•°æ®åº“的主键自增。如果是 MySQL ç­‰æ•°æ®åº“,可不写。
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class AppointmentDO extends BaseDO {
    /**
     * id
     */
    @TableId
    private Integer id;
    /**
     * æ‚£è€…编号
     */
    private String patId;
    /**
     * æ‚£è€…姓名
     */
    private String patName;
    /**
     * æ‚£è€…性别
     *
     * æžšä¸¾ {@link TODO system_user_sex å¯¹åº”的类}
     */
    private Boolean patGender;
    /**
     * æ‚£è€…生日
     */
    private LocalDate patBirthday;
    /**
     * æ‚£è€…手机
     */
    private String patMobile;
    /**
     * æ‚£è€…电话
     */
    private String patPhone;
    /**
     * èº«ä»½è¯å·
     */
    private String patIdentityId;
    /**
     * æ‚£è€…地址
     */
    private String patAddr;
    /**
     * æ‚£è€…所在科室代码
     */
    private String patDeptCode;
    /**
     * æ‚£è€…所在科室名称
     */
    private String patDeptDesc;
    /**
     * æ‚£è€…所在病区代码
     */
    private String patWardCode;
    /**
     * æ‚£è€…所在病区名称
     */
    private String patWardDesc;
    /**
     * åºŠå·
     */
    private String patBedNo;
    /**
     * é¢„约编号
     */
    private String bookId;
    /**
     * é¢„约检查时间段
     */
    private LocalDateTime bookPeriodStart;
    /**
     * é¢„约检查时间段
     */
    private LocalDateTime bookPeriodEnd;
    /**
     * é¢„约发生时间
     */
    private LocalDateTime bookTime;
    /**
     * é¢„约检查类型
     *
     * æžšä¸¾ {@link TODO ecg_check_type å¯¹åº”的类}
     */
    private Boolean bookCheckType;
    /**
     * é¢„约来源:X系统、护士手动预约
     */
    private String bookSrc;
    /**
     * ä»Žæ•°æ®å¹³å°åŒæ­¥æ—¶é—´
     */
    private LocalDateTime syncTime;
}
jh-module-ecg/jh-module-ecg-biz/src/main/java/cn/lihu/jh/module/ecg/dal/mysql/appointment/AppointmentMapper.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,44 @@
package cn.lihu.jh.module.ecg.dal.mysql.appointment;
import java.util.*;
import cn.lihu.jh.framework.common.pojo.PageResult;
import cn.lihu.jh.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.lihu.jh.framework.mybatis.core.mapper.BaseMapperX;
import cn.lihu.jh.module.ecg.dal.dataobject.appointment.AppointmentDO;
import org.apache.ibatis.annotations.Mapper;
import cn.lihu.jh.module.ecg.controller.admin.appointment.vo.*;
/**
 * é¢„约 Mapper
 *
 * @author é©¬å‰‘æ³¢
 */
@Mapper
public interface AppointmentMapper extends BaseMapperX<AppointmentDO> {
    default PageResult<AppointmentDO> selectPage(AppointmentPageReqVO reqVO) {
        return selectPage(reqVO, new LambdaQueryWrapperX<AppointmentDO>()
                .eqIfPresent(AppointmentDO::getPatId, reqVO.getPatId())
                .likeIfPresent(AppointmentDO::getPatName, reqVO.getPatName())
                .eqIfPresent(AppointmentDO::getPatGender, reqVO.getPatGender())
                .eqIfPresent(AppointmentDO::getPatBirthday, reqVO.getPatBirthday())
                .eqIfPresent(AppointmentDO::getPatMobile, reqVO.getPatMobile())
                .eqIfPresent(AppointmentDO::getPatPhone, reqVO.getPatPhone())
                .eqIfPresent(AppointmentDO::getPatIdentityId, reqVO.getPatIdentityId())
                .eqIfPresent(AppointmentDO::getPatAddr, reqVO.getPatAddr())
                .eqIfPresent(AppointmentDO::getPatDeptCode, reqVO.getPatDeptCode())
                .eqIfPresent(AppointmentDO::getPatDeptDesc, reqVO.getPatDeptDesc())
                .eqIfPresent(AppointmentDO::getPatWardCode, reqVO.getPatWardCode())
                .eqIfPresent(AppointmentDO::getPatWardDesc, reqVO.getPatWardDesc())
                .eqIfPresent(AppointmentDO::getPatBedNo, reqVO.getPatBedNo())
                .eqIfPresent(AppointmentDO::getBookId, reqVO.getBookId())
                .eqIfPresent(AppointmentDO::getBookPeriodStart, reqVO.getBookPeriodStart())
                .eqIfPresent(AppointmentDO::getBookPeriodEnd, reqVO.getBookPeriodEnd())
                .betweenIfPresent(AppointmentDO::getBookTime, reqVO.getBookTime())
                .eqIfPresent(AppointmentDO::getBookCheckType, reqVO.getBookCheckType())
                .eqIfPresent(AppointmentDO::getBookSrc, reqVO.getBookSrc())
                .orderByDesc(AppointmentDO::getId));
    }
}
jh-module-ecg/jh-module-ecg-biz/src/main/java/cn/lihu/jh/module/ecg/service/appointment/AppointmentService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,55 @@
package cn.lihu.jh.module.ecg.service.appointment;
import java.util.*;
import jakarta.validation.*;
import cn.lihu.jh.module.ecg.controller.admin.appointment.vo.*;
import cn.lihu.jh.module.ecg.dal.dataobject.appointment.AppointmentDO;
import cn.lihu.jh.framework.common.pojo.PageResult;
import cn.lihu.jh.framework.common.pojo.PageParam;
/**
 * é¢„约 Service æŽ¥å£
 *
 * @author é©¬å‰‘æ³¢
 */
public interface AppointmentService {
    /**
     * åˆ›å»ºé¢„约
     *
     * @param createReqVO åˆ›å»ºä¿¡æ¯
     * @return ç¼–号
     */
    Integer createAppointment(@Valid AppointmentSaveReqVO createReqVO);
    /**
     * æ›´æ–°é¢„约
     *
     * @param updateReqVO æ›´æ–°ä¿¡æ¯
     */
    void updateAppointment(@Valid AppointmentSaveReqVO updateReqVO);
    /**
     * åˆ é™¤é¢„约
     *
     * @param id ç¼–号
     */
    void deleteAppointment(Integer id);
    /**
     * èŽ·å¾—é¢„çº¦
     *
     * @param id ç¼–号
     * @return é¢„约
     */
    AppointmentDO getAppointment(Integer id);
    /**
     * èŽ·å¾—é¢„çº¦åˆ†é¡µ
     *
     * @param pageReqVO åˆ†é¡µæŸ¥è¯¢
     * @return é¢„约分页
     */
    PageResult<AppointmentDO> getAppointmentPage(AppointmentPageReqVO pageReqVO);
}
jh-module-ecg/jh-module-ecg-biz/src/main/java/cn/lihu/jh/module/ecg/service/appointment/AppointmentServiceImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,74 @@
package cn.lihu.jh.module.ecg.service.appointment;
import org.springframework.stereotype.Service;
import jakarta.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
import cn.lihu.jh.module.ecg.controller.admin.appointment.vo.*;
import cn.lihu.jh.module.ecg.dal.dataobject.appointment.AppointmentDO;
import cn.lihu.jh.framework.common.pojo.PageResult;
import cn.lihu.jh.framework.common.pojo.PageParam;
import cn.lihu.jh.framework.common.util.object.BeanUtils;
import cn.lihu.jh.module.ecg.dal.mysql.appointment.AppointmentMapper;
import static cn.lihu.jh.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.lihu.jh.module.ecg.enums.ErrorCodeConstants.*;
/**
 * é¢„约 Service å®žçŽ°ç±»
 *
 * @author é©¬å‰‘æ³¢
 */
@Service
@Validated
public class AppointmentServiceImpl implements AppointmentService {
    @Resource
    private AppointmentMapper appointmentMapper;
    @Override
    public Integer createAppointment(AppointmentSaveReqVO createReqVO) {
        // æ’å…¥
        AppointmentDO appointment = BeanUtils.toBean(createReqVO, AppointmentDO.class);
        appointmentMapper.insert(appointment);
        // è¿”回
        return appointment.getId();
    }
    @Override
    public void updateAppointment(AppointmentSaveReqVO updateReqVO) {
        // æ ¡éªŒå­˜åœ¨
        validateAppointmentExists(updateReqVO.getId());
        // æ›´æ–°
        AppointmentDO updateObj = BeanUtils.toBean(updateReqVO, AppointmentDO.class);
        appointmentMapper.updateById(updateObj);
    }
    @Override
    public void deleteAppointment(Integer id) {
        // æ ¡éªŒå­˜åœ¨
        validateAppointmentExists(id);
        // åˆ é™¤
        appointmentMapper.deleteById(id);
    }
    private void validateAppointmentExists(Integer id) {
        if (appointmentMapper.selectById(id) == null) {
            throw exception(APPOINTMENT_NOT_EXISTS);
        }
    }
    @Override
    public AppointmentDO getAppointment(Integer id) {
        return appointmentMapper.selectById(id);
    }
    @Override
    public PageResult<AppointmentDO> getAppointmentPage(AppointmentPageReqVO pageReqVO) {
        return appointmentMapper.selectPage(pageReqVO);
    }
}
jh-module-ecg/jh-module-ecg-biz/src/main/resources/mapper/appointment/AppointmentMapper.xml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.lihu.jh.module.ecg.dal.mysql.appointment.AppointmentMapper">
    <!--
        ä¸€èˆ¬æƒ…况下,尽可能使用 Mapper è¿›è¡Œ CRUD å¢žåˆ æ”¹æŸ¥å³å¯ã€‚
        æ— æ³•满足的场景,例如说多表关联查询,才使用 XML ç¼–写 SQL。
        ä»£ç ç”Ÿæˆå™¨æš‚时只生成 Mapper XML æ–‡ä»¶æœ¬èº«ï¼Œæ›´å¤šæŽ¨è MybatisX å¿«é€Ÿå¼€å‘插件来生成查询。
        æ–‡æ¡£å¯è§ï¼šhttps://www.iocoder.cn/MyBatis/x-plugins/
     -->
</mapper>
jh-module-ecg/jh-module-ecg-biz/src/test/java/cn/lihu/jh/module/ecg/service/appointment/AppointmentServiceImplTest.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,202 @@
package cn.lihu.jh.module.ecg.service.appointment;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.mock.mockito.MockBean;
import jakarta.annotation.Resource;
import cn.lihu.jh.framework.test.core.ut.BaseDbUnitTest;
import cn.lihu.jh.module.ecg.controller.admin.appointment.vo.*;
import cn.lihu.jh.module.ecg.dal.dataobject.appointment.AppointmentDO;
import cn.lihu.jh.module.ecg.dal.mysql.appointment.AppointmentMapper;
import cn.lihu.jh.framework.common.pojo.PageResult;
import jakarta.annotation.Resource;
import org.springframework.context.annotation.Import;
import java.util.*;
import java.time.LocalDateTime;
import static cn.hutool.core.util.RandomUtil.*;
import static cn.lihu.jh.module.ecg.enums.ErrorCodeConstants.*;
import static cn.lihu.jh.framework.test.core.util.AssertUtils.*;
import static cn.lihu.jh.framework.test.core.util.RandomUtils.*;
import static cn.lihu.jh.framework.common.util.date.LocalDateTimeUtils.*;
import static cn.lihu.jh.framework.common.util.object.ObjectUtils.*;
import static cn.lihu.jh.framework.common.util.date.DateUtils.*;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
/**
 * {@link AppointmentServiceImpl} çš„单元测试类
 *
 * @author é©¬å‰‘æ³¢
 */
@Import(AppointmentServiceImpl.class)
public class AppointmentServiceImplTest extends BaseDbUnitTest {
    @Resource
    private AppointmentServiceImpl appointmentService;
    @Resource
    private AppointmentMapper appointmentMapper;
    @Test
    public void testCreateAppointment_success() {
        // å‡†å¤‡å‚æ•°
        AppointmentSaveReqVO createReqVO = randomPojo(AppointmentSaveReqVO.class).setId(null);
        // è°ƒç”¨
        Integer appointmentId = appointmentService.createAppointment(createReqVO);
        // æ–­è¨€
        assertNotNull(appointmentId);
        // æ ¡éªŒè®°å½•的属性是否正确
        AppointmentDO appointment = appointmentMapper.selectById(appointmentId);
        assertPojoEquals(createReqVO, appointment, "id");
    }
    @Test
    public void testUpdateAppointment_success() {
        // mock æ•°æ®
        AppointmentDO dbAppointment = randomPojo(AppointmentDO.class);
        appointmentMapper.insert(dbAppointment);// @Sql: å…ˆæ’入出一条存在的数据
        // å‡†å¤‡å‚æ•°
        AppointmentSaveReqVO updateReqVO = randomPojo(AppointmentSaveReqVO.class, o -> {
            o.setId(dbAppointment.getId()); // è®¾ç½®æ›´æ–°çš„ ID
        });
        // è°ƒç”¨
        appointmentService.updateAppointment(updateReqVO);
        // æ ¡éªŒæ˜¯å¦æ›´æ–°æ­£ç¡®
        AppointmentDO appointment = appointmentMapper.selectById(updateReqVO.getId()); // èŽ·å–æœ€æ–°çš„
        assertPojoEquals(updateReqVO, appointment);
    }
    @Test
    public void testUpdateAppointment_notExists() {
        // å‡†å¤‡å‚æ•°
        AppointmentSaveReqVO updateReqVO = randomPojo(AppointmentSaveReqVO.class);
        // è°ƒç”¨, å¹¶æ–­è¨€å¼‚常
        assertServiceException(() -> appointmentService.updateAppointment(updateReqVO), APPOINTMENT_NOT_EXISTS);
    }
    @Test
    public void testDeleteAppointment_success() {
        // mock æ•°æ®
        AppointmentDO dbAppointment = randomPojo(AppointmentDO.class);
        appointmentMapper.insert(dbAppointment);// @Sql: å…ˆæ’入出一条存在的数据
        // å‡†å¤‡å‚æ•°
        Integer id = dbAppointment.getId();
        // è°ƒç”¨
        appointmentService.deleteAppointment(id);
       // æ ¡éªŒæ•°æ®ä¸å­˜åœ¨äº†
       assertNull(appointmentMapper.selectById(id));
    }
    @Test
    public void testDeleteAppointment_notExists() {
        // å‡†å¤‡å‚æ•°
        Integer id = randomIntegerId();
        // è°ƒç”¨, å¹¶æ–­è¨€å¼‚常
        assertServiceException(() -> appointmentService.deleteAppointment(id), APPOINTMENT_NOT_EXISTS);
    }
    @Test
    @Disabled  // TODO è¯·ä¿®æ”¹ null ä¸ºéœ€è¦çš„值,然后删除 @Disabled æ³¨è§£
    public void testGetAppointmentPage() {
       // mock æ•°æ®
       AppointmentDO dbAppointment = randomPojo(AppointmentDO.class, o -> { // ç­‰ä¼šæŸ¥è¯¢åˆ°
           o.setPatId(null);
           o.setPatName(null);
           o.setPatGender(null);
           o.setPatBirthday(null);
           o.setPatMobile(null);
           o.setPatPhone(null);
           o.setPatIdentityId(null);
           o.setPatAddr(null);
           o.setPatDeptCode(null);
           o.setPatDeptDesc(null);
           o.setPatWardCode(null);
           o.setPatWardDesc(null);
           o.setPatBedNo(null);
           o.setBookId(null);
           o.setBookPeriodStart(null);
           o.setBookPeriodEnd(null);
           o.setBookTime(null);
           o.setBookCheckType(null);
           o.setBookSrc(null);
       });
       appointmentMapper.insert(dbAppointment);
       // æµ‹è¯• patId ä¸åŒ¹é…
       appointmentMapper.insert(cloneIgnoreId(dbAppointment, o -> o.setPatId(null)));
       // æµ‹è¯• patName ä¸åŒ¹é…
       appointmentMapper.insert(cloneIgnoreId(dbAppointment, o -> o.setPatName(null)));
       // æµ‹è¯• patGender ä¸åŒ¹é…
       appointmentMapper.insert(cloneIgnoreId(dbAppointment, o -> o.setPatGender(null)));
       // æµ‹è¯• patBirthday ä¸åŒ¹é…
       appointmentMapper.insert(cloneIgnoreId(dbAppointment, o -> o.setPatBirthday(null)));
       // æµ‹è¯• patMobile ä¸åŒ¹é…
       appointmentMapper.insert(cloneIgnoreId(dbAppointment, o -> o.setPatMobile(null)));
       // æµ‹è¯• patPhone ä¸åŒ¹é…
       appointmentMapper.insert(cloneIgnoreId(dbAppointment, o -> o.setPatPhone(null)));
       // æµ‹è¯• patIdentityId ä¸åŒ¹é…
       appointmentMapper.insert(cloneIgnoreId(dbAppointment, o -> o.setPatIdentityId(null)));
       // æµ‹è¯• patAddr ä¸åŒ¹é…
       appointmentMapper.insert(cloneIgnoreId(dbAppointment, o -> o.setPatAddr(null)));
       // æµ‹è¯• patDeptCode ä¸åŒ¹é…
       appointmentMapper.insert(cloneIgnoreId(dbAppointment, o -> o.setPatDeptCode(null)));
       // æµ‹è¯• patDeptDesc ä¸åŒ¹é…
       appointmentMapper.insert(cloneIgnoreId(dbAppointment, o -> o.setPatDeptDesc(null)));
       // æµ‹è¯• patWardCode ä¸åŒ¹é…
       appointmentMapper.insert(cloneIgnoreId(dbAppointment, o -> o.setPatWardCode(null)));
       // æµ‹è¯• patWardDesc ä¸åŒ¹é…
       appointmentMapper.insert(cloneIgnoreId(dbAppointment, o -> o.setPatWardDesc(null)));
       // æµ‹è¯• patBedNo ä¸åŒ¹é…
       appointmentMapper.insert(cloneIgnoreId(dbAppointment, o -> o.setPatBedNo(null)));
       // æµ‹è¯• bookId ä¸åŒ¹é…
       appointmentMapper.insert(cloneIgnoreId(dbAppointment, o -> o.setBookId(null)));
       // æµ‹è¯• bookPeriodStart ä¸åŒ¹é…
       appointmentMapper.insert(cloneIgnoreId(dbAppointment, o -> o.setBookPeriodStart(null)));
       // æµ‹è¯• bookPeriodEnd ä¸åŒ¹é…
       appointmentMapper.insert(cloneIgnoreId(dbAppointment, o -> o.setBookPeriodEnd(null)));
       // æµ‹è¯• bookTime ä¸åŒ¹é…
       appointmentMapper.insert(cloneIgnoreId(dbAppointment, o -> o.setBookTime(null)));
       // æµ‹è¯• bookCheckType ä¸åŒ¹é…
       appointmentMapper.insert(cloneIgnoreId(dbAppointment, o -> o.setBookCheckType(null)));
       // æµ‹è¯• bookSrc ä¸åŒ¹é…
       appointmentMapper.insert(cloneIgnoreId(dbAppointment, o -> o.setBookSrc(null)));
       // å‡†å¤‡å‚æ•°
       AppointmentPageReqVO reqVO = new AppointmentPageReqVO();
       reqVO.setPatId(null);
       reqVO.setPatName(null);
       reqVO.setPatGender(null);
       reqVO.setPatBirthday(null);
       reqVO.setPatMobile(null);
       reqVO.setPatPhone(null);
       reqVO.setPatIdentityId(null);
       reqVO.setPatAddr(null);
       reqVO.setPatDeptCode(null);
       reqVO.setPatDeptDesc(null);
       reqVO.setPatWardCode(null);
       reqVO.setPatWardDesc(null);
       reqVO.setPatBedNo(null);
       reqVO.setBookId(null);
       reqVO.setBookPeriodStart(null);
       reqVO.setBookPeriodEnd(null);
       reqVO.setBookTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28));
       reqVO.setBookCheckType(null);
       reqVO.setBookSrc(null);
       // è°ƒç”¨
       PageResult<AppointmentDO> pageResult = appointmentService.getAppointmentPage(reqVO);
       // æ–­è¨€
       assertEquals(1, pageResult.getTotal());
       assertEquals(1, pageResult.getList().size());
       assertPojoEquals(dbAppointment, pageResult.getList().get(0));
    }
}
jh-module-ecg/pom.xml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <groupId>cn.lihu</groupId>
        <artifactId>jh</artifactId>
        <version>${revision}</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <modules>
        <module>jh-module-ecg-api</module>
        <module>jh-module-ecg-biz</module>
    </modules>
    <artifactId>jh-module-ecg</artifactId>
    <packaging>pom</packaging>
    <name>${project.artifactId}</name>
    <description>
        XX医院心电科模块
    </description>
</project>
sql/mysql/jh.sql
@@ -11,7 +11,7 @@
  `pat_id` varchar(30) NOT NULL COMMENT '患者编号',
  `pat_name` varchar(10) NOT NULL COMMENT '患者姓名',
  `pat_gender` bit(1) NOT NULL COMMENT '患者性别',
  `pat_birthday` date DEFAULT NULL COMMENT '患者生日',
  `pat_birthday` datetime DEFAULT NULL COMMENT '患者生日',
  `pat_mobile` char(11) DEFAULT NULL COMMENT '患者手机',
  `pat_phone` varchar(20) DEFAULT NULL COMMENT '患者电话',
  `pat_identity_id` varchar(20) DEFAULT NULL COMMENT '身份证号',