Files
estate/src/components/Holder/repairUser.vue
2026-06-01 18:12:58 +08:00

298 lines
8.4 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 v-if="$slots.default" />
<div v-else class="residentBox" @click="choiceResidentFun">
<div class="defaultbox" v-if="multipleSelection.length === 0 || props.username === ''">
<span>请选择</span>
<el-icon><Search /></el-icon>
</div>
<div v-else class="overflow-auto overflow-hidden w-full text-ellipsis text-nowrap">
<span>姓名{{ multipleSelection[0]?.name ?? props.username }}</span>
</div>
</div>
<el-dialog append-to-body v-model="dialog.dialogVisible" :title="dialog.dialogTitle" width="1050">
<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="mr-5 flex-1">
<el-input style="width: 170px" clearable v-model="queryParams.nickName" placeholder="请输入员工姓名" />
</div>
</div>
<div class="flex flex-items-center">
<div style="width: 70px; text-align: right; padding-right: 10px">手机号</div>
<div class="mr-5 flex-1">
<el-input style="width: 170px" clearable v-model="queryParams.phonenumber" placeholder="请输入手机号" />
</div>
</div>
<div>
<el-button type="primary" @click="getlist">查询</el-button>
<el-button @click="resetQuery">重置</el-button>
</div>
</nav>
<el-table @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="nickName" />
<el-table-column label="性别" align="center" width="85" prop="sex">
<template #default="{ row }">
<dict-tag :options="sys_user_sex" :value="row.sex" />
</template>
</el-table-column>
<el-table-column label="角色" align="center" prop="roleName" />
<el-table-column label="手机号码" align="center" prop="phonenumber" />
</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 { ResidentVO } from '@/api/system/resident/type';
import { getUserByRoleKey } from '@/api/system/user';
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'));
interface tableType extends ResidentVO {
housePath?: string;
}
const props = defineProps({
userid: {
type: String,
default: ''
},
username: {
type: String,
default: ''
},
returnvalue: {
type: String,
default: 'id'
},
titleName: {
type: String,
default: '选择维修人员'
},
userType: {
type: String,
default: 'repair'
},
isMultiple: {
type: Boolean,
default: false
}
});
const { userid, titleName, userType, returnvalue } = toRefs(props);
// ✅ 手动设置默认值(替代 withDefaults
const emit = defineEmits<{
change: [value: string | number | (string | number)[] | tableType | tableType[]]; // 支持返回数组
}>();
const dialog = ref({
dialogVisible: false,
dialogTitle: titleName.value
});
const queryParams = ref({
pageNum: 1,
pageSize: 10,
nickName: null,
phonenumber: null
});
const multipleTableRef = ref();
const tableData = ref<tableType[]>([]);
const total = ref(0);
const loading = ref(false);
// 存储选中项
const multipleSelection = ref<tableType[]>([]);
const isMultiple = computed(() => props.isMultiple ?? false);
// 优化 handleUserSelection避免重复查找
const handleUserSelection = () => {
if (!userid.value || !tableData.value.length) return;
multipleSelection.value = [];
if (userid.value.trim() !== '') {
const arr = userid.value.split(',');
arr.forEach((item) => {
const target = tableData.value.find((row) => row.userId == item);
target && multipleSelection.value.push(target);
});
nextTick(() => {
if (multipleTableRef.value) {
multipleTableRef.value.clearSelection();
multipleSelection.value.forEach((item) => {
multipleTableRef.value.toggleRowSelection(item, true);
});
}
});
}
};
// 监听
// 监听优化:只在 userid 变化时触发
// watch(userid, handleUserSelection, { immediate: true });
// watch(tableData, () => {
// if (userid.value) handleUserSelection(); // 仅在有 userid 时重新处理
// });
// ====================== 方法 ======================
// 打开选择框
function choiceResidentFun() {
dialog.value.dialogVisible = true;
handleUserSelection();
}
// 获取列表
function getlist() {
loading.value = true;
getUserByRoleKey(userType.value)
.then((res) => {
tableData.value = res.data;
total.value = res.total;
})
.catch((error) => {
console.error('获取用户列表失败:', error);
})
.finally(() => {
loading.value = false;
});
}
// ==============================================
// ✅ 新增:处理 selection-change多选专用
// ==============================================
function handleSelectionChange(selection: tableType[]) {
if (isMultiple.value) {
multipleSelection.value = selection;
}
}
// ==============================================
// 最佳单选方案:点击行选中,无报错、无循环、最稳定
// ==============================================
// 优化 handleRowClick避免重复
function handleRowClick(row: tableType) {
if (!multipleTableRef.value) return;
if (isMultiple.value) {
const index = multipleSelection.value.findIndex((item) => item.id === row.id);
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,
nickName: null,
phonenumber: null
};
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 tableType])
);
}
} else {
// 单选
if (returnvalue.value === '*') {
// ✅ 返回整个对象
emit('change', multipleSelection.value[0]);
} else {
// 返回指定字段
emit('change', multipleSelection.value[0][returnvalue.value as keyof tableType]);
}
}
multipleSelection.value = [];
multipleTableRef.value.clearSelection();
}
// 初始化
getlist();
defineExpose({
open: () => {
dialog.value.dialogVisible = true;
handleUserSelection();
}
});
</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>