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'],
8548

被折叠的 条评论
为什么被折叠?



