尚医通_第6章_数据字典模块前后端+EasyExcel读写操作

尚医通_第6章_数据字典模块前后端+EasyExcel读写操作

文章目录

01-数据字典需求分析和搭建环境

一、数据字典介绍

1、什么是数据字典

数据字典就是管理系统常用的分类数据或者一些固定数据,例如:省市区三级联动数据、民族数据、行业数据、学历数据等,由于该系统大量使用这种数据,所以我们要做一个数据管理方便管理系统数据,一般系统基本都会做数据管理。

2、页面展示效果

在这里插入图片描述

3、数据字典表设计

在这里插入图片描述

4、数据分析

在这里插入图片描述

parent_id:

上级id,通过id与parent_id构建上下级关系,例如:我们要获取所有行业数据,那么只需要查询parent_id=20000的数据

name:名称,例如:填写用户信息,我们要select标签选择民族,“汉族”就是数据字典的名称

value:值,例如:填写用户信息,我们要select标签选择民族,“1”(汉族的标识)就是数据字典的值

dict_code:编码,编码是我们自定义的,全局唯一,例如:我们要获取行业数据,我们可以通过parent_id获取,但是parent_id是不确定的,所以我们可以根据编码来获取行业数据

说明:系统中会使用省市区三级联动数据,该数据我们来自“国家统计局”官方数据,地址:http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2019/index.html

5、根据页面效果分析数据接口

数据字典是树形展示,由于数据众多,我们使用“树形数据与懒加载”的方式展现数据列表,其他就是对数据的新增、修改与删除操作,因此需要提供的接口如下:

1,根据上级id获取下级数据(构造树形数据),参考文档:https://element.eleme.cn/#/zh-CN/component/table,页面搜索:树形数据与懒加载

2,导入接口

3,导出接口

二、搭建数据字典模块

1、创建service_cmn模块

在这里插入图片描述

2、创建application.properties配置文件

# 服务端口
server.port=8202
# 服务名
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

3、使用代码生成器生成mapper接口,service,controller层,entity层生成之后删除!

代码生成器从yygh_hosp模块的拷贝[同时注意拷贝代码生成器的两个依赖哦]

4.创建启动类

@SpringBootApplication
@ComponentScan(basePackages = {"com.atguigu"})
public class ServiceCmnApplication {
    public static void main(String[] args) {
        SpringApplication.run(ServiceCmnApplication.class, args);
    }
}

5.创建一个Config配置类,扫描Mapper接口

@Configuration
@MapperScan("com.atguigu.yygh.cmn.mapper")
public class CmnConfig {
}

02-数据字典列表功能(前后端)

一、数据字典列表接口

根据element组件要求,返回列表数据必须包含hasChildren字典,如图:

https://element.eleme.cn/#/zh-CN/component/table

在这里插入图片描述
在这里插入图片描述

1、model模块添加数据字典实体**

在这里插入图片描述

@Data
@ApiModel(description = "数据字典")
@TableName("dict")
public class Dict {
    private static final long serialVersionUID = 1L;
    @ApiModelProperty(value = "id")
    private Long id;
    @ApiModelProperty(value = "创建时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @TableField("create_time")
    private Date createTime;
    @ApiModelProperty(value = "更新时间")
    @TableField("update_time")
    private Date updateTime;
    @ApiModelProperty(value = "逻辑删除(1:已删除,0:未删除)")
    @TableLogic
    @TableField("is_deleted")
    private Integer isDeleted;
    @ApiModelProperty(value = "其他参数")
    @TableField(exist = false)
    private Map<String,Object> param = new HashMap<>();
    @ApiModelProperty(value = "上级id")
    @TableField("parent_id")
    private Long parentId;
    @ApiModelProperty(value = "名称")
    @TableField("name")
    private String name;
    @ApiModelProperty(value = "值")
    @TableField("value")
    private String value;
    @ApiModelProperty(value = "编码")
    @TableField("dict_code")
    private String dictCode;
    @ApiModelProperty(value = "是否包含子节点")
    @TableField(exist = false)
    private boolean hasChildren;
}

说明:hasChildren为树形组件所需字典,标识为数据库表不存在该字段

2、添加数据字典mapper

public interface DictMapper extends BaseMapper<Dict> {
}

3、添加数据字典service

public interface DictService extends IService<Dict> {
    //根据数据id查询子数据列表
    List<Dict> findChlidData(Long id);
}
@Service
public class DictServiceImpl extends ServiceImpl<DictMapper, Dict> implements DictService {
    //根据数据id查询子数据列表
    @Override
    public List<Dict> findChlidData(Long id) {
        QueryWrapper<Dict> wrapper = new QueryWrapper<>();
        wrapper.eq("parent_id",id);
        List<Dict> dictList = baseMapper.selectList(wrapper);
        //向list集合每个dict对象中设置hasChildren
        for (Dict dict:dictList) {
            Long dictId = dict.getId();
            boolean isChild = this.isChildren(dictId);
            dict.setHasChildren(isChild);
        }
        return dictList;
    }
    //判断id下面是否有子节点
    private boolean isChildren(Long id) {
        QueryWrapper<Dict> wrapper = new QueryWrapper<>();
        wrapper.eq("parent_id",id);
        Integer count = baseMapper.selectCount(wrapper);
        return count>0;
    }
}

4、添加数据字典controller

@Api(description = "数据字典接口")
@RestController
@RequestMapping("/admin/cmn/dict")
@CrossOrigin
public class DictController {
    @Autowired
    private DictService dictService;
    //根据数据id查询子数据列表
    @ApiOperation(value = "根据数据id查询子数据列表")
    @GetMapping("findChildData/{id}")
    public R findChildData(@PathVariable Long id) {
        List<Dict> list = dictService.findChlidData(id);
        return R.ok().data("list",list);
    }
}

二、数据字典列表前端

1、添加数据字典路由

修改router/index.js文件

  {
    path: '/cmn',
    component: Layout,
    redirect: '/cmn/list',
    name: '数据管理',
    alwaysShow: true,
    meta: { title: '数据管理', icon: 'example' },
    children: [
      {
        path: 'list',
        name: '数据字典',
        component: () => import('@/views/dict/list'),
        meta: { title: '数据字典', icon: 'table' }
      }
    ]
  },

2、定义数据字典列表接口

创建文件 src/api/yygh/dict.js

import request from '@/utils/request'
export default {
    dictList(id) {//数据字典列表
      return request ({
        url: `/admin/cmn/dict/findChildData/${id}`,
        method: 'get'
      })
    }
}

3、在dict/list.vue调用

<script>
import dict from '@/api/yygh/dict'
export default {
    data() {
        return {
            list:[] //数据字典列表数组
        }
    },
    created() {
        this.getDictList(1)
    },
    methods: {
        //数据字典列表
        getDictList(id) {
            dict.dictList(id)
                .then(response => {
                    this.list = response.data.list
                })
        },
        load(tree, treeNode, resolve) {
            dict.dictList(tree.id).then(response => {
                resolve(response.data.list)
            })
      }
    }
}
</script>

4、页面数据渲染

修改dict/list.vue页面

<template>
    <div  class="app-container">
    <el-table
        :data="list"
        style="width: 100%"
        row-key="id"
        border
        lazy
        :load="load"
        :tree-props="{children: 'children', hasChildren: 'hasChildren'}">
        <el-table-column
        prop="name"
        label="名称"
        width="150">
        </el-table-column>
        <el-table-column
        prop="dictCode"
        label="编码"
        width="150">
        </el-table-column>
        <el-table-column
        prop="value"
        label="值"
        width="150">
        </el-table-column>
        <el-table-column
        prop="createTime"
        label="创建时间">
        </el-table-column>
    </el-table>
    </div>
</template>

03-技术点-EasyExcel介绍

一、EasyExcel介绍

1、数据导入:减轻录入工作量

2、数据导出:统计信息归档

3、数据传输:异构系统之间数据传输

二、EasyExcel特点

  • Java领域解析、生成Excel比较有名的框架有Apache poi、jxl等。但他们都存在一个严重的问题就是非常的耗内存。如果你的系统并发量不大的话可能还行,但是一旦并发上来后一定会OOM或者JVM频繁的full gc。
  • EasyExcel是阿里巴巴开源的一个excel处理框架,以使用简单、节省内存著称。EasyExcel能大大减少占用内存的主要原因是在解析Excel时没有将文件数据一次性全部加载到内存中,而是从磁盘上一行行读取数据,逐个解析。
  • EasyExcel采用一行一行的解析模式,并将一行的解析结果以观察者的模式通知处理(AnalysisEventListener)

EasyExcel是一个基于Java的简单、省内存的读写Excel的开源项目。在尽可能节约内存的情况下支持读写百M的Excel。

文档地址:https://alibaba-easyexcel.github.io/index.html

github地址:https://github.com/alibaba/easyexcel

1 导出示例

示例链接:https://alibaba-easyexcel.github.io/quickstart/write.html

2 导入示例

示例链接:https://alibaba-easyexcel.github.io/quickstart/read.html

3 EasyExcel集成

项目添加依赖

<dependencies>
    <!-- https://mvnrepository.com/artifact/com.alibaba/easyexcel -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>easyexcel</artifactId>
        <version>2.1.1</version>
    </dependency>
</dependencies>

04-技术点-EasyExcel写操作

一、创建项目,实现EasyExcel对Excel写操作

1、pom中引入xml相关依赖

<dependencies>
    <!-- https://mvnrepository.com/artifact/com.alibaba/easyexcel -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>easyexcel</artifactId>
        <version>2.1.1</version>
    </dependency>
</dependencies>

2、创建实体类

设置表头和添加的数据字段

@Data
public class Stu {
    //设置表头名称
    @ExcelProperty("学生编号")
    private int sno;
    //设置表头名称
    @ExcelProperty("学生姓名")
    private String sname;
}

3 、实现写操作

(1)创建方法循环设置要添加到Excel的数据

//循环设置要添加的数据,最终封装到list集合中
private static List<Stu> data() {
    List<Stu> list = new ArrayList<Stu>();
    for (int i = 0; i < 10; i++) {
        Stu data = new Stu();
        data.setSno(i);
        data.setSname("张三"+i);
        list.add(data);
    }
    return list;
}

(2)实现最终的添加操作(写法一)

public static void main(String[] args) throws Exception {
    // 写法1
    String fileName = "F:\\11.xlsx";
    // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
    // 如果这里想使用03 则 传入excelType参数即可
    EasyExcel.write(fileName, Stu.class).sheet("写入方法一").doWrite(data());
}

(3)实现最终的添加操作(写法二)

public static void main(String[] args) throws Exception {
    // 写法2,方法二需要手动关闭流
    String fileName = "F:\\112.xlsx";
    // 这里 需要指定写用哪个class去写
    ExcelWriter excelWriter = EasyExcel.write(fileName, Stu.class).build();
    WriteSheet writeSheet = EasyExcel.writerSheet("写入方法二").build();
    excelWriter.write(data(), writeSheet);
    /// 千万别忘记finish 会帮忙关闭流
    excelWriter.finish();
}

05-技术点-EasyExcel读操作

一、实现EasyExcel对Excel读操作

1、创建实体类

@Data
public class Stu {
    //设置表头名称
    //设置列对应的属性
    @ExcelProperty(value = "学生编号",index = 0)
    private int sno;
    //设置表头名称
    //设置列对应的属性
    @ExcelProperty(value = "学生姓名",index = 1)
    private String sname;
}

2、创建读取操作的监听器

public class ExcelListener extends AnalysisEventListener<Stu> {
    //创建list集合封装最终的数据
    List<Stu> list = new ArrayList<Stu>();
    //一行一行去读取excle内容
    @Override
    public void invoke(Stu user, AnalysisContext analysisContext) {
        System.out.println("***"+user);
        list.add(user);
    }
    //读取excel表头信息
    @Override
    public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
        System.out.println("表头信息:"+headMap);
    }
    //读取完成后执行
    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
    }
}

3、调用实现最终的读取

   public static void main(String[] args) throws Exception {
        String fileName = "F:\\11.xlsx";
        // 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭
        EasyExcel.read(fileName, ReadData.class, new ExcelListener()).sheet().doRead();
}

06-数据字典导出功能(前后端)

一、数据字典导出后端接口

1、查看model实体类

在model模块查看实体:com.atguigu.yygh.vo.cmn.DictEeVo

在这里插入图片描述

@Data
public class DictEeVo {
    @ExcelProperty(value = "id" ,index = 0)
    private Long id;
    @ExcelProperty(value = "上级id" ,index = 1)
    private Long parentId;
    @ExcelProperty(value = "名称" ,index = 2)
    private String name;
    @ExcelProperty(value = "值" ,index = 3)
    private String value;
    @ExcelProperty(value = "编码" ,index = 4)
    private String dictCode;
}

2、在DictService添加方法和实现**

public interface DictService extends IService<Dict> {
    /**
     * 导出
     * @param response
     */
    void exportData(HttpServletResponse response);
}
    @Override
    public void exportData(HttpServletResponse response) {
        try {
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
            // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
            String fileName = URLEncoder.encode("数据字典", "UTF-8");
            response.setHeader("Content-disposition", "attachment;filename="+ fileName + ".xlsx");
            List<Dict> dictList = baseMapper.selectList(null);
            List<DictEeVo> dictVoList = new ArrayList<>(dictList.size());
            for(Dict dict : dictList) {
                DictEeVo dictVo = new DictEeVo();
                BeanUtils.copyProperties(dict,dictVo);
                dictVoList.add(dictVo);
            }
            EasyExcel.write(response.getOutputStream(), DictEeVo.class).sheet("数据字典").doWrite(dictVoList);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

3、添加Controller方法**

@ApiOperation(value="导出")
@GetMapping(value = "/exportData")
public void exportData(HttpServletResponse response) {
    dictService.exportData(response);
}

二、数据字典导出前端

list.vue页面添加导出按钮

<div class="el-toolbar">
    <div class="el-toolbar-body" style="justify-content: flex-start;">
        <el-button type="text" @click="exportData"><i class="fa fa-plus"/> 导出</el-button>
    </div>
</div>

编写调用方法

exportData() {
    window.open("http://localhost:8202/admin/cmn/dict/exportData")
},

07-数据字典导入功能(前后端)

一、数据字典导入接口开发

1、创建读取监听器

@Component
public class DictListener extends AnalysisEventListener<DictEeVo> {
    @Autowired
    private DictMapper dictMapper;
    //一行一行读取
    @Override
    public void invoke(DictEeVo dictEeVo, AnalysisContext analysisContext) {
        //调用方法添加数据库
        Dict dict = new Dict();
        BeanUtils.copyProperties(dictEeVo,dict);
        dictMapper.insert(dict);
    }
    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
    }
}

2、添加controller方法

@ApiOperation(value = "导入")
@PostMapping("importData")
public R importData(MultipartFile file) {
    dictService.importDictData(file);
    return R.ok();
}

3、添加service方法

@Autowired
private DictListener dictListener;
@Override
public void importDictData(MultipartFile file) {
    try {
        EasyExcel.read(file.getInputStream(),DictEeVo.class,dictListener).sheet().doRead();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

二、数据字典导入前端

1、在list.vue页面添加导入按钮

<el-button type="text" @click="importData"><i class="fa fa-plus"/> 导入</el-button>

2、添加导入弹出层

<el-dialog title="导入":visible.sync="dialogImportVisible"width="480px">
    <el-form label-position="right" label-width="170px">
        <el-form-item label="文件">
            <el-upload
                       :multiple="false"
                       :on-success="onUploadSuccess"
                       :action="'http://localhost:8202/admin/cmn/dict/importData'"
                       class="upload-demo">
                <el-button size="small" type="primary">点击上传</el-button>
                <div slot="tip" class="el-upload__tip">只能上传xls文件,且不超过500kb</div>
            </el-upload>
        </el-form-item>
    </el-form>
    <div slot="footer" class="dialog-footer">
        <el-button @click="dialogImportVisible = false">取消</el-button>
    </div>
</el-dialog>

3、添加导入弹出层属性

data() {
    return {
        dialogImportVisible: false,
        list:[] //数据字典列表数组
    }
},

4、添加导入方法

importData() {
    this.dialogImportVisible = true
},
onUploadSuccess(response, file) {
    this.$message.info('上传成功')
    this.dialogImportVisible = false
    this.getDictList(1)
},
        class="upload-demo">
                <el-button size="small" type="primary">点击上传</el-button>
                <div slot="tip" class="el-upload__tip">只能上传xls文件,且不超过500kb</div>
            </el-upload>
        </el-form-item>
    </el-form>
    <div slot="footer" class="dialog-footer">
        <el-button @click="dialogImportVisible = false">取消</el-button>
    </div>
</el-dialog>

3、添加导入弹出层属性

data() {
    return {
        dialogImportVisible: false,
        list:[] //数据字典列表数组
    }
},

4、添加导入方法

importData() {
    this.dialogImportVisible = true
},
onUploadSuccess(response, file) {
    this.$message.info('上传成功')
    this.dialogImportVisible = false
    this.getDictList(1)
},
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

管程序猿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值