根据uniapp调整工程结构
This commit is contained in:
210
components/AiTreePicker.vue
Normal file
210
components/AiTreePicker.vue
Normal file
@@ -0,0 +1,210 @@
|
||||
<template>
|
||||
<section class="AiTreePicker">
|
||||
<AiSearchPopup mode="bottom" ref="areaSelector">
|
||||
<div slot="btn" @tap="handleInit">
|
||||
<slot v-if="$slots.default" />
|
||||
<div v-else class="areaSelector">
|
||||
<u-input v-model="currentSelected.girdName" disabled class="noEvents" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="areaSelector">
|
||||
<div class="fixedTop">
|
||||
<span v-text="'全部'" :class="{ current: !index }" @click="selectNode({}, -1)" />
|
||||
<span v-for="(area, i) in fullSelected" :key="area.id" v-text="area.girdName" :class="{ current: area.id == index }" @click="selectNode(area, i)" />
|
||||
</div>
|
||||
<span class="placeholder" v-text="currentSelected.girdName" />
|
||||
</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.girdName" @tap="handleSelect(op)" />
|
||||
<u-icon v-if="showArrow(op)" name="arrow-right" color="#ddd" @click="getChild(op)" />
|
||||
</div>
|
||||
</AiSearchPopup>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// import AiCell from './AiCell'
|
||||
import { mapState } from 'vuex'
|
||||
|
||||
export default {
|
||||
name: 'AiTreePicker',
|
||||
components: {
|
||||
// AiCell
|
||||
},
|
||||
model: {
|
||||
prop: 'value',
|
||||
event: 'change',
|
||||
},
|
||||
props: {
|
||||
value: { default: '' },
|
||||
name: { default: '' },
|
||||
ops: { default: () => [] },
|
||||
},
|
||||
computed: {
|
||||
...mapState(['user']),
|
||||
currentSelected() {
|
||||
return this.fullSelected?.slice(-1)?.[0] || {}
|
||||
},
|
||||
origin() {
|
||||
let meta = JSON.parse(JSON.stringify(this.ops)),
|
||||
origin = []
|
||||
while (meta.length > 0) {
|
||||
let p = meta.shift()
|
||||
origin.push(p)
|
||||
if (p.girdList?.length > 0) {
|
||||
meta.push(p.girdList.map((c) => ({ ...c, parent: p.id })))
|
||||
}
|
||||
}
|
||||
return origin.flat()
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
fullSelected: [],
|
||||
index: '',
|
||||
list: [],
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value(v) {
|
||||
v && this.getFull()
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
getFull() {
|
||||
if (this.value) {
|
||||
let current = this.origin.find((e) => e.id == this.value),
|
||||
pend = [current]
|
||||
while (!!current.parent) {
|
||||
current = this.origin.find((e) => e.id == current.parent)
|
||||
pend.push(current)
|
||||
}
|
||||
this.fullSelected = pend.reverse()
|
||||
}
|
||||
},
|
||||
getgirdList(id) {
|
||||
if (id) this.list = this.origin?.find((e) => e.id == id)?.girdList || []
|
||||
else this.list = this.ops
|
||||
},
|
||||
handleSelect(op) {
|
||||
if (op.girdList?.length > 0) {
|
||||
this.getChild(op)
|
||||
} else {
|
||||
if (op.id != this.index) {
|
||||
this.fullSelected.push(op)
|
||||
this.index = op.id
|
||||
}
|
||||
this.$emit('select', op)
|
||||
this.$emit('update:name', this.currentSelected.name)
|
||||
this.$refs.areaSelector?.handleSelect()
|
||||
}
|
||||
},
|
||||
getChild(op) {
|
||||
this.fullSelected.push(op)
|
||||
this.index = op.id
|
||||
this.getgirdList(op.id)
|
||||
},
|
||||
selectNode(item, i) {
|
||||
this.fullSelected.splice(i + 1, this.fullSelected.length - i)
|
||||
if (item.girdList?.length <= 0) {
|
||||
this.index = item.id
|
||||
}
|
||||
this.getgirdList(item.id)
|
||||
},
|
||||
handleInit() {
|
||||
this.index = this.currentSelected.id
|
||||
this.getgirdList(this.currentSelected.id)
|
||||
},
|
||||
showArrow(op) {
|
||||
return this.index != op.id && op.girdList?.length > 0
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.index = this.value
|
||||
this.getFull()
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.AiTreePicker {
|
||||
::v-deep .areaSelector {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
span {
|
||||
cursor: pointer;
|
||||
color: #333;
|
||||
height: 120px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
&:first-of-type:before {
|
||||
content: '';
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
&:before {
|
||||
color: #333;
|
||||
content: '/';
|
||||
padding: 0 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.placeholder {
|
||||
height: 120px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.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 32px;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
::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;
|
||||
}
|
||||
}
|
||||
|
||||
::v-deep.noEvents {
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user