8/19 报表-租赁管理
This commit is contained in:
20
src/api/system/report/LeaseManagementDetails/index.ts
Normal file
20
src/api/system/report/LeaseManagementDetails/index.ts
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import request from '@/utils/request';
|
||||||
|
import {
|
||||||
|
leaseManagementDetailChargeTypesResponse,
|
||||||
|
leaseManagementDetailRequest,
|
||||||
|
leaseManagementDetailResponse
|
||||||
|
} from '@/api/system/report/LeaseManagementDetails/type';
|
||||||
|
|
||||||
|
export const getLeaseManagementDetailList = (data?: leaseManagementDetailRequest): Promise<leaseManagementDetailResponse> => {
|
||||||
|
return request({
|
||||||
|
url: '/leaseManagementDetail/list',
|
||||||
|
method: 'POST',
|
||||||
|
data: data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
export const getLeaseManagementDetailChargeTypesList = (): Promise<leaseManagementDetailChargeTypesResponse> => {
|
||||||
|
return request({
|
||||||
|
url: '/leaseManagementDetail/chargeTypes',
|
||||||
|
method: 'POST'
|
||||||
|
});
|
||||||
|
};
|
||||||
203
src/api/system/report/LeaseManagementDetails/type.ts
Normal file
203
src/api/system/report/LeaseManagementDetails/type.ts
Normal file
@@ -0,0 +1,203 @@
|
|||||||
|
export type leaseManagementDetailRequest = {
|
||||||
|
/**
|
||||||
|
* 面积
|
||||||
|
*/
|
||||||
|
areaSize?: string;
|
||||||
|
/**
|
||||||
|
* 收费模式多选
|
||||||
|
*/
|
||||||
|
chargeModes?: string[];
|
||||||
|
/**
|
||||||
|
* 收费标准多选
|
||||||
|
*/
|
||||||
|
chargeStandards?: string[];
|
||||||
|
/**
|
||||||
|
* 按收费类型筛选应收/已收/未收金额区间
|
||||||
|
*/
|
||||||
|
chargeTypeFilters?: ChargeTypeFilter[];
|
||||||
|
/**
|
||||||
|
* 租赁起始日-开始
|
||||||
|
*/
|
||||||
|
leaseStartDateBegin?: string;
|
||||||
|
/**
|
||||||
|
* 租赁起始日-结束
|
||||||
|
*/
|
||||||
|
leaseStartDateEnd?: string;
|
||||||
|
/**
|
||||||
|
* 承租方
|
||||||
|
*/
|
||||||
|
lessee?: string;
|
||||||
|
/**
|
||||||
|
* 当前页码
|
||||||
|
*/
|
||||||
|
pageNum: number;
|
||||||
|
/**
|
||||||
|
* 每页条数
|
||||||
|
*/
|
||||||
|
pageSize: number;
|
||||||
|
/**
|
||||||
|
* 手机号
|
||||||
|
*/
|
||||||
|
phone?: string;
|
||||||
|
/**
|
||||||
|
* 房号
|
||||||
|
*/
|
||||||
|
roomNumber?: string;
|
||||||
|
/**
|
||||||
|
* 小区多选
|
||||||
|
*/
|
||||||
|
villageIds?: number[];
|
||||||
|
|
||||||
|
leaseEndDateBegin?: string;
|
||||||
|
leaseEndDateEnd?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ChargeTypeFilter = {
|
||||||
|
/**
|
||||||
|
* 收费类型名称
|
||||||
|
*/
|
||||||
|
chargeTypeName?: string;
|
||||||
|
/**
|
||||||
|
* 收费类型ID
|
||||||
|
*/
|
||||||
|
chargeTypeId?: string;
|
||||||
|
/**
|
||||||
|
* 应收上限
|
||||||
|
*/
|
||||||
|
receivableMax?: string;
|
||||||
|
/**
|
||||||
|
* 应收下限
|
||||||
|
*/
|
||||||
|
receivableMin?: string;
|
||||||
|
/**
|
||||||
|
* 已收上限
|
||||||
|
*/
|
||||||
|
receivedMax: string;
|
||||||
|
/**
|
||||||
|
* 已收下限
|
||||||
|
*/
|
||||||
|
receivedMin: string;
|
||||||
|
/**
|
||||||
|
* 未收上限
|
||||||
|
*/
|
||||||
|
uncollectedMax: string;
|
||||||
|
/**
|
||||||
|
* 未收下限
|
||||||
|
*/
|
||||||
|
uncollectedMin: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type leaseManagementDetailResponse = {
|
||||||
|
/**
|
||||||
|
* 收费类型
|
||||||
|
*/
|
||||||
|
chargeItems: ChargeItem[];
|
||||||
|
code: number;
|
||||||
|
msg: string;
|
||||||
|
/**
|
||||||
|
* 当前页明细行数据
|
||||||
|
*/
|
||||||
|
rows: Row[];
|
||||||
|
/**
|
||||||
|
* 总记录数
|
||||||
|
*/
|
||||||
|
total: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ChargeItem = {
|
||||||
|
/**
|
||||||
|
* 收费类型ID
|
||||||
|
*/
|
||||||
|
chargeTypeId: string;
|
||||||
|
/**
|
||||||
|
* 收费类型名称
|
||||||
|
*/
|
||||||
|
chargeTypeName: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type Row = {
|
||||||
|
/**
|
||||||
|
* 小区名称
|
||||||
|
*/
|
||||||
|
area: string;
|
||||||
|
/**
|
||||||
|
* 面积(㎡)
|
||||||
|
*/
|
||||||
|
areaSize: string;
|
||||||
|
/**
|
||||||
|
* 小区ID
|
||||||
|
*/
|
||||||
|
buildingId: string;
|
||||||
|
/**
|
||||||
|
* 收费模式
|
||||||
|
*/
|
||||||
|
chargeMode: string;
|
||||||
|
/**
|
||||||
|
* 收费标准
|
||||||
|
*/
|
||||||
|
chargeStandard: string;
|
||||||
|
/**
|
||||||
|
* 房屋ID
|
||||||
|
*/
|
||||||
|
houseId: string;
|
||||||
|
/**
|
||||||
|
* 签约记录ID
|
||||||
|
*/
|
||||||
|
id: string;
|
||||||
|
/**
|
||||||
|
* 租赁终止日
|
||||||
|
*/
|
||||||
|
leaseEndDate: string;
|
||||||
|
/**
|
||||||
|
* 租赁起始日
|
||||||
|
*/
|
||||||
|
leaseStartDate: string;
|
||||||
|
/**
|
||||||
|
* 承租方
|
||||||
|
*/
|
||||||
|
lessee: string;
|
||||||
|
/**
|
||||||
|
* 电话
|
||||||
|
*/
|
||||||
|
phone: string;
|
||||||
|
/**
|
||||||
|
* 各收费类型应收
|
||||||
|
*/
|
||||||
|
receivableAmounts: { [key: string]: any };
|
||||||
|
/**
|
||||||
|
* 各收费类型已收
|
||||||
|
*/
|
||||||
|
receivedAmounts: { [key: string]: any };
|
||||||
|
/**
|
||||||
|
* 房号
|
||||||
|
*/
|
||||||
|
roomNumber: string;
|
||||||
|
/**
|
||||||
|
* 各收费类型未收
|
||||||
|
*/
|
||||||
|
uncollectedAmounts: { [key: string]: any };
|
||||||
|
[property: string]: any;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type leaseManagementDetailChargeTypesResponse = {
|
||||||
|
code: number;
|
||||||
|
data: Datum[];
|
||||||
|
msg: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type Datum = {
|
||||||
|
chargeTypeId: string;
|
||||||
|
chargeTypeName: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 0000000000000000
|
||||||
|
export interface queryParamsType extends leaseManagementDetailRequest {
|
||||||
|
chargeTypeFilters: chargeTypeFiltersType[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface chargeTypeFiltersType extends ChargeTypeFilter {
|
||||||
|
receivable?: string;
|
||||||
|
uncollected?: string;
|
||||||
|
received?: string;
|
||||||
|
chargeTypeName?: string;
|
||||||
|
}
|
||||||
@@ -305,3 +305,36 @@ h6 {
|
|||||||
.el-menu--horizontal .el-sub-menu__title .svg-icon + span {
|
.el-menu--horizontal .el-sub-menu__title .svg-icon + span {
|
||||||
margin-left: 3px;
|
margin-left: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.scrollbarBox {
|
||||||
|
// 美化滚动条
|
||||||
|
&::-webkit-scrollbar {
|
||||||
|
width: 5px;
|
||||||
|
height: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::-webkit-scrollbar-track {
|
||||||
|
width: 6px;
|
||||||
|
background: rgba(#101F1C, 0.1);
|
||||||
|
-webkit-border-radius: 2em;
|
||||||
|
-moz-border-radius: 2em;
|
||||||
|
border-radius: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::-webkit-scrollbar-thumb {
|
||||||
|
background-color: rgba(144,147,153,.3);
|
||||||
|
background-clip: padding-box;
|
||||||
|
min-height: 28px;
|
||||||
|
-webkit-border-radius: 2em;
|
||||||
|
-moz-border-radius: 2em;
|
||||||
|
border-radius: 2em;
|
||||||
|
transition: background-color .3s;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::-webkit-scrollbar-thumb:hover {
|
||||||
|
background-color: rgba(144,147,153,.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@@ -49,7 +49,9 @@ const whiteVillageId = [
|
|||||||
'/points/*',
|
'/points/*',
|
||||||
'/outstandingFeeSummary/*',
|
'/outstandingFeeSummary/*',
|
||||||
|
|
||||||
'/paidInExpenses/*'
|
'/paidInExpenses/*',
|
||||||
|
// 租赁管理明细
|
||||||
|
'/leaseManagementDetail/*'
|
||||||
// '/building/list'
|
// '/building/list'
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
@@ -2,136 +2,116 @@
|
|||||||
<div class="p-2 h-full flex flex-col">
|
<div class="p-2 h-full flex flex-col">
|
||||||
<pageHeader></pageHeader>
|
<pageHeader></pageHeader>
|
||||||
<el-card shadow="hover">
|
<el-card shadow="hover">
|
||||||
<el-form ref="queryFormRef" label-width="140" :model="queryParams" @submit.prevent="handleQuery" :inline="true">
|
<el-form ref="queryFormRef" label-width="140" :rules="formRules" :model="queryParams" @submit.prevent="handleQuery" :inline="true">
|
||||||
<div>
|
<div>
|
||||||
<el-form-item label="区域(多选)" prop="villageId">
|
<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 type="tel" v-model.trim="queryParams.phone" placeholder="请输入电话" />
|
||||||
|
</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" placeholder="请选择收费模式" :multiple="true">
|
||||||
|
<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" placeholder="请选择收费标准" :multiple="true">
|
||||||
|
<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 class="line"></div>
|
||||||
|
|
||||||
|
<el-scrollbar>
|
||||||
|
<div style="width: fit-content">
|
||||||
|
<!-- 搜索条件: 应收/已收/未收 -->
|
||||||
|
<div class="queryBox_over">
|
||||||
|
<el-form-item
|
||||||
|
:label="`${item.chargeTypeName}(应收)`"
|
||||||
|
:prop="`chargeTypeFilters[${index}].receivable`"
|
||||||
|
v-for="(item, index) in queryParams.chargeTypeFilters"
|
||||||
|
:key="index"
|
||||||
|
>
|
||||||
|
<el-input v-model.trim="queryParams.chargeTypeFilters[index].receivable" placeholder="区间搜索 示例:100-2000" />
|
||||||
|
</el-form-item>
|
||||||
|
</div>
|
||||||
|
<div class="queryBox_over">
|
||||||
|
<el-form-item
|
||||||
|
:label="`${item.chargeTypeName}(已收)`"
|
||||||
|
:prop="`chargeTypeFilters[${index}].received`"
|
||||||
|
v-for="(item, index) in queryParams.chargeTypeFilters"
|
||||||
|
:key="index"
|
||||||
|
>
|
||||||
|
<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]"
|
||||||
|
style="margin-bottom: 0"
|
||||||
|
:label="`${item.chargeTypeName}(未收)`"
|
||||||
|
:key="index"
|
||||||
|
:prop="`chargeTypeFilters[${index}].uncollected`"
|
||||||
|
>
|
||||||
|
<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
|
<el-date-picker
|
||||||
v-model="queryTime"
|
v-model="leaseStartDate"
|
||||||
|
type="daterange"
|
||||||
|
range-separator="至"
|
||||||
|
start-placeholder="开始日期"
|
||||||
|
end-placeholder="结束日期"
|
||||||
|
@clear="handleClear('leaseStartDate')"
|
||||||
|
@update:model-value="(val: string[]) => handleUpdateLeaseDate('leaseStartDate', val)"
|
||||||
|
format="YYYY-MM-DD"
|
||||||
|
value-format="YYYY-MM-DD"
|
||||||
|
placeholder="请选择"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="租赁终止日期" prop="leaseEndDate">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="leaseEndDate"
|
||||||
type="daterange"
|
type="daterange"
|
||||||
@update:model-value="handleQueryTime"
|
|
||||||
range-separator="至"
|
range-separator="至"
|
||||||
start-placeholder="开始日期"
|
start-placeholder="开始日期"
|
||||||
end-placeholder="结束日期"
|
end-placeholder="结束日期"
|
||||||
format="YYYY-MM-DD"
|
format="YYYY-MM-DD"
|
||||||
value-format="YYYY-MM-DD"
|
value-format="YYYY-MM-DD"
|
||||||
|
@clear="handleClear('leaseEndDate')"
|
||||||
|
@update:model-value="(val: string[]) => handleUpdateLeaseDate('leaseEndDate', val)"
|
||||||
|
placeholder="请选择"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="承租方" prop="chargeItemId">
|
|
||||||
<el-select @change="handleVillageChange" v-model="queryParams.villageId" 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="houseNo">
|
|
||||||
<el-input v-model.trim="queryParams.houseNo" placeholder="关键字查询" />
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="房号" prop="month">
|
|
||||||
<el-select v-model="queryParams.month" placeholder="关键字查询">
|
|
||||||
<el-option v-for="item in MonthList" :key="item.id" :label="item.name" :value="item.id" />
|
|
||||||
</el-select>
|
|
||||||
</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]">
|
|
||||||
<div>
|
|
||||||
<div>
|
|
||||||
<el-form-item label="面积" prop="month">
|
|
||||||
<el-select v-model="queryParams.month" placeholder="请选择">
|
|
||||||
<el-option v-for="item in MonthList" :key="item.id" :label="item.name" :value="item.id" />
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="收费模式(多选)" prop="month">
|
|
||||||
<el-select v-model="queryParams.month" placeholder="请选择">
|
|
||||||
<el-option v-for="item in MonthList" :key="item.id" :label="item.name" :value="item.id" />
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="收费标准(多选)" prop="month">
|
|
||||||
<el-select v-model="queryParams.month" placeholder="请选择">
|
|
||||||
<el-option v-for="item in MonthList" :key="item.id" :label="item.name" :value="item.id" />
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<el-form-item label="租金(应收)" prop="month">
|
|
||||||
<el-select v-model="queryParams.month" placeholder="请选择">
|
|
||||||
<el-option v-for="item in MonthList" :key="item.id" :label="item.name" :value="item.id" />
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="押金(应收)" prop="month">
|
|
||||||
<el-select v-model="queryParams.month" placeholder="区间搜索 1000-10000">
|
|
||||||
<el-option v-for="item in MonthList" :key="item.id" :label="item.name" :value="item.id" />
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="物业管理费(应收)" prop="month">
|
|
||||||
<el-select v-model="queryParams.month" placeholder="请选择">
|
|
||||||
<el-option v-for="item in MonthList" :key="item.id" :label="item.name" :value="item.id" />
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="**(应收)" prop="month">
|
|
||||||
<el-select v-model="queryParams.month" placeholder="关键字查询">
|
|
||||||
<el-option v-for="item in MonthList" :key="item.id" :label="item.name" :value="item.id" />
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<el-form-item label="租金(已收)" prop="month">
|
|
||||||
<el-select v-model="queryParams.month" placeholder="请选择">
|
|
||||||
<el-option v-for="item in MonthList" :key="item.id" :label="item.name" :value="item.id" />
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="押金(已收)" prop="month">
|
|
||||||
<el-select v-model="queryParams.month" placeholder="区间搜索 1000-10000">
|
|
||||||
<el-option v-for="item in MonthList" :key="item.id" :label="item.name" :value="item.id" />
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="物业管理费(已收)" prop="month">
|
|
||||||
<el-select v-model="queryParams.month" placeholder="请选择">
|
|
||||||
<el-option v-for="item in MonthList" :key="item.id" :label="item.name" :value="item.id" />
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="**(已收)" prop="month">
|
|
||||||
<el-select v-model="queryParams.month" placeholder="关键字查询">
|
|
||||||
<el-option v-for="item in MonthList" :key="item.id" :label="item.name" :value="item.id" />
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<el-form-item label="租金(未收)" prop="month">
|
|
||||||
<el-select v-model="queryParams.month" placeholder="请选择">
|
|
||||||
<el-option v-for="item in MonthList" :key="item.id" :label="item.name" :value="item.id" />
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="押金(未收)" prop="month">
|
|
||||||
<el-select v-model="queryParams.month" placeholder="区间搜索 1000-10000">
|
|
||||||
<el-option v-for="item in MonthList" :key="item.id" :label="item.name" :value="item.id" />
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="物业管理费(未收)" prop="month">
|
|
||||||
<el-select v-model="queryParams.month" placeholder="请选择">
|
|
||||||
<el-option v-for="item in MonthList" :key="item.id" :label="item.name" :value="item.id" />
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="**(未收)" prop="month">
|
|
||||||
<el-select v-model="queryParams.month" placeholder="关键字查询">
|
|
||||||
<el-option v-for="item in MonthList" :key="item.id" :label="item.name" :value="item.id" />
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
</div>
|
|
||||||
<div class="flex justify-between">
|
|
||||||
<div>
|
|
||||||
<el-form-item label="租赁起始日期" prop="month">
|
|
||||||
<el-select v-model="queryParams.month" placeholder="请选择">
|
|
||||||
<el-option v-for="item in MonthList" :key="item.id" :label="item.name" :value="item.id" />
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="租赁终止日期" prop="month">
|
|
||||||
<el-select v-model="queryParams.month" placeholder="请选择">
|
|
||||||
<el-option v-for="item in MonthList" :key="item.id" :label="item.name" :value="item.id" />
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
</div>
|
</div>
|
||||||
<div v-if="showSearch">
|
<div v-if="showSearch">
|
||||||
<el-form-item label="">
|
<el-form-item label="">
|
||||||
<el-button type="primary">查询</el-button>
|
<el-button type="primary" @click="handleQuery">查询</el-button>
|
||||||
<el-button @click="resetQuery">重置</el-button>
|
<el-button @click="resetQuery">重置</el-button>
|
||||||
<div class="arrowBox" style="margin-left: 10px" v-if="showSearch" @click="ChangeShowSearch(false)">
|
<div class="arrowBox" style="margin-left: 10px" v-if="showSearch" @click="ChangeShowSearch(false)">
|
||||||
<span>收起</span>
|
<span>收起</span>
|
||||||
@@ -149,7 +129,7 @@
|
|||||||
</transition>
|
</transition>
|
||||||
<div v-if="!showSearch">
|
<div v-if="!showSearch">
|
||||||
<el-form-item label="">
|
<el-form-item label="">
|
||||||
<el-button type="primary">查询</el-button>
|
<el-button type="primary" @click="handleQuery">查询</el-button>
|
||||||
<el-button @click="resetQuery">重置</el-button>
|
<el-button @click="resetQuery">重置</el-button>
|
||||||
<div class="arrowBox" style="margin-left: 10px" v-if="showSearch" @click="ChangeShowSearch(false)">
|
<div class="arrowBox" style="margin-left: 10px" v-if="showSearch" @click="ChangeShowSearch(false)">
|
||||||
<span>收起</span>
|
<span>收起</span>
|
||||||
@@ -175,26 +155,39 @@
|
|||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
</template>
|
</template>
|
||||||
<el-table :span-method="mergeSpanMethod" v-loading="loading" border :data="ArrearsDetailList">
|
<el-table v-loading="loading" border :data="ArrearsDetailList">
|
||||||
<el-table-column label="序号" width="80" align="center" prop="serialNumber" />
|
|
||||||
<el-table-column label="区域" align="center" prop="area" />
|
<el-table-column label="区域" align="center" prop="area" />
|
||||||
<el-table-column label="房号" align="center" prop="houseNo" />
|
<el-table-column label="承租方" align="center" prop="lessee" />
|
||||||
<el-table-column label="客户" align="center" prop="customerName" />
|
<el-table-column label="电话" width="120" align="center" prop="phone" />
|
||||||
<el-table-column label="联系电话" align="center" prop="phone" />
|
<el-table-column label="房号" align="center" prop="roomNumber" />
|
||||||
<el-table-column label="欠费月数" width="80" align="center" prop="arrearsMonths" />
|
<el-table-column label="面积" width="80" align="center" prop="areaSize" />
|
||||||
<el-table-column label="应收账期" align="center" prop="billPeriod" />
|
<el-table-column label="收费模式" align="center" prop="chargeMode" />
|
||||||
<el-table-column label="欠费项目" align="center">
|
<el-table-column label="收费标准" align="center" prop="chargeStandard" />
|
||||||
|
<el-table-column label="租赁起始日" align="center" prop="leaseStartDate" />
|
||||||
|
<el-table-column label="租赁终止日" align="center" prop="leaseEndDate" />
|
||||||
|
<el-table-column label="应收项目" align="center">
|
||||||
<template #default>
|
<template #default>
|
||||||
<template v-for="(item, index) in dynamicColumns" :key="index">
|
<el-table-column v-for="(item, index) in dynamicColumns" :key="index" :label="item.chargeTypeName" align="center" prop="totalAmount">
|
||||||
<el-table-column :label="item" align="center">
|
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
{{ scope.row.chargeItemAmounts?.[item] || 0 }}
|
<span>{{ scope.row.receivableAmounts[item.chargeTypeId] }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</template>
|
</template>
|
||||||
<el-table-column label="金额合计" align="center" prop="totalAmount">
|
</el-table-column>
|
||||||
|
<el-table-column label="已收项目" align="center">
|
||||||
|
<template #default>
|
||||||
|
<el-table-column v-for="(item, index) in dynamicColumns" :key="index" :label="item.chargeTypeName" align="center" prop="totalAmount">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<span style="color: red">{{ scope.row.totalAmount }}</span>
|
<span>{{ scope.row.receivedAmounts[item.chargeTypeId] }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="未收项目" align="center">
|
||||||
|
<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>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</template>
|
</template>
|
||||||
@@ -204,109 +197,331 @@
|
|||||||
</el-card>
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
账龄
|
|
||||||
<script setup name="Arrears" lang="ts">
|
<script setup name="Arrears" lang="ts">
|
||||||
import pagination from '@/components/Pagination/index.vue';
|
import pagination from '@/components/Pagination/index.vue';
|
||||||
import pageHeader from '@/components/Pageheader/index.vue';
|
import pageHeader from '@/components/Pageheader/index.vue';
|
||||||
import { getArrearsDetails } from '@/api/system/report/arrears/arrears';
|
|
||||||
import { getCommunitylistAPI } from '@/api/system/community';
|
import { getCommunitylistAPI } from '@/api/system/community';
|
||||||
import { OwnerArrearsDetailVo } from '@/api/system/report/arrears/type';
|
|
||||||
import { validator } from '@/utils/Reg';
|
|
||||||
import { ColumnConfig, exportToExcel } from '@/utils/xlsx';
|
import { ColumnConfig, exportToExcel } from '@/utils/xlsx';
|
||||||
import { ArrowDownBold, ArrowUpBold } from '@element-plus/icons-vue';
|
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 { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
const ArrearsDetailList = ref<OwnerArrearsDetailVo[]>([]);
|
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 loading = ref(true);
|
||||||
const showSearch = ref(true);
|
|
||||||
const total = ref(0);
|
const total = ref(0);
|
||||||
|
|
||||||
|
const showSearch = ref(true);
|
||||||
function ChangeShowSearch(bol: boolean) {
|
function ChangeShowSearch(bol: boolean) {
|
||||||
showSearch.value = bol;
|
showSearch.value = bol;
|
||||||
}
|
}
|
||||||
const queryFormRef = ref<ElFormInstance>();
|
|
||||||
const queryTime = ref([]);
|
const leaseStartDate = ref([]);
|
||||||
function handleQueryTime(val: string[]) {
|
const leaseEndDate = ref([]);
|
||||||
queryParams.value.startTime = val[0];
|
function handleUpdateLeaseDate(type: 'leaseStartDate' | 'leaseEndDate', val: string[]) {
|
||||||
queryParams.value.endTime = val[1];
|
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];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const data = reactive({
|
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: {
|
queryParams: {
|
||||||
pageNum: 1,
|
pageNum: 1,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
villageId: '-1',
|
villageIds: [],
|
||||||
startTime: '',
|
lessee: undefined,
|
||||||
endTime: '',
|
phone: undefined,
|
||||||
houseNo: '',
|
roomNumber: undefined,
|
||||||
month: '-1'
|
areaSize: undefined,
|
||||||
},
|
chargeTypeFilters: [],
|
||||||
rule: [
|
chargeModes: [],
|
||||||
{
|
chargeStandards: [],
|
||||||
validator: (_: any, value: string, callback: (arg0?: Error) => any) => {
|
leaseEndDateBegin: undefined,
|
||||||
if (value === '' || value === undefined || value === null) {
|
leaseEndDateEnd: undefined
|
||||||
return callback();
|
|
||||||
}
|
}
|
||||||
if (!validator(value, 'fullFilterReg')) {
|
|
||||||
return callback(new Error('请输入正确的房号'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const { queryParams } = toRefs(data);
|
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([]);
|
const villageList = ref([]);
|
||||||
function getAllVillage() {
|
function getAllVillage() {
|
||||||
getCommunitylistAPI().then((res) => {
|
getCommunitylistAPI().then((res) => {
|
||||||
villageList.value = [
|
villageList.value = [...res.rows];
|
||||||
{
|
|
||||||
villageId: '-1',
|
|
||||||
villageName: '全部区域'
|
|
||||||
},
|
|
||||||
...res.rows
|
|
||||||
];
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// 区域改变时,查询收费项目
|
// 动态列名列表
|
||||||
function handleVillageChange(val: string) {
|
const dynamicColumns = ref<Datum[]>([]);
|
||||||
queryParams.value.villageId = val;
|
// 在获取数据后更新动态列
|
||||||
queryParams.value.houseNo = '-1';
|
const updateDynamicColumns = () => {
|
||||||
}
|
getLeaseManagementDetailChargeTypesList().then((res) => {
|
||||||
// 月份
|
dynamicColumns.value = res.data;
|
||||||
const MonthList = ref([]);
|
queryParams.value.chargeTypeFilters = dynamicColumns.value.map((item) => {
|
||||||
function getMonthList() {
|
|
||||||
const arr = Array.from({ length: 12 }).fill((i) => {
|
|
||||||
return {
|
return {
|
||||||
id: `${i + 1}`,
|
chargeTypeId: item.chargeTypeId,
|
||||||
name: `${i + 1}月`
|
chargeTypeName: item.chargeTypeName,
|
||||||
|
|
||||||
|
receivable: undefined,
|
||||||
|
received: undefined,
|
||||||
|
uncollected: undefined,
|
||||||
|
|
||||||
|
receivableMin: undefined,
|
||||||
|
receivableMax: undefined,
|
||||||
|
receivedMin: undefined,
|
||||||
|
receivedMax: undefined,
|
||||||
|
uncollectedMin: undefined,
|
||||||
|
uncollectedMax: undefined
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
MonthList.value = [];
|
|
||||||
MonthList.value = [
|
|
||||||
{
|
|
||||||
id: '-1',
|
|
||||||
name: '全部月数'
|
|
||||||
},
|
|
||||||
...arr
|
|
||||||
];
|
|
||||||
}
|
|
||||||
// 动态列名列表▐╬ .3╬
|
|
||||||
const dynamicColumns = ref<string[]>([]);
|
|
||||||
|
|
||||||
// 在获取数据后更新动态列
|
|
||||||
const updateDynamicColumns = (list: any[]) => {
|
|
||||||
const columns = new Set<string>();
|
|
||||||
list.forEach((row) => {
|
|
||||||
if (row.chargeItemAmounts) {
|
|
||||||
Object.keys(row.chargeItemAmounts).forEach((key) => columns.add(key));
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
return Array.from(columns);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/** 查询电抄记录列表 */
|
/** 查询电抄记录列表 */
|
||||||
const getList = async () => {
|
const getList = () => {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
const search = { ...queryParams.value };
|
const search = { ...queryParams.value };
|
||||||
// 移除空字符串字段
|
// 移除空字符串字段
|
||||||
@@ -314,14 +529,36 @@ const getList = async () => {
|
|||||||
if (search[key] === '-1') {
|
if (search[key] === '-1') {
|
||||||
search[key] = undefined;
|
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);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
getArrearsDetails(search)
|
|
||||||
|
getLeaseManagementDetailList(search)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
ArrearsDetailList.value = res.rows;
|
ArrearsDetailList.value = res.rows;
|
||||||
total.value = res.total;
|
total.value = res.total;
|
||||||
dynamicColumns.value = updateDynamicColumns(res.rows);
|
|
||||||
|
|
||||||
ArrearsDetailList.value[ArrearsDetailList.value.length - 1].serialNumber = '合计';
|
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
@@ -330,44 +567,119 @@ const getList = async () => {
|
|||||||
|
|
||||||
/** 搜索按钮操作 */
|
/** 搜索按钮操作 */
|
||||||
const handleQuery = () => {
|
const handleQuery = () => {
|
||||||
|
// 校验表单
|
||||||
|
queryFormRef.value?.validate((valid) => {
|
||||||
|
if (valid) {
|
||||||
queryParams.value.pageNum = 1;
|
queryParams.value.pageNum = 1;
|
||||||
getList();
|
getList();
|
||||||
|
}
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/** 重置按钮操作 */
|
/** 重置按钮操作 */
|
||||||
const resetQuery = () => {
|
const resetQuery = () => {
|
||||||
queryFormRef.value?.resetFields();
|
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();
|
handleQuery();
|
||||||
};
|
};
|
||||||
|
|
||||||
/** 导出Excel */
|
/** 导出Excel */
|
||||||
const handleExport = () => {
|
const handleExport = async () => {
|
||||||
if (ArrearsDetailList.value.length === 0) {
|
if (ArrearsDetailList.value.length === 0) {
|
||||||
proxy?.$modal.msgWarning('没有可导出的数据');
|
proxy?.$modal.msgWarning('没有可导出的数据');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// 显示加载提示
|
// const oldSearch = JSON.parse(
|
||||||
|
// JSON.stringify({
|
||||||
|
// ...queryParams.value,
|
||||||
|
// pageNum: undefined,
|
||||||
|
// pageSize: undefined
|
||||||
|
// })
|
||||||
|
// );
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
|
// let allData = [];
|
||||||
|
try {
|
||||||
|
// const res = await getLeaseManagementDetailList(oldSearch);
|
||||||
|
// allData = res.rows;
|
||||||
|
// 显示加载提示
|
||||||
// 使用 setTimeout 让出主线程,避免阻塞UI
|
// 使用 setTimeout 让出主线程,避免阻塞UI
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
try {
|
try {
|
||||||
const columns: ColumnConfig[] = [
|
const columns: ColumnConfig[] = [
|
||||||
{ label: '序号', prop: 'serialNumber' },
|
|
||||||
{ label: '区域', prop: 'area' },
|
{ label: '区域', prop: 'area' },
|
||||||
{ label: '房号', prop: 'houseNo' },
|
{ label: '承租方', prop: 'lessee' },
|
||||||
{ label: '客户', prop: 'customerName' },
|
{ label: '电话', prop: 'phone' },
|
||||||
{ label: '联系方式', prop: 'phone' },
|
{ label: '房号', prop: 'roomNumber' },
|
||||||
{ label: '欠费月数', prop: 'arrearsMonths' },
|
{ label: '面积', prop: 'areaSize' },
|
||||||
{ label: '应收账期', prop: 'billPeriod' },
|
{ label: '收费模式', prop: 'chargeMode' },
|
||||||
|
{ label: '收费标准', prop: 'chargeStandard' },
|
||||||
|
{ label: '租赁起始日', prop: 'leaseStartDate' },
|
||||||
|
{ label: '租赁终止日', prop: 'leaseEndDate' },
|
||||||
{
|
{
|
||||||
label: '欠费项目',
|
label: '应收项目',
|
||||||
children: [
|
children: [
|
||||||
...dynamicColumns.value.map((item) => {
|
...dynamicColumns.value.map((item) => {
|
||||||
return { label: item, prop: `chargeItemAmounts.${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()}`, mergeSpanMethod);
|
exportToExcel(ArrearsDetailList.value, columns, `租赁管理明细表_${new Date().getTime()}`);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
proxy?.$modal.msgError('导出失败,请重试');
|
proxy?.$modal.msgError('导出失败,请重试');
|
||||||
console.error('导出错误:', error);
|
console.error('导出错误:', error);
|
||||||
@@ -375,33 +687,38 @@ const handleExport = () => {
|
|||||||
loading.value = false;
|
loading.value = false;
|
||||||
}
|
}
|
||||||
}, 100);
|
}, 100);
|
||||||
};
|
} catch (error) {
|
||||||
|
proxy?.$modal.msgError('导出失败,请重试');
|
||||||
const mergeSpanMethod = ({ columnIndex, rowIndex }) => {
|
loading.value = false;
|
||||||
if (rowIndex === ArrearsDetailList.value.length - 1) {
|
|
||||||
const rowspan = 6;
|
|
||||||
if (columnIndex === 0) {
|
|
||||||
return { rowspan: 1, colspan: 1 };
|
|
||||||
}
|
}
|
||||||
if (columnIndex === 1) {
|
|
||||||
return { rowspan: 1, colspan: rowspan };
|
|
||||||
}
|
|
||||||
if (columnIndex < rowspan + 1) {
|
|
||||||
return { rowspan: 0, colspan: 0 };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 普通行不合并
|
|
||||||
return { rowspan: 1, colspan: 1 };
|
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
updateDynamicColumns();
|
||||||
getList();
|
getList();
|
||||||
getMonthList();
|
|
||||||
getAllVillage();
|
getAllVillage();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<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 {
|
.el-table {
|
||||||
height: calc(100% - 80px);
|
height: calc(100% - 80px);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -161,7 +161,9 @@ const exportData = () => {
|
|||||||
proxy?.download(
|
proxy?.download(
|
||||||
'/businessDailyReport/village/export',
|
'/businessDailyReport/village/export',
|
||||||
{
|
{
|
||||||
...search
|
...search,
|
||||||
|
// pageNum: undefined,
|
||||||
|
// pageSize: undefined
|
||||||
},
|
},
|
||||||
`营业日报_按小区统计.xlsx`
|
`营业日报_按小区统计.xlsx`
|
||||||
);
|
);
|
||||||
@@ -169,7 +171,9 @@ const exportData = () => {
|
|||||||
proxy?.download(
|
proxy?.download(
|
||||||
'/businessDailyReport/chargeItem/export',
|
'/businessDailyReport/chargeItem/export',
|
||||||
{
|
{
|
||||||
...search
|
...search,
|
||||||
|
// pageNum: undefined,
|
||||||
|
// pageSize: undefined
|
||||||
},
|
},
|
||||||
`营业日报_按收费项目统计.xlsx`
|
`营业日报_按收费项目统计.xlsx`
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
||||||
<div v-show="showSearch" class="mb-[10px]">
|
<div v-show="showSearch" class="mb-[10px]">
|
||||||
<el-card shadow="hover">
|
<el-card shadow="hover">
|
||||||
<el-form ref="queryFormRef" label-width="80px" :model="queryParams" @submit.prevent="handleQuery" :inline="true">
|
<el-form ref="queryFormRef" label-width="80px" :model="queryParams" :rules="rules" @submit.prevent="handleQuery" :inline="true">
|
||||||
<div class="flex justify-between">
|
<div class="flex justify-between">
|
||||||
<div>
|
<div>
|
||||||
<el-form-item label="楼栋(多选)" prop="buildingIds">
|
<el-form-item label="楼栋(多选)" prop="buildingIds">
|
||||||
@@ -85,11 +85,12 @@ import pagination from '@/components/Pagination/index.vue';
|
|||||||
import pageHeader from '@/components/Pageheader/index.vue';
|
import pageHeader from '@/components/Pageheader/index.vue';
|
||||||
import { ColumnConfig, exportToExcel } from '@/utils/xlsx';
|
import { ColumnConfig, exportToExcel } from '@/utils/xlsx';
|
||||||
import { listHouseUseType } from '@/api/system/houseUse';
|
import { listHouseUseType } from '@/api/system/houseUse';
|
||||||
import { DailyFeeReportVo } from '@/api/system/report/dailyFeeReport/type';
|
|
||||||
import { getMonthFeeReportList } from '@/api/system/report/monthFeeReport';
|
import { getMonthFeeReportList } from '@/api/system/report/monthFeeReport';
|
||||||
|
import { Row } from '@/api/system/report/monthFeeReport/type';
|
||||||
|
import { FormRules } from 'element-plus';
|
||||||
|
|
||||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
const ArrearsDetailList = ref<DailyFeeReportVo[]>([]);
|
const ArrearsDetailList = ref<Row[]>([]);
|
||||||
const loading = ref(true);
|
const loading = ref(true);
|
||||||
const showSearch = ref(true);
|
const showSearch = ref(true);
|
||||||
const total = ref(0);
|
const total = ref(0);
|
||||||
@@ -109,10 +110,282 @@ const data = reactive({
|
|||||||
yearRate: '',
|
yearRate: '',
|
||||||
totalArrears: '',
|
totalArrears: '',
|
||||||
totalPrepaid: ''
|
totalPrepaid: ''
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
monthReceivable: [
|
||||||
|
{
|
||||||
|
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'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
monthUnpaid: [
|
||||||
|
{
|
||||||
|
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'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
yearReceivable: [
|
||||||
|
{
|
||||||
|
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'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
yearUnpaid: [
|
||||||
|
{
|
||||||
|
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'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
totalArrears: [
|
||||||
|
{
|
||||||
|
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'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
totalPrepaid: [
|
||||||
|
{
|
||||||
|
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'
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
// 动态生成表单验证规则╘╬
|
||||||
const { queryParams } = toRefs(data);
|
const { queryParams, rules } = toRefs(data);
|
||||||
|
|
||||||
// 查询房屋类型列表
|
// 查询房屋类型列表
|
||||||
const allHouseUseList = ref([]);
|
const allHouseUseList = ref([]);
|
||||||
|
|||||||
@@ -161,14 +161,26 @@ const resetQuery = () => {
|
|||||||
handleQuery();
|
handleQuery();
|
||||||
};
|
};
|
||||||
/** 导出Excel */
|
/** 导出Excel */
|
||||||
const handleExport = () => {
|
const handleExport = async () => {
|
||||||
if (ArrearsDetailList.value.length === 0) {
|
if (ArrearsDetailList.value.length === 0) {
|
||||||
proxy?.$modal.msgWarning('没有可导出的数据');
|
proxy?.$modal.msgWarning('没有可导出的数据');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const search = { ...queryParams.value };
|
||||||
|
// 移除空字符串字段
|
||||||
|
Object.keys(search).forEach((key) => {
|
||||||
|
if (search[key] === '-1') {
|
||||||
|
search[key] = undefined;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// 显示加载提示
|
// 显示加载提示
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// const res = await getPrepaidBalanceList(search);
|
||||||
|
// ArrearsDetailList.value = [...res.rows];
|
||||||
// 使用 setTimeout 让出主线程,避免阻塞UI
|
// 使用 setTimeout 让出主线程,避免阻塞UI
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
try {
|
try {
|
||||||
@@ -200,6 +212,11 @@ const handleExport = () => {
|
|||||||
loading.value = false;
|
loading.value = false;
|
||||||
}
|
}
|
||||||
}, 100);
|
}, 100);
|
||||||
|
} catch (error) {
|
||||||
|
loading.value = false;
|
||||||
|
proxy?.$modal.msgError('导出失败,请重试');
|
||||||
|
return;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getList();
|
getList();
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="客户" prop="customerName">
|
<el-form-item label="客户" prop="customerName">
|
||||||
<el-input v-model.trim="queryParams.customerName"></el-input>
|
<el-input v-model.trim="queryParams.customerName" placeholder="请输入客户姓名"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
@@ -153,14 +153,23 @@ const resetQuery = () => {
|
|||||||
handleQuery();
|
handleQuery();
|
||||||
};
|
};
|
||||||
/** 导出Excel */
|
/** 导出Excel */
|
||||||
const handleExport = () => {
|
const handleExport = async () => {
|
||||||
if (ArrearsDetailList.value.length === 0) {
|
if (ArrearsDetailList.value.length === 0) {
|
||||||
proxy?.$modal.msgWarning('没有可导出的数据');
|
proxy?.$modal.msgWarning('没有可导出的数据');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const search = { ...queryParams.value, pageNum: undefined, pageSize: undefined };
|
||||||
// 显示加载提示
|
// 移除空字符串字段
|
||||||
|
Object.keys(search).forEach((key) => {
|
||||||
|
if (search[key] === '-1') {
|
||||||
|
search[key] = undefined;
|
||||||
|
}
|
||||||
|
});
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
|
try {
|
||||||
|
// const res = await getPrepaidBalanceDetailList(search);
|
||||||
|
// ArrearsDetailList.value = [...res.rows];
|
||||||
|
// 显示加载提示
|
||||||
// 使用 setTimeout 让出主线程,避免阻塞UI
|
// 使用 setTimeout 让出主线程,避免阻塞UI
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
try {
|
try {
|
||||||
@@ -196,6 +205,10 @@ const handleExport = () => {
|
|||||||
loading.value = false;
|
loading.value = false;
|
||||||
}
|
}
|
||||||
}, 100);
|
}, 100);
|
||||||
|
} catch (error) {
|
||||||
|
loading.value = false;
|
||||||
|
proxy?.$modal.msgError('导出失败,请重试');
|
||||||
|
}
|
||||||
};
|
};
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getList();
|
getList();
|
||||||
|
|||||||
Reference in New Issue
Block a user