@ithinkdt/core
Version:
iThinkDT Core
287 lines (253 loc) • 10.4 kB
JavaScript
import { h, isRef, unref, reactive } from 'vue'
import { getDict, registerDict } from '../../dict'
import { i18n } from '../../i18n'
import { pageInit } from '../plugin'
import { datetime, number } from './helper'
export function getRender(format, field) {
const [t, p] = (format || (field.name === 'createUser' || field.name === 'updateUser' ? 'user' : 'string')).split(
'|',
)
let factory = pageInit.dataFormatters?.[t]
if (factory?.factory) {
factory = factory.factory
}
if (!factory) factory = defaultFormatter[t]
let _render = factory?.(field, p)
if (!_render) {
console.warn('数据格式化,未注册的 format:', t)
_render = RenderFactory.string()
}
if (field.render) {
return (v, options) => field.render(v, { ...options, render: () => _render(v, options) })
}
return _render
}
export const RenderFactory = {
string: () => (v) => v,
text: (whiteSpace) => (v) =>
h('div', {
innerText: v,
style: {
whiteSpace,
},
}),
url: () => (url) => h('a', { href: url }, [url]),
email: () => (email) => h('a', { href: `mailto:${email}` }, [email]),
color: () => (color) =>
h('span', [
h('span', { style: { display: 'inline-block', width: '1em', height: '1em', background: color } }),
color,
]),
datetime: (fmt) => (v) => datetime(v, fmt),
number: (digits, trim) => (v) => number(v, digits, ',', !!trim),
percent: (digits, trim) => (v) => {
const s = number(v ? v * 100 : v, digits, ',', !!trim)
return typeof s === 'string' ? `${s}%` : s
},
yesno: () => (v) => {
return ['1', 1, true].includes(v) ? i18n.t('sys.yes') : i18n.t('sys.no')
},
file: () => (v) => {
let ids = Array.isArray(v) ? v : v?.trim() ? v.trim().split(',') : []
return ids.length > 0 ? pageInit.renderFiles(ids) : ''
},
image: () => (v) => {
let ids = Array.isArray(v) ? v : v?.trim() ? v.trim().split(',') : []
return ids.length > 0 ? pageInit.renderImages(ids) : ''
},
icon: () => (v) => {
v = pageInit.getIconRender(v)
return v
? h(v, {
style: {
fontSize: '48px',
},
})
: ''
},
user: ({ multiple, max, size, placement } = {}) => {
const map = {}
return (v) => {
const usernames = v ? (multiple ? (Array.isArray(v) ? v : v.trim() ? v.trim().split(',') : []) : [v]) : []
const users = reactive([])
const usernames1 = []
for (const [i, name] of usernames.entries()) {
if (!map[name]) {
const u = reactive({ username: name, nickname: name })
map[name] = u
usernames1.push(name)
}
users[i] = map[name]
}
if (usernames1.length > 0) {
pageInit.getUsers(usernames1).then((data) => {
for (const it of data) {
Object.assign(map[it.username], it)
}
})
}
return pageInit.renderUsers(users, { max, size, placement })
}
},
dept: ({ multiple } = {}) => {
const map = {}
return (v) => {
const deptcodes = v ? (multiple ? (Array.isArray(v) ? v : v.trim() ? v.trim().split(',') : []) : [v]) : []
const depts = reactive([])
const deptcodes1 = []
for (const [i, code] of deptcodes.entries()) {
if (!map[code]) {
const d = reactive({ code, name: code })
map[code] = d
deptcodes1.push(code)
}
depts[i] = map[code]
}
if (deptcodes1.length > 0) {
pageInit.getDepts(deptcodes1).then((data) => {
for (const it of data) {
Object.assign(map[it.code], it)
}
})
}
return pageInit.renderDepts(depts)
}
},
dict: (dictKey, { multiple } = {}) => {
let getDictMap
if (typeof dictKey === 'string' || isRef(dictKey)) {
const dictMap = getDict(dictKey, 'map', 'string', false, false)
getDictMap = () => dictMap
} else {
getDictMap = (value, model) => getDict(dictKey({ model, value }), 'map', 'string', false, false)
}
let it = (v, { model }) => {
const dictMap = getDictMap(v, model)
return dictMap.get(v?.toString())?.label ?? v
}
return multiple
? (v, data) => {
return (Array.isArray(v) ? v : v?.trim() ? v.trim().split(',') : [])
.map((s) => it(s, data))
.join(i18n.t('sys.joinSeparator'))
}
: it
},
state: (dictKey, state) => {
let getDictMap
if (typeof dictKey === 'string' || isRef(dictKey)) {
const dictMap = getDict(dictKey, 'map', 'string', false, false)
getDictMap = () => dictMap
} else {
getDictMap = (value, model) => getDict(dictKey({ model, value }), 'map', 'string', false, false)
}
const _state = state
state = _state
? typeof _state === 'object'
? (v) => _state[v]
: (value, model, dict) => _state({ model, value, dict })
: () => 'primary'
return (v, { model }) => {
const dict = getDictMap?.(v, model).get(v?.toString())
return pageInit.renderState({ text: dict?.label ?? v, type: state(v, model, dict) })
}
},
tag: (tag, { dictKey, multiple } = {}) => {
let getDictMap
if (dictKey) {
if (typeof dictKey === 'string' || isRef(dictKey)) {
const dictMap = getDict(dictKey, 'map', 'string', false, false)
getDictMap = () => dictMap
} else {
getDictMap = (value, model) => getDict(dictKey({ model, value }), 'map', 'string', false, false)
}
}
const _tag = tag
tag = _tag
? typeof _tag === 'string'
? () => ({ type: _tag })
: typeof _tag === 'object'
? (v) => ({ type: _tag[v] })
: (value, model, index, dict) => {
const ret = _tag({ model, value, index, dict }) ?? {}
if (typeof ret !== 'object') {
return {
type: ret,
}
}
return ret
}
: () => ({ type: 'primary' })
const it = (v, { model = {} } = {}, index, isLast = true) => {
const dict = getDictMap?.(v, model)?.get(v?.toString())
return pageInit.renderTag({
...tag(v, model, index, dict),
text: dict?.label ?? v,
style: {
margin: `4.5px ${isLast ? '0' : '10px'} 4.5px 0`,
},
})
}
return multiple
? (v, data) => {
return (Array.isArray(v) ? v : v?.trim() ? v.trim().split(',') : []).map((s, i, arr) =>
it(s, data, i, i === arr.length - 1),
)
}
: it
},
operation: (btns, { width } = {}) => {
return (_v, { model, index }) => {
return pageInit.renderTableBtns({ model, index, btns: unref(btns), width: unref(width) })
}
},
}
export const defaultFormatter = {
string: () => RenderFactory.string(),
text: (_, param = '') => RenderFactory.text(param || 'pre-wrap'),
email: () => RenderFactory.email(),
url: () => RenderFactory.url(),
color: () => RenderFactory.color(),
date: (_, param = '') => RenderFactory.datetime(param || 'yyyy-MM-dd'),
datetime: (_, param = '') => RenderFactory.datetime(param || 'yyyy-MM-dd HH:mm:ss'),
yesno: () => RenderFactory.yesno(),
number: (_, param = '') => {
let [digits, trim] = param.split('!')
digits = Number.parseInt(digits)
return RenderFactory.number(digits, ',', typeof trim !== 'string')
},
percent: (_, param = '') => {
let [digits, trim] = param.split('!')
digits = Number.parseInt(digits)
return RenderFactory.percent(digits, ',', typeof trim !== 'string')
},
file: () => RenderFactory.file(),
image: () => RenderFactory.image(),
icon: () => RenderFactory.icon(),
dict: ({ dictKey }, param = '') => RenderFactory.dict(param || dictKey, { multiple: false }),
dicts: ({ dictKey }, param = '') => RenderFactory.dict(param || dictKey, { multiple: true }),
state: ({ dictKey, state }, param = '') => RenderFactory.state(param || dictKey, state),
tag: ({ dictKey, tag }, param = '') => RenderFactory.tag(tag, { dictKey: param || dictKey, multiple: false }),
tags: ({ dictKey, tag }, param = '') => RenderFactory.tag(tag, { dictKey: param || dictKey, multiple: true }),
operation: ({ btns, max, width }) => RenderFactory.operation(btns, { max, width }),
user: () => RenderFactory.user({ multiple: false }),
users: (_, param = '') => RenderFactory.user({ multiple: true, max: (param && Number.parseInt(param)) || 4 }),
dept: () => RenderFactory.dept({ multiple: false }),
depts: () => RenderFactory.dept({ multiple: true }),
}
export function getDictKey(format, { dictKey, dicts = [], multiple }) {
if (dictKey) return { dictKey, multiple }
if (format === 'yesno') return { dictKey: 'yes-no' }
if (format?.startsWith('dict') || format?.startsWith('tag') || format?.startsWith('state')) {
dictKey = format.split('|')[1]
if (!dictKey) {
dictKey = Date.now() + '-' + Math.floor(Math.random() * 1_000_000)
registerDict(dictKey, dicts)
}
return {
dictKey,
multiple: format.startsWith('dicts') || format.startsWith('tags') ? true : undefined,
}
}
return {}
}