274 lines
7.8 KiB
Vue
274 lines
7.8 KiB
Vue
<template>
|
|
<section class="AiAreaSelect">
|
|
<el-row type="flex" :gutter="5">
|
|
<el-col v-for="(item,i) in areaInfo" :key="i" v-show="isShowSelector(i)" style="width: auto;">
|
|
<el-select :size="selectClass" v-if="areaLists[i].length>0||alwaysShow" @focus="$emit('focus')"
|
|
@blur="$emit('blur')" :placeholder="placeVal[i]" clearable
|
|
:disabled="isDisabledSelector(i)" :value="areaInfo[i]" @change="v=>handleSelectorChange(v,i)">
|
|
<template v-if="lockFirstOption&&i==(hideNum||0)">
|
|
<el-option v-if="!areaInfo[i]||areaInfo[i]===area.id" v-for="(area,j) in areaLists[i]" :key="j"
|
|
:value="area.id" :label="area.name"/>
|
|
</template>
|
|
<el-option v-else v-for="(area,j) in areaLists[i]" :key="j" :value="area.id" :label="area.name"/>
|
|
</el-select>
|
|
</el-col>
|
|
</el-row>
|
|
</section>
|
|
</template>
|
|
|
|
<script>
|
|
export default {
|
|
name: "AiAreaSelect",
|
|
model: {
|
|
prop: 'value',
|
|
event: 'change',
|
|
},
|
|
inject: {
|
|
elFormItem: {default: ""},
|
|
},
|
|
props: {
|
|
value: String,
|
|
areaLevel: {type: [Number, String], default: 5},
|
|
disabledLevel: {type: [Number, String], default: 0},
|
|
disabled: {type: Boolean, default: false},
|
|
hideLevel: {type: [Number, String], default: 0},
|
|
valueLevel: {type: [Number, String], default: -1},
|
|
alwaysShow: {type: Boolean, default: false},
|
|
selectClass: {type: String, default: 'small'},
|
|
lockFirstOption: {type: Boolean, default: false},
|
|
instance: Function,
|
|
action: String,
|
|
provinceAction: String
|
|
},
|
|
computed: {
|
|
hideNum() {
|
|
return Number(this.hideLevel)
|
|
},
|
|
disabledNum() {
|
|
return Number(this.disabledLevel)
|
|
},
|
|
showNum() {
|
|
return Number(this.areaLevel)
|
|
},
|
|
valueIndex() {
|
|
return Number(this.valueLevel)
|
|
},
|
|
current() {
|
|
return this.selected || this.value
|
|
},
|
|
areaInfo() {
|
|
let info = {}
|
|
const currentLevel = this.getLevelByAreaId(this.current)
|
|
for (let i = 0; i < this.showNum; i++) {
|
|
//防止地区代码出现,在获取到选项后再赋值
|
|
if (i <= currentLevel) info[i] = this.areaLists[i]?.length ? this.getAreaByAreaType(i) : ""
|
|
else info[i] = null
|
|
}
|
|
return info
|
|
},
|
|
areaObj() {
|
|
let info = {}
|
|
for (let key in this.areaInfo) {
|
|
if (this.areaInfo[key]) {
|
|
info[key] = this.areaLists[key].find(e => e.id === this.areaInfo[key])
|
|
}
|
|
}
|
|
return info
|
|
},
|
|
selectedName() {
|
|
const index = this.getLevelByAreaId(this.current)
|
|
if (index > -1) {
|
|
const area = this.areaLists[index].find(e => e.id === this.current)
|
|
return area ? area.name : ""
|
|
} else return ""
|
|
},
|
|
selectedFullName() {
|
|
let name = ""
|
|
for (let i in this.areaInfo) {
|
|
if (this.areaInfo[i]) {
|
|
const area = this.areaLists[i].find(e => e.id === this.areaInfo[i])
|
|
name += area ? area.name : ""
|
|
}
|
|
}
|
|
return name
|
|
},
|
|
areaLelve() {
|
|
return this.getLevelByAreaId(this.current);
|
|
}
|
|
},
|
|
watch: {
|
|
selected() {
|
|
if (this.valueIndex > -1) {
|
|
this.$emit("change", this.areaInfo[this.valueIndex] || null)
|
|
} else {
|
|
this.$emit("change", this.current)
|
|
}
|
|
this.$emit("area", this.areaInfo);
|
|
this.$emit('areaLelve', this.areaLelve)
|
|
},
|
|
areaObj() {
|
|
this.$emit("areaObj", this.areaObj)
|
|
},
|
|
selectedName() {
|
|
this.$emit("name", this.selectedName)
|
|
},
|
|
selectedFullName() {
|
|
this.$emit("fullname", this.selectedFullName)
|
|
},
|
|
valueLevel() {
|
|
this.refreshAreaList();
|
|
},
|
|
value(v) {
|
|
//特殊处置结果 后台传值赋值改变需要重新加载数据
|
|
this.dispatch('ElFormItem', 'el.form.change', [v]);
|
|
if (!this.selected) {
|
|
this.refreshAreaList();
|
|
}
|
|
}
|
|
},
|
|
data() {
|
|
return {
|
|
selected: null,
|
|
areaLists: {
|
|
0: [],
|
|
1: [],
|
|
2: [],
|
|
3: [],
|
|
4: [],
|
|
},
|
|
placeVal: {
|
|
0: '请选择省',
|
|
1: '请选择市',
|
|
2: '请选择区',
|
|
3: '请选择镇',
|
|
4: '请选择村'
|
|
},
|
|
ProvinceCityCounty: []
|
|
}
|
|
},
|
|
methods: {
|
|
isShowSelector(i) {
|
|
let index = Number(i)
|
|
return index >= this.hideNum
|
|
},
|
|
isDisabledSelector(i) {
|
|
let index = Number(i)
|
|
return this.disabled || (index < this.disabledNum)
|
|
},
|
|
handleSelectorChange(area, index) {
|
|
if (area) {
|
|
this.selected = area
|
|
if (index < 4 && this.areaInfo[index]) {
|
|
this.getAreasByParentId(index).then(() => {
|
|
for (let i = index; i < this.showNum; i++) {
|
|
if (this.areaLists[i + 2]) this.areaLists[i + 2] = []
|
|
}
|
|
})
|
|
}
|
|
} else {//清空操作
|
|
let i = Number(index), pre = i - 1, origin = JSON.parse(JSON.stringify(this.areaInfo))
|
|
if (pre > 0) {
|
|
this.selected = origin[pre]
|
|
for (let j = i + 1; j < this.showNum; j++) {
|
|
this.areaLists[j] = []
|
|
}
|
|
} else {
|
|
this.selected = origin[0]
|
|
for (let j = i + 2; j < this.showNum; j++) {
|
|
this.areaLists[j] = []
|
|
}
|
|
}
|
|
}
|
|
},
|
|
getAreasByParentId(index) {
|
|
index = Number(index)
|
|
return new Promise((resolve) => {
|
|
this.areaLists[index + 1] = []
|
|
if (index < 2) {
|
|
index = Number(index)
|
|
let data = this.ProvinceCityCounty.filter(e => e.parentId == this.areaInfo[index])
|
|
if (data && (index + 1 < this.showNum)) this.areaLists[index + 1] = data
|
|
this.$forceUpdate();
|
|
resolve(index)
|
|
} else {
|
|
this.instance.post(this.action || "/admin/area/queryAreaByParentId", null, {
|
|
withoutToken: true,
|
|
params: {id: this.areaInfo[index]}
|
|
}).then(res => {
|
|
if (res?.data) {
|
|
index = Number(index)
|
|
if (index + 1 < this.showNum) this.areaLists[index + 1] = res.data
|
|
this.$forceUpdate()
|
|
}
|
|
resolve(index)
|
|
})
|
|
}
|
|
|
|
})
|
|
},
|
|
getProvinceCityCounty() {
|
|
return this.instance.post(this.provinceAction || "/admin/area/queryProvinceListContainCity", null, {withoutToken: true})
|
|
},
|
|
getAreaByAreaType(areaType) {
|
|
let lvCount = [2, 4, 6, 9, 12]
|
|
return this.current?.split("").map((e, i) => i < lvCount[areaType] ? e : 0).join("")
|
|
},
|
|
getLevelByAreaId(code) {
|
|
if (code) {
|
|
if (code.length == 2 || code.endsWith('0000000000')) return 0
|
|
else if (code.endsWith('00000000')) return 1
|
|
else if (code.endsWith('000000')) return 2
|
|
else if (code.endsWith('000')) return 3
|
|
else return 4
|
|
} else return -1
|
|
},
|
|
refreshAreaList() {
|
|
for (let i = 0; i < this.showNum; i++) {
|
|
this.areaLists[i] = []
|
|
}
|
|
this.getProvinceCityCounty().then(res => {
|
|
this.ProvinceCityCounty = res.data
|
|
this.areaLists[0] = res.data.filter(d => !d.parentId)
|
|
const getAreaList = i => {
|
|
if (this.areaInfo?.[i])
|
|
this.getAreasByParentId(i).then(next => getAreaList(next + 1))
|
|
}
|
|
getAreaList(0)
|
|
})
|
|
},
|
|
/**
|
|
* 表单验证
|
|
* @param componentName
|
|
* @param eventName
|
|
* @param params
|
|
*/
|
|
dispatch(componentName, eventName, params) {
|
|
let parent = this.$parent || this.$root;
|
|
let name = parent.$options.componentName;
|
|
|
|
while (parent && (!name || name !== componentName)) {
|
|
parent = parent.$parent;
|
|
|
|
if (parent) {
|
|
name = parent.$options.componentName;
|
|
}
|
|
}
|
|
if (parent) {
|
|
parent.$emit.apply(parent, [eventName].concat(params));
|
|
}
|
|
},
|
|
},
|
|
created() {
|
|
this.refreshAreaList()
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.AiAreaSelect {
|
|
.el-col {
|
|
min-width: 90px;
|
|
}
|
|
}
|
|
</style>
|