94 lines
1.9 KiB
Vue
94 lines
1.9 KiB
Vue
|
<template>
|
||
|
<div class="area-select-container" :style="{ width: width + 'px' }">
|
||
|
<div v-if="label" class="area-select-label">{{ label }}</div>
|
||
|
<el-cascader v-model="selectedAreaPath" :options="areaOptions" :props="cascaderProps" :placeholder="placeholder" style="flex: 1" clearable />
|
||
|
</div>
|
||
|
</template>
|
||
|
|
||
|
<script setup>
|
||
|
import { ref, watch, onMounted, computed } from 'vue';
|
||
|
import request from '@/utils/axios';
|
||
|
import { useUserStore } from '@/store/modules/user';
|
||
|
|
||
|
const props = defineProps({
|
||
|
modelValue: {
|
||
|
type: Array,
|
||
|
default: () => [],
|
||
|
},
|
||
|
label: {
|
||
|
type: String,
|
||
|
default: '所属行政区域:',
|
||
|
},
|
||
|
placeholder: {
|
||
|
type: String,
|
||
|
default: '请选择行政区域',
|
||
|
},
|
||
|
width: {
|
||
|
type: [Number, String],
|
||
|
default: 500,
|
||
|
},
|
||
|
});
|
||
|
|
||
|
const emit = defineEmits(['update:modelValue']);
|
||
|
|
||
|
const userStore = useUserStore();
|
||
|
|
||
|
const areaOptions = ref([]);
|
||
|
const selectedAreaPath = ref([...props.modelValue]);
|
||
|
|
||
|
// 自定义字段映射
|
||
|
const cascaderProps = computed(() => ({
|
||
|
label: 'areaName',
|
||
|
value: 'areaCode',
|
||
|
children: 'areaChildVOS',
|
||
|
emitPath: true,
|
||
|
expandTrigger: 'hover',
|
||
|
}));
|
||
|
|
||
|
const fetchAreaData = async () => {
|
||
|
try {
|
||
|
const res = await request.get('/system/area/region', {
|
||
|
params: {
|
||
|
areaCode: '530000',
|
||
|
},
|
||
|
});
|
||
|
areaOptions.value = res.data ?? [];
|
||
|
} catch (err) {
|
||
|
console.error('加载行政区域失败', err);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// 外部更新 => 内部同步
|
||
|
watch(
|
||
|
() => props.modelValue,
|
||
|
(val) => {
|
||
|
selectedAreaPath.value = [...val];
|
||
|
}
|
||
|
);
|
||
|
|
||
|
// 内部更新 => 外部同步
|
||
|
watch(selectedAreaPath, (val) => {
|
||
|
emit('update:modelValue', val);
|
||
|
});
|
||
|
|
||
|
onMounted(() => {
|
||
|
fetchAreaData();
|
||
|
});
|
||
|
</script>
|
||
|
|
||
|
<style scoped>
|
||
|
.area-select-container {
|
||
|
display: flex;
|
||
|
align-items: center;
|
||
|
gap: 12px;
|
||
|
}
|
||
|
|
||
|
.area-select-label {
|
||
|
font-size: 14px;
|
||
|
color: #606266;
|
||
|
width: 120px;
|
||
|
line-height: 32px;
|
||
|
text-align: right;
|
||
|
}
|
||
|
</style>
|