jobsys-mpower
Version:
Enhanced component based on Taro & NutUI
265 lines (243 loc) • 7.94 kB
JSX
import { inject } from "vue"
import { MP__UPLOADER } from "../provider/MpProvider.jsx"
import { isBoolean, isFunction, isString, pick } from "lodash-es"
import MpField from "./MpField.jsx"
import MpSelect from "./MpSelect.jsx"
import MpDate from "./MpDate.jsx"
import MpSwitch from "./MpSwitch.jsx"
import MpCheckbox from "./MpCheckbox.jsx"
import MpRadio from "./MpRadio.jsx"
import MpDatetime from "./MpDatetime.jsx"
import MpNumber from "./MpNumber.jsx"
import MpRate from "./MpRate.jsx"
import MpSlider from "./MpSlider.jsx"
import MpAddress from "./MpAddress.jsx"
import MpCascader from "./MpCascader.jsx"
import MpTime from "./MpTime.jsx"
import MpFieldUploader from "./MpFieldUploader.jsx"
/**
*
* @param item
* @param submitForm
* @param props
* @param slots
* @return {*|JSX.Element}
*/
const render = (item, submitForm, { props, slots }) => {
const uploaderProvider = inject(MP__UPLOADER, () => ({}))
if (item.type === "slot" && slots[item.key]) {
return slots[item.key]({ submitForm })
}
let renderItem = null
const pickerTypes = ["select", "date", "datetime", "time", "address", "cascade"]
const isPicker = pickerTypes.includes(item.type)
// 处理 hidden
if ((isFunction(item.hidden) && item.hidden(submitForm)) || (isBoolean(item.hidden) && item.hidden)) {
return null
}
// MpField 的 props
let fieldProps = pick(item, ["placeholder", "help", "required", "disabled", "rules", "readonly", "isLink", "fieldProps"])
fieldProps.required = isFunction(fieldProps.required) ? fieldProps.required(submitForm) : fieldProps.required
fieldProps.disabled = isFunction(fieldProps.disabled) ? fieldProps.disabled(submitForm) : fieldProps.disabled
fieldProps = { readonly: props.readonly, disabled: props.disabled, ...fieldProps }
if (fieldProps.readonly || fieldProps.disabled) {
fieldProps.required = false
}
fieldProps.label = item.title
fieldProps.name = item.key
fieldProps.placeholder = fieldProps.placeholder || (isPicker ? `请选择${item.title}` : `请填写${item.title}`)
fieldProps.rules = fieldProps.rules?.length
? fieldProps.rules.map((rule) => {
if (rule.pattern) {
return {
...rule,
pattern: new RegExp(rule.pattern),
}
}
return { ...rule }
})
: []
// 具体组件的 props
const componentProps = pick(item, ["options", "defaultProps"])
//混合了Field和input slot组件的slots组合
const componentSlots = item.defaultSlots || {}
item.type = item.type ? item.type.toLowerCase() : item.type
//特殊:readonly 的情况下不显示 required
if (fieldProps.required) {
fieldProps.rules.push({
required: true,
message: isPicker ? `请选择${item.title}` : `请填写${item.title}`,
trigger: isPicker ? "onChange" : "onBlur", //特意
})
}
//特殊:readonly 情况下不显示 placeholder
if (fieldProps.readonly || fieldProps.disabled) {
fieldProps.placeholder = "--"
}
if (item.customRender) {
renderItem = item.customRender({ submitForm, item })
if (!renderItem) {
return null
}
} else if (item.match) {
// 匹配模式, 合并选项后需要移除 match
const matchItem = { ...item, ...item.match(submitForm), match: null }
return render(matchItem, submitForm, { props, slots })
} else {
switch (item.type) {
case "select":
renderItem = (
<MpSelect v-model={submitForm[item.key]} {...componentProps} {...fieldProps}>
{componentSlots}
</MpSelect>
)
break
case "date":
renderItem = (
<MpDate v-model={submitForm[item.key]} {...componentProps} {...fieldProps}>
{componentSlots}
</MpDate>
)
break
case "datetime":
renderItem = (
<MpDatetime v-model={submitForm[item.key]} {...componentProps} {...fieldProps}>
{componentSlots}
</MpDatetime>
)
break
case "time":
renderItem = (
<MpTime v-model={submitForm[item.key]} {...componentProps} {...fieldProps}>
{componentSlots}
</MpTime>
)
break
case "switch":
renderItem = (
<MpSwitch v-model={submitForm[item.key]} {...componentProps} {...fieldProps}>
{componentSlots}
</MpSwitch>
)
break
case "radio":
renderItem = (
<MpRadio v-model={submitForm[item.key]} {...componentProps} {...fieldProps}>
{componentSlots}
</MpRadio>
)
break
case "checkbox":
renderItem = (
<MpCheckbox v-model={submitForm[item.key]} {...componentProps} {...fieldProps}>
{componentSlots}
</MpCheckbox>
)
break
case "address":
renderItem = (
<MpAddress v-model={submitForm[item.key]} {...fieldProps}>
{componentSlots}
</MpAddress>
)
break
case "cascade":
renderItem = (
<MpCascader v-model={submitForm[item.key]} {...componentProps} {...fieldProps}>
{componentSlots}
</MpCascader>
)
break
case "number":
renderItem = (
<MpNumber v-model={submitForm[item.key]} {...componentProps} {...fieldProps}>
{componentSlots}
</MpNumber>
)
break
case "rate":
renderItem = (
<MpRate v-model={submitForm[item.key]} {...componentProps} {...fieldProps}>
{componentSlots}
</MpRate>
)
break
case "slider":
renderItem = (
<MpSlider v-model={submitForm[item.key]} {...componentProps} {...fieldProps}>
{componentSlots}
</MpSlider>
)
break
case "uploader":
renderItem = (
<MpFieldUploader v-model={submitForm[item.key]} {...componentProps} {...fieldProps}>
{componentSlots}
</MpFieldUploader>
)
if (item.required) {
if (!Object.keys(uploaderProvider).length) {
console.error("请在根组件中注入 NEWBIE_UPLOADER 配置项")
renderItem = null
break
}
/*if (item.defaultProps?.maxNum && item.defaultProps?.maxNum > 1) {
rules.type = "array"
rules.message = `请上传${item.title}`
} else {
rules = {
type: "object",
required: true,
message: `请上传${item.title}`,
fields: {
[uploaderProvider.path]: {
type: "string",
required: true,
message: `请上传${item.title}`,
},
},
}
}*/
}
break
/* case "html":
renderItem = Fields.createHtml(item, submitForm)
break
case "text":
renderItem = Fields.createText(item, submitForm)
break
case "group":
renderItem = Fields.createGroup(item, submitForm, { provider: { uploaderProvider } })
break*/
case "textarea":
fieldProps.type = "textarea"
renderItem = (
<MpField v-model={submitForm[item.key]} {...fieldProps}>
{componentSlots}
</MpField>
)
break
case "password":
fieldProps.type = "password"
renderItem = (
<MpField v-model={submitForm[item.key]} {...fieldProps}>
{componentSlots}
</MpField>
)
break
default:
renderItem = (
<MpField v-model={submitForm[item.key]} {...fieldProps}>
{componentSlots}
</MpField>
)
break
}
}
const formItem = [renderItem]
if (item.break) {
formItem.unshift(<nut-divider {...props.dividerProps}>{() => (isString(item.break) ? item.break : null)}</nut-divider>)
}
return formItem
}
export default render