66 lines
1.9 KiB
Vue
66 lines
1.9 KiB
Vue
<template>
|
|
<div class="aa-plate">
|
|
<div class="aa-plate-field" :class="{ 'is-focus': focused, 'is-valid': valid, 'is-invalid': invalid }">
|
|
<select class="aa-plate-prov" v-model="prov">
|
|
<option v-for="p in provinces" :key="p" :value="p">{{ p }}</option>
|
|
</select>
|
|
<input
|
|
class="aa-plate-input"
|
|
:value="body"
|
|
maxlength="7"
|
|
placeholder="A12345"
|
|
@input="onInput"
|
|
@focus="focused = true"
|
|
@blur="focused = false"
|
|
/>
|
|
</div>
|
|
<div class="aa-plate-tip" :class="tipClass" v-html="tipText"></div>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
export default {
|
|
name: 'AaPlateInput',
|
|
props: {
|
|
value: { type: String, default: '' },
|
|
provinces: { type: Array, default: () => ['京', '沪', '粤', '津', '冀', '鲁', '苏', '浙', '川', '渝'] }
|
|
},
|
|
data() {
|
|
return {
|
|
prov: this.value ? this.value[0] : '京',
|
|
body: this.value ? this.value.slice(1) : '',
|
|
focused: false
|
|
};
|
|
},
|
|
computed: {
|
|
valid() {
|
|
return /^[A-Z][A-Z0-9]{5}$/.test(this.body) || /^[A-Z][A-Z0-9]{6}$/.test(this.body);
|
|
},
|
|
invalid() {
|
|
return !!this.body && !this.valid;
|
|
},
|
|
isNewEnergy() {
|
|
return /^[A-Z][A-Z0-9]{6}$/.test(this.body);
|
|
},
|
|
tipClass() {
|
|
if (!this.body) return '';
|
|
return this.valid ? 'valid' : 'invalid';
|
|
},
|
|
tipText() {
|
|
if (!this.body) return '格式:省份 + 字母 + 5/6 位(新能源 6 位)';
|
|
if (this.valid) return '车牌号合法:' + this.prov + this.body + '<span class="aa-plate-tag">' + (this.isNewEnergy ? '新能源' : '普通') + '</span>';
|
|
return '车牌格式不正确(首位应为字母)';
|
|
}
|
|
},
|
|
methods: {
|
|
onInput(e) {
|
|
this.body = e.target.value.toUpperCase().replace(/[^A-Z0-9]/g, '').slice(0, 7);
|
|
e.target.value = this.body;
|
|
this.$emit('input', this.prov + this.body);
|
|
}
|
|
}
|
|
};
|
|
</script>
|
|
|
|
<style src="./PlateInput.css"></style>
|