基于JEECG制作一个通用的级联字典选择控件-DictCascadeUniversal

11 篇文章 1 订阅

字典是所有MIS系统不可缺少的重要组成部分。为减少输入,标准化输入内容,使得数据更加准确地被输入。往往需要在数据库中配置各种各样的字典表。如下图:

而绝大部分字典的字段简单,且高度一致。建议一个通用的字典表,并设计一个灵活度高的字典选择控件能大大提高效率。很多低代码开发平台提供了基础字典的通用方式,但灵活度上稍有欠缺,如:显示效果不好,不能管理级联(树状)字典信息……以JEECG所提供的字典管理为例,如下图所示:

针对上面两个问题,进行一个方便管理,方便自定义的通用字典选择控件

(1)数据库表设计

(2)具体效果

(3)使用配置

(4)效果展示

目前共配置了4种方式,可通过对组件的修改,不断增加选择样式。获取值通过@getSelectedItem方法,获取的是对象,属性丰富。如下:

复选框获取值

单选框获取值

下拉框获取值

下拉树获取值

(5)代码下载

见有道云笔记(下面的代码端是图太多发不了文章凑字的,直接下载有道云笔记里的代码文件即可,欢迎交流)

有道云笔记

数据库表结构,放置于boot数据库

/*
 Navicat MySQL Data Transfer

 Source Server         : 116.62.233.186
 Source Server Type    : MySQL
 Source Server Version : 50737
 Source Host           : 116.62.233.186:3306
 Source Schema         : hanlin_boot

 Target Server Type    : MySQL
 Target Server Version : 50737
 File Encoding         : 65001

 Date: 23/07/2022 16:13:36
*/

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for dict_cascade_universal
-- ----------------------------
DROP TABLE IF EXISTS `dict_cascade_universal`;
CREATE TABLE `dict_cascade_universal`  (
  `id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  `create_by` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建人',
  `create_time` datetime NULL DEFAULT NULL COMMENT '创建日期',
  `update_by` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新人',
  `update_time` datetime NULL DEFAULT NULL COMMENT '更新日期',
  `sys_org_code` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '所属部门',
  `pid` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '父级节点',
  `has_child` varchar(3) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '是否有子节点',
  `name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '名称',
  `show_order` int(11) NULL DEFAULT NULL COMMENT '显示顺序',
  `comment` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '备注',
  `del_flag` int(11) NULL DEFAULT 0 COMMENT '是否删除',
  `path` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '路径',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;

SET FOREIGN_KEY_CHECKS = 1;

组件文件:放置于前端component任意文件夹处

<template>
  <div>
    <div v-if='controlType=="弹出窗口树"'>
      hello,树
    </div>
    <div v-else-if='controlType=="dropdown"'>
      <a-select @change="onChange" style="width: 220px" v-model='selectedItemId'>
        <a-select-option v-for='item in options' :value="item.key">
          {{ item.title }}
        </a-select-option>
      </a-select>
<!--      {{selectedItems}}-->
    </div>
    <div v-else-if='controlType=="treeSelect_single"'>
      <a-tree-select
        v-model="selectedItemId"
        style="width: 100%"
        :dropdown-style="{ maxHeight: '300px', overflow: 'auto' }"
        :tree-data="options"
        :placeholder="placeholder"
        @change='onChange'
      >
      </a-tree-select>
<!--      {{selectedItems}}-->
    </div>
    <div v-else-if='controlType=="radiobox_group"'>
      <a-radio-group name="radioGroup" v-model='selectedItems' @change="onChange">
        <a-radio v-for="item in options" :value="item">
          {{item.title}}
        </a-radio>
      </a-radio-group>

<!--      {{selectedItems}}-->
    </div>
    <div v-else-if='controlType=="checkbox_group"'>
      <a-checkbox-group @change="onChange" v-model='selectedItems'>
        <a-checkbox v-for='item in options' :value="item">
          {{item.title}}
        </a-checkbox>
      </a-checkbox-group>
<!--      {{selectedItems}}-->
    </div>
    <div v-else>
      请配置控件类型
    </div>
  </div>
</template>

<script>
import { httpAction, getAction, postAction } from '@/api/manage'

export default {
  name: 'KingDictCascadeUniversal',
  props: {
    DictRootId: '',
    controlType: '',//弹出窗口树、下拉菜单、下拉树菜单、单选框、复选框
    placeholder:''
  },
  data() {
    return {
      dictName: '',
      dictPath: '',
      dictId: '',
      options:[],
      selectedItems:[],
      selectedItemId:""
    }
  },
  methods: {
    getArrayItem(arr){
      let that = this
      arr.forEach(function(arrItem){
        if (arrItem.key === that.selectedItemId) {
          that.selectedItems = arrItem
          that.selectedItems.children=[]
          return
        }

        if (arrItem.children != null && arrItem.children.length > 0) {
          that.getArrayItem(arrItem.children)
        }
      })
    },
    onChange:function(){
      //region 获取对象信息 selectedItems
      let that = this
      switch(this.controlType){
        case "dropdown":
          let rsArr = this.options.filter(function(item){
            return item.key === that.selectedItemId
          })
          this.selectedItems = rsArr[0]
          break
        case "treeSelect_single":

          this.getArrayItem(this.options)
          break
      }
      //endregion

      this.$emit('getSelectedItems', this.selectedItems)
    },
    getTreeNodes(arr, pid, rootNode){
      debugger
      let that = this

      let parentNodes = arr.filter(function(item){
        return item.pid === pid
      })

      parentNodes.forEach(function(item) {
        let optionObj = new Object();
        optionObj.key = item.id
        optionObj.value = item.id
        optionObj.title = item.name
        optionObj.path = item.path

        if(rootNode == null){
          optionObj.children = []
          that.options.push(optionObj)
        }
        else{
          rootNode.children.push(optionObj)
        }
        that.getTreeNodes(arr, optionObj.key, optionObj)
      })
    }
  },
  created(){
    let that = this
    this.options = []
    let params = new Object()
    params.rootID = this.DictRootId

    getAction('/jeecg-system/kingsystem/dictCascadeUniversal/getAllNodesFromRoot', params).then(function(res) {
      if(that.DictRootId == "-1")
      {
        that.DictRootId = "0"
      }
      that.getTreeNodes(res, that.DictRootId, null)
    })
  }
}
</script>

<style scoped>

</style>

 调用示例:放置于views下任意文件夹后端

<template>
  <div>
    <kingDictCascadeUniversal DictRootId='1550011878280650753' controlType='dropdown' @getSelectedItems='getSelectedValue'></kingDictCascadeUniversal>
    <br>

    <kingDictCascadeUniversal DictRootId='1550011878280650753' controlType='checkbox_group' @getSelectedItems='getSelectedValue'></kingDictCascadeUniversal>
    <br>
    <kingDictCascadeUniversal DictRootId='1550011911256268801' controlType='radiobox_group' @getSelectedItems='getSelectedValue'></kingDictCascadeUniversal>

    <br>
    <kingDictCascadeUniversal DictRootId='1550744481837195266' controlType='treeSelect_single' style='width:200px' placeholder='请选择' @getSelectedItems='getSelectedValue'></kingDictCascadeUniversal>

    {{selectedItems}}
  </div>
</template>
<script>
import kingDictCascadeUniversal from '@comp/kingsystem/KingDictCascadeUinversal/KingDictCascadeUniversal'
export default {
  components: {
    kingDictCascadeUniversal,
  },
  data(){
    return {
      selectedItems:{}
    }
  },
  methods:{
    getSelectedValue(rs){
      this.selectedItems = rs
    }
  }
};
</script>

后端代码:根据jeecg,按需自动生成。或通过mybatisplus生成(略) 

Vue级联选择器使用v-model来实现双向数据绑定。v-model指令在内部使用了value和input事件,使得父组件能够通过v-model来控制子组件的值,并且子组件的值的变化也可以反馈给父组件。 在级联选择器的父组件中,你可以使用v-model来绑定一个变量,这个变量将会被用来存储当前所选的值。例如: ```html <template> <div> <cascade-selector v-model="selectedValue"></cascade-selector> </div> </template> <script> import CascadeSelector from './CascadeSelector.vue'; export default { components: { CascadeSelector }, data() { return { selectedValue: '' }; } } </script> ``` 在子组件CascadeSelector中,你可以使用props接收父组件传递的值,并在选择发生变化时,通过$emit('input', value)来触发父组件的input事件,从而更新父组件的数据。例如: ```html <template> <div> <select v-model="selected" @change="handleChange"> <option value="">请选择</option> <option v-for="item in options" :value="item.value" :key="item.value">{{ item.label }}</option> </select> </div> </template> <script> export default { props: ['value'], data() { return { selected: '' }; }, computed: { options() { // 返回级联选择器的选项数据 } }, mounted() { // 初始化选中值 this.selected = this.value; }, methods: { handleChange() { this.$emit('input', this.selected); } } } </script> ``` 这样,父组件和子组件之间就建立了双向数据绑定,父组件中的selectedValue会随着子组件的选择发生变化而更新。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值