分布式预约挂号平台(八) | 郑医宝の数据字典管理 后端 前端

什么是数据字典?
管理系统常用的分类数据或一些固定数据,如省市区三级联动数据、民族数据、行业数据、学历数据等,需要做一个数据管理方便管理系统数据

一、数据库开发
1.创建数据库

微服务架构设计模式:分库分表

create database if not exists yygh_cmn character set utf8mb4;
use yygh_cmn;
# 数据字典
CREATE TABLE `dict` (
  # 使用id与parent_id表示层级关系,比如省市区三级联动数据,省下面有市,市下面有区
  # parent_id=1 表示一级,parent_id=2表示二级,当 id=1 是表示当前这个是第一级
  `id` BIGINT(20) NOT NULL DEFAULT '0' COMMENT '编号',      
  `parent_id` BIGINT(20) NOT NULL DEFAULT '0' COMMENT '上级id',
  `name` VARCHAR(100) NOT NULL DEFAULT '' COMMENT '名称',
  `value` BIGINT(20) DEFAULT NULL COMMENT '值',
  `dict_code` VARCHAR(20) DEFAULT NULL COMMENT '编码',
  `create_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  `is_deleted` TINYINT(3) NOT NULL DEFAULT '0' COMMENT '逻辑删除(1:已删除,0:未删除)',
  # is_deleted tinyint(3) not null default '1' comment '删除标记(0:不可用,1:可用)',  老师使用
  PRIMARY KEY (`id`),
  KEY `idx_dict_code` (`dict_code`),
  KEY `idx_parent_id` (`parent_id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8 COMMENT='组织架构表';
2.添加数据
# 一级:id=1 全部分类 
# 二级:id=86 省 id=10000 医院等级  id=20000 证件类型  id=30000 学历  id=99100 民族  parent_id=1
# 三级: parent_id是上面几个id值
insert into dict(id,parent_id,name,value,dict_code) values(1,0,'全部分类',1,'ROOT')
insert into dict(id,parent_id,name,value,dict_code) values(86,1,'省',86,'Province')
insert into dict(id,parent_id,name,value) values(110000,86,'北京市',110000),
												(130000,86,'河北省',130000),
												(140000,86,'山西省',140000),
												(150000,86,'内蒙古自治区',150000),
												(220000,86,'吉林省',220000),
												(230000,86,'黑龙江省',230000),
												(310000,86,'上海市',310000),
												(320000,86,'江苏省',320000),
												(340000,86,'安徽省',340000),
												(360000,86,'江西省',360000),
												(370000,86,'山东省',370000),
												(420000,86,'湖北省',420000),
												(610000,86,'陕西省',610000)
insert into dict(id,parent_id,name,value,dict_code) values(10000,1,'医院等级',null,'Hosptype')
insert into dict(id,parent_id,name,value) values(10001,10000,'三级甲等',1),
												(10002,10000,'三级乙等',2),
												(10003,10000,'二级甲等',3),
												(10004,10000,'二级乙等',4),
												(10005,10000,'一级',5)
insert into dict(id,parent_id,name,value,dict_code) values(20000,1,'证件类型',20000,'CretificatesType')
insert into dict(id,parent_id,name,value) values(20001,20000,'身份证',10),
												(20002,20000,'户口本',20)
insert into dict(id,parent_id,name,value,dict_code) values(30000,1,'学历',30000,'Education')
insert into dict(id,parent_id,name,value) values(30001,30000,'高中',30001),
												(30002,30000,'大专',30002),
												(30003,30000,'本科',30003),
												(30004,30000,'研究生',30004),
												(30005,30000,'博士',30005),
												(30006,30000,'其他',30006)
insert into dict(id,parent_id,name,value,dict_code) values(99100,1,'民族',99100,'Nation')
insert into dict(id,parent_id,name,value) values(99101,99100,'汉族',99101),
												(99102,99100,'满族',99102),
												(99103,99100,'彝族',99103),
												(99104,99100,'维吾尔族',99104)
二、数据字典后端开发
1.添加数据字典实体类
package com.zhengyibao.yygh.model.cmn;

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.zhengyibao.yygh.model.base.BaseEntity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

/**
 * @author wenmiao
 * @create 2021-10-03 18:20
 * @explain
 */
@Data  //lombok生成get、set方法
@ApiModel(description = "数据字典")
@TableName("dict")
public class Dict extends BaseEntity {
    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value="上级id")
    @TableField("parent_id")
    private Long parentId;

    @ApiModelProperty(value="名称")
    @TableField("name")
    private String name;

    @ApiModelProperty(value="值")
    @TableField("value")
    private Long value;

    @ApiModelProperty(value="编码")
    @TableField("dict_code")
    private String dictCode;

    @ApiModelProperty(value="是否包含子节点")
    @TableField(exist=false)   //数据表中没有这个字段也能正常运行
    private boolean hasChildren;   //为了在前端做层级显示使用的属性
}
2.创建微服务子模块service_cmn

在yygh_parent/service下创建 service_cmn 模块用来开发数据字典的后端
new - - module - - Maven

3.为微服务模块添加配置信息application.properties
# 可以是.properties格式,也可以是yml格式
# 服务端口,每个服务的端口号都不一样
server.port=8203
# 服务名
spring.application.name=service-cmn

# 环境设置:dev、test、prod
spring.profiles.active=dev

# mysql数据库连接
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/yygh_cmn?characterEncoding=utf-8&useSSL=false
spring.datasource.username=root
spring.datasource.password=root123

#返回json的全局时间格式
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
spring.jackson.time-zone=GMT+8

# 设置日志级别为DEBUG,默认为INFO,错误信息只能在控制台中进行删除
# logging.level.root=DEBUG
4.添加启动类ServiceCmnApplication
package com.zhengyibao.yygh.cmn;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;

/**
 * @author wenmiao
 * @create 2021-09-26 22:52
 * @explain 启动类
 */

@SpringBootApplication   //启动类注解
@ComponentScan(basePackages = "com.zhengyibao")  //设置扫描规则,使用配置类Swagger2Config进行测试
                                                 //1.加载common/service_util中的到service模块的pom.xml中,可以扫描Swagger2Config配置类
                                                 //2.而两者包名不同,但包名都是以com.zhengyibao开头,还需要额外在启动类上添加包扫描
public class ServiceCmnApplication {
    public static void main(String[] args){
        SpringApplication.run(ServiceCmnApplication.class, args);
    }
}
5.三层架构 - - mapper持久层
package com.zhengyibao.yygh.cmn.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.zhengyibao.yygh.model.cmn.Dict;

/**
 * @author wenmiao
 * @create 2021-09-27 21:33
 * @explain
 */
//由于HospitalSet不在service_hosp模块中,去service模块的pom.xml文件中将model模块引入
//mybatis-plus在mapper提供了BaseMapper<T>接口,继承这个接口,可获得CRUD功能
public interface DictMapper extends BaseMapper<Dict>{
}
6.三层架构 - - mapper持久层的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.zhengyibao.yygh.cmn.mapper.DictMapper">
</mapper>
7.三层架构 - - mapper持久层的扫描实现类的配置类
package com.zhengyibao.yygh.cmn.config;

import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author wenmiao
 * @create 2021-09-28 8:27
 * @explain 配置类
 */

@Configuration  //配置类
@MapperScan("com.zhengyibao.yygh.cmn.mapper")  //由于mapper的实现类会动态被创建,所以需要加配置类来扫描mapper的包查找他的实现类
public class CmnConfig {
    //分页插件  分页查询的配置类,如果不添加会导致查询时limit失效
    @Bean
    public PaginationInterceptor paginationInterceptor(){
        return new PaginationInterceptor();
    }
}

8.三层架构 - - service业务层接口
package com.zhengyibao.yygh.cmn.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.zhengyibao.yygh.model.cmn.Dict;

import java.util.List;

/**
 * @author wenmiao
 * @create 2021-09-27 21:47
 * @explain service接口
 */
//继承IService,是mybatis-plus提供的,可以让Mybatis-Plus在Service层去调用Mapper
public interface DictService extends IService<Dict>{

    //根据id查询子数据列表
    List<Dict> findChildData(Long id);
}
9.三层架构 - - service业务层实现类
package com.zhengyibao.yygh.cmn.service.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zhengyibao.yygh.cmn.mapper.DictMapper;
import com.zhengyibao.yygh.cmn.service.DictService;
import com.zhengyibao.yygh.model.cmn.Dict;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class DictServiceImpl extends ServiceImpl<DictMapper,Dict> implements DictService {

    //之前需要使用@Autowired将service注入进去,但由于继承了ServiceImpl,里面已经将baseMapper注入,可以直接调用

    //根据id查询子数据列表
    @Override
    public List<Dict> findChildData(Long id) {

        //使用条件构造器,构造条件
        QueryWrapper<Dict> wrapper=new QueryWrapper<>();
        wrapper.eq("parent_id",id);  //select * from dict where parent_id=id;
        //根据条件进行查询
        List<Dict> dictList=baseMapper.selectList(wrapper);
        //向list集合中的每个dict对象中设置hasChildren
        for (Dict dict:dictList){
            Long dictid=dict.getId();   //获取id值
            boolean isChildren=this.isChildren(id);  //判断有没有子节点,若有子节点isChildren=true,没有isChildren=false
            dict.setHasChildren(isChildren);    //设置hasChildren属性
        }
        return dictList;
    }

    //判断id下面是否有子节点,如果有子节点设置属性hasChildren=true,否则设置hasChildren=false
    private boolean isChildren(Long id){
        //使用条件构造器,构造条件
        QueryWrapper<Dict> wrapper=new QueryWrapper<>();
        wrapper.eq("parent_id",id);
        Integer count=baseMapper.selectCount(wrapper);   //查看有多少条数据
        return count>0;   //如果查出有数据(即count>0),返回true,否则返回false
    }
}
10.三层架构 - - controller表示层
package com.zhengyibao.yygh.cmn.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.mysql.jdbc.StringUtils;
import com.zhengyibao.yygh.cmn.service.DictService;
import com.zhengyibao.yygh.common.result.Result;
import com.zhengyibao.yygh.model.cmn.Dict;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * @author wenmiao
 * @create 2021-10-03 19:52
 * @explain
 */

@Api(tags="数据字典接口")
@RestController
@RequestMapping("/admin/cmn/dict")
public class DictController {

    @Autowired
    private DictService dictService;

    //根据id查询子数据列表
    @ApiOperation(value = "根据id查询id下面的子分类")
    @GetMapping("findChildData/{id}")
    public Result findChildData(@PathVariable Long id){
        List<Dict> dictList=dictService.findChildData(id);
        return Result.ok(dictList);
    }
}
11.测试

访问http://localhost:8203/swagger-ui.html进行swagger2测试

在这里插入图片描述

三、数据字典前端开发
1.添加数据字典路由index.js
//2.为数据字典模块添加路由
{
  path: '/cmn',  //第一层的路径 views下面的cmn
  component: Layout,
  redirect: '/cmn/list',
  name: '数据管理',
  alwaysShow:true,  //总是显示,如果下面只有一个层级,如果想显示数据管理需要加上这个属性
  meta: { title: '数据管理', icon: 'el-icon-s-help' },    //icon是列表前面显示的图标
  children: [
    {
      path: 'list',   //第二层的路径,列表功能
      name: '数据字典',
      component: () => import('@/views/dict/list'),   //2.设置跳转页面的路径   import是引入页面路径
      meta: { title: '数据字典', icon: 'table' }
    }
  ]
},
2.创建数据字典管理列表跳转页面 list.vue 实现查询

src/views下创建dict/list.vue文件

<!-- 默认模板输入快捷键:default -->
<template>
    <div class="app-container">
        <!-- 封装了3个属性,:data查出来用于懒加载的数据,:load是一个递归操作,显示下一层级的内容,:tree-props判断dictList中的属性值是true还是false来显示 -->
        <el-table :data="dictList" :load="getChildrens" :tree-props="{children: 'children', hasChildren: 'hasChildren'}" style="width: 100%;" row-key="id"  border lazy>
        <el-table-column label="名称" width="230" align="left">
            <template slot-scope="scope">
                <span>{{scope.row.name}}</span>
            </template>
        </el-table-column>
        <el-table-column label="编码" width="220">
            <template slot-scope="{row}">
                {{row.dictCode}}
            </template>
        </el-table-column>
        <el-table-column label="值" width="230" align="left">
            <template slot-scope="scope">
                <span>{{scope.row.value}}</span>
            </template>
        </el-table-column>
        <el-table-column label="创建时间" align="center">
            <template slot-scope="scope">
                <span>{{scope.row.createTime}}</span>
            </template>
        </el-table-column>
  </el-table>

    </div>
</template>

<script>

//引入对应的api
import { findDictList } from '@/api/dict.js'

export default {
    data(){
        return{
            dictList:[]   //数据字典列表数组
        }
    },
    created(){
        this.getDictList(1)
    },
    methods:{
        //获得数据字典列表
        getDictList(id){
            findDictList(id)
                .then(response =>{
                    this.dictList=response.data
                })
        },
        //做递归查询,显示数据列表下一层级
        getChildrens(tree,treeNode,resolve){
            findDictList(tree.id)
                .then(response =>{
                    resolve(response.data)
                })
        }
    }
}
</script>
3.定义接口路径 dict.js

src/api下创建dict.js文件

import request from '@/utils/request'  //这个里面是将axios做了封装,可以直接引入

//在api文件夹下创建js文件,进行ES6模块化开发规范,定义接口路径


//根据条件查询数据字典列表
export function findDictList(id) { //路径所需内容作为参数传入接口,current 当前页,limit 每页记录数,searchObj 条件对象
  return request({
    url: `/admin/cmn/dict/findDictList/${id}`,          //条件分页查询接口路径(在后端controller中寻找路径,@RequestMapping/@GetMapping)
    method: 'get',                          //提交方式                              //使用模板字符串` ${} `来取出需要的参数
  })                                        
}    
4.修改vue.config.js文件的端口号

这个端口号需要与后端接口的端口号一致,后面再使用 EasyExcel 技术进行多端口访问

proxy: {
   [process.env.VUE_APP_BASE_API]: {
     target: "http://localhost:8203",
     ws: true,
     changeOrigin: true,
     pathRewrite: {
       ['^' + process.env.VUE_APP_BASE_API]: ''
     }
   }
},
5.测试

在这里插入图片描述

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值