Validator.jsx 6.9 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
import React from 'react';
import {
	Upload,
	Input,
	Button,
	Select,
	Icon,
	Row,
	Col,
	message,
	Tag,
	Tooltip,
	Card,
	Divider,
	Switch,
	InputNumber,
	Form,
} from 'antd';
import AceEditor from 'react-ace';
import 'brace/mode/javascript';
徐立's avatar
徐立 committed
21
import UUID from 'react-native-uuid';
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
const FormItem = Form.Item;
const Option = Select.Option;
const types = {
	string: '字符',
	number: '数字',
	boolean: '布尔值',
	method: '公式',
	regexp: '正则表达式',
	integer: '整数',
	float: '浮点数',
	array: '列表',
	object: '对象',
	enum: '枚举',
	date: '日期',
	url: '超链接',
	hex: '16进制数',
	email: '邮箱',
	any: '任意',
};
徐立's avatar
徐立 committed
41

42 43 44 45 46
class Enums extends React.Component {
	state = {
		inputVisible: false,
		inputValue: '',
	};
徐立's avatar
徐立 committed
47

48 49 50 51
	handleClose = (removedTag) => {
		const tags = this.props.value.filter((tag) => tag !== removedTag);
		this.props.onChange(tags);
	};
徐立's avatar
徐立 committed
52

53 54 55
	showInput = () => {
		this.setState({ inputVisible: true }, () => this.input.focus());
	};
徐立's avatar
徐立 committed
56

57 58 59
	handleInputChange = (e) => {
		this.setState({ inputValue: e.target.value });
	};
徐立's avatar
徐立 committed
60

61 62 63 64 65 66
	handleInputConfirm = () => {
		const { inputValue } = this.state;
		let tags = this.props.value;
		if (inputValue && tags.indexOf(inputValue) === -1) {
			tags = [...tags, inputValue];
		}
徐立's avatar
徐立 committed
67

68 69 70 71 72 73
		this.setState({
			inputVisible: false,
			inputValue: '',
		});
		this.props.onChange(tags);
	};
徐立's avatar
徐立 committed
74

75
	saveInputRef = (input) => (this.input = input);
徐立's avatar
徐立 committed
76

77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
	render() {
		const { inputVisible, inputValue } = this.state;
		const tags = this.props.value;
		return (
			<div>
				{tags.map((tag, index) => {
					const isLongTag = tag.length > 20;
					const tagElem = (
						<Tag key={tag} onClose={() => this.handleClose(tag)}>
							{isLongTag ? `${tag.slice(0, 20)}...` : tag}
						</Tag>
					);
					return isLongTag ? (
						<Tooltip title={tag} key={tag}>
							{tagElem}
						</Tooltip>
					) : (
						tagElem
					);
				})}
				{inputVisible && (
					<Input
						ref={this.saveInputRef}
						type="text"
						size="small"
						style={{ width: 78 }}
						value={inputValue}
						onChange={this.handleInputChange}
						onBlur={this.handleInputConfirm}
						onPressEnter={this.handleInputConfirm}
					/>
				)}
				{!inputVisible && (
					<Tag onClick={this.showInput} style={{ background: '#fff', borderStyle: 'dashed' }}>
						<Icon type="plus" /> New Tag
					</Tag>
				)}
			</div>
		);
	}
}
徐立's avatar
徐立 committed
118

119 120 121 122
export default class Validator extends React.Component {
	constructor(props) {
		super(props);
		const value = props.value || [];
徐立's avatar
徐立 committed
123

124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
		this.state = { rules: value };
	}
	triggerChange = (changedValue) => {
		// Should provide an event to pass value to Form.
		const onChange = this.props.onChange;
		if (onChange) {
			onChange(changedValue);
		}
	};
	componentWillReceiveProps(nextProps) {
		// Should be a controlled component.
		if ('value' in nextProps) {
			const value = nextProps.value;
			this.setState(value);
		}
	}
	change = (i, t, e) => {
		const { rules } = this.state;
		if (t == 'message' || t == 'pattern') {
			rules[i][t] = e.target.value;
		} else {
			rules[i][t] = e;
			if (t == 'type' && e == 'date') {
				rules[i].validatorFunc =
					"var errors = [];if (!( typeof value.getTime === 'function' &&typeof value.getMonth === 'function' &&typeof value.getYear === 'function')) {errors.push(new Error('请输入日期!', rule.field));} callback(errors);";
			}
		}
徐立's avatar
徐立 committed
151

152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194
		if (!('value' in this.props)) {
			this.setState({ rules });
		}
		this.triggerChange(rules);
	};
	add = () => {
		const { rules } = this.state;
		rules.push({ id: UUID.v4(), message: '请输入' });
		if (!('value' in this.props)) {
			this.setState({ rules });
		}
		this.triggerChange(rules);
	};
	delete = (i) => {
		const { rules } = this.state;
		rules.splice(i, 1);
		if (!('value' in this.props)) {
			this.setState({ rules });
		}
		this.triggerChange(rules);
	};
	render() {
		const { rules } = this.state;
		return (
			<div>
				<Button size="small" type="primary" style={{ margin: 'auto' }} onClick={this.add}>
					新增
				</Button>
				<div style={{ minHeight: 10 }}>
					{rules.map((r, i) => (
						<div key={r.id}>
							<FormItem label="类型" labelCol={{ span: 8 }} wrapperCol={{ span: 16 }}>
								<Select
									style={{ width: 150 }}
									onChange={this.change.bind(this, i, 'type')}
									value={r.type}>
									{Object.keys(types).map((ty) => (
										<Option key={ty} value={ty}>
											{types[ty]}
										</Option>
									))}
								</Select>
							</FormItem>
徐立's avatar
徐立 committed
195

196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230
							<FormItem label="是否必填" labelCol={{ span: 8 }} wrapperCol={{ span: 16 }}>
								<Switch onChange={this.change.bind(this, i, 'required')} checked={r.required} />
							</FormItem>
							<FormItem label="正则表达式" labelCol={{ span: 8 }} wrapperCol={{ span: 16 }}>
								<Input onChange={this.change.bind(this, i, 'pattern')} value={r.pattern} />
							</FormItem>
							<FormItem label="最小值" labelCol={{ span: 8 }} wrapperCol={{ span: 16 }}>
								<InputNumber onChange={this.change.bind(this, i, 'min')} value={r.min} />
							</FormItem>
							<FormItem label="最大值" labelCol={{ span: 8 }} wrapperCol={{ span: 16 }}>
								<InputNumber onChange={this.change.bind(this, i, 'max')} value={r.max} />
							</FormItem>
							<FormItem label="长度" labelCol={{ span: 8 }} wrapperCol={{ span: 16 }}>
								<InputNumber onChange={this.change.bind(this, i, 'len')} value={r.len} />
							</FormItem>
							<FormItem
								label={
									<span>
										<span style={{ color: 'red' }}> * </span>
										错误提示
									</span>
								}
								labelCol={{ span: 8 }}
								wrapperCol={{ span: 16 }}>
								<Input onChange={this.change.bind(this, i, 'message')} value={r.message} />
							</FormItem>
							<FormItem label="枚举" labelCol={{ span: 8 }} wrapperCol={{ span: 16 }}>
								<Enums onChange={this.change.bind(this, i, 'enum')} value={r.enum || []} />
							</FormItem>
							<FormItem label="自定义验证" labelCol={{ span: 24 }} wrapperCol={{ span: 24 }}>
								<AceEditor
									height={300}
									width="100%"
									onChange={this.change.bind(this, i, 'validatorFunc')}
									placeholder="var errors = [];\n
徐立's avatar
徐立 committed
231 232
if (value == 'xxx') {
errors.push(new Error('请输入正确值!', rule.field));
233
}
徐立's avatar
徐立 committed
234 235
callback(errors);
"
236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254
									mode={'javascript'}
									theme={'textmate'}
									fontSize={12}
									showPrintMargin={true}
									showGutter={true}
									highlightActiveLine={true}
									value={r.validatorFunc}
									name="UNIQUE_ID_OF_DIV"
									// keyboardHandler="vim"
									setOptions={{
										enableBasicAutocompletion: true,
										enableLiveAutocompletion: true,
										enableSnippets: true,
										showLineNumbers: true,
										tabSize: 2,
									}}
									editorProps={{ $blockScrolling: true }}
								/>
							</FormItem>
徐立's avatar
徐立 committed
255

256 257 258 259 260 261 262 263 264 265 266 267 268
							<Button
								type="danger"
								style={{ margin: 'auto' }}
								size="small"
								onClick={this.delete.bind(this, i)}>
								删除
							</Button>
						</div>
					))}
				</div>
			</div>
		);
	}
徐立's avatar
徐立 committed
269
}