Files
estate/src/components/Holder/house.vue
2026-05-21 14:13:28 +08:00

345 lines
10 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<slot name="default" />
<el-dialog append-to-body v-model="dialog.dialogVisible" :title="dialog.dialogTitle" width="1250">
<nav class="flex flex-items-center mb-8">
<!-- <div class="flex flex-items-center">
<div style="width: 70px; text-align: right; padding-right: 10px">房屋类型</div>
<div class="flex-1">
<el-select @change="handleChangeHouse" style="width: 140px" v-model="queryParams.houseUseTypeId">
<el-option v-for="(item, index) in houseUseTypeList" :key="index" :label="item.name" :value="item.id"></el-option>
</el-select>
</div>
</div> -->
<div class="flex flex-items-center">
<div style="width: 50px; text-align: right; padding-right: 10px">楼栋</div>
<div class="flex-1"></div>
<el-select @change="handleChangebuilding" clearable style="width: 140px" v-model="queryParams.buildingId">
<el-option v-for="(item, index) in buildinglist" :key="index" :label="item.buildingName" :value="item.id"></el-option>
</el-select>
</div>
<div class="flex flex-items-center mr-20px">
<div style="width: 50px; text-align: right; padding-right: 10px">单元</div>
<div class="flex-1">
<el-select @change="handleChangeUnit" clearable style="width: 140px" v-model="queryParams.unitNoId">
<el-option v-for="(item, index) in unitlist" :key="index" :label="item.unitNoName" :value="item.unitNoId"></el-option>
</el-select>
</div>
</div>
<div class="flex flex-items-center mr-20px">
<div style="width: 80px; text-align: right; padding-right: 10px">房屋类型</div>
<div class="flex-1">
<el-select clearable @change="handleHouseUseChange" style="width: 140px" v-model="queryParams.houseUseTypeId">
<el-option v-for="(item, index) in houseUseTypeList" :key="index" :label="item.name" :value="item.id"></el-option>
</el-select>
</div>
</div>
<div class="flex flex-items-center mr-20px">
<div style="width: 80px; text-align: right; padding-right: 10px">业主名称</div>
<div class="flex-1">
<el-input clearable @clear="handleClear" v-model="queryParams.residentName" placeholder="查找业主"></el-input>
</div>
</div>
<div>
<el-button type="primary" @click="getlist">查询</el-button>
<el-button @click="resetQuery">重置</el-button>
</div>
</nav>
<el-table
v-loading="loading"
@row-click="handleRowClick"
ref="multipleTableRef"
:data="tableData"
border
@selection-change="handleSelectionChange"
>
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="序号" align="center" width="55" type="index" />
<el-table-column label="小区" align="center" prop="villageName" />
<el-table-column label="楼栋" align="center" prop="buildingName" />
<el-table-column label="单元" align="center" prop="unitNoName" />
<el-table-column label="房间" align="center" prop="houseNo" />
<el-table-column label="业主" align="center">
<template #default="scope">
<span>{{ scope.row.residentName ? scope.row.residentName : '---' }}</span>
</template>
</el-table-column>
</el-table>
<template #footer>
<div class="dialog-footer flex flex-items-center flex-justify-between">
<pagination
style="margin-top: 0"
layout="total, prev, pager, next, jumper"
v-show="total > 0"
:total="total"
v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize"
@pagination="getlist"
/>
<div>
<el-button @click="conback">退出</el-button>
<el-button type="primary" @click="confirm"> 确定 </el-button>
</div>
</div>
</template>
</el-dialog>
</template>
<script setup lang="ts">
import { getBuildinglistAPI, getBuildingOnly, getHouselistAPI } from '@/api/system/house';
import { listHouseUseType } from '@/api/system/houseUse';
import { BillHouse, listBillHouse } from '@/api/system/SdbBill';
import { ref, watch, nextTick, getCurrentInstance, ComponentInternalInstance, toRefs } from 'vue';
// const { proxy } = getCurrentInstance() as ComponentInternalInstance;
// const { sys_user_sex } = toRefs<any>(proxy?.useDict('sys_user_sex'));
// const { com_build_use } = toRefs<any>(proxy?.useDict('com_build_use'));
const props = defineProps({
returnvalue: {
type: String,
default: 'houseId'
},
titleName: {
type: String,
default: '选择房屋'
},
/** 是否多选 false 单选 */
isMultiple: {
type: Boolean,
default: false
}
});
const { titleName, returnvalue } = toRefs(props);
const showids = ref([]);
// ✅ 手动设置默认值(替代 withDefaults
const emit = defineEmits<{
change: [value: string | number | (string | number)[] | BillHouse | BillHouse[]]; // 支持返回数组
}>();
const dialog = ref({
dialogVisible: false,
dialogTitle: titleName.value
});
const queryParams = ref({
pageNum: 1,
pageSize: 10,
// houseUseTypeId: null,
buildingId: null,
unitNoId: null,
houseUseTypeId: null,
residentName: ''
});
const multipleTableRef = ref();
const tableData = ref<BillHouse[]>([]);
const total = ref(0);
const loading = ref(false);
// 存储选中项
const multipleSelection = ref<BillHouse[]>([]);
const isMultiple = computed(() => props.isMultiple ?? false);
// 优化 handleUserSelection避免重复查找
const handleUserSelection = () => {
if (!tableData.value.length) return;
multipleSelection.value = [];
if (showids.value.length > 0) {
const arr = showids.value;
arr.forEach((item) => {
const target = tableData.value.find((row) => row.houseId == item);
target && multipleSelection.value.push(target);
});
nextTick(() => {
if (multipleTableRef.value) {
multipleTableRef.value.clearSelection();
multipleSelection.value.forEach((item) => {
multipleTableRef.value.toggleRowSelection(item, true);
});
}
});
}
};
// ====================== 方法 ======================
const houseUseTypeList = ref([]);
// 获取列表
function getlist() {
loading.value = true;
listBillHouse(queryParams.value)
.then((res) => {
tableData.value = res.rows;
total.value = res.total;
handleUserSelection();
})
.catch((error) => {
console.error('获取列表失败:', error);
})
.finally(() => {
loading.value = false;
});
}
/** 楼栋列表 */
const buildinglist = ref([]);
/** 房屋列表 */
const unitlist = ref([]);
/** 获取楼栋 列表 */
function handleChangeHouse() {
getBuildinglistAPI().then((res) => {
buildinglist.value = res.data;
});
}
function handleClear() {
queryParams.value.residentName = '';
getlist();
}
function handleHouseUseChange() {
getlist();
}
/** 单元列表 */
function handleChangebuilding(val: string) {
queryParams.value.unitNoId = null;
unitlist.value = [];
if (queryParams.value.buildingId) {
getHouselistAPI(val).then((res) => {
unitlist.value = res.data.units;
getlist();
});
}
getlist();
}
function handleChangeUnit() {
getlist();
}
// ==============================================
// ✅ 新增:处理 selection-change多选专用
// ==============================================
function handleSelectionChange(selection: BillHouse[]) {
if (isMultiple.value) {
multipleSelection.value = selection;
}
}
// ==============================================
// 最佳单选方案:点击行选中,无报错、无循环、最稳定
// ==============================================
// 优化 handleRowClick避免重复
function handleRowClick(row: BillHouse) {
if (!multipleTableRef.value) return;
if (isMultiple.value) {
const index = multipleSelection.value.findIndex((item) => item.houseId === row.houseId);
if (index > -1) {
// 取消选中
multipleSelection.value.splice(index, 1);
multipleTableRef.value?.toggleRowSelection(row, false);
} else {
// 选中
multipleSelection.value.push(row);
multipleTableRef.value?.toggleRowSelection(row, true);
}
} else {
// 【单选模式】先清空,再选中当前行
multipleSelection.value = [];
multipleTableRef.value.clearSelection();
multipleSelection.value = [row];
multipleTableRef.value.toggleRowSelection(row, true);
}
}
// 重置查询
function resetQuery() {
queryParams.value = {
pageNum: 1,
pageSize: 10,
houseUseTypeId: null,
buildingId: null,
unitNoId: null,
residentName: ''
};
getlist();
}
// 退出
function conback() {
dialog.value.dialogVisible = false;
resetQuery();
}
// ==============================================
// ✅ 核心修改:根据 returnvalue 返回对应的值
// ==============================================
function confirm() {
dialog.value.dialogVisible = false;
if (isMultiple.value) {
// 多选
if (returnvalue.value === '*') {
// ✅ 返回整个对象数组
emit('change', multipleSelection.value);
} else {
// 返回指定字段数组
emit(
'change',
multipleSelection.value.map((item) => item[returnvalue.value as keyof BillHouse])
);
}
} else {
// 单选
if (returnvalue.value === '*') {
// ✅ 返回整个对象
emit('change', multipleSelection.value[0]);
} else {
// 返回指定字段
emit('change', multipleSelection.value[0][returnvalue.value as keyof BillHouse]);
}
}
multipleSelection.value = [];
multipleTableRef.value.clearSelection();
}
defineExpose({
open: (showidArray: string[] = []) => {
showids.value = showidArray;
getlist();
dialog.value.dialogVisible = true;
listHouseUseType({
pageNum: 1,
pageSize: 99999
}).then((res) => {
houseUseTypeList.value = res.rows;
});
handleChangeHouse();
}
});
</script>
<style scoped lang="scss">
.residentBox {
width: 385px;
height: 35px;
line-height: 35px;
border: 1px solid #ccc;
border-radius: 5px;
padding: 0 10px;
.defaultbox {
display: flex;
align-items: center;
justify-content: space-between;
}
cursor: pointer;
&:hover {
background-color: #f4f8ff;
}
}
</style>