import { ValidatorPosition } from './position/validator-position'; import CheckboxSetter from '../setter/checkbox-setter'; import { executeFunction, getItemDefaultProps, getItemListByPosition, getItemPrototypeListByPosition, } from '../util/util'; import { getJSExpressionPrototype } from './common-style'; import React from 'react'; import ExprSetter from '@/common/setter/expr-setter'; import { __dataSource__, getFormExprNameByPosition, symbolMap, timeMillisecondMap, timeUnitList, timeUnitList2, timeUnitMap, } from '@/common/util/expr-const'; import dayjs from 'dayjs'; const { ActionSetter } = window.VisualEngineUtils || {}; export const compareList = [ { label: '不能超过', value: '<=', }, { label: '不能小于', value: '>=', }, ]; const compareMap = {}; compareList.forEach((item) => { const { label, value } = item || {}; compareMap[value] = label; }); const required = { title: '必填', value: 'required', position: [ ValidatorPosition.filter, ValidatorPosition.form, ValidatorPosition.formDialog, ValidatorPosition.cnArrayTable, ValidatorPosition.cnArraySubAreaCard, ], getDefaultProps: () => { return { required: true, }; }, }; const phone = { title: '手机号', value: 'phone', position: [ ValidatorPosition.filter, ValidatorPosition.form, ValidatorPosition.formDialog, ValidatorPosition.cnArrayTable, ValidatorPosition.cnArraySubAreaCard, ], getDefaultProps: () => { return { format: 'phone', }; }, }; const email = { title: '邮箱', value: 'email', position: [ ValidatorPosition.filter, ValidatorPosition.form, ValidatorPosition.formDialog, ValidatorPosition.cnArrayTable, ValidatorPosition.cnArraySubAreaCard, ], getDefaultProps: () => { return { format: 'email', }; }, }; const number = { title: '数字(包含小数)', value: 'number', position: [ ValidatorPosition.filter, ValidatorPosition.form, ValidatorPosition.formDialog, ValidatorPosition.cnArrayTable, ValidatorPosition.cnArraySubAreaCard, ], getDefaultProps: () => { return { format: 'number', }; }, }; const integer = { title: '整数', value: 'integer', position: [ ValidatorPosition.filter, ValidatorPosition.form, ValidatorPosition.formDialog, ValidatorPosition.cnArrayTable, ValidatorPosition.cnArraySubAreaCard, ], getDefaultProps: () => { return { format: 'integer', }; }, }; const idcard = { title: '身份证', value: 'idcard', position: [ ValidatorPosition.filter, ValidatorPosition.form, ValidatorPosition.formDialog, ValidatorPosition.cnArrayTable, ValidatorPosition.cnArraySubAreaCard, ], getDefaultProps: () => { return { format: 'idcard', }; }, }; const zh = { title: '中文', value: 'zh', position: [ ValidatorPosition.filter, ValidatorPosition.form, ValidatorPosition.formDialog, ValidatorPosition.cnArrayTable, ValidatorPosition.cnArraySubAreaCard, ], getDefaultProps: () => { return { format: 'zh', }; }, }; const pattern = { title: '正则表达式', value: 'pattern', position: [ ValidatorPosition.filter, ValidatorPosition.form, ValidatorPosition.formDialog, ValidatorPosition.cnArrayTable, ValidatorPosition.cnArraySubAreaCard, ], configure: [ { name: 'pattern', title: '正则表达式', display: 'inline', setter: 'StringSetter', // supportVariable: true, }, ], }; const maxItems = { title: '最大条目数(可编辑表格适用)', value: 'maxItems', position: [ ValidatorPosition.form, ValidatorPosition.formDialog, ValidatorPosition.cnArraySubAreaCard, ], configure: [ { name: 'maxItems', title: '最大条目数', display: 'inline', setter: 'NumberSetter', // supportVariable: true, }, ], }; const minItems = { title: '最小条目数(可编辑表格适用)', value: 'minItems', position: [ ValidatorPosition.form, ValidatorPosition.formDialog, ValidatorPosition.cnArraySubAreaCard, ], configure: [ { name: 'minItems', title: '最小条目数', display: 'inline', setter: 'NumberSetter', // supportVariable: true, }, ], }; const checkUploadIsComplete = { title: '校验上传是否完成(上传组件专用)', value: 'checkUploadIsComplete', position: [ ValidatorPosition.filter, ValidatorPosition.form, ValidatorPosition.formDialog, ValidatorPosition.cnArrayTable, ValidatorPosition.cnArraySubAreaCard, ], getDefaultProps: () => { return { format: 'checkUploadIsComplete', }; }, }; const custom = (staticConfig) => { const { position: staticPosition } = staticConfig || {}; const result = { title: '自定义校验', value: 'custom', position: [ ValidatorPosition.filter, ValidatorPosition.form, ValidatorPosition.formDialog, ValidatorPosition.cnArrayTable, ValidatorPosition.cnArraySubAreaCard, ], 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, ValidatorPosition.cnArraySubAreaCard, ].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 校验不通过时调用 * @param filterValue 当前筛选栏的所有数据 * @param state 当前页面的全部数据 */ function validator(rule, value, callback, filterValue, state) { // if(value !== 'xxx') { // callback('校验不通过的错误信息') // } // // 校验通过时调用 // callback() }`; } return [ { name: 'validator', title: '自定义校验', display: 'inline', setter: ( ), // supportVariable: true, }, ]; }, }; if (ValidatorPosition.filter === staticPosition) { result.title = '【已废弃】'; } return result; }; const filterCustom = { title: '自定义校验', value: 'filterCustom', position: [ValidatorPosition.filter], getDefaultProps: () => { return {}; }, getPrototypeList: (position) => { const 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 || "校验不通过"; }`; return [ { name: 'validator', title: '高级自定义校验', display: 'inline', setter: ( ), // supportVariable: true, }, ]; }, }; const dateInterval = { title: '起止时间间隔校验', value: 'dateInterval', position: [ ValidatorPosition.filter, ValidatorPosition.form, ValidatorPosition.formDialog, ], 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 || {}; const { name, message, options } = validateItemConfig || {}; const { compare, num, unit } = options || {}; if ([ValidatorPosition.filter].includes(position)) { 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(); }, }; } } else if ( [ValidatorPosition.form, ValidatorPosition.formDialog].includes(position) ) { if (name && unit && compare && typeof num === 'number') { return { validator: (value, rules, context) => { 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) { return ( message || `间隔时间 ${compareMap[compare] || compare} ${num} ${ timeUnitMap[unit] || unit }` ); } } } } 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) { return ( message || `间隔时间 ${compareMap[compare] || compare} ${num} ${ timeUnitMap[unit] || unit }` ); } } } } } } }, }; } } }, }; export const componentMap = { required, phone, email, idcard, integer, number, zh, pattern, maxItems, minItems, custom, filterCustom, dateInterval, checkUploadIsComplete, }; // 注册回调动作 export function registerValidator(plugin) { const { name } = plugin || {}; if (name) { componentMap[name] = plugin; } } // 获取列表 export function getValidatorListByPosition(position) { const defaultValidatorList = Object.keys(componentMap); const result = []; if (position !== undefined) { defaultValidatorList.forEach((name) => { let item = componentMap[name]; if (typeof item === 'function') { item = executeFunction(item, position); } if (item && item.position && item.position.includes(position)) { result.push(item); } }); } return result; } 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: false, // extraProps:{ // collapsed:false, // }, // initialValue:{ // format:'required', // }, className: 'cn-array-setter-validator', setter: { componentName: 'ArraySetter', props: { mode: 'list', itemSetter: { componentName: 'ObjectSetter', // initialValue: { // "type": "JSFunction", // "value": "() => {return {primaryKey: String(Math.floor(Math.random() * 10000)),children: \"Title\",optType:\"link\" };}" // }, initialValue: { // todo active: true, }, props: { config: { items: [ { name: 'name', display: 'inline', title: '校验格式', isRequired: true, tip: '校验示例—筛选项名称为"订单数量"/校验格式选择"必填",错误提示默认为"订单数量是必填字段"(您也可以下方填写自定义错误提示文案)', setter: { componentName: 'CnSelectSetter', props: (field) => { const parentComponentConfig = field?.parent?.parent?.parent?.getValue?.(); const componentName = parentComponentConfig?.componentName; const validatorList = getItemListByPosition({ position, componentMap, extraQueryParams: { showInFilterComponentList: componentName, }, }); return { options: validatorList, selectProps: { placeholder: '请选择校验格式', }, }; }, }, 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: , componentName: ( ), title: '简单表达式', }, getJSExpressionPrototype({ type: 'form' }), ], }, }, }, // { // name: 'active', // display: 'inline', // isRequired:true, // title: '是否启用', // setter: 'BoolSetter', // }, { name: 'triggerType', display: 'inline', title: '触发时机', // isRequired:true, setter: { componentName: 'CnSelectSetter', props: { options: [ { label: '输入时', value: 'onInput', }, { label: '获得焦点时', value: 'onFocus', }, { label: '失去焦点时', value: 'onBlur', }, ], selectProps: { hasClear: true, }, }, }, }, ...configure, ], }, }, }, }, }, }, ]; return []; }