RY的数据字典管理:
字典管理是用来维护数据类型的数据,如下拉框、单选按钮、复选框、树选择的数据,方便系统管理员维护。减少对后端的访问,原来的下拉菜单点击一下就需要对后端进行访问,现在通过数据字典减少了对后端的访问。
如果不使用数据字典,对于每次查找的一些字段都要向后端发送请求。比如选择的时候 下拉框,因为数据都是动态选择的,不能直接输入。这样开发起来效率会很低。
数据库表结构
字典类型表
包括了 类型名称 、 字典类型需要是英文,status状态/
plsql
create table sys_dict_type
(
dict_id bigint auto_increment comment '字典主键'
primary key,
dict_name varchar(100) default '' null comment '字典名称',
dict_type varchar(100) default '' null comment '字典类型',
status char default '0' null comment '状态(0正常 1停用)',
create_by varchar(64) default '' null comment '创建者',
create_time datetime null comment '创建时间',
update_by varchar(64) default '' null comment '更新者',
update_time datetime null comment '更新时间',
remark varchar(500) null comment '备注',
constraint dict_type
unique ()
)
comment '字典类型表';
用到了label和value.
plsql
create table sys_dict_data
(
dict_code bigint auto_increment comment '字典编码'
primary key,
dict_sort int default 0 null comment '字典排序',
dict_label varchar(100) default '' null comment '字典标签',
dict_value varchar(100) default '' null comment '字典键值',
dict_type varchar(100) default '' null comment '字典类型',
css_class varchar(100) null comment '样式属性(其他样式扩展)',
list_class varchar(100) null comment '表格回显样式',
is_default char default 'N' null comment '是否默认(Y是 N否)',
status char default '0' null comment '状态(0正常 1停用)',
create_by varchar(64) default '' null comment '创建者',
create_time datetime null comment '创建时间',
update_by varchar(64) default '' null comment '更新者',
update_time datetime null comment '更新时间',
remark varchar(500) null comment '备注'
)
comment '字典数据表';
数据字典使用
在页面中获取数据字典:
vue
<script setup>
import {getCurrentInstance} from 'vue' 导入getCurrentInstance
const {proxy}=getCurrentInstance()
const {port_type} =proxy.useDict('port_type') //通过UseDict获取数据字典
</script>
<template>
<div v-for="item in port_type" :key="item.value" >
{{item.label}}:{{item.value}}
</div>
</template>
页面加载的时候像后端发送数据字典的请求。
vue
console.log(port_type.value) //就是一个Proxy数组
原理
前端
在main.js中导入了useDict。
并进行全局的挂载。
java
在 Vue 3 中,app.config.globalProperties 是一个可以让我们在 全局 为应用添加自定义属性或方法的对象。它的作用大致相当于 Vue 2 时代的 Vue.prototype。
当我们执行:
、
app.config.globalProperties.useDict = useDict
实际上就是给整个 Vue 应用的实例注入了一个名为 useDict 的方法,使得在任何组件实例里,都能够通过 this.useDict(在 Options API)或 proxy.useDict(在 Composition API 中通过 getCurrentInstance() 获取)去调用它。
拿到所有的数据字典。根据传进来的参数进行遍历字典,返回数据。
UseDictStore,对于某个页面的数据字典,会拿到之后存入到pinia中去,先看pinia中有没有数据,如果有就从pinia中拿,没有数据再去查询后端。
javascript
import useDictStore from '@/store/modules/dict'
import { getDicts } from '@/api/system/dict/data'
/**
* 获取字典数据
*/
export function useDict(...args) {
const res = ref({});
return (() => {
args.forEach((dictType, index) => {
res.value[dictType] = [];
const dicts = useDictStore().getDict(dictType);
if (dicts) {
res.value[dictType] = dicts;
} else {
getDicts(dictType).then(resp => {
res.value[dictType] = resp.data.map(p => ({ label: p.dictLabel, value: p.dictValue, elTagType: p.listClass, elTagClass: p.cssClass }))
useDictStore().setDict(dictType, res.value[dictType]);
})
}
})
return toRefs(res.value);
})()
}
向后端发送数据字典请求的代码
javascript
export function getDicts(dictType) {
return request({
url: '/system/dict/data/type/' + dictType,
method: 'get'
})
}
在pinia中存储字典数据
java
const useDictStore = defineStore(
'dict',
{
state: () => ({
dict: new Array()
}),
actions: {
// 获取字典
getDict(_key) {
if (_key == null && _key == "") {
return null;
}
try {
for (let i = 0; i < this.dict.length; i++) {
if (this.dict[i].key == _key) {
return this.dict[i].value;
}
}
} catch (e) {
return null;
}
},
// 设置字典
setDict(_key, value) {
if (_key !== null && _key !== "") {
this.dict.push({
key: _key,
value: value
});
}
},
// 删除字典
removeDict(_key) {
var bln = false;
try {
for (let i = 0; i < this.dict.length; i++) {
if (this.dict[i].key == _key) {
this.dict.splice(i, 1);
return true;
}
}
} catch (e) {
bln = false;
}
return bln;
},
// 清空字典
cleanDict() {
this.dict = new Array();
},
// 初始字典
initDict() {
}
}
})
export default useDictStore
持久化之后页面再次回来,不会发送请求了,而是直接从pinia中获取数据。
后端
在admin包下面 sysDictDataController
根据数据字典类型查询数据
java
@GetMapping(value = "/type/{dictType}")
public AjaxResult dictType(@PathVariable String dictType)
{
List<SysDictData> data = dictTypeService.selectDictDataByType(dictType);
if (StringUtils.isNull(data))
{
data = new ArrayList<SysDictData>();
}
return success(data);
}
这边代码做了一个缓存的操作,每次启动项目的时候都会将数据查询所有的数据字典,缓存到redis中去。
java
@Override
public List<SysDictData> selectDictDataByType(String dictType)
{
List<SysDictData> dictDatas = DictUtils.getDictCache(dictType); //拿到缓存的字典
if (StringUtils.isNotEmpty(dictDatas))
{
return dictDatas;
}
dictDatas = dictDataMapper.selectDictDataByType(dictType); //根据dictType查询数据库
if (StringUtils.isNotEmpty(dictDatas))
{
DictUtils.setDictCache(dictType, dictDatas);
return dictDatas;
}
return null;
}
缓存工具类
java
public static List<SysDictData> getDictCache(String key)
{
//拿到一个一个JSON树,将JSon数组转为List集合
JSONArray arrayCache = SpringUtils.getBean(RedisCache.class).getCacheObject(getCacheKey(key));
if (StringUtils.isNotNull(arrayCache))
{
return arrayCache.toList(SysDictData.class);
}
return null;
}
/**
* 获得缓存的基本对象。
*
* @param key 缓存键值
* @return 缓存键值对应的数据
*/
public <T> T getCacheObject(final String key)
{
ValueOperations<String, T> operation = redisTemplate.opsForValue();
return operation.get(key);
}
public static String getCacheKey(String configKey)
{
return CacheConstants.SYS_DICT_KEY + configKey;
}
public static final String SYS_DICT_KEY = "sys_dict:";
查看Redis缓存,发现存在数据字典。
删除redis中的数据字典,重新启动项目。发现数据字典又出来,说明项目启动的时候自动回去查询数据字典。
在SysDictTypeServiceImpl上面添加注解,这个注解可以让项目在启动的时候加载这个方法。
java
@PostConstruct//package javax.annotation; 这个javax的注解 加了这个注解之后 spring项目启动后会运行这个方法
public void init()
{
loadingDictCache();
}
java
@Override
public void loadingDictCache()
{
// 1. 构造一个条件对象(SysDictData),并设置 status = "0"
SysDictData dictData = new SysDictData();
dictData.setStatus("0");
// 2. 查询数据库中符合条件(status = "0")的字典数据,然后使用 Stream 流处理
Map<String, List<SysDictData>> dictDataMap = dictDataMapper
.selectDictDataList(dictData) // 2.1 从数据库中获取所有的字典数据
.stream() // 2.2 转换为 Stream
.collect( // 2.3 分组
Collectors.groupingBy(SysDictData::getDictType)
);
// 3. 遍历每一组字典数据(以 dictType 作为分组依据)
for (Map.Entry<String, List<SysDictData>> entry : dictDataMap.entrySet())
{
// 4. 按照某个排序字段(getDictSort)对每个分组内的字典数据进行排序,然后放进缓存
DictUtils.setDictCache(
entry.getKey(), // key: dictType
entry.getValue()
.stream()
.sorted(Comparator.comparing(SysDictData::getDictSort))
.collect(Collectors.toList())
);
}
}