127 lines
2.7 KiB
Vue
Raw Normal View History

2025-06-08 20:18:35 +08:00
<template>
<div class="area-select-container" :style="{ width: width + 'px' }">
<div v-if="label" class="area-select-label">{{ label }}</div>
2025-06-09 15:38:49 +08:00
<el-cascader
v-bind="$attrs"
v-model="selectedAreaPath"
:options="areaOptions"
:props="cascaderProps"
:placeholder="placeholder"
style="flex: 1"
clearable
/>
2025-06-08 20:18:35 +08:00
</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({
2025-06-09 15:38:49 +08:00
inheritAttrs: {
type: Boolean,
default: false,
},
2025-06-08 20:18:35 +08:00
modelValue: {
type: [Array, String],
2025-06-08 20:18:35 +08:00
default: () => [],
},
label: {
type: String,
default: '所属行政区域:',
},
placeholder: {
type: String,
default: '请选择行政区域',
},
width: {
type: [Number, String],
default: 500,
},
emitPath: {
type: Boolean,
default: true,
},
2025-06-08 20:18:35 +08:00
});
const emit = defineEmits(['update:modelValue']);
const userStore = useUserStore();
const areaOptions = ref([]);
// 检查计算属性有没有循环依赖用
// const selectedAreaPath = props.emitPath ? ref([].concat(props.modelValue)) : ref(props.modelValue);
const selectedAreaPath = computed({
get() {
// 初始回显 & 外部变更都走这里
if (props.emitPath) {
return Array.isArray(props.modelValue) ? props.modelValue : [];
} else {
return typeof props.modelValue === 'string' ? props.modelValue : '';
}
},
set(val) {
// 组件内部选中时走这里
if (props.emitPath) {
emit('update:modelValue', Array.isArray(val) ? val : []);
} else {
emit('update:modelValue', typeof val === 'string' ? val : '');
}
},
});
2025-06-08 20:18:35 +08:00
// 自定义字段映射
const cascaderProps = computed(() => ({
label: 'areaName',
value: 'areaCode',
children: 'areaChildVOS',
emitPath: props.emitPath,
2025-06-08 20:18:35 +08:00
expandTrigger: 'hover',
}));
const fetchAreaData = async () => {
try {
const res = await request.get('/system/area/region', {
params: {
areaCode: '530000',
},
});
areaOptions.value = res.data ?? [];
2025-07-02 09:40:26 +08:00
// console.log('AreaSelect区域数据', areaOptions.value);
2025-06-08 20:18:35 +08:00
} catch (err) {
console.error('加载行政区域失败', err);
}
};
// !!!禁止使用外部更新,会造成循环依赖
2025-06-12 13:11:18 +08:00
// // 外部更新 => 内部同步
// watch(
// () => props.modelValue,
// (val) => {
// selectedAreaPath.value = [...val];
// }
// );
2025-06-08 20:18:35 +08:00
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>