ruoyi dicts的使用

uniapp 同样也可以使用dicts

dict目录文件

dict.js

import Vue from 'vue'
import { mergeRecursive } from "@/utils/ruoyi";
import DictMeta from './DictMeta'
import DictData from './DictData'

// 默认选项集合
const DEFAULT_DICT_OPTIONS = {
  types: [],
}

/**
 *
 * @classdesc 字典
 * @property {Object} label 标签对象,内部属性名为字典类型名称
 * @property {Object} dict 字段数组,内部属性名为字典类型名称
 * @property {Array.<DictMeta>} _dictMetas 字典元数据数组
 */
export default class Dict {
  // 构造器
  constructor() {
    this.owner = null
    this.label = {}
    this.type = {}
  }

  init(options) {
    // 选项为数组转为 types
    if (options instanceof Array) {
      options = { types: options }
    }
    // 合并types对象
    const opts = mergeRecursive(DEFAULT_DICT_OPTIONS, options)
    // 没有获取到数据抛出异常
    if (opts.types === undefined) {
      throw new Error('need dict types')
    }
    //
    const ps = []
    // 构建为 DictMeta 对象存入 _dictMetas
    this._dictMetas = opts.types.map(t => DictMeta.parse(t))
    // 循环处理_dictMetas, 初始化 DictMeta
    this._dictMetas.forEach(dictMeta => {
      // dicts 传入的名称
      const type = dictMeta.type
      // dict.label添加属性 dictName:{}   label:{"dictName":{}},type:{dictType: []}
      Vue.set(this.label, type, {})
      //dict.type 添加属性 dictName:[]
      Vue.set(this.type, type, [])
      if (dictMeta.lazy) {
        // 延迟加载
        return
      }
      // 执行请求,将数据组装到dict元数据汇总
      ps.push(loadDict(this, dictMeta))
    })
    return Promise.all(ps)
  }

  /**
   * 重新加载字典
   * @param {String} type 字典类型
   */
  reloadDict(type) {
    const dictMeta = this._dictMetas.find(e => e.type === type)
    if (dictMeta === undefined) {
      return Promise.reject(`the dict meta of ${type} was not found`)
    }
    return loadDict(this, dictMeta)
  }
}

/**
 * 加载字典
 * @param {Dict} dict 字典
 * @param {DictMeta} dictMeta 字典元数据
 * @returns {Promise}
 */
function loadDict(dict, dictMeta) {
  return dictMeta.request(dictMeta)
    .then(response => {
      const type = dictMeta.type
      console.log(type)
      // 将response转换成DictData
      let dicts = dictMeta.responseConverter(response, dictMeta)
      if (!(dicts instanceof Array)) {
        console.error('the return of responseConverter must be Array.<DictData>')
        dicts = []
      } else if (dicts.filter(d => d instanceof DictData).length !== dicts.length) {
        console.error('the type of elements in dicts must be DictData')
        dicts = []
      }
      //将response的数据插入到dict.type['dictName']的数组中
      //splice实现了响应式改变数组元素,所以这里不用vue.set  type:{dictType: [{dicts[0]},{dicts[1]} ]}
      dict.type[type].splice(0, Number.MAX_SAFE_INTEGER, ...dicts)
      //将dicts(也就是dictData)赋值给dict.type[type]
      dicts.forEach(d => {
        //dict.label{'dictName':{}}添加属性d.value:d.label
        // label:{"dictName":{d.value: d.label}
        Vue.set(dict.label[type], d.value, d.label)
      })
      console.log(dicts)
      return dicts
    })
}

DictConverter.js


import DictOptions from './DictOptions'
import DictData from './DictData'

export default function(dict, dictMeta) {
  const label = determineDictField(dict, dictMeta.labelField, ...DictOptions.DEFAULT_LABEL_FIELDS)
  const value = determineDictField(dict, dictMeta.valueField, ...DictOptions.DEFAULT_VALUE_FIELDS)
  return new DictData(dict[label], dict[value], dict)
}

/**
 * 确定字典字段
 * @param {DictData} dict
 * @param  {...String} fields
 */
function determineDictField(dict, ...fields) {
  //find 符合条件的第一个元素     call对象是否存在 某个属性
  return fields.find(f => Object.prototype.hasOwnProperty.call(dict, f))
}

DictData.js

/**
 * 最后元数据内的dict成品
 * @classdesc 字典数据
 * @property {String} label 标签
 * @property {*} value 标签
 * @property {Object} raw 原始数据
 */
export default class DictData {
  constructor(label, value, raw) {
    this.label = label
    this.value = value
    this.raw = raw
  }
}

DictMeta.js

import { mergeRecursive } from "@/utils/ruoyi";
import DictOptions from './DictOptions'

/**
 * @classdesc 字典元数据
 * @property {String} type 类型
 * @property {Function} request 请求
 * @property {String} label 标签字段
 * @property {String} value 值字段
 */
export default class DictMeta {
  constructor(options) {
    this.type = options.type
    this.request = options.request
    this.responseConverter = options.responseConverter
    this.labelField = options.labelField
    this.valueField = options.valueField
    this.lazy = options.lazy === true
  }
}

DictMeta.js
/**
 * 解析字典元数据
 * @param {Object} options
 * @returns {DictMeta}
 */
DictMeta.parse= function(options) {
  let opts = null
  if (typeof options === 'string') {
    // 解析元数据
    opts = DictOptions.metas[options] || {}
    // 获取元数据 key为options的属性
    opts.type = options
  } else if (typeof options === 'object') {
    // 如果是对象 直接设置
    opts = options
  }
  //创建{type:'字典名称"}并且赋值给DictOptions.meta属性
  opts = mergeRecursive(DictOptions.metas['*'], opts)
  //构造dictmeta原数据
  return new DictMeta(opts)
}

DictOptions.js

import { mergeRecursive } from "@/utils/ruoyi";
import dictConverter from './DictConverter'

export const options = {
  metas: {
    '*': {
      /**
       * 字典请求,方法签名为function(dictMeta: DictMeta): Promise
       */
      request: (dictMeta) => {
        console.log(`load dict ${dictMeta.type}`)
        return Promise.resolve([])
      },
      /**
       * 字典响应数据转换器,方法签名为function(response: Object, dictMeta: DictMeta): DictData
       */
      responseConverter,
      labelField: 'label',
      valueField: 'value',
    },
  },
  /**
   * 默认标签字段
   */
  DEFAULT_LABEL_FIELDS: ['label', 'name', 'title'],
  /**
   * 默认值字段
   */
  DEFAULT_VALUE_FIELDS: ['value', 'id', 'uid', 'key'],
}

/**
 * 映射字典
 * @param {Object} response 字典数据
 * @param {DictMeta} dictMeta 字典元数据
 * @returns {DictData}
 */
function responseConverter(response, dictMeta) {
  const dicts = response.content instanceof Array ? response.content : response
  if (dicts === undefined) {
    console.warn(`no dict data of "${dictMeta.type}" found in the response`)
    return []
  }
  // 返回处理后的集合
  return dicts.map(d => dictConverter(d, dictMeta))
}

export function mergeOptions(src) {
  mergeRecursive(options, src)
}

export default options

index.js

import Dict from './Dict'
import { mergeOptions } from './DictOptions'

export default function(Vue, options) {
  mergeOptions(options)
  Vue.mixin({
    data() {
      if (this.$options === undefined || this.$options.dicts === undefined || this.$options.dicts === null) {
        return {}
      }
      const dict = new Dict()
      dict.owner = this
      return {
        dict
      }
    },
    created() {
      if (!(this.dict instanceof Dict)) {
        return
      }
      // 参数存在onCreated就执行后面
      options.onCreated && options.onCreated(this.dict)
      this.dict.init(this.$options.dicts).then(() => {
        // 参数存在就执行后
        options.onReady && options.onReady(this.dict)
        // 扩展方法
        this.$nextTick(() => {
          // 通知方法
          this.$emit('dictReady', this.dict)
          // 当前组件是否存在 onDictReady方法,并且是个函数
          if (this.$options.methods && this.$options.methods.onDictReady instanceof Function) {
            // call 调用,传入当前dict对像
            this.$options.methods.onDictReady.call(this, this.dict)
          }
        })
      })
    },
  })
}

DictData目录文件

index.js

import Vue from 'vue'
import store from '@/store'
import DataDict from '@/utils/dict'
import { getDicts as getDicts } from '@/api/system/dict/data'

// 查询dict
function searchDictByKey(dict, key) {
  if (key == null && key == "") {
    return null
  }
  try {
    for (let i = 0; i < dict.length; i++) {
      if (dict[i].key == key) {
        return dict[i].value
      }
    }
  } catch (e) {
    return null
  }
}

// install函数,
function install() {
  Vue.use(DataDict, {
    metas: {
      '*': {
        labelField: 'dictLabel',
        valueField: 'dictValue',
        request(dictMeta) {
          const storeDict = searchDictByKey(store.getters.dict, dictMeta.type)
          if (storeDict) {
            return new Promise(resolve => { resolve(storeDict) })
          } else {
            return new Promise((resolve, reject) => {
              getDicts(dictMeta.type).then(res => {
                store.dispatch('dict/setDict', { key: dictMeta.type, value: res.data })
                resolve(res.data)
              }).catch(error => {
                reject(error)
              })
            })
          }
        },
      },
    },
  })
}

export default {
  install,
}

uniapp 使用实例(个别文件)

注意因为我用的是uni-ui组件库,所以key值是text({text:‘’,value:‘’}),如果key是label就不需要下面几部修改,直接按照原有的赋值就可以,当然如果需要改key和value的键名可以按照一下方式修改

1. 安装vue-meta

import VueMeta from 'vue-meta'
Vue.use(VueMeta)

2. 改字典key值

其他的文件按照ruoyi的方式加上就可以

Dict.js

function loadDict(dict, dictMeta) {
  return dictMeta.request(dictMeta)
    .then(response => {
      const type = dictMeta.type
      let dicts = dictMeta.responseConverter(response, dictMeta)
      if (!(dicts instanceof Array)) {
        console.error('the return of responseConverter must be Array.<DictData>')
        dicts = []
      } else if (dicts.filter(d => d instanceof DictData).length !== dicts.length) {
        console.error('the type of elements in dicts must be DictData')
        dicts = []
      }
      dict.type[type].splice(0, Number.MAX_SAFE_INTEGER, ...dicts)
      dicts.forEach(d => {
        Vue.set(dict.label[type], d.value, d.text)
      })
      return dicts
    })
}

DictData.js

/**
 * @classdesc 字典数据
 * @property {String} text 标签
 * @property {*} value 标签
 * @property {Object} raw 原始数据
 */
export default class DictData {
  constructor(text, value, raw) {
    this.text = text
    this.value = value
    this.raw = raw
  }
}

DictOptions

  /**
   * 默认标签字段
   */
  DEFAULT_LABEL_FIELDS: ['text','label', 'name', 'title'],
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值