Files
dvcp_v2_webapp/ui/packages/common/AiAreaSelect.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>