Files
sunProduct/src/components/Holder/appUser.vue
2026-07-30 17:59:32 +08:00

275 lines
7.9 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="1050">
<nav class="flex flex-items-center mb-8 justify-between">
<div class="flex flex-items-center">
<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" style="width: 200px" v-model="queryParams.userName" placeholder="请输入业主账号"></el-input>
</div>
</div>
<div class="flex flex-items-center mr-20px">
<div style="width: 60px; text-align: right; padding-right: 10px">手机号</div>
<div class="flex-1">
<el-input clearable @clear="handleClear" style="width: 200px" v-model="queryParams.userPhone" placeholder="请输入手机号"></el-input>
</div>
</div>
</div>
<div>
<el-button type="primary" @click="getList">查询</el-button>
<el-button @click="resetQuery">重置</el-button>
</div>
</nav>
<el-table v-loading="loading" ref="multipleTableRef" :data="tableData" border @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="业主" align="center">
<template #default="scope">
<span>{{ scope.row.user_name ? scope.row.user_name : '---' }}</span>
</template>
</el-table-column>
<el-table-column label="手机号" align="center" prop="user_phone" />
</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 pagination from '@/components/Pagination/index.vue';
import { ref, nextTick, toRefs } from 'vue';
import { AppUserList, getAppUser } from '@/api/system/cars';
type ReturnValueType = keyof AppUserList | '*';
const props = withDefaults(
defineProps<{
returnable: ReturnValueType;
titleName?: string;
isMultiple?: boolean;
}>(),
{
returnable: '*',
titleName: '选择业主',
isMultiple: false
}
);
const { titleName, returnable } = toRefs(props);
const userid = ref([]);
// ✅ 手动设置默认值(替代 withDefaults)
const emit = defineEmits<{
change: [value: AppUserList[keyof AppUserList] | AppUserList | AppUserList[]]; // 支持返回数组
}>();
const dialog = ref({
dialogVisible: false,
dialogTitle: titleName.value
});
const queryParams = ref({
pageNum: 1,
pageSize: 10,
userPhone: '',
userName: ''
});
const multipleTableRef = ref();
const tableData = ref<AppUserList[]>([]);
const total = ref(0);
const loading = ref(false);
const isFetching = ref(false);
// 存储选中项
const multipleSelection = ref<AppUserList[]>([]);
const isMultiple = computed(() => props.isMultiple ?? false);
// 优化 handleUserSelection,避免重复查找
const handleUserSelection = () => {
isFetching.value = true;
if (!multipleTableRef.value || !tableData.value.length) {
isFetching.value = false;
return;
}
const rowsToSelect = tableData.value.filter((row) => {
return multipleSelection.value.some((selected) => selected.user_id === row.user_id);
});
multipleTableRef.value.clearSelection();
if (rowsToSelect.length > 0) {
nextTick(() => {
rowsToSelect.forEach((row) => {
multipleTableRef.value?.toggleRowSelection(row, true);
});
isFetching.value = false;
});
} else {
isFetching.value = false;
}
};
// ====================== 方法 ======================
function handleClear() {
queryParams.value.userName = '';
getList();
}
// 获取列表
function getList() {
isFetching.value = true; // 加锁
loading.value = true;
getAppUser(queryParams.value)
.then((res) => {
tableData.value = res.rows;
total.value = res.total;
handleUserSelection();
})
.catch((error) => {
console.error('获取用户列表失败:', error);
})
.finally(() => {
loading.value = false;
isFetching.value = false; // 加锁
});
}
// ==============================================
// ✅ 新增:处理 selection-change(多选专用)
// ==============================================
function handleSelectionChange(selection: AppUserList[]) {
if (isFetching.value) return;
if (isMultiple.value) {
const currentSelectedIds = new Set(selection.map((item) => item.user_id));
const otherPageSelections = multipleSelection.value.filter((item) => {
const isCurrentPageItem = tableData.value.some((row) => row.user_id === item.user_id);
if (isCurrentPageItem) {
return currentSelectedIds.has(item.user_id);
} else {
return true;
}
});
// 3. 合并:其他页保留的 + 当前页新选中的
const finalSelection = [...otherPageSelections, ...selection];
// 4. 去重(以防万一)
const uniqueMap = new Map();
finalSelection.forEach((item) => uniqueMap.set(item.user_id, item));
multipleSelection.value = Array.from(uniqueMap.values());
console.log(multipleSelection.value.map((item) => item.user_id));
} else {
// --- 单选逻辑 ---
if (selection.length > 0) {
const lastSelected = selection[selection.length - 1];
multipleSelection.value = [lastSelected];
nextTick(() => {
if (selection.length > 1) {
multipleTableRef.value?.clearSelection();
multipleTableRef.value?.toggleRowSelection(lastSelected, true);
}
});
} else {
multipleSelection.value = [];
}
}
}
// 重置查询
function resetQuery() {
queryParams.value = {
pageNum: 1,
pageSize: 10,
userPhone: '',
userName: ''
};
getList();
}
// 退出
function conBack() {
dialog.value.dialogVisible = false;
resetQuery();
}
// ==============================================
// ✅ 核心修改:根据 returnable 返回对应的值
// ==============================================
function confirm() {
dialog.value.dialogVisible = false;
if (isMultiple.value) {
// 多选
if (returnable.value === '*') {
// ✅ 返回整个对象数组
emit('change', multipleSelection.value);
} else {
// 返回指定字段数组
emit(
'change',
multipleSelection.value.map((item) => item[returnable.value])
);
}
} else {
// 单选
if (returnable.value === '*') {
// ✅ 返回整个对象
emit('change', multipleSelection.value[multipleSelection.value.length - 1]);
} else {
// 返回指定字段
emit('change', multipleSelection.value[multipleSelection.value.length - 1][returnable.value]);
}
}
multipleSelection.value = [];
multipleTableRef.value.clearSelection();
}
defineExpose({
open: (arr: string[] = []) => {
userid.value = arr;
if (arr && arr.length > 0) {
multipleSelection.value = arr.map(
(id) =>
({
user_id: id
}) as AppUserList
);
} else {
multipleSelection.value = [];
}
getList();
dialog.value.dialogVisible = true;
}
});
</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>