UNPKG

jobsys-explore

Version:

Enhanced component based on vant

308 lines (287 loc) 9.62 kB
import { inject } from "vue" import { EX_UPLOADER } from "../provider/ExProvider.jsx" import { isBoolean, isFunction, isString, merge, pick } from "lodash-es" import ExField from "./ExField.jsx" import ExSelect from "./ExSelect.jsx" import ExDate from "./ExDate.jsx" import ExSwitch from "./ExSwitch.jsx" import ExCheckbox from "./ExCheckbox.jsx" import ExRadio from "./ExRadio.jsx" import ExDatetime from "./ExDatetime.jsx" import ExNumber from "./ExNumber.jsx" import ExRate from "./ExRate.jsx" import ExSlider from "./ExSlider.jsx" import ExAddress from "./ExAddress.jsx" import ExCascader from "./ExCascader.jsx" import ExTime from "./ExTime.jsx" import ExFieldUploader from "./ExFieldUploader.jsx" import ExMatrixRadio from "./ExMatrixRadio.jsx" import ExMatrixScale from "./ExMatrixScale.jsx" import ExMatrixCheckbox from "./ExMatrixCheckbox.jsx" import { Divider } from "vant" /** * * @param {FormItemConfig} item * @param {Object} submitForm * @param {Object} [props] * @param {Object} [slots] * @return {*|JSX.Element} */ const render = (item, submitForm, { props, slots }) => { const uploaderProvider = inject(EX_UPLOADER, () => ({})) const pickerTypes = ["select", "date", "datetime", "time", "address", "cascade"] const isPicker = pickerTypes.includes(item.type) // ExField 的 props const fieldPropsList = ["placeholder", "help", "append", "required", "disabled", "rules", "readonly", "isLink", "fieldProps"] let fieldProps = pick(item, fieldPropsList) 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) => rule.pattern ? { ...rule, pattern: new RegExp(rule.pattern), } : { ...rule }, ) : [] // 具体组件的 props const componentProps = merge(pick(item, ["options", "defaultProps", "rows"]), item.exProps || {}) //混合了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 = "--" } let renderItem = null // 处理 hidden if ((isFunction(item.hidden) && item.hidden(submitForm)) || (isBoolean(item.hidden) && item.hidden)) { return null } else if (item.type === "slot" && slots[item.key]) { return slots[item.key]({ submitForm }) } else 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 = ( <ExSelect v-model={submitForm[item.key]} {...componentProps} {...fieldProps}> {componentSlots} </ExSelect> ) break case "date": renderItem = ( <ExDate v-model={submitForm[item.key]} {...componentProps} {...fieldProps}> {componentSlots} </ExDate> ) break case "datetime": renderItem = ( <ExDatetime v-model={submitForm[item.key]} {...componentProps} {...fieldProps}> {componentSlots} </ExDatetime> ) break case "time": renderItem = ( <ExTime v-model={submitForm[item.key]} {...componentProps} {...fieldProps}> {componentSlots} </ExTime> ) break case "switch": renderItem = ( <ExSwitch v-model={submitForm[item.key]} {...componentProps} {...fieldProps}> {componentSlots} </ExSwitch> ) break case "radio": renderItem = ( <ExRadio v-model={submitForm[item.key]} {...componentProps} {...fieldProps}> {componentSlots} </ExRadio> ) break case "checkbox": renderItem = ( <ExCheckbox v-model={submitForm[item.key]} {...componentProps} {...fieldProps}> {componentSlots} </ExCheckbox> ) break case "address": renderItem = ( <ExAddress v-model={submitForm[item.key]} {...componentProps} {...fieldProps}> {componentSlots} </ExAddress> ) break case "cascade": renderItem = ( <ExCascader v-model={submitForm[item.key]} {...componentProps} {...fieldProps}> {componentSlots} </ExCascader> ) break case "number": renderItem = ( <ExNumber v-model={submitForm[item.key]} {...componentProps} {...fieldProps}> {componentSlots} </ExNumber> ) break case "rate": renderItem = ( <ExRate v-model={submitForm[item.key]} {...componentProps} {...fieldProps}> {componentSlots} </ExRate> ) break case "slider": renderItem = ( <ExSlider v-model={submitForm[item.key]} {...componentProps} {...fieldProps}> {componentSlots} </ExSlider> ) break case "uploader": renderItem = ( <ExFieldUploader v-model={submitForm[item.key]} {...componentProps} {...fieldProps}> {componentSlots} </ExFieldUploader> ) 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 = ( <ExField v-model={submitForm[item.key]} {...fieldProps}> {componentSlots} </ExField> ) break case "password": fieldProps.type = "password" renderItem = ( <ExField v-model={submitForm[item.key]} {...fieldProps}> {componentSlots} </ExField> ) break case "matrix-radio": { if (item.required) { fieldProps.rules[fieldProps.rules.length - 1].validator = () => { for (let i = 0; i < item.rows.length; i++) { if (!submitForm[item.key][item.rows[i]]) { return `请选择${item.rows[i]}` } } return true } } renderItem = <ExMatrixRadio v-model={submitForm[item.key]} {...componentProps} {...fieldProps} /> break } case "matrix-scale": { if (item.required) { fieldProps.rules[fieldProps.rules.length - 1].validator = () => { for (let i = 0; i < item.rows.length; i++) { if (!submitForm[item.key][item.rows[i]]) { return `请选择${item.rows[i]}` } } return true } } renderItem = <ExMatrixScale v-model={submitForm[item.key]} {...componentProps} {...fieldProps} /> break } case "matrix-checkbox": { if (item.required) { fieldProps.rules[fieldProps.rules.length - 1].validator = () => { for (let i = 0; i < item.rows.length; i++) { if (!submitForm[item.key][item.rows[i]]) { return `请选择${item.rows[i]}` } } return true } } renderItem = <ExMatrixCheckbox v-model={submitForm[item.key]} {...componentProps} {...fieldProps} /> break } default: renderItem = ( <ExField v-model={submitForm[item.key]} {...fieldProps}> {componentSlots} </ExField> ) break } } const formItem = [renderItem] if (item.break) { formItem.unshift(<Divider {...props.dividerProps}>{{ default: () => (isString(item.break) ? item.break : null) }}</Divider>) } return formItem } export default render