56 lines
1.9 KiB
Plaintext
56 lines
1.9 KiB
Plaintext
import React, { useState, useMemo } from 'react';
|
|
import './PlateInput.css';
|
|
|
|
export default function PlateInput({
|
|
modelValue = '',
|
|
provinces = ['京', '沪', '粤', '津', '冀', '鲁', '苏', '浙', '川', '渝'],
|
|
onChange
|
|
}) {
|
|
const [prov, setProv] = useState(modelValue ? modelValue[0] : '京');
|
|
const [body, setBody] = useState(modelValue ? modelValue.slice(1) : '');
|
|
const [focused, setFocused] = useState(false);
|
|
|
|
const valid = /^[A-Z][A-Z0-9]{5}$/.test(body) || /^[A-Z][A-Z0-9]{6}$/.test(body);
|
|
const invalid = !!body && !valid;
|
|
const isNewEnergy = /^[A-Z][A-Z0-9]{6}$/.test(body);
|
|
const tipClass = !body ? '' : valid ? 'valid' : 'invalid';
|
|
const tipText = !body
|
|
? '格式:省份 + 字母 + 5/6 位(新能源 6 位)'
|
|
: valid
|
|
? '车牌号合法:' + prov + body + '<span class="aa-plate-tag">' + (isNewEnergy ? '新能源' : '普通') + '</span>'
|
|
: '车牌格式不正确(首位应为字母)';
|
|
|
|
const onInput = (e) => {
|
|
const v = e.target.value.toUpperCase().replace(/[^A-Z0-9]/g, '').slice(0, 7);
|
|
e.target.value = v;
|
|
setBody(v);
|
|
if (onChange) onChange(prov + v);
|
|
};
|
|
|
|
return (
|
|
<div className="aa-plate">
|
|
<div
|
|
className={'aa-plate-field' + (focused ? ' is-focus' : '') + (valid ? ' is-valid' : '') + (invalid ? ' is-invalid' : '')}
|
|
>
|
|
<select className="aa-plate-prov" value={prov} onChange={(e) => setProv(e.target.value)}>
|
|
{provinces.map((p) => (
|
|
<option key={p} value={p}>
|
|
{p}
|
|
</option>
|
|
))}
|
|
</select>
|
|
<input
|
|
className="aa-plate-input"
|
|
value={body}
|
|
maxLength={7}
|
|
placeholder="A12345"
|
|
onInput={onInput}
|
|
onFocus={() => setFocused(true)}
|
|
onBlur={() => setFocused(false)}
|
|
/>
|
|
</div>
|
|
<div className={'aa-plate-tip ' + tipClass} dangerouslySetInnerHTML={{ __html: tipText }} />
|
|
</div>
|
|
);
|
|
}
|