Teng's blog Teng's blog
首页
Java
H5前端
GitHub (opens new window)
首页
Java
H5前端
GitHub (opens new window)
  • 01.项目介绍
  • 02.后台系统-搭建项目
  • 03.后台系统-医院设置模块
  • 04.后台系统-统一异常处理
  • 05.后台系统-统一日志处理
  • 06.后台系统-搭建管理后台前端
  • 07.后台系统-医院设置前端
  • 08.后台系统-数据字典
  • 09.SpringCache+Redis缓存数据
  • 10.集成与配置Nginx
  • 11.启动医院接口模拟系统
  • 12.后台系统-上传医院信息
  • 13.后台系统-上传科室信息
  • 14.后台系统-上传排班信息
  • 15.搭建服务注册中心Nacos
  • 16.后台系统-医院管理
  • 17.后台系统-排班管理
  • 18.搭建服务网关Gateway
  • 19.前台系统-搭建前端环境
  • 20.前台系统-首页
  • 21.前台系统-医院详情页
  • 22.前台系统-用户登录
  • 23.后台系统-短信服务
  • 24.用户认证与网关整合
  • 25.前台系统-微信登录
  • 26.前台系统-实名认证
  • 27.前台系统-就诊人管理
  • 28.后台系统-平台用户管理
  • 29.前台系统-预约挂号详情
  • 30.前台系统-预约确认
  • 31.前台系统-预约下单
  • 32.前台系统-订单管理
  • 33.后台系统-订单管理
  • 34.前台系统-微信支付
  • 35.前台系统-取消预约
  • 36.前台系统-就医提醒
  • 37.后台系统-预约统计
    • 需求分析
    • 集成ECharts
    • 获取医院每天平台预约数据 service-order
      • 添加实体 model
      • 添加mapper接口
      • 添加service接口与实现
      • 添加controller方法
      • 修改父pom文件
    • 创建模块service-order-client
      • 修改pom
      • 添加controller方法
    • 搭建 service-statistics
      • 配置pom
      • 添加配置文件
      • 添加启动类
      • 添加controller
      • 添加网关配置 service-gateway
    • 前端实现 yygh-admin
      • 封装api请求
      • 创建页面组件
      • 添加路由
  • 38.小结
  • 附录:医院接口模拟系统说明
  • 附录:在线预约挂号API接口文档
  • Project-尚医通
Shetengteng
2022-01-07

37.后台系统-预约统计

# 需求分析

统计医院每天的预约情况,通过图表的形式展示,统计的数据都来自订单模块,在该模块封装好数据,在统计模块通过feign的形式获取数据,在实际的生成环境中,有很多种各式统计,数据来源于各个服务模块,需要一个统计模块来专门管理

# 集成ECharts

提示

ECharts的简单入门

🚀 ECharts

简单入门

- name: 🚀 ECharts
  desc: '简单入门'
  link: /pages/613bc7/
  bgColor: '#DFEEE7'
  textColor: '#2A3344'
1
2
3
4
5

安装到yygh-admin项目中

npm install --save echarts@4.1.0
1

# 获取医院每天平台预约数据 service-order

# 添加实体 model

在 model中添加统计结果的实体类

package com.stt.yygh.vo.order;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

@Data
@ApiModel(description = "OrderCountVo")
public class OrderCountVo {
	
	@ApiModelProperty(value = "安排日期")
	private String reserveDate;

	@ApiModelProperty(value = "预约单数")
	private Integer count;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

添加对应的查询类

package com.stt.yygh.vo.order;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

@Data
@ApiModel(description = "OrderCountQueryVo")
public class OrderCountQueryVo {
	
	@ApiModelProperty(value = "医院编号")
	private String hoscode;

	@ApiModelProperty(value = "医院名称")
	private String hosname;

	@ApiModelProperty(value = "安排日期")
	private String reserveDateBegin;
	private String reserveDateEnd;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# 添加mapper接口

修改 service-order 中的 OrderInfoMapper 类

package com.stt.yygh.order.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.stt.yygh.model.order.OrderInfo;
import com.stt.yygh.vo.order.OrderCountQueryVo;
import com.stt.yygh.vo.order.OrderCountVo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

import java.util.List;

@Mapper
public interface OrderInfoMapper extends BaseMapper<OrderInfo> {
    List<OrderCountVo> selectOrderCount(@Param("vo") OrderCountQueryVo orderCountQueryVo);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 创建xml文件

添加对应的xml文件,创建com.stt.yygh.order.mapper.xml包,并创建OrderInfoMapper.xml文件,内容如下

针对不同的查询条件获取不同的统计结果

<?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="com.stt.yygh.order.mapper.OrderInfoMapper">

    <select id="selectOrderCount" resultType="com.stt.yygh.vo.order.OrderCountVo">
        select reserve_date as reserveDate, count(reserve_date) as count
        from order_info
        <where>
            <if test="vo.hosname != null and vo.hosname != ''">
                and hosname like CONCAT('%',#{vo.hosname},'%')
            </if>
            <if test="vo.reserveDateBegin != null and vo.reserveDateBegin != ''">
                and reserve_date >= #{vo.reserveDateBegin}
            </if>
            <if test="vo.reserveDateEnd != null and vo.reserveDateEnd != ''">
                and reserve_date &lt;= #{vo.reserveDateEnd}
            </if>
            and is_deleted = 0
        </where>
        group by reserve_date
        order by reserve_date
    </select>
</mapper>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

# 修改mapper-locations配置

添加application.properties配置,需要配置xml解析的路径,用于mybatis-plus识别

mybatis-plus.mapper-locations=classpath:com/stt/yygh/order/mapper/xml/*.xml
1

# 添加service接口与实现

在OrderService类添加接口

package com.stt.yygh.order.service;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.stt.yygh.model.order.OrderInfo;
import com.stt.yygh.vo.order.OrderCountQueryVo;
import com.stt.yygh.vo.order.OrderQueryVo;

import java.util.Map;

public interface OrderService extends IService<OrderInfo> {
...
    // 订单统计
    Map<String, Object> getCountMap(OrderCountQueryVo orderCountQueryVo);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

对应实现

依据项目示例,从数据库中获取了统计数据,然后解析处理x轴和y轴数据给前端;如果直接给统计数据如 List<OrderCountVo> 的json形式让,前端自我解析成x和y轴,其实避免了后端和前端统计展示框架要求的数据耦合,前端后期如果要更换统计展示框架时,可能需要后端再做业务数据的转换

package com.stt.yygh.order.service.impl;
...
@Service
public class OrderServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo> implements OrderService {
...
    @Override
    public Map<String, Object> getCountMap(OrderCountQueryVo orderCountQueryVo) {
        List<OrderCountVo> orderCountVoList = baseMapper.selectOrderCount(orderCountQueryVo);
        Map<String, Object> re = new HashMap<>(2);
        //日期列表 x轴
        re.put("dateList", orderCountVoList.stream()
                .map(OrderCountVo::getReserveDate)
                .collect(Collectors.toList()));
        //统计列表 y轴
        re.put("countList", orderCountVoList.stream()
                .map(OrderCountVo::getCount)
                .collect(Collectors.toList()));
        return re;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# 添加controller方法

在OrderApiController类添加方法

package com.stt.yygh.order.controller;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.stt.yygh.common.result.Result;
import com.stt.yygh.common.utils.AuthContextHolder;
import com.stt.yygh.enums.OrderStatusEnum;
import com.stt.yygh.model.order.OrderInfo;
import com.stt.yygh.order.service.OrderService;
import com.stt.yygh.vo.order.OrderCountQueryVo;
import com.stt.yygh.vo.order.OrderQueryVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;

@Api(tags = "订单接口")
@RestController
@RequestMapping("/api/order/orderInfo")
public class OrderApiController {

    @Autowired
    private OrderService service;

  ...

    @ApiOperation(value = "获取订单统计数据")
    @PostMapping("inner/getCountMap")
    public Map<String, Object> getCountMap(@RequestBody OrderCountQueryVo orderCountQueryVo) {
        return service.getCountMap(orderCountQueryVo);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

# 修改父pom文件

修改 yygh-server的pom文件

由于mybatis的自定义sql写在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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <modules>
        <module>common</module>
        <module>model</module>
        <module>service</module>
        <module>service-client</module>
        <module>service-gateway</module>
    </modules>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.1.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.stt.yygh</groupId>
    <artifactId>yygh_parent</artifactId>
    <version>0.0.1</version>

    <name>yygh_parent</name>
    <packaging>pom</packaging>
    <description>尚医通</description>

    <properties>
	...
    </properties>

    <!--配置dependencyManagement锁定依赖的版本-->
    <dependencyManagement>
    ...
    </dependencyManagement>

    <!-- 项目打包时会将java目录中的*.xml文件也进行打包 -->
    <build>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
                <filtering>false</filtering>
            </resource>
        </resources>
    </build>
</project>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

# 创建模块service-order-client

由于order的统计信息可以被其他模块获取得到,因此需要添加一个外部调用的依赖

创建同service-user-client

# 修改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>service-client</artifactId>
        <groupId>com.stt.yygh</groupId>
        <version>1.0</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>service-order-client</artifactId>
    <packaging>jar</packaging>
    <version>1.0</version>
    <name>service-order-client</name>
    <description>service-order-client</description>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

</project>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

# 添加controller方法

package com.stt.yygh.order.client;

import com.stt.yygh.vo.order.OrderCountQueryVo;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;

import java.util.Map;

@Component
@FeignClient(value = "service-order")
public interface OrderFeignClient {
    /**
     * 获取订单统计数据
     */
    @PostMapping("/api/order/orderInfo/inner/getCountMap")
    Map<String, Object> getCountMap(@RequestBody OrderCountQueryVo orderCountQueryVo);

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# 搭建 service-statistics

搭建方式同service-user,该服务调用service-order进行统一的统计管理

# 配置pom

修改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>service</artifactId>
        <groupId>com.stt.yygh</groupId>
        <version>0.0.1</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <version>1.0</version>
    <artifactId>service-statistics</artifactId>
    <packaging>jar</packaging>
    <name>service-statistics</name>
    <description>service-statistics</description>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>com.stt.yygh</groupId>
            <artifactId>service-order-client</artifactId>
            <version>1.0</version>
        </dependency>
    </dependencies>

</project>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

# 添加配置文件

创建application.properties文件

# 服务端口
server.port=8208
# 服务名
spring.application.name=service-statistics
# 环境设置:dev、test、prod
spring.profiles.active=dev

# nacos服务地址
spring.cloud.nacos.discovery.server-addr=localhost:8848
1
2
3
4
5
6
7
8
9

# 添加启动类

创建 ServiceStatisticsApplication 类,注意 EnableFeignClients 注解的扫描包配置

package com.stt.yygh.statistics;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.ComponentScan;

@EnableDiscoveryClient
//取消数据源自动配置
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
@EnableFeignClients(basePackages = {"com.stt"})
@ComponentScan(basePackages = {"com.stt"})
public class ServiceStatisticsApplication {
    public static void main(String[] args) {
        SpringApplication.run(ServiceStatisticsApplication.class, args);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 添加controller

package com.stt.yygh.statistics.controller;

import com.stt.yygh.common.result.Result;
import com.stt.yygh.order.client.OrderFeignClient;
import com.stt.yygh.vo.order.OrderCountQueryVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@Api(tags = "统计管理接口")
@RestController
@RequestMapping("/admin/statistics")
public class StatisticsController {

    @Autowired
    private OrderFeignClient orderFeignClient;

    @ApiOperation(value = "获取订单统计数据")
    @GetMapping("getCountMap")
    public Result getCountMap(@ApiParam(name = "orderCountQueryVo", value = "查询对象") OrderCountQueryVo orderCountQueryVo) {
        return Result.ok(orderFeignClient.getCountMap(orderCountQueryVo));
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

# 添加网关配置 service-gateway

在service-gateway的application.properties中增加对应路由配置

spring.cloud.gateway.routes[7].id=service-statistics
spring.cloud.gateway.routes[7].uri=lb://service-statistics
spring.cloud.gateway.routes[7].predicates= Path=/*/statistics/**
1
2
3

# 前端实现 yygh-admin

# 封装api请求

创建/api/statistics.js

import request from '@/utils/request'

const api_name = '/admin/statistics'

export default {
  getCountMap(searchObj) {
    return request({
      url: `${api_name}/getCountMap`,
      method: 'get',
      params: searchObj
    })
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13

# 创建页面组件

创建/views/statistics/order/index.vue组件

<template>
  <div class="app-container">
    <!--表单-->
    <el-form :inline="true" class="demo-form-inline">
      <el-form-item>
        <el-input v-model="searchObj.hosname" placeholder="点击输入医院名称"/>
      </el-form-item>
      <el-form-item>
        <el-date-picker v-model="searchObj.reserveDateBegin" type="date" placeholder="选择开始日期"
                        value-format="yyyy-MM-dd"/>
      </el-form-item>
      <el-form-item>
        <el-date-picker v-model="searchObj.reserveDateEnd" type="date" placeholder="选择截止日期" value-format="yyyy-MM-dd"/>
      </el-form-item>
      <el-button :disabled="btnDisabled" type="primary" icon="el-icon-search" @click="showChart()">查询</el-button>
    </el-form>
    <div class="chart-container">
      <div id="chart" ref="chart" class="chart" style="height:500px;width:100%"/>
    </div>
  </div>
</template>

<script>
import echarts from 'echarts'
import statisticsApi from '@/api/statistics'

export default {

  data() {
    return {
      searchObj: {
        hosname: '',
        reserveDateBegin: '',
        reserveDateEnd: ''
      },
      btnDisabled: false,
      chart: null,
      title: '',
      xData: [], // x轴数据
      yData: [] // y轴数据
    }
  },

  methods: {
    // 初始化图表数据
    showChart() {
      statisticsApi.getCountMap(this.searchObj).then(res => {
        this.yData = res.data.countList
        this.xData = res.data.dateList
        this.setChartData()
      })
    },

    setChartData() {
      // 基于准备好的dom,初始化echarts实例
      var myChart = echarts.init(document.getElementById('chart'))
      // 指定图表的配置项和数据
      var option = {
        title: {
          text: this.title + '挂号量统计'
        },
        tooltip: {},
        legend: {
          data: [this.title]
        },
        xAxis: {
          data: this.xData
        },
        yAxis: {
          minInterval: 1
        },
        series: [{
          name: this.title,
          type: 'line',
          data: this.yData
        }]
      }
      // 使用刚指定的配置项和数据显示图表
      myChart.setOption(option)
    }
  }
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83

# 添加路由

在 src/router/index.js 文件添加路由

  {
    path: '/statistics',
    component: Layout,
    redirect: '/statistics/order/index',
    name: 'BasesInfo',
    meta: { title: '统计管理', icon: 'table' },
    alwaysShow: true,
    children: [
      {
        path: 'order/index',
        name: '预约统计',
        component: () => import('@/views/statistics/order/index'),
        meta: { title: '预约统计' }
      }
    ]
  },
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Last Updated: 2022/01/16, 11:29:51
36.前台系统-就医提醒
38.小结

← 36.前台系统-就医提醒 38.小结→

Theme by Vdoing | Copyright © 2021-2022 Shetengteng | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式