parent
23270c60bc
commit
12ab8b03d9
@ -0,0 +1,21 @@ |
|||||||
|
import Vue from 'vue' |
||||||
|
import DataDict from '@/utils/dict' |
||||||
|
import { getDicts as getDicts } from '@/api/system/dict/data' |
||||||
|
|
||||||
|
function install() { |
||||||
|
Vue.use(DataDict, { |
||||||
|
metas: { |
||||||
|
'*': { |
||||||
|
labelField: 'dictLabel', |
||||||
|
valueField: 'dictValue', |
||||||
|
request(dictMeta) { |
||||||
|
return getDicts(dictMeta.type).then(res => res.data) |
||||||
|
}, |
||||||
|
}, |
||||||
|
}, |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
export default { |
||||||
|
install, |
||||||
|
} |
@ -0,0 +1,82 @@ |
|||||||
|
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) { |
||||||
|
if (options instanceof Array) { |
||||||
|
options = { types: options } |
||||||
|
} |
||||||
|
const opts = mergeRecursive(DEFAULT_DICT_OPTIONS, options) |
||||||
|
if (opts.types === undefined) { |
||||||
|
throw new Error('need dict types') |
||||||
|
} |
||||||
|
const ps = [] |
||||||
|
this._dictMetas = opts.types.map(t => DictMeta.parse(t)) |
||||||
|
this._dictMetas.forEach(dictMeta => { |
||||||
|
const type = dictMeta.type |
||||||
|
Vue.set(this.label, type, {}) |
||||||
|
Vue.set(this.type, type, []) |
||||||
|
if (dictMeta.lazy) { |
||||||
|
return |
||||||
|
} |
||||||
|
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 |
||||||
|
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.label) |
||||||
|
}) |
||||||
|
return dicts |
||||||
|
}) |
||||||
|
} |
@ -0,0 +1,17 @@ |
|||||||
|
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) { |
||||||
|
return fields.find(f => Object.prototype.hasOwnProperty.call(dict, f)) |
||||||
|
} |
@ -0,0 +1,13 @@ |
|||||||
|
/** |
||||||
|
* @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 |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,38 @@ |
|||||||
|
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 |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* 解析字典元数据 |
||||||
|
* @param {Object} options |
||||||
|
* @returns {DictMeta} |
||||||
|
*/ |
||||||
|
DictMeta.parse= function(options) { |
||||||
|
let opts = null |
||||||
|
if (typeof options === 'string') { |
||||||
|
opts = DictOptions.metas[options] || {} |
||||||
|
opts.type = options |
||||||
|
} else if (typeof options === 'object') { |
||||||
|
opts = options |
||||||
|
} |
||||||
|
opts = mergeRecursive(DictOptions.metas['*'], opts) |
||||||
|
return new DictMeta(opts) |
||||||
|
} |
@ -0,0 +1,51 @@ |
|||||||
|
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 |
@ -0,0 +1,33 @@ |
|||||||
|
import Dict from './Dict' |
||||||
|
import { mergeOptions } from './DictOptions' |
||||||
|
|
||||||
|
export default function(Vue, options) { |
||||||
|
mergeOptions(options) |
||||||
|
Vue.mixin({ |
||||||
|
data() { |
||||||
|
if (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 |
||||||
|
} |
||||||
|
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) |
||||||
|
if (this.$options.methods && this.$options.methods.onDictReady instanceof Function) { |
||||||
|
this.$options.methods.onDictReady.call(this, this.dict) |
||||||
|
} |
||||||
|
}) |
||||||
|
}) |
||||||
|
}, |
||||||
|
}) |
||||||
|
} |
Loading…
Reference in new issue