AiAreaPicker

This commit is contained in:
花有清香月有阴
2021-12-10 16:47:42 +08:00
parent 9662dae6bd
commit 1d98c00999
5 changed files with 278 additions and 26 deletions

View File

@@ -0,0 +1,222 @@
<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 + '/img/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>