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,
],
},
},
},
},
},
},
];
}