import React from 'react'; import { ValidatorPosition } from '@/type/validator-position'; import dayjs from 'dayjs'; import { getFormExprNameByPosition, symbolMap, timeMillisecondMap, timeUnitList, timeUnitList2, timeUnitMap, __dataSource__, } from '../util/expr-const'; import CheckboxSetter from '../setter/checkbox-setter'; import ExprSetter from '../setter/expr-setter'; import { getJSExpressionPrototype } from './common-style'; import { getItemDefaultProps, getItemListByPosition, getItemPrototypeListByPosition, } from '../util/util'; const { ActionSetter } = window.VisualEngineUtils || {}; export const compareList = [ { label: '不能超过', value: '<=', }, { label: '不能小于', value: '>=', }, ]; const compareMap: any = {}; compareList.forEach((item) => { const { label, value } = item || {}; compareMap[value] = label; }); const required = { title: '必填', value: 'required', position: [ ValidatorPosition.filter, ValidatorPosition.form, ValidatorPosition.formDialog, ValidatorPosition.cnArrayTable, ], getDefaultProps: () => { return { required: true, }; }, }; const phone = { title: '手机号', value: 'phone', position: [ ValidatorPosition.filter, ValidatorPosition.form, ValidatorPosition.formDialog, ValidatorPosition.cnArrayTable, ], getDefaultProps: () => { return { format: 'phone', }; }, }; const email = { title: '邮箱', value: 'email', position: [ ValidatorPosition.filter, ValidatorPosition.form, ValidatorPosition.formDialog, ValidatorPosition.cnArrayTable, ], getDefaultProps: () => { return { format: 'email', }; }, }; const number = { title: '数字(包含小数)', value: 'number', position: [ ValidatorPosition.filter, ValidatorPosition.form, ValidatorPosition.formDialog, ValidatorPosition.cnArrayTable, ], getDefaultProps: () => { return { format: 'number', }; }, }; const integer = { title: '整数', value: 'integer', position: [ ValidatorPosition.filter, ValidatorPosition.form, ValidatorPosition.formDialog, ValidatorPosition.cnArrayTable, ], getDefaultProps: () => { return { format: 'integer', }; }, }; const idcard = { title: '身份证', value: 'idcard', position: [ ValidatorPosition.filter, ValidatorPosition.form, ValidatorPosition.formDialog, ValidatorPosition.cnArrayTable, ], getDefaultProps: () => { return { format: 'idcard', }; }, }; const zh = { title: '中文', value: 'zh', position: [ ValidatorPosition.filter, ValidatorPosition.form, ValidatorPosition.formDialog, ValidatorPosition.cnArrayTable, ], getDefaultProps: () => { return { format: 'zh', }; }, }; const pattern = { title: '正则表达式', value: 'pattern', position: [ ValidatorPosition.filter, ValidatorPosition.form, ValidatorPosition.formDialog, ValidatorPosition.cnArrayTable, ], configure: [ { name: 'pattern', title: '正则表达式', display: 'inline', setter: 'StringSetter', // supportVariable: true, }, ], }; const maxItems = { title: '最大条目数(可编辑表格适用)', value: 'maxItems', position: [ValidatorPosition.form, ValidatorPosition.formDialog], configure: [ { name: 'maxItems', title: '最大条目数', display: 'inline', setter: 'NumberSetter', // supportVariable: true, }, ], }; const minItems = { title: '最小条目数(可编辑表格适用)', value: 'minItems', position: [ValidatorPosition.form, ValidatorPosition.formDialog], configure: [ { name: 'minItems', title: '最小条目数', display: 'inline', setter: 'NumberSetter', // supportVariable: true, }, ], }; const custom = { title: '自定义校验', value: 'custom', position: [ ValidatorPosition.filter, ValidatorPosition.form, ValidatorPosition.formDialog, ValidatorPosition.cnArrayTable, ], getDefaultProps: () => { return {}; }, getPrototypeList: (position) => { let defaultCode = `/** * validator * 用法请参考formily * * @param value 当前值 * @param rules 当前校验规则 * @param context 当前上下文 */ function validator(value, rules, context, state) { // // message: 用户配置的错误提示信息 // const { message } = rules; // //field: 当前字段; form: 当前表单实例 // const { field, form } = context; // // 查询其他字段的值 // const otherFieldValue = field.query('name').value() // //如果return了值,那就表示校验不通过;如果没有return值,表示校验通过 // return message || "校验不通过"; }`; if ([ValidatorPosition.cnArrayTable].includes(position)) { defaultCode = `/** * validator * 用法请参考formily * * @param value 当前值 * @param rules 当前校验规则 * @param context 当前上下文 */ function validator(value, rules, context) { // // message: 用户配置的错误提示信息 // const { message } = rules; // // field: 当前字段; form: 当前表单实例 // const { field, form } = context; // // 当前行的index // const index = field?.path?.segments?.[1]; // // 查询当前行其他字段的值,xxx代表可编辑表格的字段编码,yyy代表表格某列的字段编码 // const otherFieldValue = field.query(\`xxx.$\{index}.yyy\`).value() // // 查询其他字段的值 // const otherFieldValue = field.query('name').value() // //如果return了值,那就表示校验不通过;如果没有return值,表示校验通过 // return message || "校验不通过"; }`; } if ([ValidatorPosition.filter].includes(position)) { defaultCode = `/** * validator * * @param rule 校验规则 * @param value 当前输入框的值 * @param callback 校验不通过时调用 */ function validator(rule, value, callback) { // if(value !== 'xxx') { // callback('校验不通过的错误信息') // } // // 校验通过时调用 // callback() }`; } return [ { name: 'validator', title: '自定义校验', display: 'inline', setter: ( ), // supportVariable: true, }, ]; }, }; const dateInterval = { title: '起止时间间隔校验', value: 'dateInterval', position: [ValidatorPosition.filter], showInFilterComponentList: ['RangePicker'], configure: [ { name: 'compare', title: '起止间隔', display: 'inline', setter: { componentName: 'SelectSetter', props: { options: compareList, }, }, }, { name: 'num', title: '数量', display: 'inline', setter: 'NumberSetter', }, { name: 'unit', title: '单位', display: 'inline', setter: { componentName: 'SelectSetter', props: { options: [...timeUnitList2, ...timeUnitList], }, }, }, ], action: (config) => { const { position, validateItemConfig } = config || {}; if ([ValidatorPosition.filter].includes(position)) { const { name, message, options } = validateItemConfig; const { compare, num, unit } = options || {}; if (name && unit && compare && typeof num === 'number') { return { validator: (rule, value, cb) => { if (Array.isArray(value)) { const start = value[0]; const end = value[1]; if (start && end) { const isDay = timeUnitList.find((item) => item.value === unit); const func = symbolMap[compare]; if (isDay) { const startDay = dayjs(start).startOf(unit); const endDay = dayjs(end).startOf(unit); const diff = endDay.diff(startDay, unit); if (typeof func === 'function') { const result = func(diff, num); if (typeof result === 'boolean') { if (result !== true) { cb( message || `间隔时间 ${ compareMap[compare] || compare } ${num} ${timeUnitMap[unit] || unit}`, ); return; } } } } else { const startTime = dayjs(start).valueOf(); const endTime = dayjs(end).valueOf(); if (typeof func === 'function') { const diff = endTime - startTime; const result = func(diff, num * timeMillisecondMap[unit]); if (typeof result === 'boolean') { if (result !== true) { cb( message || `间隔时间 ${ compareMap[compare] || compare } ${num} ${timeUnitMap[unit] || unit}`, ); return; } } } } } } cb(); }, }; } } }, }; export const componentMap = { required, phone, email, idcard, integer, number, zh, pattern, maxItems, minItems, custom, dateInterval, }; export function createValidatorSetters(config = {}) { const { position } = config; const prototypeList = getItemPrototypeListByPosition({ position, primaryKey: 'name', componentMap, }); const configure = []; if (prototypeList?.length > 0) { configure.push({ name: 'options', display: 'plain', title: '请完善校验的配置', setter: { componentName: 'ObjectSetter', props: { config: { items: [...prototypeList], }, }, }, }); } else { return []; } return [ { name: 'rules', title: '配置字段的校验格式', display: 'accordion', collapsed: true, className: 'cn-array-setter-validator', setter: { componentName: 'ArraySetter', props: { mode: 'list', itemSetter: { componentName: 'ObjectSetter', initialValue: { // todo active: true, }, props: { config: { items: [ { name: 'name', display: 'inline', title: '校验格式', isRequired: true, setter: { componentName: 'SelectSetter', props: (field) => { const parentComponentConfig = field?.parent?.parent?.parent?.getValue?.(); const componentName = parentComponentConfig?.componentName; const validatorList = getItemListByPosition({ position, componentMap, extraQueryParams: { showInFilterComponentList: componentName, }, }); return { options: validatorList, }; }, }, extraProps: { setValue(target, value) { const defaultProps = getItemDefaultProps( componentMap, position, value, ); if ( defaultProps && Object.keys(defaultProps)?.length > 0 ) { target?.parent?.setPropValue?.( 'options', defaultProps, ); } else { target?.parent?.setPropValue?.('options', {}); } }, }, }, { name: 'message', display: 'inline', title: '错误提示', isRequired: true, setter: { componentName: 'CnI18nSetter', props: { placeholder: '错误提示文案', }, }, }, { name: 'active', display: 'inline', className: 'cn-array-setter-validator-active', title: '启用', // setter: , setter: { componentName: 'MixedSetter', props: { setters: [ { componentName: , title: '启用/禁用', }, { componentName: ( ), title: '简单表达式', }, getJSExpressionPrototype({ type: 'form' }), ], }, }, }, { name: 'triggerType', display: 'inline', title: '触发时机', // isRequired:true, setter: { componentName: 'SelectSetter', props: { options: [ { label: '输入时', value: 'onInput', }, { label: '获得焦点时', value: 'onFocus', }, { label: '失去焦点时', value: 'onBlur', }, ], }, }, }, ...configure, ], }, }, }, }, }, }, ]; }