react实现页面动态表单设计器(自定义推拽表单)
含完整代码讲解
实现效果
左侧为拖拽表单,中间为组件,右侧为属性,可设置label,输入限制等
安装插件
cnpm i dynamic-customization-form
使用
<Dynamicforms
getlistChange={getlistChange} //获取表单保存的值
width={1300} //动态设置宽高
height={650} />
组件介绍
左侧
多个表单控件,可自由选择拖拽至中间
中间
对推拽后的空间进行值的输入和选择
右侧
基本设置,可设置控件标签,是否必填,校验规则
校验规则有如下几种
多选,下拉,单选可动态设置每个选择的label以及值
最后可点击表单保存,也可以表单重置
代码解析
可以通过代码自己理解去封装组件!
此为发包代码讲解,自己写,可以在项目里封装,导出引入即可!
left 左侧拖拽组件
left-index.jsx 拖动功能
import React, { useState } from "react";
import "./index.less";
import { example } from "./interface";
const Config = (props) => {
const [list, setList] = useState(example);
// fn 拖动开始
const dragStartFn=(item)=> {
// 自动识别配置必要参数
let param = {
...item,
required: false, //是否必填
};
props.setNewParams(param);
props.setDragEnd(false);
}
// fn 拖动结束
const dragEndFn=()=> {
props.setDragEnd(true);
}
const renderList=()=> {
return list.map((item, index) => {
return (
<div
onDragStart={()=>dragStartFn(item)}
className="catalogue-item"
draggable="true"
onDragEnd={dragEndFn}
key={index}
>
{item.label}
</div>
);
});
}
return (
<div
onDragEnter={(e) => {
if (!props.valid) return;
e.preventDefault();
props.setValid(false);
}}
className="catalogue"
>
{renderList()}
</div>
);
};
export default Config;
html5拖拽和释放功能知识扩展
默认情况下,图片、链接和文本是可拖动的。HTML5 在所有 HTML 元素上规定了一个 draggable 属性, 表示元素是否可以拖动。图片和链接的 draggable 属性自动被设置为 true,而其他所有元素此属性的默认值为 false。
拖拽:Drag
释放:Drop
- 某个元素被拖动时,会依次触发以下事件:
ondragstart:拖动开始,当鼠标按下并且开始移动鼠标时,触发此事件;整个周期只触发一次;
ondrag:只要元素仍被拖拽,就会持续触发此事件;
ondragend:拖拽结束,当鼠标松开后,会触发此事件;整个周期只触发一次。
- 当把拖拽元素移动到一个有效的放置目标时,目标对象会触发以下事件:
ondragenter:只要一把拖拽元素移动到目标时,就会触发此事件;
ondragover:拖拽元素在目标中拖动时,会持续触发此事件;
ondragleave:拖拽元素离开目标时(没有在目标上放下),会触发ondragleave
ondrop: 当拖拽元素在目标放下(松开鼠标),则触发ondrop事件。
left-interface.js 需要渲染的组件遍历列表
- 你可以自己增加修改删除哦!
export const example = [
{
label: "单行文本", // 标签名称
tips: "请输入", // 提示语
rule: "validateNone", // 需要限制规则名称
type: "Input", // 控件类型
value: "",
allowClear: true, //是否允许清除-默认true
},
{
label: "多行文本", // 标签名称
tips: "请输入", // 提示语
rule: "validateNone", // 需要限制规则名称
type: "InputTextera", // 控件类型
value: "",
allowClear: true, //是否允许清除-默认true
},
{
label: "数字框", // 标签名称
tips: "请输入", // 提示语
rule: "validateNone", // 需要限制规则名称
type: "InputNumber", // 控件类型
value: null,
},
{
label: "下拉框", // 标签名称
tips: "请输入", // 提示语
rule: "validateNone", // 需要限制规则名称
type: "Select", // 控件类型
options: [{ label: "选项1", value: 1 }], // 控件选项参数名称
value: "",
},
{
label: "单选", // 标签名称
tips: "请输入", // 提示语
rule: "validateNone", // 需要限制规则名称
type: "Radio", // 控件类型
options: [{ label: "选项1", value: 1}], // 控件选项参数名称
value: "",
},
{
label: "复选框", // 标签名称
tips: "请输入", // 提示语
rule: "validateNone", // 需要限制规则名称
type: "Checkbox", // 控件类型
options: [{ label: "选项1", value: 1 }], // 控件选项参数名称
value: "",
},
{
label: "开关", // 标签名称
tips: "开启", // 提示语
rule: "validateNone", // 需要限制规则名称
type: "Switch", // 控件类型
value: false,
},
{
label: "日期选择", // 标签名称
tips: "请选择", // 提示语
rule: "validateNone", // 需要限制规则名称
type: "DatePicker", // 控件类型
value: "",
},
{
label: "日期区间", // 标签名称
tips: "请选择", // 提示语
rule: "validateNone", // 需要限制规则名称
type: "RangePicker", // 控件类型
value: [],
},
];
left-index.less样式设置
.catalogue {
width: 15%;
border: 1px solid #f1e8e8;
padding: 15px;
height: 100%;
&-item {
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 5px;
cursor: move;
color: #000;
user-select: none;
padding: 8px 10px;
background: #f6f7ff;
font-size: 12px;
cursor: move;
border: 1px dashed #f6f7ff;
border-radius: 3px;
}
> div:last-child {
margin-bottom: 0;
}
}
center 中间表单组件
center-index.jsx 表单功能
import React, { useEffect, useState } from 'react';
import moment from 'moment';
import {
Form,
Checkbox,
Switch,
Input,
Select,
Radio,
InputNumber,
DatePicker,
} from 'antd';
import * as validateParams from '../left/validate';
import './index.less';
let draging = null;
const Option = Select.Option;
const CheckboxGroup = Checkbox.Group;
const { RangePicker } = DatePicker;
let targetName = 'drag-move'; //需要换位目标
let targetIndex = -1; //当前换位位置
let prevIndex = -1; //原坐标
const UiForm = (props) => {
const {
formList,
newParams,
setList,
dragEnd,
valid,
setValid,
setActive,
active,
} = props;
useEffect(() => {
renderForm(props.formList);
}, [props.formList]);
// render 表单
function renderForm(arr) {
return arr.map((item, index) => {
if (!item || !item.label) return;
return (
<div
key={item.key}
onClick={setActive.bind(this, index)}
onDragStart={dragStartFn.bind(this, index)}
onDragOver={dragOverFn.bind(this, index)}
onDragEnd={dragEndFn.bind(this)}
draggable
className={`drag-move drag-item drag-item-${active == index ? 'active' : ''
}`}
>
<Form.Item
label={item.label}
name={index}
hasFeedback
rules={[
{
required: item.required,
message: item.tips,
},
{
validator: validateParams[item.rule],
},
]}
>
{renderSwatch(item, index)}
</Form.Item>
</div>
);
});
}
// render 表单类型判定
function renderSwatch(item, index) {
switch (item.type) {
case 'Input':
return (
<Input
allowClear={item.allowClear === undefined ? true : item.allowClear}
onChange={checkNoSpace.bind(this, index)}
placeholder={item.tips}
key={item.key}
value={item.value}
/>
);
case 'InputTextera':
return (
<Input.TextArea
allowClear={item.allowClear === undefined ? true : item.allowClear}
onChange={checkNoSpace.bind(this, index)}
placeholder={item.tips}
value={item.value}
rows={5}
/>
);
case 'InputNumber':
return (
<InputNumber
min={item.min}
onChange={checkNoSpace.bind(this, index)}
placeholder={item.tips}
key={item.key}
style={{ width: '50%' }}
value={item.value}
/>
);
case 'Select':
return (
<Select
showSearch
mode={item.mode}
onChange={checkNoSpace.bind(this, index)}
placeholder={item.tips}
allowClear={item.allowClear === undefined ? true : item.allowClear}
value={item.value}
key={item.key}
filterOption={(input, option) => (option?.children).includes(input)}
>
{item.options.map((its) => {
return (
<Option key={its.value} value={its.value}>
{' '}
{its.label}{' '}
</Option>
);
})}{' '}
</Select>
);
case 'Radio':
return (
<Radio.Group
onChange={checkNoSpace.bind(this, index)}
key={item.key}
value={item.value}
>
{item.options.map((its) => {
return (
<Radio key={its.value} value={its.value}>
{' '}
{its.label}{' '}
</Radio>
);
})}
</Radio.Group>
);
case 'Checkbox':
return (
<CheckboxGroup
onChange={checkNoSpace.bind(this, index)}
options={item.options}
value={item.value}
/>
);
case 'Switch':
return (
<Switch
onChange={checkNoSpace.bind(this, index)}
checked={item.value}
key={item.key}
/>
);
case 'DatePicker':
return (
<DatePicker
onChange={checkSetTime.bind(this, index)}
placeholder={item.tips}
key={item.key}
value={item.value}
/>
);
case 'RangePicker':
return (
<RangePicker
format={item.format ? item.format : 'YY-MM-DD HH:mm:ss'}
showTime
allowClear={item.allowClear === undefined ? true : item.allowClear}
value={item.value}
showNow={false}
key={item.key}
placeholder={item.tips}
onChange={checkSetArrTime.bind(this, index)}
onOk={checkSetArrTime.bind(this, index)}
/>
);
default:
return '';
}
}
// fn 拖动开始
function dragStartFn(index, e) {
e.dataTransfer.setData('te', e.target.innerText); //不能使用text,firefox会打开新tab
draging = e.target;
prevIndex = index;
}
// fn 拖动中
function dragOverFn(index, e) {
e.preventDefault();
let target = getParentNode(e.target);
if (!target || target.className.includes(targetName)) return;
if (target !== draging) {
targetIndex = index;
}
}
// fn 拖动结束
function dragEndFn() {
if (prevIndex === -1 || targetIndex === -1) return;
let newList = [...formList];
let prev = newList[prevIndex];
let target = newList[targetIndex];
newList.splice(prevIndex, 1, target);
newList.splice(targetIndex, 1, prev);
setList(newList);
}
// 数组转对象
function arrToObj1(arr, idx) {
return arr.reduce((obj, item, index) => {
if (index == idx) {
obj[index] = '';
} else {
obj[index] = item;
}
return obj;
}, {});
}
// fn 新生成元素
function dargAddFn() {
let newForm = Object.values(props.form.getFieldValue());
let setform = arrToObj1(newForm, formList.length);
props.form.setFieldsValue({
...setform,
});
// 直接新增
if (!dragEnd || !newParams.label) return;
var code = '' + (parseInt(Math.random() * 1000000) + 1000000);
code = code.substring(1, 7);
newParams.key = newParams.type + code;
setList([...formList, newParams]);
}
// 阶梯查询父级元素
function getParentNode(el) {
try {
if (el.className === '') return getParentNode(el.parentNode);
if (el.className.includes(targetName)) return el;
let parentName = el.parentNode.className;
if (parentName.includes(targetName)) return getParentNode(el.parentNode);
if (!parentName.includes(targetName)) return el.parentNode;
} catch (error) {
console.log(error);
console.log(el.className);
return undefined;
}
}
// 时间选择传值
function checkSetTime(index, val) {
let newList = [...formList];
newList[index].value = moment(val._d).format('YYYY-MM-DD');
setList(newList);
}
// 时间区间选择传值
function checkSetArrTime(index, val) {
let param;
if (val === null) param = val;
else if (val[1] != null) param = moment(val[1]._d).format('YYYY-MM-DD');
else param = moment(val[0]._d).format('YYYY-MM-DD');
let newList = [...formList];
newList[index].value = param;
setList(newList);
}
// 表单传值
function checkNoSpace(index, e) {
let param = e && e.target ? e.target.value : e;
let newList = [...formList];
newList[index].value = param;
setList(newList);
}
useEffect(() => {
if (valid) dargAddFn();
if (dragEnd) {
draging = null;
targetIndex = -1;
}
}, [dragEnd]);
return (
<div
onDragEnter={(e) => {
if (valid) return;
e.preventDefault();
setValid(true);
}}
id="uiform"
className="uiform"
>
<Form form={props.form}>{renderForm(formList)}</Form>
</div>
);
};
export default UiForm;
center-index.less
@color: 'red';
@hover: '#333';
@disabled: '#000';
@error: 'red';
.drag-item {
transition: all 0.3s;
margin: 5px 0;
cursor: move;
&-active {
box-shadow: 0 0 2px @color;
}
}
.uiform {
.ant-input-textarea-affix-wrapper {
.ant-input-clear-icon {
position: absolute;
right: 30px !important;
}
.ant-input-textarea-suffix {
.ant-form-item-feedback-icon {
position: absolute;
top: 6px;
right: 0px;
font-size: 14px;
}
}
}
}
right -右侧所选控件设置组件-label、value、表单校验、下拉、单选、复选等选项数据值设置
right-index.jsx
import React, { useState } from 'react';
import { Switch, Input, Select, Button, Tag } from 'antd';
import './index.less';
import If from './If';
import { OptionsValidate } from './validate';
import {
ArrowUpOutlined,
ArrowDownOutlined,
DeleteOutlined,
} from '@ant-design/icons';
let draging = null;
let targetName = 'config-item-option'; //需要换位目标
let targetIndex = -1; //当前换位位置
let prevIndex = -1; //原坐标
const Option = Select.Option;
const Config = (props) => {
const { active, formList, setList, setActive } = props;
// fn 拖动开始
function dragStartFn(index, e) {
e.dataTransfer.setData('te', e.target.innerText); //不能使用text,firefox会打开新tab
draging = e.target;
prevIndex = index;
}
// fn 拖动中
function dragOverFn(index, e) {
e.preventDefault();
let target = getParentNode(e.target);
if (!target || target.className !== targetName) return;
if (target !== draging && draging) {
//getBoundingClientRect()用于获取某个元素相对于视窗的位置集合
let targetRect = target.getBoundingClientRect();
let dragingRect = draging.getBoundingClientRect();
if (target && target.animated) return;
targetIndex = index;
}
}
// fn 拖动结束
function dragEndFn() {
let newList = [...formList];
let param = newList[active].options;
let prev = param[prevIndex];
let target = param[targetIndex];
param.splice(prevIndex, 1, target);
param.splice(targetIndex, 1, prev);
newList[active].options = [...param];
setList([...newList]);
}
// 阶梯查询父级元素
function getParentNode(el) {
if (el.className === '') return getParentNode(el.parentNode);
if (el.className === targetName) return el;
let parentName = el.parentNode.className;
if (parentName !== targetName) return getParentNode(el.parentNode);
if (parentName === targetName) return el.parentNode;
}
//获取元素在父元素中的index
function dragIndex(el) {
let index = 0;
if (!el || !el.parentNode) return -1;
//previousElementSibling属性返回指定元素的前一个兄弟元素(相同节点树层中的前一个元素节点)。
while (el && (el = el.previousElementSibling)) {
index++;
}
return index;
}
function dragAnimate(prevRect, target) {
let ms = 300;
let currentRect = target.getBoundingClientRect();
//nodeType 属性返回以数字值返回指定节点的节点类型。1=元素节点 2=属性节点
if (prevRect.nodeType === 1) {
prevRect = prevRect.getBoundingClientRect();
}
dragStyle(target, 'transition', 'none');
dragStyle(
target,
'transform',
'translate3d(' +
(prevRect.left - currentRect.left) +
'px,' +
(prevRect.top - currentRect.top) +
'px,0)',
);
target.offsetWidth; // 触发重绘
dragStyle(target, 'transition', 'all ' + ms + 'ms');
dragStyle(target, 'transform', 'translate3d(0,0,0)');
clearTimeout(target.animated);
target.animated = setTimeout(() => {
dragStyle(target, 'transition', '');
dragStyle(target, 'transform', '');
target.animated = false;
}, ms);
}
//给元素添加style
function dragStyle(el, prop, val) {
let style = el && el.style;
if (!style) return false;
if (val === void 0) {
//使用DefaultView属性可以指定打开窗体时所用的视图
if (document.defaultView && document.defaultView.getComputedStyle) {
val = document.defaultView.getComputedStyle(el, '');
} else if (el.currentStyle) {
val = el.currentStyle;
}
return prop === void 0 ? val : val[prop];
} else {
if (!(prop in style)) prop = '-webkit-' + prop;
style[prop] = val + (typeof val === 'string' ? '' : 'px');
}
}
// 表单传值
function changeValue(name, e) {
let param = e && e.target ? e.target.value : e;
let arr = [...formList];
arr[active][name] = param;
setList(arr);
}
// 表单传值-option
function changeOptionValue(index, e) {
let value = e && e.target ? e.target.value : e;
let arr = [...formList];
let param = arr[active].options;
param[index].value = value;
setList(arr);
}
function changeOptionLabel(index, e) {
let value = e && e.target ? e.target.value : e;
let arr = [...formList];
let param = arr[active].options;
param[index].label = value;
setList(arr);
}
// 数组转对象
function arrToObj1(arr) {
return arr.reduce((obj, item, index) => {
obj[index] = item;
return obj;
}, {});
}
// fn 删除控件
function delItemFn() {
let newList = [...formList];
newList.splice(active, 1);
let newForm = newList.map((o) => o.value);
let setform = {};
if (newForm.length > 0) {
setform = arrToObj1(newForm);
}
props.form.setFieldsValue({
...setform,
});
setList(newList);
setActive(-1);
}
// fn option 新增
function addOptionFn() {
let index = formList[active]?.options?.length || 0;
let param = {
label: `选项${index}`,
value: index,
};
let newList = [...formList];
let options = newList[active].options;
newList[active].options = [...options, param];
setList(newList);
}
// fn 删除 options
function delOptionFn(index) {
let newList = [...formList];
newList[active]?.options?.splice(index, 1);
setList(newList);
}
// fn 排序 options
function orderOptionFn(index, desc, disabled) {
if (disabled) return; //排除无法换位的情况
let newList = [...formList];
let param = newList[active]?.options;
let prev = param ? param[index] : '';
let newIndex;
switch (desc) {
case true:
newIndex = param ? param[index + 1] : '';
newList[active]?.options?.splice(index + 1, 1, prev);
break;
default:
newIndex = param ? param[index - 1] : '';
newList[active]?.options?.splice(index - 1, 1, prev);
}
newList[active]?.options?.splice(index, 1, newIndex);
setList(newList);
}
// render options 选项卡
function renderOption() {
return formList[active]?.options?.map((item, index) => {
let max = (formList[active]?.options?.length || 1) - 1;
return (
<div
onDragStart={dragStartFn.bind(this, index)}
onDragOver={dragOverFn.bind(this, index)}
onDragEnd={dragEndFn.bind(this)}
draggable
key={index}
className="config-item-option"
>
<input
onChange={changeOptionLabel.bind(this, index)}
value={item.label}
type="text"
/>
<input
onChange={changeOptionValue.bind(this, index)}
type="text"
value={item.value}
/>
<div className="config-item-option-edit">
<ArrowUpOutlined
className={`config-item-option-disa${index === 0 ? 'bled' : ''}`}
onClick={orderOptionFn.bind(this, index, false, index === 0)}
/>
<ArrowDownOutlined
className={`config-item-option-disa${
index === max ? 'bled' : ''
}`}
onClick={orderOptionFn.bind(this, index, true, index === max)}
/>
</div>
<DeleteOutlined
onClick={delOptionFn.bind(this, index)}
className="config-item-option-del"
/>
</div>
);
});
}
return (
<div className="config">
<If show={active !== -1}>
<>
{/* 标签 */}
<div className="config-item">
<p className="config-item-title">标签</p>
<div>
<Input
allowClear={true}
onChange={changeValue.bind(this, 'label')}
placeholder="请输入"
value={formList[active]?.label}
/>
</div>
</div>
{/* 是否必填 */}
<div className="config-item">
<p className="config-item-title">是否必填</p>
<div>
<Switch
onChange={changeValue.bind(this, 'required')}
checked={formList[active]?.required}
/>
</div>
</div>
{/* 提示语 */}
<div className="config-item">
<p className="config-item-title">提示语</p>
<div>
<Input
allowClear={true}
onChange={changeValue.bind(this, 'tips')}
placeholder="请输入"
value={formList[active]?.tips}
/>
</div>
</div>
{/* rule */}
<div className="config-item">
<p className="config-item-title">限制规则</p>
<div>
<Select
showSearch
onChange={changeValue.bind(this, 'rule')}
placeholder="请选择"
allowClear={true}
style={{ width: '100%' }}
value={formList[active]?.rule}
filterOption={(input, option) =>
(option?.children).includes(input)
}
>
{OptionsValidate.map((its) => {
return (
<Option key={its.value} value={its.value}>
{its.label}
</Option>
);
})}
</Select>
</div>
</div>
{/* options */}
<If show={active !== -1 && formList[active]?.options !== undefined}>
<div className="config-item">
<p className="config-item-title">选项</p>
<Tag
type="primary"
style={{ marginBottom: '10px', cursor: 'pointer' }}
onClick={addOptionFn.bind(this)}
color="blue"
>
新增选项
</Tag>
你可以对选项进行新增修改删除操作
<div>{renderOption()}</div>
</div>
</If>
<Button onClick={delItemFn.bind(this)} type="primary">
删除
</Button>
</>
</If>
</div>
);
};
export default Config;
right-index.less
@color: '#000';
@hover: '#0958d9';
@disabled: '#ccc';
@error: '#000';
.config {
width: 30%;
padding: 15px;
border: 1px solid #f1e8e8;
overflow: auto;
&-item {
margin-bottom: 10px;
padding-bottom: 15px;
border-bottom: 1px solid rgba(0, 0, 0, 0.07);
&-title {
color: #666;
}
&-option {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 5px;
padding: 5px;
user-select: none;
cursor: move;
input {
border: none;
outline: none;
padding: 2px 5px;
width: 30%;
background-color: #fff;
border: 1px solid #d9d9d9;
border-radius: 5px;
}
&-edit {
display: flex;
align-items: center;
> span {
margin-left: 5px;
}
}
&-disa {
cursor: pointer;
color: @color;
&:hover {
color: @hover;
}
}
&-disabled {
cursor: not-allowed;
color: @disabled;
}
&-del {
color: @error;
cursor: pointer;
}
}
}
}
right-If.jsx 控制下拉、单选、复选等选项数据值设置显影
const conditionContainer = (props) => {
return props.show ? props.children : '';
};
export default conditionContainer;
right-validate.js 表单校验规则
// 密码校验
export const validatePass = (rule, value) => {
if (value === '') {
return Promise.resolve();
} else {
if (!/^(?:\d+|[a-zA-Z]+|[.!@#$%^&*]+){6,12}$/.test(value)) {
return Promise.reject('请输入6-12位密码');
} else {
return Promise.resolve();
}
}
};
// 数字
export const validateNumber = (rule, value) => {
if (value != '') {
if (!/^[1-9]\d*$/.test(value)) {
return Promise.reject('只能输入数字');
} else {
return Promise.resolve();
}
} else {
return Promise.resolve();
}
};
// 金额
export const validatePrice = (rule, value) => {
if (value != '' && value != undefined && value != null) {
let num = parseFloat(value);
if (isNaN(num)) {
return Promise.reject('请输入有效金额');
} else {
return Promise.resolve();
}
} else {
return Promise.resolve();
}
};
// 不作为
export const validateNone = () => {
return Promise.resolve();
};
// 真实姓名
export const validateName = (rule, value) => {
if (value === '' || !value) {
return Promise.resolve();
} else {
if (!/^([\u4e00-\u9fa5]{1,20}|[a-zA-Z\.\s]{2,5})$/.test(value)) {
return Promise.reject('请输入真实姓名');
} else {
return Promise.resolve();
}
}
};
// 身份证
export const validateIdCard = (rule, value) => {
if (value != '' && value != undefined) {
if (
!/^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$|^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/.test(
value,
)
) {
return Promise.reject('请输入有效身份证');
} else {
return Promise.resolve();
}
} else {
return Promise.resolve();
}
};
//手机号
export const validatePhone = (rule, value) => {
if (value != '' && value != undefined) {
if (
!/^1(3[0-9]|4[5,7]|5[0,1,2,3,5,6,7,8,9]|6[2,5,6,7]|7[0,1,7,8]|8[0-9]|9[1,8,9])\d{8}$/.test(
value,
)
) {
return Promise.reject('请输入有效手机号');
} else {
return Promise.resolve();
}
} else {
return Promise.resolve();
}
};
// 检测支付宝账号
export const validateZFB = (rule, value) => {
if (
/^([a-zA-Z\d])(\w|\-)+@[a-zA-Z\d]+\.[a-zA-Z]{2,4}$/.test(value) ||
/^1[3456789]\d{9}$/.test(value)
) {
return Promise.resolve();
} else {
return Promise.reject('请输入有效支付宝账号');
}
};
// 邮箱
export const validateEmail = (rule, value) => {
let email = /^([a-zA-Z\d])(\w|\-)+@[a-zA-Z\d]+\.[a-zA-Z]{2,4}$/.test(value);
if (email) {
return Promise.resolve();
} else {
return Promise.reject('请输入有效邮箱');
}
};
export const OptionsValidate = [
{ label: '密码校验', value: 'validatePass' },
{ label: '数字', value: 'validateNumber' },
{ label: '金额', value: 'validatePrice' },
{ label: '不限制', value: 'validateNone' },
{ label: '真实姓名', value: 'validateName' },
{ label: '身份证', value: 'validateIdCard' },
{ label: '手机号', value: 'validatePhone' },
{ label: '支付宝账号', value: 'validateZFB' },
{ label: '邮箱', value: 'validateEmail' },
];