Files
estate/src/views/system/resident/index.vue
2026-05-01 18:36:37 +08:00

415 lines
12 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>
<div class="p-2 h-full flex flex-col">
<Pageheader title="住户管理"></Pageheader>
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
<div v-show="showSearch" class="mb-[10px]">
<el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
<el-form-item label="住户类型" prop="type">
<el-select v-model="queryParams.type" placeholder="请输入住户类型" style="width: 240px">
<el-option v-for="item in com_resident_relationship" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item label="住户状态" prop="status">
<el-select v-model="queryParams.status" placeholder="请输入住户状态" style="width: 240px">
<el-option v-for="item in com_review" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
</el-card>
</div>
</transition>
<el-card style="flex: 1" shadow="never">
<div class="residentBody h-full">
<div class="treebox h-full">
<div class="treeTitlebox">{{ currentVilageInfo.villageName ?? '12' }}</div>
<div class="treeboxbody">
<!-- 树状+ -->
<el-tree :highlight-current="true" style="max-width: 600px" :data="treedata" :props="defaultProps" @node-click="handleNodeClick" />
</div>
</div>
<div class="flex-1 h-full">
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['resident:resident:add']">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['resident:resident:edit']"
>修改</el-button
>
</el-col>
<el-col :span="1.5">
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['resident:resident:remove']"
>删除</el-button
>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table class="tablebox" v-loading="loading" border :data="residentList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="姓名" min-width="120" align="center" prop="name" />
<el-table-column label="类型" min-width="120" align="center" prop="type">
<template #default="scope">
<DictTag :value="scope.row.type" :options="com_resident_relationship"></DictTag>
</template>
</el-table-column>
<el-table-column label="状态" min-width="120" align="center" prop="status">
<template #default="scope">
<DictTag :value="scope.row.status" :options="com_review"></DictTag>
</template>
</el-table-column>
<el-table-column label="证件号" min-width="120" align="center" prop="idCard" />
<el-table-column label="手机号码" min-width="120" align="center" prop="phone" />
<el-table-column label="房间" min-width="120" align="center" prop="houseAddress" />
<el-table-column label="操作" align="center" min-width="120" fixed="right" class-name="small-padding fixed-width">
<template #default="scope">
<el-button
v-if="scope.row.status !== '1'"
link
type="primary"
icon="Edit"
@click="handleMain(scope.row)"
v-hasPermi="['resident:resident:edit']"
>审核</el-button
>
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['resident:resident:edit']">修改</el-button>
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['resident:resident:remove']"
>删除
</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total > 0"
:total="total"
v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</div>
</div>
</el-card>
</div>
</template>
<script setup name="Resident" lang="ts">
import Pageheader from '@/components/Pageheader/index.vue';
import { listResident, delResident } from '@/api/system/resident/index';
import { ResidentVO, ResidentQuery, ResidentForm } from '@/api/system/resident/type';
import { getHousePathById } from '@/utils/house';
import { useHouseStore } from '@/store/modules/house';
const houseStore = useHouseStore();
const currentVilageInfo = ref({
'villageId': null,
'villageName': '',
'villageCode': '',
'city': '',
'address': '',
'completDate': '',
'houseUse': 0,
'villageArea': null,
'parkingSpaceCount': null,
'villageImageUrl': '',
'status': '0',
'remark': '',
'manageName': '',
'managePhone': '',
'manageQq': '',
'manageVx': '',
'manageEmail': ''
});
function init() {
houseStore.getviliageinfo(localStorage.getItem('villageid')).then((res) => {
if (res) {
currentVilageInfo.value = res;
}
});
}
init();
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { com_resident_relationship } = toRefs<any>(proxy?.useDict('com_resident_relationship'));
const { com_review } = toRefs<any>(proxy?.useDict('com_review'));
const router = useRouter();
const residentList = ref<ResidentVO[]>([]);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref<Array<string | number>>([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const queryFormRef = ref<ElFormInstance>();
const initFormData: ResidentForm = {
id: undefined,
code: undefined,
name: undefined,
type: undefined,
gender: undefined,
idCard: undefined,
phone: undefined,
villageId: undefined,
buildingId: undefined,
houseId: undefined,
status: undefined,
cardImageFront: undefined,
cardImageBack: undefined,
remark: undefined
};
const data = reactive<PageData<ResidentForm, ResidentQuery>>({
form: { ...initFormData },
queryParams: {
pageNum: 1,
pageSize: 10,
date: '',
type: null,
status: null,
houseId: null,
buildingId: null,
unitNo: null
}
});
const disabledDate = (time: Date) => {
return time.getTime() > Date.now();
};
const shortcuts = [
{
text: '今天',
value: new Date()
},
{
text: '昨天',
value: () => {
const date = new Date();
date.setDate(date.getDate() - 1);
return date;
}
},
{
text: ' 近3天',
value: () => {
const date = new Date();
date.setDate(date.getDate() - 3);
return date;
}
},
{
text: '最近一周',
value: () => {
const date = new Date();
date.setDate(date.getDate() - 7);
return date;
}
},
{
text: '最近一个月',
value: () => {
const date = new Date();
date.setMonth(date.getMonth() - 1);
return date;
}
},
{
text: '最近三个月',
value: () => {
const date = new Date();
date.setMonth(date.getMonth() - 3); // 真正减3个月不是90天
return date;
}
}
];
const { queryParams, form } = toRefs(data);
// ! 树形------------------------------------------------------------------------
interface Tree {
label: string;
value: number;
type: string;
children?: Tree[];
}
// 四个参数对应于节点点击的节点对象TreeNode 的 node 属性, TreeNode和事件对象
const handleNodeClick = (data: Tree, node) => {
const obj2 = {
[data.type]: data.value
};
if (data.type === 'unitNo') {
obj2[node.parent.data.type] = node.parent.data.value;
}
queryParams.value = {
...queryParams.value,
...{
houseId: null,
buildingId: null,
unitNo: null
},
...obj2
};
getList();
};
const defaultProps = {
children: 'children',
label: 'label'
};
// ! 树形------------------------------------------------------------------------
const treedata = ref([]);
function gettree() {
treedata.value = [];
houseStore.getCurrentVilageTreeHouse().then((res) => {
treedata.value = res;
});
}
gettree();
/** 查询住户管理列表 */
const getList = async () => {
loading.value = true;
residentList.value = [];
const res = await listResident(queryParams.value);
residentList.value = res.rows;
residentList.value.forEach((item) => {
const arr = getHousePathById(treedata.value, item.houseId, 'label');
item.houseAddress = arr.join(' ');
});
total.value = res.total;
loading.value = false;
};
getList();
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.value.pageNum = 1;
queryParams.value = {
...queryParams.value,
...{
houseId: null,
buildingId: null,
unitNo: null
}
};
getList();
};
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value?.resetFields();
queryParams.value = {
...queryParams.value,
...{
houseId: null,
buildingId: null,
unitNo: null
}
};
handleQuery();
};
/** 多选框选中数据 */
const handleSelectionChange = (selection: ResidentVO[]) => {
ids.value = selection.map((item) => item.id);
single.value = selection.length != 1;
multiple.value = !selection.length;
};
/** 新增按钮操作 */
const handleAdd = () => {
router.push({
path: '/house/addResident'
});
};
/** 修改按钮操作 */
const handleUpdate = async (row?: ResidentVO) => {
router.push({
path: '/house/editResident',
query: {
id: row.id
}
});
};
/** 审核/ 用户详情 */
const handleMain = (row: ResidentVO) => {
router.push({
path: '/house/ResidentMain',
query: {
id: row.id
}
});
};
/** 删除按钮操作 */
const handleDelete = async (row?: ResidentVO) => {
const _ids = row?.id || ids.value;
await proxy?.$modal.confirm('该信息删除后无法恢复,确定要删除吗?').finally(() => (loading.value = false));
await delResident(_ids);
proxy?.$modal.msgSuccess('删除成功');
await getList();
};
onMounted(() => {
// getList();
});
</script>
<style lang="scss" scoped>
.residentBody {
display: flex;
.treebox {
width: 250px;
margin-right: 10px;
.treeTitlebox {
height: 60px;
line-height: 60px;
padding-left: 20px;
font-size: 18px;
font-weight: 600;
background-color: rgba(233, 242, 255, 0.5);
color: rgba(16, 16, 16, 1);
}
.treeboxbody {
margin-top: 10px;
&:deep(.el-tree-node__content) {
margin-bottom: 5px;
height: 35px;
line-height: 35px;
.el-tree-node__expand-icon {
font-size: 18px;
}
&:hover {
background: #d1e3ff;
.el-text {
color: #227aff;
}
.el-tree-node__expand-icon {
color: #227aff;
}
}
}
}
}
.tablebox {
height: calc(100% - 105px);
/* 空数据也不会无限变宽 */
:deep(.el-table__empty-block) {
width: 100% !important;
max-width: 100% !important;
}
}
}
</style>