224 lines
5.0 KiB
Vue
224 lines
5.0 KiB
Vue
<template>
|
|
<section class="AiAreaPicker">
|
|
<ai-search-popup mode="bottom" ref="areaSelector">
|
|
<div slot="btn" @tap="handleInit">
|
|
<slot v-if="$slots.default"/>
|
|
<div v-else class="areaSelector">
|
|
<image :src="icon" class="location"/>
|
|
<div v-text="currentArea.name"/>
|
|
</div>
|
|
</div>
|
|
<div class="areaSelector">
|
|
<div class="fixedTop">
|
|
<span v-for="(area, i) in fullArea" :key="area.id" v-text="area.name" :class="{ current: area.id == index }"
|
|
@click="selectNode(area, i)"/>
|
|
</div>
|
|
<span v-text="currentArea.name"/>
|
|
</div>
|
|
<div class="pendingItem flexRow" flex v-for="op in list" :key="op.id">
|
|
<div class="fill" :class="{ self: index == op.id }" v-html="op.name" @tap="handleSelect(op)"/>
|
|
<u-icon v-if="index != op.id" name="arrow-right" color="#ddd" @click="getChild(op)"/>
|
|
</div>
|
|
</ai-search-popup>
|
|
</section>
|
|
</template>
|
|
|
|
<script>
|
|
import AiSearchPopup from './AiSearchPopup'
|
|
import AiCell from './AiCell.vue'
|
|
import {mapState} from 'vuex'
|
|
|
|
export default {
|
|
name: 'AiAreaPicker',
|
|
components: {AiCell, AiSearchPopup},
|
|
props: {
|
|
areaId: {default: ''},
|
|
name: {default: ''},
|
|
all: Boolean,
|
|
},
|
|
computed: {
|
|
...mapState(['user']),
|
|
dataRange() {
|
|
let rules = [10, 8, 6, 3, 0],
|
|
level = 0
|
|
if (this.all) return (level = 0)
|
|
rules.some((e, i) => {
|
|
let reg = new RegExp(`0{${e}}`, 'g')
|
|
if (reg.test(this.areaId || this.user.areaId || this.$areaId)) {
|
|
return (level = i)
|
|
}
|
|
})
|
|
return level
|
|
},
|
|
currentArea() {
|
|
return this.fullArea?.slice(-1)?.[0] || {}
|
|
},
|
|
icon() {
|
|
return this.$cdn + 'location.svg'
|
|
},
|
|
},
|
|
data() {
|
|
return {
|
|
fullArea: [{name: '全国', id: 0}],
|
|
index: '',
|
|
list: [],
|
|
}
|
|
},
|
|
watch: {
|
|
areaId(v) {
|
|
v && this.getFullArea()
|
|
},
|
|
},
|
|
methods: {
|
|
getFullArea() {
|
|
let areaId = this.areaId || (this.all ? '' : this.$areaId)
|
|
areaId &&
|
|
this.$http
|
|
.post('/admin/area/getAllParentAreaId', null, {
|
|
withoutToken: true,
|
|
params: {areaId},
|
|
})
|
|
.then((res) => {
|
|
if (res?.data) {
|
|
if (res.data.length > 1) {
|
|
this.fullArea = res.data.reverse().slice(this.dataRange)
|
|
} else {
|
|
this.fullArea = res.data
|
|
}
|
|
this.fullArea.unshift({name: '全国', id: 0})
|
|
}
|
|
})
|
|
},
|
|
getChildAreas(id) {
|
|
id &&
|
|
this.$http
|
|
.post('/admin/area/queryAreaByParentId', null, {
|
|
withoutToken: true,
|
|
params: {id},
|
|
})
|
|
.then((res) => {
|
|
if (res?.data) {
|
|
this.list = res.data
|
|
let self = this.fullArea.find((e) => e.id == this.index)
|
|
this.list.unshift(self)
|
|
}
|
|
})
|
|
},
|
|
getProvinces() {
|
|
this.$http.post('/admin/area/queryProvinceList', null, {withoutToken: true}).then((res) => {
|
|
if (res?.data) {
|
|
this.list = res.data
|
|
}
|
|
})
|
|
},
|
|
handleSelect(op) {
|
|
if (op.id != this.index) {
|
|
this.fullArea.push(op)
|
|
this.index = op.id
|
|
}
|
|
this.$emit('select', op)
|
|
this.$emit('update:name', this.currentArea.name)
|
|
this.$refs.areaSelector?.handleSelect()
|
|
},
|
|
getChild(op) {
|
|
this.fullArea.push(op)
|
|
this.index = op.id
|
|
this.getChildAreas(op.id)
|
|
},
|
|
selectNode(area, i) {
|
|
this.fullArea.splice(i + 1, this.fullArea.length - i)
|
|
if (this.all && !area.id) {
|
|
this.index = ''
|
|
this.getProvinces()
|
|
} else {
|
|
this.index = area.id
|
|
this.getChildAreas(area.id)
|
|
}
|
|
},
|
|
handleInit() {
|
|
this.index = this.currentArea.id
|
|
if (this.all && !this.currentArea.id) this.getProvinces()
|
|
else this.getChildAreas(this.currentArea.id)
|
|
},
|
|
},
|
|
created() {
|
|
this.index = this.areaId
|
|
this.getFullArea()
|
|
},
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.AiAreaPicker {
|
|
::v-deep .areaSelector {
|
|
display: flex;
|
|
align-items: center;
|
|
|
|
span {
|
|
cursor: pointer;
|
|
color: #333;
|
|
|
|
&:first-of-type:before {
|
|
content: '';
|
|
padding: 0;
|
|
}
|
|
|
|
&:before {
|
|
color: #333;
|
|
content: '/';
|
|
padding: 0 16px;
|
|
}
|
|
}
|
|
|
|
.current {
|
|
color: #3f8df5;
|
|
}
|
|
|
|
.fixedTop {
|
|
position: fixed;
|
|
top: 0;
|
|
width: 100%;
|
|
left: 0;
|
|
background: #fff;
|
|
border-bottom: 4px solid #f5f5f5;
|
|
z-index: 1;
|
|
text-align: start;
|
|
padding: 0 16px;
|
|
}
|
|
}
|
|
|
|
::v-deep.u-drawer-content {
|
|
position: fixed;
|
|
|
|
.areaSelector {
|
|
padding: 0 16px;
|
|
box-sizing: border-box;
|
|
border-bottom: 16px solid #f5f5f5;
|
|
|
|
span {
|
|
line-height: 100px;
|
|
}
|
|
}
|
|
}
|
|
|
|
::v-deep.pendingItem {
|
|
color: #333;
|
|
margin-left: 32px;
|
|
padding-right: 32px;
|
|
height: 104px;
|
|
border-bottom: 1px solid #ddd;
|
|
text-align: start;
|
|
|
|
.self {
|
|
font-weight: bold;
|
|
}
|
|
}
|
|
|
|
.location {
|
|
width: 28px;
|
|
height: 80px;
|
|
margin-right: 12px;
|
|
}
|
|
}
|
|
</style>
|