2022-05-18  2022-05-18    12548 字   26 分钟

一、项目概述和环境搭建

(一)项目背景

 随着疫情的逐步结束,国民对于个人的身体健康越来越重视,对健康认识不断提高,对健康的需求也在不断增加,健康检查作为防患于未然的主动预防措施在人们思想中已有很深的认识,医疗管家管理系统 致力于建立一座健康管理机构和会员之间的灵活沟通的桥梁,医疗管家管理平台利用计算机对体检工作流程、结果收集、结论汇总、健康评估、会员管理等多种信息进行数字化管理,给会员提供定制化的健康体检方案,并持续追踪会员的健康状态,为会员的健康提供终身的服务。

(二)原型展示

展示静态原型

(三)技术架构

(四)功能架构

(五)软件开发流程

需求分析

 1.相关系统分析员向用户初步了解需求,然后用相关的工具软件列出要开发的系统的大功能模块,每个大功能模块有哪些小功能模块,对于有些需求比较明确相关的界面时,在这一步里面可以初步定义好少量的界面。
 2.系统分析员深入了解和分析需求,根据自己的经验和需求用WORD或相关的工具再做出一份文档系统的功能需求文档。这次的文档会清楚列出系统大致的大功能模块,大功能模块有哪些小功能模块,并且还列出相关的界面和界面功能。
 3.系统分析员向用户再次确认需求。

概要设计

 首先,开发者需要对软件系统进行概要设计,即系统设计。概要设计需要对软件系统的设计进行考虑,包括系统的基本处理流程、系统的组织结构、模块划分、功能分配、接口设计、运行设计、数据结构设计和出错处理设计等,为软件的详细设计提供基础

详细设计

 在概要设计的基础上,开发者需要进行软件系统的详细设计。在详细设计中,描述实现具体模块所涉及到的主要算法、数据结构、类的层次结构及调用关系,需要说明软件系统各个层次中的每一个程序(每个模块或子程序)的设计考虑,以便进行编码和测试。应当保证软件的需求完全分配给整个软件。详细设计应当足够详细,能够根据详细设计报告进行编码

编码

 在软件编码阶段,开发者根据《软件系统详细设计报告》中对数据结构、算法分析和模块实现等方面的设计要求,开始具体的编写程序工作,分别实现各模块的功能,从而实现对目标系统的功能、性能、接口、界面等方面的要求。在规范化的研发流程中,编码工作在整个项目流程里最多不会超过1/2,通常在1/3的时间,所谓磨刀不误砍柴功,设计过程完成的好,编码效率就会极大提高,编码时不同模块之间的进度协调和协作是最需要小心的,也许一个小模块的问题就可能影响了整体进度,让很多程序员因此被迫停下工作等待,这种问题在很多研发过程中都出现过。编码时的相互沟通和应急的解决手段都是相当重要的,对于程序员而言,bug永远存在,你必须永远面对这个问题

测试

 测试编写好的系统。交给用户使用,用户使用后一个一个的确认每个功能。软件测试有很多种:按照测试执行方,可以分为内部测试和外部测试;按照测试范围,可以分为模块测试和整体联调;按照测试条件,可以分为正常操作情况测试和异常情况测试;按照测试的输入范围,可以分为全覆盖测试和抽样测试。以上都很好理解,不再解释。总之,测试同样是项目研发中一个相当重要的步骤,对于一个大型软件,3个月到1年的外部测试都是正常的,因为永远都会有不可预料的问题存在。完成测试后,完成验收并完成最后的一些帮助文档,整体项目才算告一段落,当然日后少不了升级,修补等等工作,只要不是想通过一锤子买卖骗钱,就要不停的跟踪软件的运营状况并持续修补升级,直到这个软件被彻底淘汰为止

交付

 在软件测试证明软件达到要求后,软件开发者应向用户提交开发的目标安装程序、数据库的数据字典、《用户安装手册》、《用户使用指南》、需求报告、设计报告、测试报告等双方合同约定的产物。
 《用户安装手册》应详细介绍安装软件对运行环境的要求、安装软件的定义和内容、在客户端、服务器端及中间件的具体安装步骤、安装后的系统配置。
 《用户使用指南》应包括软件各项功能的使用流程、操作步骤、相应业务介绍、特殊提示和注意事项等方面的内容,在需要时还应举例说明。

验收

 用户验收。

维护

根据用户需求的变化或环境的变化,对应用程序进行全部或部分的修改

二、项目环境搭建

(一)项目结构

本项目采用maven分模块开发方式,即对整个项目拆分为几个maven工程,父工程提供统一的依赖规范,其余的每个maven 工程存放特定类型的代码,具体如下:

各模块职责定位:

offcnpe_parent:父工程,打包方式为pom,统一锁定依赖的版本,同时聚合其他子模块 便于统一执行maven命令

offcnpe_pojo 数据模型,打包方式为jar,存放项目中使用到表对应的数据模型

offcnpe_interface:打包方式为jar,存放服务接口。

offcnpe_provider:Dubbo服务模块,打包方式为war,存放服务实现类、Dao接 口、Mapper映射文件等,作为服务提供方,需要部署到tomcat运行。

offcnpe_controller:小U健康管理后台,打包方式为war,作为Dubbo服务消费方,存放 Controller、HTML页面、js、css、spring配置文件等,需要部署到tomcat运行

offcnpe_mobile:移动端前台,打包方式为war,作为Dubbo服务消费方,存放 Controller、HTML页面、js、css、spring配置文件等,需要部署到tomcat运行.

offcnpe_util: 工具模块,打包方式为jar,存放项目中使用到的一些工具类、返回结果和常量类

(二)工程搭建

通过前面的项目功能架构图可以知道本项目分为小U健康管理后台和小U健康前台(移动端)

1:offcnpe_parent 父工程,打包方式为pom,用于统一管理依赖版本

pom.xml文件内容

<!--指定当前工程父工程是 2.4.3 -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.3</version>
        <relativePath/>
    </parent>
    <groupId>com.offcn</groupId>
    <artifactId>offcnpe_parent</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>
    <!-- 当前的工程是父工程 统一控制我们技术版本 -->
    <properties>
        <java.version>1.8</java.version>
        <!--mybatis plus-->
        <baomidou.version>3.4.2</baomidou.version>
        <!--dubbo-->
        <dubbo.version>2.7.6</dubbo.version>
        <!--mysql-->
        <mysql.version>5.1.47</mysql.version>
        <!--接口文档-->
        <swagger.version>2.6.1</swagger.version>
        <!--poi-->
        <poi.version>3.14</poi.version>
    </properties>
    <dependencyManagement>
        <dependencies>
            <!-- springboot 整合mybatisplus 工具包 -->
            <dependency>
                <groupId>com.baomidou</groupId>
                <artifactId>mybatis-plus-boot-starter</artifactId>
                <version>${baomidou.version}</version>
            </dependency>
            <!-- mybatisplus 代码生成器包 -->
            <dependency>
                <groupId>com.baomidou</groupId>
                <artifactId>mybatis-plus-generator</artifactId>
                <version>3.4.1</version>
            </dependency>
            <!-- 数据库驱动包 -->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>${mysql.version}</version>
            </dependency>
            <!-- 接口文档相关包 -->
            <dependency>
                <groupId>io.springfox</groupId>
                <artifactId>springfox-swagger2</artifactId>
                <version>${swagger.version}</version>
            </dependency>
            <dependency>
                <groupId>io.springfox</groupId>
                <artifactId>springfox-swagger-ui</artifactId>
                <version>${swagger.version}</version>
            </dependency>
            <!-- dubbo 服务相关jar -->
            <dependency>
                <groupId>org.apache.dubbo</groupId>
                <artifactId>dubbo-spring-boot-starter</artifactId>
                <version>${dubbo.version}</version>
            </dependency>
            <!-- poi报表操作包 -->
            <dependency>
                <groupId>org.apache.poi</groupId>
                <artifactId>poi-ooxml</artifactId>
                <version>${poi.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

2: offcnpe_pojo 数据模型,打包方式为jar,存放项目中使用到表对应的数据模型

<?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>
        <artifactId>offcnpe_parent</artifactId>
        <groupId>com.offcn</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>offcnpe_pojo</artifactId>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
        </dependency>
    </dependencies>
</project>

3:offcnpe_util: 工具模块,打包方式为jar,存放项目中使用到的一些工具类、返回结果和常量类

<?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>
        <artifactId>offcnpe_parent</artifactId>
        <groupId>com.offcn</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>offcnpe_util</artifactId>
    <dependencies>
        <dependency>
            <groupId>com.offcn</groupId>
            <artifactId>offcnpe_pojo</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.velocity</groupId>
            <artifactId>velocity-engine-core</artifactId>
            <version>2.0</version>
        </dependency>
    </dependencies>

</project>

4: offcnpe_interface:打包方式为jar,存放服务接口

<?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>
        <artifactId>offcnpe_parent</artifactId>
        <groupId>com.offcn</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>offcnpe_interface</artifactId>
    <dependencies>
        <dependency>
            <groupId>com.offcn</groupId>
            <artifactId>offcnpe_pojo</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>com.offcn</groupId>
            <artifactId>offcnpe_util</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
</project>

5: offcnpe_provider Dubbo服务模块

(1)pom.xml文件内容
<?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>
        <artifactId>offcnpe_parent</artifactId>
        <groupId>com.offcn</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>offcnpe_provider</artifactId>
    <!--
       springboot  mybatisplus  数据库驱动 连接池  dubbo  zookeeper..
    -->
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <!-- dubbo的依赖 -->
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
        </dependency>
        <!-- zk的依赖 -->
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-dependencies-zookeeper</artifactId>
            <version>2.7.6</version>
            <type>pom</type>
            <exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-log4j12</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>com.offcn</groupId>
            <artifactId>offcnpe_interface</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.20</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>
(2)application.yml配置文件内容
#端口  访问路径
server:
  port: 9002
  servlet:
    context-path: /

#spring应用名称
spring:
  application:
    name: offcnpe_provider
    #数据源配置
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql:///offcnpe
    username: root
    password: root
    type: com.alibaba.druid.pool.DruidDataSource

#mybatis-plus
mybatis-plus:
  configuration:
    #开启驼峰标识
    map-underscore-to-camel-case: true
    #控制台显示sql语句
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  global-config:
    #逻辑删除
    db-config:
      logic-not-delete-value: 1
      logic-delete-value: 0
      #加载我们的xml文件
  mapper-locations: classpath:/mappers/xml/*.xml
  type-aliases-package: com.offcn.pojo
#dubbo端口和名称
dubbo:
  protocol:
    name: dubbo
    port: 20880
  registry:
    address: zookeeper://192.168.233.100:2181
    timeout: 10000
  #扫描我们service注解
  scan:
    base-packages: com.offcn.service.impl
(3)构建springboot的启动类
package com.offcn;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class PeServiceProviderApplication {
    public static void main(String[] args) {
        SpringApplication.run(PeServiceProviderApplication.class, args);
    }
}

6:offcnpe_controller健康管家管理后台工程

(1)pom.xml文件内容
<?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>
        <artifactId>offcnpe_parent</artifactId>
        <groupId>com.offcn</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>offcnpe_controller</artifactId>
    <!-- 添加依赖 -->
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
       <!-- 项目初期没有用到权限管理的时候将这个依赖暂时注释掉 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- dubbo的依赖 -->
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
        </dependency>
        <!-- zk的依赖 -->
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-dependencies-zookeeper</artifactId>
            <version>2.7.6</version>
            <type>pom</type>
            <exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-log4j12</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>com.offcn</groupId>
            <artifactId>offcnpe_interface</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.20</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.68</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <fork>true</fork>
                    <addResources>true</addResources>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>
(2)application.yml文件内容
server:
  servlet:
    context-path: /
  port: 9003

spring:
  application:
    name: offcnpe_controller
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql:///offcnpe
    username: root
    password: root
    type: com.alibaba.druid.pool.DruidDataSource
  devtools:
    restart:
      enabled: true
      additional-paths: src/main/java
  redis:
    host: 192.168.233.100
    port: 6379
    password: 123456
dubbo:
  protocol:
    name: dubbo
    port: 20881
  registry:
    address: zookeeper://192.168.233.100:2181
    timeout: 10000
(3)构建springboot启动类
package com.offcn;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class PeControllerApplication {
    public static void main(String[] args) {
        SpringApplication.run(PeControllerApplication.class,args);
    }
}

7:offcnpe_mobile移动端前台工程

(1)pom文件内容
<?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>
        <artifactId>offcnpe_parent</artifactId>
        <groupId>com.offcn</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>offcnpe_mobile</artifactId>
    <!-- 添加依赖 -->
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- dubbo的依赖 -->
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
        </dependency>
        <!-- zk的依赖 -->
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-dependencies-zookeeper</artifactId>
            <version>2.7.6</version>
            <type>pom</type>
            <exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-log4j12</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
        </dependency>
        <dependency>
            <groupId>com.offcn</groupId>
            <artifactId>offcnpe_interface</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.20</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>
(2)application.yml文件内容
server:
  servlet:
    context-path: /
  port: 9004

spring:
  application:
    name: offcnpe_mobile
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql:///demo
    username: root
    password: root
    type: com.alibaba.druid.pool.DruidDataSource
dubbo:
  protocol:
    name: dubbo
    port: 20882
  registry:
    address: zookeeper://192.168.233.100:2181
    timeout: 10000
(3)构建springboot启动类
@SpringBootApplication
public class PeMobileApplication {
    public static void main(String[] args) {
        SpringApplication.run(PeMobileApplication.class,args);
    }
}

(三)启动服务测试环境大家是否成功

1:启动zookeeper并启动dubbo-admin监控平台 2:启动offcnpe_provider服务器查看是否正常 3:启动offcnpe_controller服务器查看是否正常

三、预约管理–检查项管理

(一)需求分析

本章节完成的功能开发是预约管理功能,包括检查项管理、检查组管理、体检套餐管理、预约设置等。预约管理属于系统的基础功能,主要就是管理一些体检的基础数据。

(二)基础环境搭建

1: 创建数据库offcnpe

create database offcnpe

2: 导入数据表

sqlyong 中执行sql脚本

3: 导入项目所需工具资源

(1)返回消息常量类MessageConstant,放到offcnpe_util工程中

项目开发过程中一般会提供一些公共资源,供多个模块或者系统来使用。 本章节我们导入的公共资源有

/**
 * 消息常量
 */
public class MessageConstant {
    public static final String DELETE_CHECKITEM_FAIL = "删除检查项失败";
    public static final String DELETE_CHECKITEM_SUCCESS = "删除检查项成功";
    public static final String ADD_CHECKITEM_SUCCESS = "新增检查项成功";
    public static final String ADD_CHECKITEM_FAIL = "新增检查项失败";
    public static final String EDIT_CHECKITEM_FAIL = "编辑检查项失败";
    public static final String EDIT_CHECKITEM_SUCCESS = "编辑检查项成功";
    public static final String QUERY_CHECKITEM_SUCCESS = "查询检查项成功";
    public static final String QUERY_CHECKITEM_FAIL = "查询检查项失败";
    public static final String UPLOAD_SUCCESS = "上传成功";
    public static final String ADD_CHECKGROUP_FAIL = "新增检查组失败";
    public static final String ADD_CHECKGROUP_SUCCESS = "新增检查组成功";
    public static final String DELETE_CHECKGROUP_FAIL = "删除检查组失败";
    public static final String DELETE_CHECKGROUP_SUCCESS = "删除检查组成功";
    public static final String QUERY_CHECKGROUP_SUCCESS = "查询检查组成功";
    public static final String QUERY_CHECKGROUP_FAIL = "查询检查组失败";
    public static final String EDIT_CHECKGROUP_FAIL = "编辑检查组失败";
    public static final String EDIT_CHECKGROUP_SUCCESS = "编辑检查组成功";
    public static final String PIC_UPLOAD_SUCCESS = "图片上传成功";
    public static final String PIC_UPLOAD_FAIL = "图片上传失败";
    public static final String ADD_SETMEAL_FAIL = "新增套餐失败";
    public static final String ADD_SETMEAL_SUCCESS = "新增套餐成功";
    public static final String IMPORT_ORDERSETTING_FAIL = "批量导入预约设置数据失败";
    public static final String IMPORT_ORDERSETTING_SUCCESS = "批量导入预约设置数据成功";
    public static final String GET_ORDERSETTING_SUCCESS = "获取预约设置数据成功";
    public static final String GET_ORDERSETTING_FAIL = "获取预约设置数据失败";
    public static final String ORDERSETTING_SUCCESS = "预约设置成功";
    public static final String ORDERSETTING_FAIL = "预约设置失败";
    public static final String ADD_MEMBER_FAIL = "新增会员失败";
    public static final String ADD_MEMBER_SUCCESS = "新增会员成功";
    public static final String DELETE_MEMBER_FAIL = "删除会员失败";
    public static final String DELETE_MEMBER_SUCCESS = "删除会员成功";
    public static final String EDIT_MEMBER_FAIL = "编辑会员失败";
    public static final String EDIT_MEMBER_SUCCESS = "编辑会员成功";
    public static final String TELEPHONE_VALIDATECODE_NOTNULL = "手机号和验证码都不能为空";
    public static final String LOGIN_SUCCESS = "登录成功";
    public static final String VALIDATECODE_ERROR = "验证码输入错误";
    public static final String QUERY_ORDER_SUCCESS = "查询预约信息成功";
    public static final String QUERY_ORDER_FAIL = "查询预约信息失败";
    public static final String QUERY_SETMEALLIST_SUCCESS = "查询套餐列表数据成功";
    public static final String QUERY_SETMEALLIST_FAIL = "查询套餐列表数据失败";
    public static final String QUERY_SETMEAL_SUCCESS = "查询套餐数据成功";
    public static final String QUERY_SETMEAL_FAIL = "查询套餐数据失败";
    public static final String SEND_VALIDATECODE_FAIL = "验证码发送失败";
    public static final String SEND_VALIDATECODE_SUCCESS = "验证码发送成功";
    public static final String SELECTED_DATE_CANNOT_ORDER = "所选日期不能进行体检预约";
    public static final String ORDER_FULL = "预约已满";
    public static final String HAS_ORDERED = "已经完成预约,不能重复预约";
    public static final String ORDER_SUCCESS = "预约成功";
    public static final String GET_USERNAME_SUCCESS = "获取当前登录用户名称成功";
    public static final String GET_USERNAME_FAIL = "获取当前登录用户名称失败";
    public static final String GET_MENU_SUCCESS = "获取当前登录用户菜单成功";
    public static final String GET_MENU_FAIL = "获取当前登录用户菜单失败";
    public static final String GET_MEMBER_NUMBER_REPORT_SUCCESS = "获取会员统计数据成功";
    public static final String GET_MEMBER_NUMBER_REPORT_FAIL = "获取会员统计数据失败";
    public static final String GET_SETMEAL_COUNT_REPORT_SUCCESS = "获取套餐统计数据成功";
    public static final String GET_SETMEAL_COUNT_REPORT_FAIL = "获取套餐统计数据失败";
    public static final String GET_BUSINESS_REPORT_SUCCESS = "获取运营统计数据成功";
    public static final String GET_BUSINESS_REPORT_FAIL = "获取运营统计数据失败";
    public static final String GET_SETMEAL_LIST_SUCCESS = "查询套餐列表数据成功";
    public static final String GET_SETMEAL_LIST_FAIL = "查询套餐列表数据失败";
}
(2)返回结果Result和PageResult类,放到offcnpe_util工程中
public class Result implements Serializable{
    private boolean flag;//执行结果,true为执行成功 false为执行失败
    private String message;//返回结果信息,主要用于页面提示信息
    private Object data;//返回数据
    public Result(boolean flag, String message) {
        super();
        this.flag = flag;
        this.message = message;
    }

    public Result(boolean flag, String message, Object data) {
        this.flag = flag;
        this.message = message;
        this.data = data;
    }

    public boolean isFlag() {
        return flag;
    }
    public void setFlag(boolean flag) {
        this.flag = flag;
    }
    public String getMessage() {
        return message;
    }
    public void setMessage(String message) {
        this.message = message;
    }

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }
}

/**
 * 分页结果封装对象
 */
public class PageResult implements Serializable{
    private Long total;//总记录数
    private List rows;//当前页结果
    public PageResult(Long total, List rows) {
        super();
        this.total = total;
        this.rows = rows;
    }
    public Long getTotal() {
        return total;
    }
    public void setTotal(Long total) {
        this.total = total;
    }
    public List getRows() {
        return rows;
    }
    public void setRows(List rows) {
        this.rows = rows;
    }
}
(3)封装查询条件的QueryPageBean类,放到offcnpe_util工程中
/**
 * 封装查询条件
 */
public class QueryPageBean implements Serializable{
    private Integer currentPage;//页码
    private Integer pageSize;//每页记录数
    private String queryString;//查询条件

    public Integer getCurrentPage() {
        return currentPage;
    }

    public void setCurrentPage(Integer currentPage) {
        this.currentPage = currentPage;
    }

    public Integer getPageSize() {
        return pageSize;
    }

    public void setPageSize(Integer pageSize) {
        this.pageSize = pageSize;
    }

    public String getQueryString() {
        return queryString;
    }

    public void setQueryString(String queryString) {
        this.queryString = queryString;
    }
}
(4)html、js、css、图片等静态资源,放到offcnpe_controller工程中

注意:后续随着项目开发还会陆续导入其他一些公共资源。

(5)使用Mybatis-plus逆向工程生成基本文件

在offcn_pe工程中执行逆向工程的代码:


public class MyBatisPlusGenerator {
    public static void main(String[] args) {
        // 代码生成器
        AutoGenerator mpg = new AutoGenerator();
        // 全局配置
        GlobalConfig gc = new GlobalConfig();
        //String projectPath = System.getProperty("user.dir");
        gc.setOutputDir("生成代码的路径");
        gc.setAuthor("zs");
        gc.setOpen(false);
        //实体属性 Swagger2 注解
        gc.setSwagger2(false);
        mpg.setGlobalConfig(gc);

        // 数据源配置
        DataSourceConfig dsc = new DataSourceConfig();
        //dsc.setUrl("jdbc:mysql://127.0.0.1:3306/demo?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true");
        dsc.setUrl("jdbc:mysql:///offcnpe");
        dsc.setDriverName("com.mysql.jdbc.Driver");
        dsc.setUsername("root");
        dsc.setPassword("root");
        mpg.setDataSource(dsc);

        // 包配置
        PackageConfig pc = new PackageConfig();
        pc.setParent("com.offcn");
        pc.setEntity("pojo");
        pc.setMapper("mapper");
        pc.setServiceImpl("service.xml");
        mpg.setPackageInfo(pc);

        // 配置模板
        TemplateConfig templateConfig = new TemplateConfig();
        //默认关闭不需要的生成内容
        //templateConfig.setXml(null);
        templateConfig.setService(null);
        templateConfig.setServiceImpl(null);
        mpg.setTemplate(templateConfig);

        // 策略配置
        StrategyConfig strategy = new StrategyConfig();
        strategy.setNaming(NamingStrategy.underline_to_camel);//数据库表映射到实体的命名策略
        strategy.setColumnNaming(NamingStrategy.underline_to_camel);//数据库表字段映射到实体的命名策略
        strategy.setSuperEntityClass("com.baomidou.mybatisplus.extension.activerecord.Model");
        strategy.setEntityLombokModel(true);
        strategy.setRestControllerStyle(true);
        strategy.setEntityLombokModel(true);

        String tableNames="t_checkgroup,t_checkgroup_checkitem,t_checkitem,t_member,t_menu," +
                "t_order,t_ordersetting," +
                "t_permission,t_role,t_role_menu," +
                "t_role_permission,t_setmeal,t_setmeal_checkgroup,t_user,t_user_role";
        strategy.setInclude(tableNames.split(","));
        strategy.setControllerMappingHyphenStyle(true);
        strategy.setTablePrefix("t_");
        mpg.setStrategy(strategy);
        mpg.execute();
    }
}

(三)新增检查项功能实现

1:编写页面

(1)弹出新增窗口

页面中已经提供了新增窗口,只是处于隐藏状态。只需要将控制展示状态的属性 dialogFormVisible改为true就可以显示出新增窗口。 新建按钮绑定的方法为handleCreate,所以在handleCreate方法中修改 dialogFormVisible属性的值为true即可。同时为了增加用户体验度,需要每次点击新建 按钮时清空表单输入项

// 重置表单 
resetForm() { 
    this.formData = {}; 
},
// 弹出添加窗口 
handleCreate() {
    this.resetForm(); 
    this.dialogFormVisible = true; 
}

(2)提交表单数据

点击新增窗口中的确定按钮时,触发handleAdd方法,所以需要在handleAdd方法中进行完善,因为表单中添加了校验,只有校验通过然后发送ajax请求发送数据,如果校验失败表单不能提交成功的。

/*
                *   获取表单对象,调用校验方法,使用钩子函数完成数据操作
                * */
                this.$refs['dataAddForm'].validate((valid) => {
                    //测试数据是否正常封装
                    //console.log(this.formData)
                    if(valid){
                         //校验成功
                        axios.post('/checkitem/add',this.formData,).then((res) => {
                             //res就是我们返回的offcnpe_util中的Result对象封装的结果,json数据格式
                            //关闭新增窗口(不管什么情况都需要关闭窗口)
                            this.dialogFormVisible = false;
                             if(res.data.flag){
                                 console.log('成功');
                                 //调用分页方法
                                 this.findPage();
                                 //弹出提示信息
                                 this.$message({
                                     message : res.data.message,
                                     type : 'success'
                                 });
                             }else{
                                 console.log('失败');
                                 //弹出失败信息
                                 this.message().error(res.data.message);
                             }
                        });
                    }else{
                         //校验失败
                        this.message().error('数据校验失败,请检查执行');
                        return ;
                    }
                });
            },

2:后台代码

(1)控制器方法 在offcnpe_controller中的CheckitemController添加方法
    @RequestMapping("/add")
    @ResponseBody
    public Result add(@RequestBody Checkitem checkitem){
        System.out.println(checkitem);
        try {
            checkItemService.add(checkitem);
        }catch (Exception e){
            e.printStackTrace();
            return new Result(true, MessageConstant.ADD_CHECKITEM_SUCCESS);
        }
        return new Result(true,MessageConstant.ADD_CHECKITEM_FAIL);
    }
(2)服务接口 在offcnpe_interface 创建接口
public interface CheckItemService {

    public void add(Checkitem checkitem);

}
(3) 服务实现类

在offcnpe_service_provider中实现接口CheckItemService

@Service
public class CheckItemsServiceImpl implements CheckItemService {

    @Resource
    private CheckitemMapper checkitemMapper;

    @Override
    public void add(Checkitem checkitem) {
         checkitemMapper.insert(checkitem);
    }
}

(四)检查项分页功能

1:功能分析

本项目所有分页功能都是基于ajax的异步请求来完成的,请求参数和后台响应数据格式都 使用json数据格式。 请求参数包括页码、每页显示记录数、查询条件。 请求参数的json格式为:{currentPage:1,pageSize:10,queryString:‘‘offcn’’} 后台响应数据包括总记录数、当前页需要展示的数据集合。 响应数据的json格式为:{total:1000,rows:[]} 如下图所示:

2:编写页面

(1)定义分页相关模型数据

pagination: {//分页相关模型数据
     currentPage: 1,//当前页码
     pageSize:10,//每页显示的记录数
     total:0,//总记录数
     queryString:null//查询条件
},
dataList: [],//当前页要展示的分页列表数据

(2)利用vue的钩子函数执行分页方法

在页面中提供了findPage方法用于分页查询,为了能够在checkitem.html页面加载后直 接可以展示分页数据,可以在VUE提供的钩子函数created中调用findPage方法

//钩子函数,VUE对象初始化完成后自动执行
created() {
     this.findPage();
},

(3)编辑分页方法

//分页查询
findPage() {
   //封装查询参数
   var param = {
    //当前页
    currentPage: this.pagination.currentPage,
     //每页显示数据条数
     pageSize:  this.pagination.pageSize,
     //查询的条件字符串
     queryString: this.pagination.queryString
   };
   //ajax请求完成数据的请求和响应
   axios.post('/checkitem/pageQuery',param,).then((res) => {
      this.pagination.total=res.data.total; //查询的总条数
      this.dataList = res.data.rows; //当前页面展示的数据内容
   });
},

(4) 点击查询按钮和点击分页的页码依然需要进行分页查询操作

a:
查询按钮绑定findPage方法
<el-button @click="findPage()" class="dalfBut">查询</el-button>

b
点击页码执行findPage方法
  <el-pagination
       class="pagiantion"
       @current-change="handleCurrentChange"
       :current-page="pagination.currentPage"
       :page-size="pagination.pageSize"
       layout="total, prev, pager, next, jumper"
       :total="pagination.total">
  </el-pagination>
  
@current-change="handleCurrentChange" UI框架给我们提供的点击页码自动回调的函数

编写方法handleCurrentChange
 //切换页码
  handleCurrentChange(currentPage) {
      //将点击的页码给我们的当前页从新赋值
      this.pagination.currentPage = currentPage;
      //调用分页查询方法
      this.findPage();
  },

3:后台代码实现

(1)CheckitemController增加方法findPage

 @RequestMapping("/findPage")
    @ResponseBody
    public PageResult findPage(@RequestBody QueryPageBean queryPageBean){
        PageResult pageResult = checkItemService.findPage(queryPageBean);
        return pageResult;
    }

(2)在CheckItemService服务接口中扩展分页查询方法

 PageResult findPage(QueryPageBean queryPageBean);

(3)在CheckItemServiceImpl服务实现类中实现分页查询方法,基于Mybatis-Plus分页助手插件实现分页

 //分页查询检查项所有的数据内容
    @Override
    public PageResult findPage(QueryPageBean queryPageBean) {
        //构建分页page对象
        Page<Checkitem> page1 = new Page<>(queryPageBean.getCurrentPage(),queryPageBean.getPageSize());
        //构建查询条件对象
        QueryWrapper<Checkitem> wrapper = new QueryWrapper<>();
        if(queryPageBean.getQueryString()!=null &&queryPageBean.getQueryString().length()>0){
            wrapper.like("name",queryPageBean.getQueryString());
            wrapper.or();
            wrapper.like("code",queryPageBean.getQueryString());
        }
        //分页查询数据
        Page<Checkitem> checkitemPage = checkitemMapper.selectPage(page1, wrapper);
        return new PageResult(checkitemPage.getTotal(),checkitemPage.getRecords());
    }

(4)offcnpe_util项目中添加分页工具类

@Configuration
public class MyBatisPlusConfig {
    /**
     *分页插件
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor mybatisPlusInterceptor=new MybatisPlusInterceptor();
        PaginationInnerInterceptor innerInterceptor=new PaginationInnerInterceptor();
        innerInterceptor.setDbType(DbType.MYSQL);
        innerInterceptor.setOverflow(true);
        mybatisPlusInterceptor.addInnerInterceptor(innerInterceptor);
        return mybatisPlusInterceptor;
    }
}

一、删除检查项功能

(一)编写页面

 为了防止用户误操作,点击删除按钮时需要弹出确认删除的提示,用户点击取消则不做 任何操作,用户点击确定按钮再提交删除请求

1:绑定单击事件

 <el-button size="mini" type="danger" @click="handleDelete(scope.row)">删除</el-button>  
 
 scope.row就是当前行的json对象

2:构建删除方法

  // 删除  
  handleDelete(row) {  
  this.$confirm("确认删除当前数据么","提示",{type:'waring'}).then(() => {  
  //用户点击确认按钮  
  axios.post("/checkitem/deleteInfoById?id="+row.id).then((res) => {  
  if(res.data.flag){  
  //删除成功  
  this.$message({  
  message: res.data.message,  
  type: 'success'  
  });  
  this.findPage();  
  }else{  
  //删除失败  
  this.$message().error(res.data.message)  
  }  
  });  
  }).catch(() => {  
  //用户点击取消按钮  
  this.$message({  
  message: '用户取消了删除操作',  
  type: 'info'  
  });  
  } );  
  }

(二)后台代码实现

1:控制器方法


 //删除检查项  
  @RequestMapping("/deleteInfoById")  
  @ResponseBody  
  public Result deleteInfoById(Integer id){  
  System.out.println(id);  
  try{  
  checkItemService.deleteInfoById(id);  
  }catch (Exception e){  
  e.printStackTrace();  
  new Result(false,MessageConstant.DELETE_CHECKITEM_FAIL);  
  }  
  return new Result(true,MessageConstant.DELETE_CHECKITEM_SUCCESS);  
  }  

2:服务接口中的方法

  void deleteInfoById(Integer id);

3:在CheckItemServiceImpl服务实现类实现删除功能

  @Override  
  public void deleteInfoById(Integer id) {  
  checkitemMapper.deleteById(id);  
  }

二、编辑检查项功能

(一)编写页面

 用户点击编辑按钮时,需要弹出编辑窗口并且将当前记录的数据进行回显,用户修改完 成后点击确定按钮将修改后的数据提交到后台进行数据库操作

1:给编辑按钮绑定事件


 <el-button type="primary" size="mini" @click="handleUpdate(scope.row)">编辑</el-button>  
 
 对应事件方法  
 
 handleUpdate(row) {  
 
 }

2:弹出编辑窗口回显数据

  // 弹出编辑窗口  
  handleUpdate(row) {  
  this.resetForm();  
  //显示编辑窗口  
  this.dialogFormVisible4Edit = true;  
  //根据当前行的id回显数据  
  axios.get("/checkitem/findInfoById?id="+row.id).then((res) => {  
  //true 代表查询到了数据  
  if(res.data.flag){  
  console.info(res.data.data);  
  //<el-input v-model="formData.code"/>  
  //进行数据回显,基于vue的数据绑定实现的 绑定的对象就是formData,这个对象有值,就会自动回显到文本框中  
  this.formData = res.data.data;  
  }else{  
  this.$message().error(res.data.message);  
  }  
  });  
  },

3:点击确定按钮进行数据更新

 在编辑窗口中修改完成后,点击确定按钮需要提交请求,所以需要为确定按钮绑定事件 并提供处理函数handleEdit
 

<elbutton type="primary" @click="handleEdit()">确定</el‐button>

4:编辑方法绑定函数

  //编辑  
  handleEdit() {  
  this.$refs['dataEditForm'].validate((valid) =>{  
  if(valid){  
  axios.post('/checkitem/updateInfoById',this.formData).then((res) => {  
  if(res.data.flag){  
  this.$message({  
  message: res.data.message,  
  type:'success'  
  });  
  }else{  
  this.$message().error(res.data.message);  
  }  
  }).finally(() =>{  
  //无论校验成功还是失败都需要调用分页方法  
  this.findPage();  
  //隐藏我们弹出的数据框  
  this.dialogFormVisible4Edit = false;  
  });  
  }else{  
  this.$message().error("表单校验失败");  
  return false;  
  }  
  });  
  },

(二)后台功能实现

1:控制器方法


//回显检查项数据
    @RequestMapping("/findInfoById")
    @ResponseBody
    public Result findInfoById(Integer id){
        Checkitem infoById = null;
        try{
            infoById = checkItemService.findInfoById(id);
        }catch (Exception e){
            e.printStackTrace();
            new Result(false,MessageConstant.DELETE_CHECKITEM_FAIL);
        }
        return new Result(true,MessageConstant.DELETE_CHECKITEM_SUCCESS,infoById);
    }
    //更新检查项数据
    @RequestMapping("/updateInfoById")
    @ResponseBody
    public Result updateInfoById(@RequestBody Checkitem checkitem){
        try{
            checkItemService.updateInfoById(checkitem);
        }catch (Exception e){
            e.printStackTrace();
            return new Result(false,MessageConstant.EDIT_CHECKITEM_FAIL);
        }
        return new Result(true,MessageConstant.EDIT_CHECKITEM_SUCCESS);
    }

2:接口方法


    Checkitem findInfoById(Integer id);

    void updateInfoById(Checkitem checkitem);

3:在CheckItemServiceImpl服务实现类实现删除功能

   @Override
    public Checkitem findInfoById(Integer id) {
        return checkitemMapper.selectById(id);
    }
    @Override
    public void updateInfoById(Checkitem checkitem) {
        checkitemMapper.updateById(checkitem);
    }

三、新增检查组

(一) 需求分析

检查组其实就是多个检查项的集合,例如有一个检查组为“一般检查”,这个检查组可以包 括多个检查项:身高、体重、收缩压、舒张压等。所以在添加检查组时需要选择这个检 查组包括的检查项。 检查组对应的实体类为CheckGroup,对应的数据表为t_checkgroup。检查组和检查项 为多对多关系,所以需要中间表t_checkgroup_checkitem进行关联。

(二)回显所有检查项

1:前端内容

(1) 绑定事件
 <el-button type="primary" class="butT" @click="handleCreate()">新建</el-button>

点击新建按钮弹出dialog并加载出检查项 的相关数据

(2)事件函数
// 重置表单 
resetForm() { 
    this.formData = {}; 
},
//我们点击新建按钮,在弹出的窗口中需要加载所有的检查项的数据.
handleCreate() {
   //显示隐藏窗口
   this.dialogFormVisible = true;
   //默认选中第一个选项卡
   this.activeName = 'first';
   //重置表单
   this.resetForm();
   //清除默认勾选的检查项
   this.checkitemIds = [];
   //异步请求获取所有检查项信息
   axios.get("/checkitem/showAllItem").then((res) => {
       if(res.data.flag){
           this.tableData = res.data.data;
        }else{
           this.$message().error(res.data.messge);
         }
    });
},

2:后台内容

(1)在控制器中添加方法

  //展示所有检查项信息
    @RequestMapping("/showAllItem")
    @ResponseBody
    public Result showAllItem(){
        List<Checkitem> infoById = null;
        try{
            infoById = checkItemService.showAllItem();
        }catch (Exception e){
            e.printStackTrace();
            new Result(false,MessageConstant.QUERY_CHECKITEM_FAIL);
        }
        return new Result(true,MessageConstant.QUERY_CHECKITEM_SUCCESS,infoById);
    }
(2)在接口中添加方法
List<Checkitem> showAllItem();
(3)实现接口方法
 @Override
 public List<Checkitem> showAllItem() {
     return checkitemMapper.selectList(null);
 }

(三) 提交按钮完成检查组数据添加

当用户点击新增窗口中的确定按钮时发送ajax请求将数据提交到后台进行数据库操作。提 交到后台的数据分为两部分:检查组基本信息(对应的模型数据为formData)和检查项 id数组(对应的模型数据为checkitemIds)

1:前端内容

(1)绑定事件
<elbutton type="primary" @click="handleAdd()">确定</el‐button>

点击确定按钮 出发handleAdd函数实现检查组添加

(2)事件函数

 handleAdd () {
               axios.post("/checkgroup/addGroup?checkitemIds="+this.checkitemIds,this.formData).then((res) => {
                   this.dialogFormVisible = false;
                   if(res.data.flag){
                       this.$message({
                           message: res.data.message,
                           type: 'success'
                       });
                   }else{
                        this.message().error(res.data.message);
                   }
               }).finally(() => {
                   //从新进行分页查询
                   this.findPage();
               });

            },

2:后台内容

(1)添加控制方法 在CheckGroupController中

 @RequestMapping("/addGroup")
    public Result addGroup(@RequestBody Checkgroup checkgroup,Integer [] checkitemIds){
        try {
            checkGroupService.addGroup(checkgroup,checkitemIds);
        }catch (Exception e){
            e.printStackTrace();
            return  new Result(false, MessageConstant.ADD_CHECKGROUP_FAIL);
        }
        return new Result(true,MessageConstant.ADD_CHECKGROUP_SUCCESS);

    }
(2)服务层接口内容
void addGroup(Checkgroup checkgroup, Integer[] checkitemIds);
(3)服务接口的实现类
package com.offcn.service.impl;

import com.offcn.mapper.CheckgroupCheckitemMapper;
import com.offcn.mapper.CheckgroupMapper;
import com.offcn.pojo.Checkgroup;
import com.offcn.pojo.CheckgroupCheckitem;
import com.offcn.service.CheckGroupService;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.List;

@Service(interfaceClass = CheckGroupService.class)
@Transactional
public class CheckGroupServiceImpl implements CheckGroupService {
    @Resource
    private CheckgroupMapper checkgroupMapper;
    @Resource
    private CheckgroupCheckitemMapper checkgroupCheckitemMapper;
    @Override
    public void addGroup(Checkgroup checkgroup, Integer[] checkitemIds) {
        //添加检查组
         checkgroupMapper.insert(checkgroup);
         for(Integer id:checkitemIds){
             CheckgroupCheckitem checkgroupCheckitem = new CheckgroupCheckitem();
             checkgroupCheckitem.setCheckgroupId(checkgroup.getId());
             checkgroupCheckitem.setCheckitemId(id);
             //添加检查组和检查项的中间表数据
             checkgroupCheckitemMapper.insert(checkgroupCheckitem);
         }
    }
}

医疗管家-检查组信息维护

一、检查组分页显示

(一)前端页面内容

1:编写分页函数

  //分页查询  
  findPage() {  
  //发送ajax的请求完成页面数据加载  
  var param ={  
  currentPage: this.pagination.currentPage,  
  pageSize: this.pagination.pageSize,  
  queryString: this.pagination.queryString  
  };  
  //发送ajax请求  
  axios.post("/checkgroup/findPage",param,).then((res) => {  
  //给我们的vue的变量赋值  
  this.pagination.total = res.data.total;  
  this.dataList = res.data.rows;  
  });  
  },

2:分页方法执行时机

 加载页面的时候使用vue的钩子函数完成分页功能

  created() {  
  this.findPage();  
  },  
  
 点击页码完成分页数据展示  
  //切换页码  
  handleCurrentChange(currentPage) {  
  this.pagination.currentPage = currentPage;  
  this.findPage();  
  },  
 
 
 查询按钮完成分页显示功能  
 <el-button @click="findPage()" class="dalfBut">查询</el-button>  
 

(二)后台内容

1:控制器方法

  //分页显示检查组  
  @RequestMapping("/findPage")  
  public PageResult findPage(@RequestBody QueryPageBean queryPageBean){  
  PageResult pageResult = checkGroupService.findPage(queryPageBean);  
  return  pageResult;  
  }

2: 服务接口

  PageResult findPage(QueryPageBean queryPageBean);

3:接口实现类

  @Override  
  public PageResult findPage(QueryPageBean queryPageBean) {  
  Page<Checkgroup> page1 = new Page(queryPageBean.getCurrentPage(),queryPageBean.getPageSize());  
  QueryWrapper<Checkgroup> queryWrapper = new QueryWrapper<>();  
  if(queryPageBean.getQueryString()!=null && queryPageBean.getQueryString().length()>0){  
  queryWrapper.like("code",queryPageBean.getQueryString());  
  queryWrapper.or();  
  queryWrapper.like("name",queryPageBean.getQueryString());  
  queryWrapper.or();  
  queryWrapper.like("helpCode",queryPageBean.getQueryString());  
  }  
  Page<Checkgroup> checkgroupPage = checkgroupMapper.selectPage(page1, queryWrapper);  
  return new PageResult(checkgroupPage.getTotal(),checkgroupPage.getRecords());  
  }

二、编辑检查组功能

(一)回显编辑信息功能

1:前端内容编写

(1)点击按钮弹出编辑窗口并回显检查组数据

 

// 弹出编辑窗口  
 handleUpdate(row) {  
  this.dialogFormVisible4Edit = true;  
  //回显当前检查组的基本信息  
  axios.get("/checkgroup/findGroupInfoById?id"+row.id).then((res) => {  
  //回显数据  
  if(res.data.flag){  
  this.formData = res.data.data;  
  }else{  
  this.$message.error(res.data.message);  
  }  
  });  
  //异步请求获取所有检查项信息  
  axios.get("/checkitem/showAllItem").then((res) => {  
  if(res.data.flag){  
  this.tableData = res.data.data;  
  //基于双向绑定给我们的checkitemIds赋值 就可以默认勾选当前检查项的所有默认检查组  
  //必须等到我们的检查项的列表加载完毕才可以进行勾选 所有我们的异步请求需要添加到这个位置  
  // java  List<Integer>  转换成的json就是这个效果 [3,4,576,]  
  axios.get("/checkitem/getCheckItemIdByGroupId?id="+row.id).then((res) => {  
  this.checkitemIds = res.data;  
  });  
   
  }else{  
  this.$message().error(res.data.messge);  
  }  
  });  
 },

2:后台内容

(1):控制器方法
a:CheckgroupController

 

//根据检查组的id获取检查组的信息  
  @RequestMapping("/findGroupInfoById")  
  public Result findGroupInfoById(Integer id){  
  Checkgroup checkgroup = null;  
  try {  
  checkgroup = checkGroupService.findGroupInfoById(id);  
  }catch (Exception e){  
  e.printStackTrace();  
  return new Result(false,MessageConstant.QUERY_CHECKGROUP_FAIL);  
  }  
  return new Result(true,MessageConstant.QUERY_CHECKGROUP_SUCCESS,checkgroup);  
  }
b:CheckitemController
  //根据检查组的id获取检查组包含的检查项的id  
  @RequestMapping("/getCheckItemIdByGroupId")  
  @ResponseBody  
  public  List<Integer> getCheckItemIdByGroupId(Integer id){  
  return checkItemService.getCheckItemIdByGroupId(id);  
  }
(2)服务接口方法
a:CheckGroupService
Checkgroup  findGroupInfoById(Integer id);
b:CheckItemService
List<Integer> getCheckItemIdByGroupId(Integer id);
(3)服务接口的实现方法
a:CheckGroupServiceImpl
   @Override
    public Checkgroup findGroupInfoById(Integer id) {
        return checkgroupMapper.selectById(id);
    }
b:CheckItemsServiceImpl
@Override
    public List<Integer> getCheckItemIdByGroupId(Integer id) {
        LambdaQueryWrapper<CheckgroupCheckitem> lambdaQueryWrapper = new LambdaQueryWrapper();
        lambdaQueryWrapper.eq(CheckgroupCheckitem::getCheckgroupId,id);
        lambdaQueryWrapper.select(CheckgroupCheckitem::getCheckitemId);

        return checkgroupCheckitemMapper.selectObjs(lambdaQueryWrapper).stream().map(o -> (Integer) o).collect(Collectors.toList());
    }

(二)提交确认按钮完成检查组修改

1:编写前端提交更新函数


 //编辑检查组
            handleEdit() {
                axios.post("/checkgroup/editGroup?checkitemIds="+this.checkitemIds,this.formData).then((res) => {
                    this.dialogFormVisible4Edit = false;
                    if(res.data.flag){
                        this.$message({
                            message: res.data.message,
                            type: 'success'
                        });
                    }else{
                        this.message().error(res.data.message);
                    }
                }).finally(() => {
                    //从新进行分页查询
                    this.findPage();
                });
            },

2:后台内容

(1)控制器方法
//编辑检查项
    @RequestMapping("/editGroup")
    public Result editGroup(@RequestBody Checkgroup checkgroup,Integer [] checkitemIds){
        try {
            checkGroupService.updateGroup(checkgroup,checkitemIds);
        }catch (Exception e){
            e.printStackTrace();
            return  new Result(false, MessageConstant.EDIT_CHECKGROUP_FAIL);
        }
        return new Result(true,MessageConstant.EDIT_CHECKGROUP_SUCCESS);
    }

(2)服务接口内容

void updateGroup(Checkgroup checkgroup, Integer[] checkitemIds);

(3)接口的实现类内容

@Override
    public void updateGroup(Checkgroup checkgroup, Integer[] checkitemIds) {
         //更新检查组数据
         checkgroupMapper.updateById(checkgroup);
         //删除检查组和检查项的中间关系表数据
         Map<String,Object> map = new HashMap<>();
         map.put("checkgroup_id",checkgroup.getId());
         checkgroupCheckitemMapper.deleteByMap(map);
         //从新添加检查组和检查项的中间表数据
        for(Integer id:checkitemIds){
            CheckgroupCheckitem checkgroupCheckitem = new CheckgroupCheckitem();
            checkgroupCheckitem.setCheckgroupId(checkgroup.getId());
            checkgroupCheckitem.setCheckitemId(id);
            checkgroupCheckitemMapper.insert(checkgroupCheckitem);
        }
    }

三、删除检查组操作

(一) 前端页面内容编写

        // 删除
            handleDelete(row) {
                //删除组操作
                this.$confirm("确认删除选中的数据么?","提示",{type:"warning"}).then(() => {
                     //使用ajax方式完成数据的删除
                     axios.get("/checkgroup/deleteInfoById?id="+row.id).then((res) => {
                          if(res.data.flag){
                              this.$message({
                                  message: res.data.message,
                                  type:'success'
                              });
                          }else{
                              this.$message.error(res.data.message);
                          }
                     }).finally(() => {
                          this.findPage();
                     })
                }).catch(() => {
                    this.$message({
                        message: '取消了当前删除检查组操作',
                        type: 'info'
                    });
                });
            }

(二) 删除检查组的后台内容

1:控制器方法

 //删除检查组
    @RequestMapping("/deleteInfoById")
    public Result deleteInfoById(Integer id){
         try{
             checkGroupService.deleteInfoById(id);
         }catch (Exception e){
             e.printStackTrace();
             return new Result(false,MessageConstant.DELETE_CHECKGROUP_FAIL);
         }
         return  new Result(true,MessageConstant.DELETE_CHECKGROUP_SUCCESS);
    }

2: 接口方法

 void deleteInfoById(Integer id);

3:接口的实现方法

 //删除检查组
    @Override
    public void deleteInfoById(Integer id) {
        //删除中间表数据
        Map<String,Object> map = new HashMap<>();
        map.put("checkgroup_id",id);
        checkgroupCheckitemMapper.deleteByMap(map);
        //删除检查组
        checkgroupMapper.deleteById(id);
    }

医疗管家-套餐管理维护

一、体检套餐管理

套餐其实就是检查组的集合,例如有一个套餐为“老年套餐”,这个体检套餐可以包括多个检查组:心脑血管检查、甲状腺检查、肺部筛查等。所以在添加套餐时需要选择这 个套餐包括的检查组。 套餐对应的实体类为Setmeal,对应的数据表为t_setmeal。套餐和检查组为多对多关 系,所以需要中间表t_setmeal_checkgroup进行关联

(一)添加套餐功能

添加套餐功能中涉及到两部分,一部分是添加套餐信息还有一部分是添加套餐对应的检查组的信息,所以在点击套餐页面中的新建的时候在弹出一个已经准备好的隐藏框,在弹出的窗口中需要加载出所有的检查组的信息,每个套餐还有对应的配套图片,我们使用element-ui提供的上传组件完成上传功能

1: 弹出添加套餐窗口

(1)前台页面
a:编写新建套餐按钮事件
// 弹出添加窗口
   handleCreate() {
       //重置表单
       this.resetForm();
       //显示弹出窗口
       this.dialogFormVisible = true;
       axios.get("/checkgroup/showAllGroupInfo").then((res) => {
           if(res.data.flag){
               this.tableData = res.data.data;
            }else{
                this.$message.erro(res.data.message);
            }
       });
   },
b:重置表单事件
 // 重置表单
   resetForm() {
      //清空表单数据
      this.formData = {};
      //清空选中的检查组
      this.checkitemIds = [];
      //默认选中第一个选项卡
      this.activeName = 'first';
      //清空图片的预览url
      this.imageUrl = null;
   },
(2)后台代码实现
a:控制器方法
//展示所有的检查组信息
    @RequestMapping("/showAllGroupInfo")
    public Result showAllGroupInfo(){
        List<Checkgroup> list = null;
        try{
            list = checkGroupService.showAllGroupInfo();
        }catch (Exception  e){
            e.printStackTrace();
            return new Result(false,MessageConstant.QUERY_CHECKITEM_FAIL);
        }
        return new Result(true,MessageConstant.QUERY_CHECKGROUP_SUCCESS,list);

    }
b:服务接口
 List<Checkgroup> showAllGroupInfo();
c:实现接口提供服务
 @Override
 public List<Checkgroup> showAllGroupInfo() {
     return checkgroupMapper.selectList(null);
 }

2:处理上传图片功能

(1)前台页面
a:element-ui上传组件
<el-form-item label="上传图片">
	<el-upload
		class="avatar-uploader"
		action="/setmeal/uploadpic"
		:auto-upload="autoUpload"
		name="imgFile"
		:show-file-list="false"
		:on-success="handleAvatarSuccess"
		:before-upload="beforeAvatarUpload">
		<img v-if="imageUrl" :src="imageUrl" class="avatar">
		<i v-else class="el-icon-plus avatar-uploader-icon"></i>
	</el-upload>
</el-form-item>

当前页面使用elementui的上传组件 action: 上传文件的地址 auto-upload: 自动上传 name:上传文件的名称 on-success: 上传成功后的回调函数 before-upload: 上传之前回调的函数

b:编辑上传组件的js函数
//上传图片之前执行 规范了上传图片的类型和上传图片的大小
beforeAvatarUpload(file) {
	const isJPG = file.type === 'image/jpeg';
	const isLt2M = file.size / 1024 / 1024 < 2;
		if (!isJPG) {
		    this.$message.error('上传套餐图片只能是 JPG 格式!');
		}
		if (!isLt2M) {
		    this.$message.error('上传套餐图片大小不能超过 2MB!');
		}
	return isJPG && isLt2M;
},



//文件上传成功后的钩子,response为服务端返回的值,file为当前上传的文件封装成的js对象
handleAvatarSuccess(response, file) {
    this.imageUrl="http://localhost:9003/setmealpic/"+response.data
    //设置模型数据(图片名称),后续提交ajax请求时会提交到后台最终保存到数据库
    this.formData.img = response.data;
},
(2)后台功能实现代码
a:控制方法
//上传图片方法
    @RequestMapping("/uploadpic")
    public Result uploadpic(@RequestParam("imgFile") MultipartFile multipartFile){
        String originalFilename = multipartFile.getOriginalFilename();
        int lastIndexOf = originalFilename.lastIndexOf(".");
        //获取文件后缀
        String suffix = originalFilename.substring(lastIndexOf - 1);
        String fileName  = UUID.randomUUID().toString()+suffix;
        File file = new File("D:/upload/"+fileName);
        try {
            multipartFile.transferTo(file);
            return new Result(false, MessageConstant.PIC_UPLOAD_FAIL);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new Result(true,MessageConstant.PIC_UPLOAD_SUCCESS,fileName);
    }
b:设置虚拟路径完成图片的存储和访问

@Configuration
public class MyConfiguration extends WebMvcConfigurerAdapter {
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/setmealpic/**").addResourceLocations("file:D:/upload/");
    }
}


avatar
青山
悟已往之不谏 知来者之可追
一言
今日诗词
站点信息
本站访客数 :
本站总访问量 :