734 lines
27 KiB
Vue
734 lines
27 KiB
Vue
<template>
|
||
<div class="p-2 h-full flex flex-col">
|
||
<pageHeader></pageHeader>
|
||
<div class="overflow-auto flex-1">
|
||
<el-card shadow="hover">
|
||
<el-form ref="queryFormRef" :inline="true" :model="queryParams" :rules="formRules" label-width="140" @submit.prevent="handleQuery">
|
||
<div>
|
||
<el-form-item label="小区(多选)" prop="villageIds">
|
||
<el-select v-model="queryParams.villageIds" :multiple="true" placeholder="请选择小区">
|
||
<el-option v-for="item in villageList" :key="item.villageId" :label="item.villageName" :value="item.villageId" />
|
||
</el-select>
|
||
</el-form-item>
|
||
<el-form-item label="承租方" prop="lessee">
|
||
<el-input v-model.trim="queryParams.lessee" placeholder="请输入承租方" />
|
||
</el-form-item>
|
||
<el-form-item label="电话" prop="phone">
|
||
<el-input v-model.trim="queryParams.phone" placeholder="请输入电话" type="tel" />
|
||
</el-form-item>
|
||
<el-form-item label="房号" prop="roomNumber">
|
||
<el-input v-model.trim="queryParams.roomNumber" placeholder="请输入房号" />
|
||
</el-form-item>
|
||
</div>
|
||
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
||
<div v-show="showSearch" class="mb-[10px]" style="overflow: auto; overflow-y: hidden">
|
||
<div>
|
||
<!-- 搜索条件: 面积/收费模式/收费标准 -->
|
||
<div>
|
||
<el-form-item label="面积" prop="areaSize" style="margin-bottom: 0">
|
||
<el-input v-model.trim="queryParams.areaSize" placeholder="请输入面积区间" />
|
||
</el-form-item>
|
||
<el-form-item label="收费模式(多选)" prop="chargeModes" style="margin-bottom: 0">
|
||
<el-select v-model="queryParams.chargeModes" :multiple="true" placeholder="请选择收费模式">
|
||
<el-option v-for="item in com_house_rental_pricing_model" :key="item.value" :label="item.label" :value="item.value" />
|
||
</el-select>
|
||
</el-form-item>
|
||
<el-form-item label="收费标准(多选)" prop="chargeStandards" style="margin-bottom: 0">
|
||
<el-select v-model="queryParams.chargeStandards" :multiple="true" placeholder="请选择收费标准">
|
||
<el-option v-for="item in com_house_rental_pricing" :key="item.value" :label="item.label" :value="item.value" />
|
||
</el-select>
|
||
</el-form-item>
|
||
</div>
|
||
<div v-if="queryParams.chargeTypeFilters.length > 0" class="line"></div>
|
||
|
||
<el-scrollbar>
|
||
<div style="width: fit-content">
|
||
<!-- 搜索条件: 应收/已收/未收 ▐╬╬-->
|
||
<div class="queryBox_over">
|
||
<el-form-item
|
||
v-for="(item, index) in queryParams.chargeTypeFilters"
|
||
:key="index"
|
||
:label="`${item.chargeTypeName}(应收)`"
|
||
:prop="`chargeTypeFilters[${index}].receivable`"
|
||
>
|
||
<el-input v-model.trim="queryParams.chargeTypeFilters[index].receivable" placeholder="区间搜索 示例:100-2000" />
|
||
</el-form-item>
|
||
</div>
|
||
<div class="queryBox_over">
|
||
<el-form-item
|
||
v-for="(item, index) in queryParams.chargeTypeFilters"
|
||
:key="index"
|
||
:label="`${item.chargeTypeName}(已收)`"
|
||
:prop="`chargeTypeFilters[${index}].received`"
|
||
>
|
||
<el-input v-model.trim="queryParams.chargeTypeFilters[index].received" placeholder="区间搜索 示例:100-2000" />
|
||
</el-form-item>
|
||
</div>
|
||
<div class="queryBox_over">
|
||
<el-form-item
|
||
v-for="(item, index) in [...queryParams.chargeTypeFilters]"
|
||
:key="index"
|
||
:label="`${item.chargeTypeName}(未收)`"
|
||
:prop="`chargeTypeFilters[${index}].uncollected`"
|
||
style="margin-bottom: 0"
|
||
>
|
||
<el-input v-model.trim="queryParams.chargeTypeFilters[index].uncollected" placeholder="区间搜索 示例:100-2000" />
|
||
</el-form-item>
|
||
</div>
|
||
</div>
|
||
</el-scrollbar>
|
||
<div class="line"></div>
|
||
<!-- 搜索条件: 租赁起始日期/租赁终止日期 -->
|
||
<div class="flex justify-between">
|
||
<div>
|
||
<el-form-item label="租赁起始日期" prop="leaseStartDate">
|
||
<el-date-picker
|
||
v-model="leaseStartDate"
|
||
end-placeholder="结束日期"
|
||
format="YYYY-MM-DD"
|
||
placeholder="请选择"
|
||
range-separator="至"
|
||
start-placeholder="开始日期"
|
||
type="daterange"
|
||
value-format="YYYY-MM-DD"
|
||
@clear="handleClear('leaseStartDate')"
|
||
@update:model-value="(val: string[]) => handleUpdateLeaseDate('leaseStartDate', val)"
|
||
/>
|
||
</el-form-item>
|
||
<el-form-item label="租赁终止日期" prop="leaseEndDate">
|
||
<el-date-picker
|
||
v-model="leaseEndDate"
|
||
end-placeholder="结束日期"
|
||
format="YYYY-MM-DD"
|
||
placeholder="请选择"
|
||
range-separator="至"
|
||
start-placeholder="开始日期"
|
||
type="daterange"
|
||
value-format="YYYY-MM-DD"
|
||
@clear="handleClear('leaseEndDate')"
|
||
@update:model-value="(val: string[]) => handleUpdateLeaseDate('leaseEndDate', val)"
|
||
/>
|
||
</el-form-item>
|
||
</div>
|
||
<div v-if="showSearch">
|
||
<el-form-item label="">
|
||
<el-button type="primary" @click="handleQuery">查询</el-button>
|
||
<el-button @click="resetQuery">重置</el-button>
|
||
<div v-if="showSearch" class="arrowBox" style="margin-left: 10px" @click="ChangeShowSearch(false)">
|
||
<span>收起</span>
|
||
<el-icon style="margin-left: 5px"><ArrowUpBold /></el-icon>
|
||
</div>
|
||
<div v-else class="arrowBox" style="margin-left: 10px" @click="ChangeShowSearch(true)">
|
||
<span>展开</span>
|
||
<el-icon style="margin-left: 5px"><ArrowDownBold /></el-icon>
|
||
</div>
|
||
</el-form-item>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</transition>
|
||
<div v-if="!showSearch">
|
||
<el-form-item label="">
|
||
<el-button type="primary" @click="handleQuery">查询</el-button>
|
||
<el-button @click="resetQuery">重置</el-button>
|
||
<div v-if="showSearch" class="arrowBox" style="margin-left: 10px" @click="ChangeShowSearch(false)">
|
||
<span>收起</span>
|
||
<el-icon style="margin-left: 5px"><ArrowUpBold /></el-icon>
|
||
</div>
|
||
<div v-else class="arrowBox" style="margin-left: 10px" @click="ChangeShowSearch(true)">
|
||
<span>展开</span>
|
||
<el-icon style="margin-left: 5px"><ArrowDownBold /></el-icon>
|
||
</div>
|
||
</el-form-item>
|
||
</div>
|
||
</el-form>
|
||
</el-card>
|
||
<el-card shadow="never" style="margin-top: 5px; height: 800px">
|
||
<template #header>
|
||
<div class="flex justify-between items-center">
|
||
<span>租赁管理明细</span>
|
||
<el-button type="primary" @click="handleExport">导出</el-button>
|
||
</div>
|
||
</template>
|
||
<el-table v-loading="loading" :data="ArrearsDetailList" border>
|
||
<el-table-column align="center" label="区域" prop="area" />
|
||
<el-table-column align="center" label="承租方" prop="lessee" />
|
||
<el-table-column align="center" label="电话" prop="phone" width="120" />
|
||
<el-table-column align="center" label="房号" prop="roomNumber" />
|
||
<el-table-column align="center" label="面积" prop="areaSize" width="80" />
|
||
<el-table-column align="center" label="收费模式" prop="chargeMode" />
|
||
<el-table-column align="center" label="收费标准" prop="chargeStandard" />
|
||
<el-table-column align="center" label="租赁起始日" prop="leaseStartDate" />
|
||
<el-table-column align="center" label="租赁终止日" prop="leaseEndDate" />
|
||
<el-table-column align="center" label="应收项目">
|
||
<template #default>
|
||
<el-table-column v-for="(item, index) in dynamicColumns" :key="index" :label="item.chargeTypeName" align="center" prop="totalAmount">
|
||
<template #default="scope">
|
||
<span>{{ scope.row.receivableAmounts[item.chargeTypeId] }}</span>
|
||
</template>
|
||
</el-table-column>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column align="center" label="已收项目">
|
||
<template #default>
|
||
<el-table-column v-for="(item, index) in dynamicColumns" :key="index" :label="item.chargeTypeName" align="center" prop="totalAmount">
|
||
<template #default="scope">
|
||
<span>{{ scope.row.receivedAmounts[item.chargeTypeId] }}</span>
|
||
</template>
|
||
</el-table-column>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column align="center" label="未收项目">
|
||
<template #default>
|
||
<el-table-column v-for="(item, index) in dynamicColumns" :key="index" :label="item.chargeTypeName" align="center" prop="totalAmount">
|
||
<template #default="scope">
|
||
<span>{{ scope.row.uncollectedAmounts[item.chargeTypeId] }}</span>
|
||
</template>
|
||
</el-table-column>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
<pagination v-show="total > 0" v-model:limit="queryParams.pageSize" v-model:page="queryParams.pageNum" :total="total" @pagination="getList" />
|
||
</el-card>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
<script lang="ts" name="Arrears" setup>
|
||
import pagination from '@/components/Pagination/index.vue';
|
||
import pageHeader from '@/components/Pageheader/index.vue';
|
||
import { getCommunitylistAPI } from '@/api/system/community';
|
||
import { ColumnConfig, exportToExcel } from '@/utils/xlsx';
|
||
import { ArrowDownBold, ArrowUpBold } from '@element-plus/icons-vue';
|
||
import { getLeaseManagementDetailChargeTypesList, getLeaseManagementDetailList } from '@/api/system/report/LeaseManagementDetails';
|
||
import { Datum, queryParamsType, Row } from '@/api/system/report/LeaseManagementDetails/type';
|
||
import { FormRules } from 'element-plus';
|
||
import { validator } from '@/utils/Reg';
|
||
|
||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||
const { com_house_rental_pricing_model, com_house_rental_pricing } = toRefs<any>(
|
||
proxy?.useDict('com_house_rental_pricing_model', 'com_house_rental_pricing')
|
||
);
|
||
|
||
const ArrearsDetailList = ref<Row[]>([]);
|
||
const loading = ref(true);
|
||
const total = ref(0);
|
||
|
||
const showSearch = ref(true);
|
||
function ChangeShowSearch(bol: boolean) {
|
||
showSearch.value = bol;
|
||
}
|
||
|
||
const leaseStartDate = ref([]);
|
||
const leaseEndDate = ref([]);
|
||
function handleUpdateLeaseDate(type: 'leaseStartDate' | 'leaseEndDate', val: string[]) {
|
||
if (type === 'leaseStartDate') {
|
||
queryParams.value.leaseStartDateBegin = val[0];
|
||
queryParams.value.leaseStartDateEnd = val[1];
|
||
} else if (type === 'leaseEndDate') {
|
||
queryParams.value.leaseEndDateBegin = val[0];
|
||
queryParams.value.leaseEndDateEnd = val[1];
|
||
}
|
||
}
|
||
function handleClear(type: 'leaseStartDate' | 'leaseEndDate') {
|
||
if (type === 'leaseStartDate') {
|
||
leaseStartDate.value = [];
|
||
queryParams.value.leaseStartDateBegin = '';
|
||
queryParams.value.leaseStartDateEnd = '';
|
||
} else if (type === 'leaseEndDate') {
|
||
leaseEndDate.value = [];
|
||
queryParams.value.leaseEndDateBegin = '';
|
||
queryParams.value.leaseEndDateEnd = '';
|
||
}
|
||
}
|
||
|
||
const queryFormRef = ref<ElFormInstance>();
|
||
const data = reactive<{
|
||
queryParams: queryParamsType;
|
||
}>({
|
||
queryParams: {
|
||
pageNum: 1,
|
||
pageSize: 10,
|
||
villageIds: [],
|
||
lessee: undefined,
|
||
phone: undefined,
|
||
roomNumber: undefined,
|
||
areaSize: undefined,
|
||
chargeTypeFilters: [],
|
||
chargeModes: [],
|
||
chargeStandards: [],
|
||
leaseEndDateBegin: undefined,
|
||
leaseEndDateEnd: undefined
|
||
}
|
||
});
|
||
|
||
const { queryParams } = toRefs(data);
|
||
// 动态生成表单验证规则
|
||
const formRules = computed<FormRules>(() => {
|
||
const dynamicRules: FormRules = {};
|
||
queryParams.value.chargeTypeFilters.forEach((_, index) => {
|
||
dynamicRules[`chargeTypeFilters[${index}].receivable`] = [
|
||
{
|
||
validator: (_: any, value: string, callback: (error?: any) => void) => {
|
||
if (!value || value === '') {
|
||
callback();
|
||
return;
|
||
}
|
||
const rangePattern = /^(-?\d+(\.\d{1,2})?)-(-?\d+(\.\d{1,2})?)?$/;
|
||
const singlePattern = /^-?\d+(\.\d{1,2})?$/;
|
||
const MAX_AMOUNT = 99999999;
|
||
|
||
if (rangePattern.test(value)) {
|
||
const parts = value.split('-');
|
||
const min = Number(parts[0]);
|
||
const max = parts[1] !== '' ? Number(parts[1]) : null; // 空字符串才是 null
|
||
|
||
// 校验下限
|
||
if (Math.abs(min) > MAX_AMOUNT) {
|
||
return callback(new Error(`金额不能超过 ${MAX_AMOUNT}`));
|
||
}
|
||
|
||
// 只有当 max 存在时才校验
|
||
if (max !== null) {
|
||
if (Math.abs(max) > MAX_AMOUNT) {
|
||
return callback(new Error(`金额不能超过 ${MAX_AMOUNT}`));
|
||
}
|
||
if (min > max) {
|
||
return callback(new Error('下限不能大于上限'));
|
||
}
|
||
}
|
||
|
||
return callback();
|
||
} else if (singlePattern.test(value)) {
|
||
const amount = Number(value);
|
||
if (Math.abs(amount) > MAX_AMOUNT) {
|
||
return callback(new Error(`金额不能超过 ${MAX_AMOUNT}`));
|
||
} else {
|
||
return callback();
|
||
}
|
||
} else {
|
||
callback(new Error('格式错误,示例: 0-1000、-1000、0-、1000'));
|
||
}
|
||
},
|
||
trigger: 'blur'
|
||
}
|
||
];
|
||
|
||
dynamicRules[`chargeTypeFilters[${index}].received`] = [
|
||
{
|
||
validator: (_: any, value: string, callback: (error?: any) => void) => {
|
||
if (!value || value === '') {
|
||
callback();
|
||
return;
|
||
}
|
||
const rangePattern = /^(-?\d+(\.\d{1,2})?)-(-?\d+(\.\d{1,2})?)?$/;
|
||
const singlePattern = /^-?\d+(\.\d{1,2})?$/;
|
||
const MAX_AMOUNT = 99999999;
|
||
|
||
if (rangePattern.test(value)) {
|
||
const parts = value.split('-');
|
||
const min = Number(parts[0]);
|
||
const max = parts[1] !== '' ? Number(parts[1]) : null; // 空字符串才是 null
|
||
|
||
// 校验下限
|
||
if (Math.abs(min) > MAX_AMOUNT) {
|
||
return callback(new Error(`金额不能超过 ${MAX_AMOUNT}`));
|
||
}
|
||
|
||
// 只有当 max 存在时才校验
|
||
if (max !== null) {
|
||
if (Math.abs(max) > MAX_AMOUNT) {
|
||
return callback(new Error(`金额不能超过 ${MAX_AMOUNT}`));
|
||
}
|
||
if (min > max) {
|
||
return callback(new Error('下限不能大于上限'));
|
||
}
|
||
}
|
||
|
||
return callback();
|
||
} else if (singlePattern.test(value)) {
|
||
const amount = Number(value);
|
||
if (Math.abs(amount) > MAX_AMOUNT) {
|
||
return callback(new Error(`金额不能超过 ${MAX_AMOUNT}`));
|
||
} else {
|
||
return callback();
|
||
}
|
||
} else {
|
||
callback(new Error('格式错误,示例: 0-1000、-1000、0-、1000'));
|
||
}
|
||
},
|
||
trigger: 'blur'
|
||
}
|
||
];
|
||
|
||
dynamicRules[`chargeTypeFilters[${index}].uncollected`] = [
|
||
{
|
||
validator: (_: any, value: string, callback: (error?: any) => void) => {
|
||
if (!value || value === '') {
|
||
callback();
|
||
return;
|
||
}
|
||
const rangePattern = /^(-?\d+(\.\d{1,2})?)-(-?\d+(\.\d{1,2})?)?$/;
|
||
const singlePattern = /^-?\d+(\.\d{1,2})?$/;
|
||
const MAX_AMOUNT = 99999999;
|
||
|
||
if (rangePattern.test(value)) {
|
||
const parts = value.split('-');
|
||
const min = Number(parts[0]);
|
||
const max = parts[1] !== '' ? Number(parts[1]) : null; // 空字符串才是 null
|
||
|
||
// 校验下限
|
||
if (Math.abs(min) > MAX_AMOUNT) {
|
||
return callback(new Error(`金额不能超过 ${MAX_AMOUNT}`));
|
||
}
|
||
|
||
// 只有当 max 存在时才校验
|
||
if (max !== null) {
|
||
if (Math.abs(max) > MAX_AMOUNT) {
|
||
return callback(new Error(`金额不能超过 ${MAX_AMOUNT}`));
|
||
}
|
||
if (min > max) {
|
||
return callback(new Error('下限不能大于上限'));
|
||
}
|
||
}
|
||
|
||
return callback();
|
||
} else if (singlePattern.test(value)) {
|
||
const amount = Number(value);
|
||
if (Math.abs(amount) > MAX_AMOUNT) {
|
||
return callback(new Error(`金额不能超过 ${MAX_AMOUNT}`));
|
||
} else {
|
||
return callback();
|
||
}
|
||
} else {
|
||
callback(new Error('格式错误,示例: 0-1000、-1000、0-、1000'));
|
||
}
|
||
},
|
||
trigger: 'blur'
|
||
}
|
||
];
|
||
});
|
||
// 面积
|
||
dynamicRules[`areaSize`] = [
|
||
{
|
||
validator: (_: any, value: string, callback: (error?: any) => void) => {
|
||
if (!value || value === '') {
|
||
callback();
|
||
return;
|
||
}
|
||
const rangePattern = /^(-?\d+(\.\d{1,2})?)-(-?\d+(\.\d{1,2})?)?$/;
|
||
const singlePattern = /^-?\d+(\.\d{1,2})?$/;
|
||
const MAX_AMOUNT = 99999999;
|
||
|
||
if (rangePattern.test(value)) {
|
||
const [min, max] = value.split('-').map(Number);
|
||
if (Math.abs(min) > MAX_AMOUNT || Math.abs(max) > MAX_AMOUNT) {
|
||
return callback(new Error(`面积不能超过 ${MAX_AMOUNT}`));
|
||
} else if (min > max) {
|
||
return callback(new Error('下限不能大于上限'));
|
||
} else {
|
||
return callback();
|
||
}
|
||
} else if (singlePattern.test(value)) {
|
||
const amount = Number(value);
|
||
if (Math.abs(amount) > MAX_AMOUNT) {
|
||
return callback(new Error(`面积不能超过 ${MAX_AMOUNT}`));
|
||
} else {
|
||
return callback();
|
||
}
|
||
} else {
|
||
callback(new Error('格式错误,示例: 0-100、-100、0-、100'));
|
||
}
|
||
},
|
||
trigger: 'blur'
|
||
}
|
||
];
|
||
// tel
|
||
dynamicRules[`tel`] = [
|
||
{
|
||
validator: (_: any, value: string, callback: (error?: any) => void) => {
|
||
if (!value || value === '') {
|
||
callback();
|
||
return;
|
||
}
|
||
validator(value, 'phone') ? callback() : callback(new Error('请输入正确的手机号'));
|
||
},
|
||
trigger: 'blur'
|
||
}
|
||
];
|
||
// 承租方
|
||
dynamicRules[`lessee`] = [
|
||
{
|
||
validator: (_: any, value: string, callback: (error?: any) => void) => {
|
||
if (!value || value === '') {
|
||
callback();
|
||
return;
|
||
}
|
||
validator(value, 'Character') ? callback() : callback(new Error('请输入正确的承租方姓名'));
|
||
},
|
||
trigger: 'blur'
|
||
}
|
||
];
|
||
// 房 间 号
|
||
dynamicRules[`roomNumber`] = [
|
||
{
|
||
validator: (_: any, value: string, callback: (error?: any) => void) => {
|
||
if (!value || value === '') {
|
||
callback();
|
||
return;
|
||
}
|
||
validator(value, 'Character') ? callback() : callback(new Error('请输入正确的房间号'));
|
||
},
|
||
trigger: 'blur'
|
||
}
|
||
];
|
||
return dynamicRules;
|
||
});
|
||
// 查询小区
|
||
const villageList = ref([]);
|
||
function getAllVillage() {
|
||
getCommunitylistAPI().then((res) => {
|
||
villageList.value = [...res.rows];
|
||
});
|
||
}
|
||
// 动态列名列表
|
||
const dynamicColumns = ref<Datum[]>([]);
|
||
// 在获取数据后更新动态列
|
||
const updateDynamicColumns = () => {
|
||
getLeaseManagementDetailChargeTypesList().then((res) => {
|
||
dynamicColumns.value = res.data;
|
||
queryParams.value.chargeTypeFilters = dynamicColumns.value.map((item) => {
|
||
return {
|
||
chargeTypeId: item.chargeTypeId,
|
||
chargeTypeName: item.chargeTypeName,
|
||
|
||
receivable: undefined,
|
||
received: undefined,
|
||
uncollected: undefined,
|
||
|
||
receivableMin: undefined,
|
||
receivableMax: undefined,
|
||
receivedMin: undefined,
|
||
receivedMax: undefined,
|
||
uncollectedMin: undefined,
|
||
uncollectedMax: undefined
|
||
};
|
||
});
|
||
});
|
||
};
|
||
|
||
/** 查询电抄记录列表 */
|
||
const getList = () => {
|
||
loading.value = true;
|
||
const search = { ...queryParams.value };
|
||
// 移除空字符串字段
|
||
Object.keys(search).forEach((key) => {
|
||
if (search[key] === '-1') {
|
||
search[key] = undefined;
|
||
}
|
||
|
||
if (key === 'chargeTypeFilters') {
|
||
search[key] = search[key]
|
||
.map((item) => {
|
||
// 1000-2000, -1000, 1000-, 1000
|
||
// 处理空字符串
|
||
if (!item.receivable && !item.received && !item.uncollected) {
|
||
return null;
|
||
}
|
||
const [receivableMin, receivableMax] = item.receivable ? item.receivable.split('-') : [];
|
||
const [receivedMin, receivedMax] = item.received ? item.received.split('-') : [];
|
||
const [uncollectedMin, uncollectedMax] = item.uncollected ? item.uncollected.split('-') : [];
|
||
return {
|
||
chargeTypeId: item.chargeTypeId,
|
||
receivableMin: receivableMin || undefined,
|
||
receivableMax: receivableMax || undefined,
|
||
receivedMin: receivedMin || undefined,
|
||
receivedMax: receivedMax || undefined,
|
||
uncollectedMin: uncollectedMin || undefined,
|
||
uncollectedMax: uncollectedMax || undefined
|
||
};
|
||
})
|
||
.filter(Boolean);
|
||
}
|
||
});
|
||
|
||
getLeaseManagementDetailList(search)
|
||
.then((res) => {
|
||
ArrearsDetailList.value = res.rows;
|
||
total.value = res.total;
|
||
})
|
||
.finally(() => {
|
||
loading.value = false;
|
||
});
|
||
};
|
||
|
||
/** 搜索按钮操作 */
|
||
const handleQuery = () => {
|
||
// 校验表单
|
||
queryFormRef.value?.validate((valid) => {
|
||
if (valid) {
|
||
queryParams.value.pageNum = 1;
|
||
getList();
|
||
}
|
||
});
|
||
};
|
||
|
||
/** 重置按钮操作 */
|
||
const resetQuery = () => {
|
||
queryFormRef.value?.resetFields();
|
||
leaseStartDate.value = [];
|
||
leaseEndDate.value = [];
|
||
queryParams.value = {
|
||
pageNum: 1,
|
||
pageSize: 10,
|
||
villageIds: [],
|
||
lessee: undefined,
|
||
phone: undefined,
|
||
roomNumber: undefined,
|
||
areaSize: undefined,
|
||
chargeTypeFilters: [],
|
||
chargeModes: [],
|
||
chargeStandards: [],
|
||
leaseEndDateBegin: undefined,
|
||
leaseEndDateEnd: undefined
|
||
};
|
||
queryParams.value.chargeTypeFilters = dynamicColumns.value.map((item) => {
|
||
return {
|
||
chargeTypeId: item.chargeTypeId,
|
||
chargeTypeName: item.chargeTypeName,
|
||
receivable: undefined,
|
||
received: undefined,
|
||
uncollected: undefined,
|
||
receivableMin: undefined,
|
||
receivableMax: undefined,
|
||
receivedMin: undefined,
|
||
receivedMax: undefined,
|
||
uncollectedMin: undefined,
|
||
uncollectedMax: undefined
|
||
};
|
||
});
|
||
handleQuery();
|
||
};
|
||
|
||
/** 导出Excel */
|
||
const handleExport = async () => {
|
||
if (ArrearsDetailList.value.length === 0) {
|
||
proxy?.$modal.msgWarning('没有可导出的数据');
|
||
return;
|
||
}
|
||
// const oldSearch = JSON.parse(
|
||
// JSON.stringify({
|
||
// ...queryParams.value,
|
||
// pageNum: undefined,
|
||
// pageSize: undefined
|
||
// })
|
||
// );
|
||
loading.value = true;
|
||
// let allData = [];
|
||
try {
|
||
// const res = await getLeaseManagementDetailList(oldSearch);
|
||
// allData = res.rows;
|
||
// 显示加载提示
|
||
// 使用 setTimeout 让出主线程,避免阻塞UI
|
||
setTimeout(() => {
|
||
try {
|
||
const columns: ColumnConfig[] = [
|
||
{ label: '区域', prop: 'area' },
|
||
{ label: '承租方', prop: 'lessee' },
|
||
{ label: '电话', prop: 'phone' },
|
||
{ label: '房号', prop: 'roomNumber' },
|
||
{ label: '面积', prop: 'areaSize' },
|
||
{ label: '收费模式', prop: 'chargeMode' },
|
||
{ label: '收费标准', prop: 'chargeStandard' },
|
||
{ label: '租赁起始日', prop: 'leaseStartDate' },
|
||
{ label: '租赁终止日', prop: 'leaseEndDate' },
|
||
{
|
||
label: '应收项目',
|
||
children: [
|
||
...dynamicColumns.value.map((item) => {
|
||
return {
|
||
label: item.chargeTypeName,
|
||
prop: `receivableAmounts.${item.chargeTypeId}`
|
||
};
|
||
})
|
||
]
|
||
},
|
||
{
|
||
label: '已收项目',
|
||
children: [
|
||
...dynamicColumns.value.map((item) => {
|
||
return {
|
||
label: item.chargeTypeName,
|
||
prop: `receivedAmounts.${item.chargeTypeId}`
|
||
};
|
||
})
|
||
]
|
||
},
|
||
{
|
||
label: '未收项目',
|
||
children: [
|
||
...dynamicColumns.value.map((item) => {
|
||
return {
|
||
label: item.chargeTypeName,
|
||
prop: `uncollectedAmounts.${item.chargeTypeId}`
|
||
};
|
||
})
|
||
]
|
||
}
|
||
];
|
||
exportToExcel(ArrearsDetailList.value, columns, `租赁管理明细表_${new Date().getTime()}`);
|
||
} catch (error) {
|
||
proxy?.$modal.msgError('导出失败,请重试');
|
||
console.error('导出错误:', error);
|
||
} finally {
|
||
loading.value = false;
|
||
}
|
||
}, 100);
|
||
} catch (error) {
|
||
proxy?.$modal.msgError('导出失败,请重试');
|
||
loading.value = false;
|
||
}
|
||
};
|
||
|
||
onMounted(() => {
|
||
updateDynamicColumns();
|
||
getList();
|
||
getAllVillage();
|
||
});
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.line {
|
||
height: 1px;
|
||
background: #eee;
|
||
margin: 15px 0;
|
||
}
|
||
.queryBox_over {
|
||
display: flex;
|
||
flex-wrap: nowrap;
|
||
flex-direction: row;
|
||
overflow: auto;
|
||
overflow-y: hidden;
|
||
|
||
& > div {
|
||
display: flex;
|
||
flex-wrap: nowrap;
|
||
}
|
||
}
|
||
|
||
.el-table {
|
||
height: calc(100% - 80px);
|
||
}
|
||
.arrow {
|
||
padding-right: 15px;
|
||
}
|
||
|
||
.arrowBox {
|
||
cursor: pointer;
|
||
|
||
&:hover {
|
||
color: #409eff;
|
||
}
|
||
}
|
||
</style>
|