账号界面

This commit is contained in:
aixianling
2024-12-12 15:40:27 +08:00
parent 39f6275e31
commit 823c327894
7 changed files with 375 additions and 5 deletions

View File

@@ -0,0 +1,379 @@
<template>
<section class="ai-area">
<div v-if="inputClicker&&!$scopedSlots.default" @click="chooseArea" class="input-clicker">
<el-row type="flex" justify="space-between">
<div class="prepend">
<i style="font-size: 16px" class="iconfont iconLocation"/>
切换地区
</div>
<div class="content nowrap-text fill" v-text="fullName"/>
<i class="iconfont iconChange pad-r10"/>
</el-row>
</div>
<el-button v-else-if="!customClicker&&!$scopedSlots.default" class="area-btn" type="primary" size="mini"
@click="chooseArea">
{{ btnShowArea ? selectedArea.name : "切换地区" }}
</el-button>
<a class="custom-clicker" v-else @click="chooseArea">
<slot :areaname="selectedArea.name" :fullname="fullName" :id="selected"/>
</a>
<ai-dialog :visible.sync="dialog" title="选择地区" width="60%" @onConfirm="confirmArea" :modal="mask"
@open="selected=(value||'')">
<ai-highlight content="您当前选择&nbsp;@v" :value="selectedArea.name" color="#333" bold/>
<div class="area_edge">
<div class="area-box" v-for="ops in showOps">
<h2 v-text="ops.header"/>
<div class="area-item" :class="{selected: selectedMap.includes(area.id)}" v-for="area in ops.list"
@click="getChildrenAreas(area)">
<ai-badge>
<span>{{ area.name }}</span>
<div slot="badge" v-if="showBadge&&area.tipName" :class="getLabelClassByLabelType(area.labelType)">
{{ area.tipName }}
</div>
</ai-badge>
</div>
</div>
</div>
</ai-dialog>
</section>
</template>
<script>
import instance from "../../../lib/js/request";
import Area from "../../../lib/js/area";
export default {
name: 'AiArea',
inject: {
elFormItem: {default: ""},
elForm: {default: ''},
},
model: {
prop: 'value',
event: 'change'
},
props: {
instance: {default: () => instance},
action: String,
areaLevel: {type: [Number, String], default: 5},
btnShowArea: {type: Boolean, default: false},
customClicker: {type: Boolean, default: false},
disabled: {type: Boolean, default: false},
hideLevel: {type: [Number, String], default: 0},
inputClicker: {type: Boolean, default: true},
provinceAction: String,
separator: {type: String, default: ""},
showBadge: {type: Boolean, default: true},
value: String,
valueLevel: {type: [Number, String], default: -1},
root: String,
mask: {type: Boolean, default: true}
},
data() {
return {
selected: null,
areaOps: [],
fullName: '',
dialog: false,
ProvinceCityCounty: [],
}
},
computed: {
rootArea: v => new Area(v.root),
currentArea: v => v.selected || v.value,
startLevel: v => Math.max(Number(v.hideLevel), 0, v.rootArea.level),//地区最高可选行政地区等级
endLevel: v => Number(v.areaLevel) || 0,//地区最低可选行政地区等级
selectedArea: v => new Area(v.currentArea, v.hashMap),
selectedMap: v => v.selectedArea.areaMap,
validateState: v => ['', 'success'].includes(v.elFormItem?.validateState),
hashMap() {
//地区数据缓存器,用于快速获取数据
const hash = {}
this.areaOps.flat().map(e => hash[e.id] = e)
return hash
},
showOps() {
const levelLabels = {
0: "省/直辖市",
1: "市",
2: "县/区",
3: "乡/镇/街道",
4: "村/社区"
}
let ops = this.areaOps.map((list, i) => ({
header: levelLabels[i], i, list
})).slice(Math.max(0, this.startLevel), this.endLevel)
if (this.startLevel > 0 && ops.length > 0) {
const tmp = this.$copy(ops[0]?.list?.[0] || {})
if (this.startLevel >= ops[0].i) {
const opsMap = this.selectedMap.length > 0 ? this.selectedMap : this.rootArea.areaMap
ops[0].list = [this.hashMap[opsMap[ops[0].i]]].filter(Boolean) || []
} else {
const prev = +tmp.type - 1
const prevId = tmp.parentId
prev > -1 && ops.unshift({header: levelLabels[prev], list: [this.hashMap[prevId]]})
}
}
return ops
}
},
watch: {
value: {
immediate: true,
handler(v) {
this.dispatch('ElFormItem', 'el.form.change', [v]);
this.initAreaName()
}
}
},
methods: {
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));
}
},
chooseArea() {
if (this.disabled) return
this.selected = this.$copy(this.value)
this.initOptions().then(() => this.dialog = true)
},
confirmArea() {
if (this.valueLevel > -1) {
this.$emit("change", this.selectedMap[this.valueLevel])
} else {
this.$emit("change", this.selected)
}
this.$emit("area", this.selected, this.selectedArea);
this.dialog = false
},
getChildrenAreas(area) {
this.selected = area.id;
const level = Area.getLevelByAreaId(area.id);
if (level < 4) {
this.getAreasByParentId(area.id).then(list => {
this.areaOps.splice(level + 1, 5, list)
})
}
},
getAreasByParentId(id) {
const level = Area.getLevelByAreaId(id)
return new Promise(resolve => {
if (level < 2) {
this.getProvinceCityCounty().then(() => {
resolve(this.ProvinceCityCounty.filter(e => e.parentId == id))
})
} else {
this.instance.post(this.action || "/admin/area/queryAreaByParentId", null, {
withoutToken: true,
params: {id}
}).then(res => {
if (res?.data) {
resolve(res.data)
}
})
}
})
},
getLabelClassByLabelType(type) {
let cls = "badge-label"
switch (type) {
case '1':
cls += ' label-town'
break;
case '3':
cls += ' label-village'
break;
default:
cls += ' label-poor'
break
}
return cls
},
getProvinceCityCounty() {
return new Promise(resolve => {
if (localStorage.getItem("ProvinceCityCounty")) {
resolve(JSON.parse(localStorage.getItem("ProvinceCityCounty")))
} else {
this.instance.post(this.provinceAction || "/admin/area/queryProvinceListContainCity", null, {
withoutToken: true
}).then(res => {
if (res && res.data) {
localStorage.setItem("ProvinceCityCounty", JSON.stringify(res.data))
resolve(res.data)
}
})
}
}).then(list => this.ProvinceCityCounty = list)
},
initOptions() {
this.areaOps = []
const opsMap = this.selectedMap.length > 0 ? this.selectedMap : this.rootArea.areaMap
let map = {};
return Promise.all([null, ...opsMap].map((id, i) => this.getAreasByParentId(id).then(list => map[i] = list))).then(() => {
this.areaOps = Object.values(map)
})
},
initAreaName() {
if (this.value) {
Area.createByAction(this.currentArea, this.instance).then(names => {
this.selectedArea.getName(names)
this.fullName = this.selectedArea.nameMap.join(this.separator)
this.$emit("update:name", this.selectedArea.name)
this.$emit("fullname", this.fullName)
})
}
}
}
}
</script>
<style lang="scss" scoped>
.ai-area {
.area-btn {
box-shadow: 0 2px 8px 0 rgba(76, 132, 255, 0.6);
}
.input-clicker {
width: 320px;
cursor: pointer;
border: 1px solid #D0D4DC;
line-height: 32px;
border-radius: 2px;
font-size: 14px;
.prepend {
background: rgba(245, 245, 245, 1);
width: auto;
border-right: 1px solid #D0D4DC;
padding: 0 8px;
white-space: nowrap;
}
.content {
text-align: left;
padding-left: 14px;
padding-right: 8px;
direction: rtl;
}
.suffix {
width: auto;
padding: 0 12px
}
&:hover {
border-color: $primaryColor;
}
}
.custom-clicker {
text-decoration: none;
cursor: pointer;
padding: 3px;
}
.area_edge {
max-height: 350px;
overflow-y: auto;
white-space: normal;
}
.area-box {
box-shadow: 0px -1px 0px 0px rgba(238, 238, 238, 1);
padding: 16px 0 8px 0;
& > section {
font-size: 0;
}
& > h2 {
color: rgba(51, 51, 51, 1);
line-height: 22px;
margin-bottom: 8px;
font-size: 14px;
font-weight: 600;
}
.area-item {
display: inline-block;
border-radius: 2px;
border: 1px solid #D0D4DC;
margin: 8px 8px 8px 0;
padding: 3px 10px;
cursor: pointer;
text-align: center;
line-height: normal;
font-size: 14px;
&:hover {
color: rgba($primaryColor, .8);
border-color: rgba($primaryColor, .8);
}
}
a {
text-decoration: none;
border-radius: 4px;
border: 1px solid #ddd;
line-height: normal;
margin: 5px;
padding: 3px;
cursor: pointer;
span {
margin: 0 10px;
}
&:hover {
color: rgba($primaryColor, .8);
border-color: rgba($primaryColor, .8);
}
}
.selected {
color: rgba($primaryColor, .8);
border-color: rgba($primaryColor, .8);
}
}
.badge-label {
font-size: 12px;
font-weight: bold;
border-radius: 15px;
color: #fff;
width: 12px;
letter-spacing: 10px;
text-align: center;
overflow: hidden;
padding: 3px 5px;
white-space: nowrap;
transition: width 1s, letter-spacing 0.05s;
&.label-town {
background: rgba($primaryColor, .8);
}
&.label-village {
background: rgba($primaryColor, .8);
}
&.label-poor {
background: #ffb14c;
}
&:hover {
width: initial;
letter-spacing: unset;
}
}
}
</style>

View File

@@ -0,0 +1,295 @@
<template>
<section class="AiAreaGet">
<el-cascader v-if="refresh" ref="areaCascader" :value="value" size="small" :props="props" :show-all-levels="showAll"
:options="options" @visible-change="editing=true" clearable
filterable :before-filter="handleFindArea" @change="handleAfterFilter"
v-bind="$attrs" v-on="$listeners" popper-class="popperSelectors"/>
</section>
</template>
<script>
/**
* 智能地区选择器
* @displayName AiAreaGet
*/
export default {
name: "AiAreaGet",
inject: {
elFormItem: {default: ""},
},
model: {
prop: 'value',
event: 'change',
},
props: {
/**
* 接口方法类:必填
*/
instance: {default: () => null},
/**
* 绑定地区编码
* @model
*/
value: {default: ""},
/**
* 是否多选
*/
multiple: Boolean,
/**
* 获取地区信息接口地址,默认为:/admin/area/queryAreaByParentId
*/
action: {default: "/admin/area/queryAreaByParentId"},
/**
* 限制获取地区编码的范围,1:省 2:地级市 3:县/区 4:镇/街道 5:村/社区
* @values 1,2,3,4,5
*/
valueLevel: {default: 5},
/**
* 指定根级地区范围
*/
root: {default: ""},
/**
* 获取地区名称,支持.sync 双向获取绑定
*/
name: {default: ""},
/**
* 显示完整地区名称
*/
showAll: Boolean
},
data() {
return {
rules: [10, 8, 6, 3, 0],
cacheOptions: [],
editing: false,
filterData: [],
caches: [],
roots: [],
refresh: true,
rootLoad: ""
}
},
watch: {
value(v) {
!this.editing && !this.caches.includes(this.value) && this.getCacheOptions()
this.dispatch('ElFormItem', 'el.form.change', [v]);
setTimeout(() => this.$emit("update:name", this.$refs.areaCascader?.inputValue))
},
root() {
if (this.value) {
this.getCacheOptions()
} else {
setTimeout(() => {
this.refresh = false
this.$nextTick(() => this.refresh = true)
}, 200)
}
},
options: {
handler() {
this.$nextTick(() => this.$forceUpdate())
}, deep: true, immediate: true
}
},
computed: {
fullArea() {
const length = 12,
getFull = v => this.rules.map(e => {
let reg = new RegExp(`(\\d{${length-e}})\\d{${e}}`, 'g')
return v?.replace(reg, '$1' + Array(e).fill(0).join(''))
}).filter((e, i) => i <= this.getLevel(v))
return this.multiple ? [this.value].flat()?.map(e => getFull(e)) : getFull(this.value)
},
props() {
return {
label: 'name',
value: 'id',
lazy: true,
multiple: this.multiple,
checkStrictly: true,
emitPath: false,
lazyLoad: (node, resolve) => {
if (!(this.caches.includes(node.value) && this.fullArea.includes(node.value)) || node.loading) {
if (node?.level == 0) {
this.getRoots(resolve, "lazyLoad")
} else if (node?.level > 0 && node.children?.length == 0) {
let {id, leaf} = node.data
leaf ? resolve([]) : this.getAreasByParent(id, resolve)
} else resolve([])
} else resolve([])
}
}
},
options() {
return [...this.cacheOptions, ...this.filterData]
},
filtering() {
let v = this.$refs?.areaCascader?.filtering
if (!v) this.filterData = []
return v
}
},
methods: {
getLevel(code) {
let lv = -1
this.rules.some((e, index) => {
let reg = new RegExp(`0{${e}}$`, "g")
if (reg.test(code)) {
lv = index
return true
}
})
return lv
},
getRoots(resolve, from) {
let url = '/admin/area/queryProvinceList'
if (this.root) {
url = "/admin/area/queryAreaByAreaid"
if (this.rootLoad == this.root) {
let waitRoots = (count = 0) => setTimeout(() => {
if (this.roots.length > 0 || count == 5) {
resolve(this.roots)
} else waitRoots(++count)
}, 500)
return from == "lazyLoad" ? '' : waitRoots()
}
}
this.rootLoad = JSON.parse(JSON.stringify(this.root))
if (this.roots.some(e => e.id == this.root)) {
resolve(this.roots)
} else this.instance.post(url, null, {
params: {id: this.root, from}, withoutToken: true
}).then(res => {
if (res?.data) {
this.roots = [res.data].flat().map(e => ({...e, leaf: e.type == this.valueLevel}))
resolve(this.roots)
}
})
},
getAreasByParent(id, resolve) {
id && this.instance.post(this.action, null, {
params: {id}, withoutToken: true,
}).then(res => {
if (res?.data) {
resolve(res.data.map(e => ({...e, leaf: e.type == this.valueLevel})))
}
})
},
async getCacheOptions() {
let finished = 0
const hasChild = ids => ids?.some(e => this.fullArea?.flat()?.includes(e)),
appendChildren = (area, resolve) => {
let values = [this.value].flat()
if (values.includes(area.id)) {
finished++
if (finished == values.length) {
this.$emit("update:name", area.name)
resolve()
}
} else this.getAreasByParent(area.id, data => {
this.$set(area, "children", data)
data.map(d => {
this.caches.push(d.id)
hasChild([d.id]) && appendChildren(d, resolve)
})
})
}
if (!!this.value?.toString()) {
this.cacheOptions = []
this.caches = []
await this.getRoots(data => {
this.caches = data?.map(e => e.id) || []
new Promise(resolve => {
if (hasChild(data.map(e => e.id))) {
data.map(e => hasChild([e.id]) && appendChildren(e, resolve))
} else resolve()
}).then(() => {
this.cacheOptions = data
})
}, "initWithValue")
} else if (!!this.root) {
this.caches = []
await this.getRoots(data => {
this.caches = data?.map(e => e.id) || []
new Promise(resolve => {
if (hasChild(data.map(e => e.id))) {
data.map(e => hasChild([e.id]) && appendChildren(e, resolve))
} else resolve()
}).then(() => {
this.cacheOptions = data
})
}, "initWithRoot")
}
},
/**
* 表单验证
* @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));
}
},
handleFindArea(areaName) {
return new Promise(resolve => {
this.instance.post("/admin/area/queryAreaByAreaName", null, {
params: {areaName}
}).then(res => {
if (res?.data) {
let range = new RegExp(`^${this.root.replace(/0+$/g, '')||'\d'}`)
this.filterData = res.data.filter(e => !this.caches.includes(e.id) && range.test(e.id)).map(e => ({
...e,
leaf: e.type == this.valueLevel
}))
resolve()
}
})
})
},
handleAfterFilter(v) {
this.$emit('select', this.$refs.areaCascader?.getCheckedNodes(true))
this.$refs.areaCascader?.toggleDropDownVisible(false)
if (!this.multiple) {
if (this.filterData?.length > 0) {
this.filterData = []
}
this.editing = this.caches.includes(v);
}
}
},
created() {
setTimeout(() => {
this.cacheOptions.length == 0 && this.getCacheOptions()
})
}
}
</script>
<style lang="scss" scoped>
.AiAreaGet {
width: 100%;
.el-cascader {
width: 100%;
}
}
</style>
<style lang="scss">
.popperSelectors {
.el-cascader-menu__wrap {
height: 300px;
}
}
</style>

View File

@@ -0,0 +1,273 @@
<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>

View File

@@ -0,0 +1,67 @@
<script>
import instance from "dui/lib/js/request";
export default {
name: "AiAreaTree",
props: {
instance: {default: () => instance},
action: {default: "/admin/area/queryAreaByParentId"},
rootId: String,
value: String,
range: {default: 5} //可选最小级别地区
},
model: {
prop: "value",
event: "input"
},
data() {
return {
areaProps: {
label: "name",
isLeaf: "isLeaf"
}
}
},
methods: {
getAreas(node, resolve) {
let id = node.data?.id
if (node.level == 0) {
id = this.rootId
}
this.getAreasByParent(id).then(resolve)
},
handleClick(data) {
this.$emit("input", data.id)
},
getAreasByParent(id) {
return this.instance.post(this.action, null, {
withoutToken: !0,
params: {id}
}).then(res => {
return res.data?.map(e => ({...e, isLeaf: e.type == this.range})) || []
})
}
},
}
</script>
<template>
<el-scrollbar class="AiAreaTree">
<el-tree :load="getAreas" @node-click="handleClick" lazy :props="areaProps"/>
</el-scrollbar>
</template>
<style scoped lang="scss">
.AiAreaTree {
min-width: 200px;
height: 100%;
:deep(.el-scrollbar__wrap) {
overflow-x: hidden;
}
:deep(.el-tree) {
background-color: transparent;
}
}
</style>