37.后台系统-预约统计
# 需求分析
统计医院每天的预约情况,通过图表的形式展示,统计的数据都来自订单模块,在该模块封装好数据,在统计模块通过feign的形式获取数据,在实际的生成环境中,有很多种各式统计,数据来源于各个服务模块,需要一个统计模块来专门管理
 # 集成ECharts
提示
ECharts的简单入门
- name: 🚀 ECharts
  desc: '简单入门'
  link: /pages/613bc7/
  bgColor: '#DFEEE7'
  textColor: '#2A3344'
 2
3
4
5
安装到yygh-admin项目中
npm install --save echarts@4.1.0
 # 获取医院每天平台预约数据 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;
}
 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;
}
 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);
}
 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 <= #{vo.reserveDateEnd}
            </if>
            and is_deleted = 0
        </where>
        group by reserve_date
        order by reserve_date
    </select>
</mapper>
 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
 # 添加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);
}
 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;
    }
}
 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);
    }
}
 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>
 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>
 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);
}
 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>
 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
 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);
    }
}
 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));
    }
}
 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/**
 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
    })
  }
}
 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>
 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: '预约统计' }
      }
    ]
  },
 2
3
4
5
6
7
8
9
10
11
12
13
14
15
16