UNPKG

@ithinkdt/core

Version:

iThinkDT Core

185 lines (159 loc) 5.63 kB
import { isRef, computed } from 'vue' // eslint-disable-next-line vue/prefer-import-from-vue import { isObject } from '@vue/shared' import { merge } from '@ithinkdt/common' import { useI18n } from '../../i18n' import { useDict } from '../../dict' import { getRender, getDictKey } from './render' function def(t, filed, value) { if (filed in t) return Object.defineProperty(t, filed, { value, enumerable: false, writable: false, configurable: false, }) } function fieldDec(decName, init) { return (value, ctx) => { if (ctx.kind === 'class' || ctx.kind === 'method') { console.warn(`${decName} Decorator 不能用在 class 或 method!`) } const initializer = init(value, ctx) ctx.addInitializer?.(initializer) if (ctx.kind === 'field') return initializer } } export function Label(label) { return fieldDec('Label', (_value, { name }) => { return function (value) { def(Object.getPrototypeOf(this).constructor, `__label_${name}`, label) return value } }) } export function Field(formatOrOptions) { return fieldDec('Field', (_value, { name }) => { const options = typeof formatOrOptions === 'string' ? { format: formatOrOptions } : formatOrOptions return function (value) { def(Object.getPrototypeOf(this).constructor, `__field_${name}`, options) return value } }) } function applyEntity(i18n, clazz) { if (!i18n) return let inst = i18n.inst if (!inst) { inst = () => useI18n('local', i18n) } inst = typeof inst === 'function' ? inst : () => inst let _inst const t = (k) => { if (!_inst) _inst = inst() const s = i18n.prefix ? `${i18n.prefix}.${k}` : k const _s = _inst.t(s) return _s === s ? (k.startsWith('_') ? t(k.slice(1)) : _s) : _s } const $t = (s) => { return computed(() => t(s)) } def(clazz, `__$t`, $t) const obj = new clazz() for (const k of Object.keys(obj)) { def(clazz, `__label_${k}`, $t(k)) } } export function Entity({ i18n } = {}) { return (value, { kind }) => { if (kind !== 'class') { console.warn(`Entity Decorator 不能用在 field 或 method!`) } applyEntity(i18n, value) } } export function analyzeEntity(EntityClass, { i18n } = {}) { applyEntity(i18n, EntityClass) function fi(name, type, requiredOrOptions, isSearchItem = false) { if (isRef(requiredOrOptions) || !isObject(requiredOrOptions)) { requiredOrOptions = requiredOrOptions === undefined ? {} : { required: requiredOrOptions, } } const $t = EntityClass[`__$t`] const field = EntityClass[`__field_${name}`] ?? {} const { dictKey, multiple } = getDictKey(field.format, field) if (dictKey) { const props = (requiredOrOptions.props ??= {}) if ('options' in props === false) { props.options = useDict(dictKey) } if ('multiple' in props === false) { props.multiple = multiple } } return { label: EntityClass[`__label_${name}`] ?? $t?.(name) ?? name, name, type, view: !isSearchItem && getRender( field?.format ?? (dictKey ? multiple ? `dicts` : `dict` : field?.name && ['createUser', 'updateUser'].includes(field.name) ? 'user' : 'string'), field, ), ...requiredOrOptions, } } return { fi, qi: (name, type, requiredOrOptions) => fi(name, type, requiredOrOptions, true), r: (name) => { const field = EntityClass[`__field_${name}`] ?? {} const { dictKey, multiple } = getDictKey(field.format, field) const render = getRender(field?.format ?? (dictKey ? (multiple ? `dicts` : `dict`) : 'string'), field) return (v, model) => render(v, { model }) }, col(name, widthOrOptions) { if (isRef(widthOrOptions) || !isObject(widthOrOptions)) { widthOrOptions = widthOrOptions === undefined ? {} : { width: widthOrOptions, } } const $t = EntityClass[`__$t`] const field = EntityClass[`__field_${name}`] ?? {} const { dictKey, multiple } = getDictKey(field.format, field) return { label: EntityClass[`__label_${name}`] ?? $t?.(name) ?? name, key: name, ...merge( { format: dictKey ? multiple ? `dicts` : `dict` : ['createUser', 'updateUser'].includes(name) ? 'user' : 'string', dictKey, }, field || {}, widthOrOptions, ), } }, } }