Merge branch 'master' of http://47.109.37.87:3000/by2025/admin-vben5
Some checks are pending
Gitea Actions Demo / Explore-Gitea-Actions (push) Waiting to run

This commit is contained in:
FLL
2025-07-18 19:48:20 +08:00
34 changed files with 3541 additions and 121 deletions

View File

@@ -0,0 +1,61 @@
import type { CarChargeVO, CarChargeForm, CarChargeQuery } from './model';
import type { ID, IDS } from '#/api/common';
import type { PageResult } from '#/api/common';
import { commonExport } from '#/api/helper';
import { requestClient } from '#/api/request';
/**
* 查询费用-车辆收费列表
* @param params
* @returns 费用-车辆收费列表
*/
export function carChargeList(params?: CarChargeQuery) {
return requestClient.get<PageResult<CarChargeVO>>('/property/carCharge/list', { params });
}
/**
* 导出费用-车辆收费列表
* @param params
* @returns 费用-车辆收费列表
*/
export function carChargeExport(params?: CarChargeQuery) {
return commonExport('/property/carCharge/export', params ?? {});
}
/**
* 查询费用-车辆收费详情
* @param id id
* @returns 费用-车辆收费详情
*/
export function carChargeInfo(id: ID) {
return requestClient.get<CarChargeVO>(`/property/carCharge/${id}`);
}
/**
* 新增费用-车辆收费
* @param data
* @returns void
*/
export function carChargeAdd(data: CarChargeForm) {
return requestClient.postWithMsg<void>('/property/carCharge', data);
}
/**
* 更新费用-车辆收费
* @param data
* @returns void
*/
export function carChargeUpdate(data: CarChargeForm) {
return requestClient.putWithMsg<void>('/property/carCharge', data);
}
/**
* 删除费用-车辆收费
* @param id id
* @returns void
*/
export function carChargeRemove(id: ID | IDS) {
return requestClient.deleteWithMsg<void>(`/property/carCharge/${id}`);
}

View File

@@ -0,0 +1,169 @@
import type { PageQuery, BaseEntity } from '#/api/common';
export interface CarChargeVO {
/**
* 主键
*/
id: string | number;
/**
* 车牌号
*/
carNumber: string;
/**
* 业主
*/
personId: string | number;
/**
* 楼层
*/
floorId: string | number;
/**
* 车位
*/
location: string;
/**
* 状态
*/
state: string;
/**
* 收费项目
*/
costItemsId: string | number;
/**
* 计费开始时间
*/
starTime: string;
/**
* 计费结束时间
*/
endTime: string;
/**
* 说明
*/
remark: string;
/**
* 搜索值
*/
searchValue: string;
}
export interface CarChargeForm extends BaseEntity {
/**
* 主键
*/
id?: string | number;
/**
* 车牌号
*/
carNumber?: string;
/**
* 业主
*/
personId?: string | number;
/**
* 楼层
*/
floorId?: string | number;
/**
* 车位
*/
location?: string;
/**
* 状态
*/
state?: string;
/**
* 收费项目
*/
costItemsId?: string | number;
/**
* 计费开始时间
*/
starTime?: string;
/**
* 计费结束时间
*/
endTime?: string;
/**
* 说明
*/
remark?: string;
/**
* 搜索值
*/
searchValue?: string;
}
export interface CarChargeQuery extends PageQuery {
/**
* 车牌号
*/
carNumber?: string;
/**
* 业主
*/
personId?: string | number;
/**
* 楼层
*/
floorId?: string | number;
/**
* 车位
*/
location?: string;
/**
* 状态
*/
state?: string;
/**
* 收费项目
*/
costItemsId?: string | number;
/**
* 计费开始时间
*/
starTime?: string;
/**
* 计费结束时间
*/
endTime?: string;
/**
* 搜索值
*/
searchValue?: string;
/**
* 日期范围参数
*/
params?: any;
}

View File

@@ -0,0 +1,61 @@
import type { HouseChargeVO, HouseChargeForm, HouseChargeQuery } from './model';
import type { ID, IDS } from '#/api/common';
import type { PageResult } from '#/api/common';
import { commonExport } from '#/api/helper';
import { requestClient } from '#/api/request';
/**
* 查询房屋收费列表
* @param params
* @returns 房屋收费列表
*/
export function houseChargeList(params?: HouseChargeQuery) {
return requestClient.get<PageResult<HouseChargeVO>>('/property/houseCharge/list', { params });
}
/**
* 导出房屋收费列表
* @param params
* @returns 房屋收费列表
*/
export function houseChargeExport(params?: HouseChargeQuery) {
return commonExport('/property/houseCharge/export', params ?? {});
}
/**
* 查询房屋收费详情
* @param id id
* @returns 房屋收费详情
*/
export function houseChargeInfo(id: ID) {
return requestClient.get<HouseChargeVO>(`/property/houseCharge/${id}`);
}
/**
* 新增房屋收费
* @param data
* @returns void
*/
export function houseChargeAdd(data: HouseChargeForm) {
return requestClient.postWithMsg<void>('/property/houseCharge', data);
}
/**
* 更新房屋收费
* @param data
* @returns void
*/
export function houseChargeUpdate(data: HouseChargeForm) {
return requestClient.putWithMsg<void>('/property/houseCharge', data);
}
/**
* 删除房屋收费
* @param id id
* @returns void
*/
export function houseChargeRemove(id: ID | IDS) {
return requestClient.deleteWithMsg<void>(`/property/houseCharge/${id}`);
}

View File

@@ -0,0 +1,130 @@
import type {PageQuery, BaseEntity} from '#/api/common';
export interface HouseChargeVO {
/**
* 主键
*/
id: string | number;
/**
* 房屋
*/
roomId: string | number;
/**
* 收费项目
*/
costItemsId: string | number;
/**
* 应收金额
*/
amountReceivable: number;
/**
* 计费开始时间
*/
startTime: string;
/**
* 计费结束时间
*/
endTime: string;
/**
* 状态
*/
state: string;
/**
* 说明
*/
remark: string;
chargeTime: any[];
/**
* 缴费周期
*/
chargeCycle: number;
}
export interface HouseChargeForm extends BaseEntity {
/**
* 主键
*/
id?: string | number;
/**
* 房屋
*/
roomId?: string | number;
/**
* 收费项目
*/
costItemsId?: string | number;
/**
* 应收金额
*/
amountReceivable?: number;
/**
* 计费开始时间
*/
startTime?: string;
/**
* 计费结束时间
*/
endTime?: string;
/**
* 状态
*/
state?: string;
/**
* 说明
*/
remark?: string;
}
export interface HouseChargeQuery extends PageQuery {
/**
* 房屋
*/
roomId?: string | number;
/**
* 收费项目
*/
costItemsId?: string | number;
/**
* 应收金额
*/
amountReceivable?: number;
/**
* 计费开始时间
*/
startTime?: string;
/**
* 计费结束时间
*/
endTime?: string;
/**
* 状态
*/
state?: string;
/**
* 日期范围参数
*/
params?: any;
}

View File

@@ -0,0 +1,61 @@
import type { ReturnPayFeeVO, ReturnPayFeeForm, ReturnPayFeeQuery } from './model';
import type { ID, IDS } from '#/api/common';
import type { PageResult } from '#/api/common';
import { commonExport } from '#/api/helper';
import { requestClient } from '#/api/request';
/**
* 查询退费审核列表
* @param params
* @returns 退费审核列表
*/
export function returnPayFeeList(params?: ReturnPayFeeQuery) {
return requestClient.get<PageResult<ReturnPayFeeVO>>('/property/returnPayFee/list', { params });
}
/**
* 导出退费审核列表
* @param params
* @returns 退费审核列表
*/
export function returnPayFeeExport(params?: ReturnPayFeeQuery) {
return commonExport('/property/returnPayFee/export', params ?? {});
}
/**
* 查询退费审核详情
* @param id id
* @returns 退费审核详情
*/
export function returnPayFeeInfo(id: ID) {
return requestClient.get<ReturnPayFeeVO>(`/property/returnPayFee/${id}`);
}
/**
* 新增退费审核
* @param data
* @returns void
*/
export function returnPayFeeAdd(data: ReturnPayFeeForm) {
return requestClient.postWithMsg<void>('/property/returnPayFee', data);
}
/**
* 更新退费审核
* @param data
* @returns void
*/
export function returnPayFeeUpdate(data: ReturnPayFeeForm) {
return requestClient.putWithMsg<void>('/property/returnPayFee', data);
}
/**
* 删除退费审核
* @param id id
* @returns void
*/
export function returnPayFeeRemove(id: ID | IDS) {
return requestClient.deleteWithMsg<void>(`/property/returnPayFee/${id}`);
}

View File

@@ -0,0 +1,154 @@
import type { PageQuery, BaseEntity } from '#/api/common';
export interface ReturnPayFeeVO {
/**
* 主键
*/
id: string | number;
/**
* 退款单号
*/
returnNo?: string;
/**
* 支付单号
*/
payNo?: string;
/**
* 退款原因
*/
reason?: string;
/**
* 费用类型id
*/
itemId?: string | number;
/**
* 业主id
*/
userId?: string | number;
/**
* 支付金额
*/
payAcount?: number;
/**
* 支付时间
*/
payTime?: string;
/**
* 退费状态
*/
state: string;
/**
* 说明
*/
remark: string;
}
export interface ReturnPayFeeForm extends BaseEntity {
/**
* 主键
*/
id?: string | number;
/**
* 退款单号
*/
returnNo?: string;
/**
* 支付单号
*/
payNo?: string;
/**
* 退款原因
*/
reason?: string;
/**
* 费用类型id
*/
itemId?: string | number;
/**
* 业主id
*/
userId?: string | number;
/**
* 支付金额
*/
payAcount?: number;
/**
* 支付时间
*/
payTime?: string;
/**
* 退费状态
*/
state?: string;
/**
* 说明
*/
remark?: string;
}
export interface ReturnPayFeeQuery extends PageQuery {
/**
* 退款单号
*/
returnNo?: string;
/**
* 支付单号
*/
payNo?: string;
/**
* 退款原因
*/
reason?: string;
/**
* 费用类型id
*/
itemId?: string | number;
/**
* 业主id
*/
userId?: string | number;
/**
* 支付金额
*/
payAcount?: number;
/**
* 支付时间
*/
payTime?: string;
/**
* 退费状态
*/
state?: string;
/**
* 日期范围参数
*/
params?: any;
}

View File

@@ -0,0 +1,61 @@
import type { CostMeterWaterVO, CostMeterWaterForm, CostMeterWaterQuery } from './model';
import type { ID, IDS } from '#/api/common';
import type { PageResult } from '#/api/common';
import { commonExport } from '#/api/helper';
import { requestClient } from '#/api/request';
/**
* 查询费用-水电抄列表
* @param params
* @returns 费用-水电抄列表
*/
export function costMeterWaterList(params?: CostMeterWaterQuery) {
return requestClient.get<PageResult<CostMeterWaterVO>>('/property/costMeterWater/list', { params });
}
/**
* 导出费用-水电抄列表
* @param params
* @returns 费用-水电抄列表
*/
export function costMeterWaterExport(params?: CostMeterWaterQuery) {
return commonExport('/property/costMeterWater/export', params ?? {});
}
/**
* 查询费用-水电抄详情
* @param id id
* @returns 费用-水电抄详情
*/
export function costMeterWaterInfo(id: ID) {
return requestClient.get<CostMeterWaterVO>(`/property/costMeterWater/${id}`);
}
/**
* 新增费用-水电抄
* @param data
* @returns void
*/
export function costMeterWaterAdd(data: CostMeterWaterForm) {
return requestClient.postWithMsg<void>('/property/costMeterWater', data);
}
/**
* 更新费用-水电抄
* @param data
* @returns void
*/
export function costMeterWaterUpdate(data: CostMeterWaterForm) {
return requestClient.putWithMsg<void>('/property/costMeterWater', data);
}
/**
* 删除费用-水电抄
* @param id id
* @returns void
*/
export function costMeterWaterRemove(id: ID | IDS) {
return requestClient.deleteWithMsg<void>(`/property/costMeterWater/${id}`);
}

View File

@@ -0,0 +1,157 @@
import type { PageQuery, BaseEntity } from '#/api/common';
export interface CostMeterWaterVO {
/**
* 主键
*/
id: string | number;
/**
* 费用类型id
*/
itemId: string | number;
/**
* 抄表类型id
*/
meterTypeId: string | number;
/**
* 对象名称
*/
objName: string;
/**
* 本期度数
*/
curDegrees: string;
/**
* 上期度数
*/
preDegrees: string;
/**
* 上期读表时间
*/
preReadingTime: string;
/**
* 本期读表时间
*/
curReadingTime: string;
/**
* 备注
*/
remark: string;
/**
* 搜索值
*/
searchValue: string;
}
export interface CostMeterWaterForm extends BaseEntity {
/**
* 主键
*/
id?: string | number;
/**
* 费用类型id
*/
itemId?: string | number;
/**
* 抄表类型id
*/
meterTypeId?: string | number;
/**
* 对象名称
*/
objName?: string;
/**
* 本期度数
*/
curDegrees?: string;
/**
* 上期度数
*/
preDegrees?: string;
/**
* 上期读表时间
*/
preReadingTime?: string;
/**
* 本期读表时间
*/
curReadingTime?: string;
/**
* 备注
*/
remark?: string;
/**
* 搜索值
*/
searchValue?: string;
}
export interface CostMeterWaterQuery extends PageQuery {
/**
* 费用类型id
*/
itemId?: string | number;
/**
* 抄表类型id
*/
meterTypeId?: string | number;
/**
* 对象名称
*/
objName?: string;
/**
* 本期度数
*/
curDegrees?: string;
/**
* 上期度数
*/
preDegrees?: string;
/**
* 上期读表时间
*/
preReadingTime?: string;
/**
* 本期读表时间
*/
curReadingTime?: string;
/**
* 搜索值
*/
searchValue?: string;
/**
* 日期范围参数
*/
params?: any;
}

View File

@@ -1,4 +1,4 @@
import type { PageQuery, BaseEntity } from '#/api/common';
import type {PageQuery, BaseEntity} from '#/api/common';
export interface MaintainPlanVO {
/**
@@ -56,6 +56,11 @@ export interface MaintainPlanVO {
*/
state: string;
planDate: any[]
userId: string[];
machineMaintainPlanStaffBoList:any[];
}
export interface MaintainPlanForm extends BaseEntity {
@@ -168,7 +173,7 @@ export interface MaintainPlanQuery extends PageQuery {
state?: string;
/**
* 日期范围参数
*/
* 日期范围参数
*/
params?: any;
}

View File

@@ -2,7 +2,7 @@ import type { PageQuery, BaseEntity } from '#/api/common';
export interface RoomVO {
/**
*
*
*/
id: string | number;
@@ -22,10 +22,15 @@ export interface RoomVO {
roomType: number;
/**
* 面积(平方米)
* 建筑面积(平方米)
*/
area: number;
/**
* 套内面积(平方米)
*/
insideInArea: number;
/**
* 户型(如2室1厅1卫)
*/
@@ -50,7 +55,7 @@ export interface RoomVO {
export interface RoomForm extends BaseEntity {
/**
*
*
*/
id?: string | number;

View File

@@ -0,0 +1,91 @@
<script setup lang="ts">
import { computed, ref } from 'vue';
import { useVbenModal } from '@vben/common-ui';
import { $t } from '@vben/locales';
import { cloneDeep } from '@vben/utils';
import { useVbenForm } from '#/adapter/form';
import { carChargeAdd, carChargeInfo, carChargeUpdate } from '#/api/property/carCharge';
import { defaultFormValueGetter, useBeforeCloseDiff } from '#/utils/popup';
import { addModalSchema } from './data';
const emit = defineEmits<{ reload: [] }>();
const [BasicForm, formApi] = useVbenForm({
commonConfig: {
// 默认占满两列
formItemClass: 'col-span-2',
// 默认label宽度 px
labelWidth: 140,
// 通用配置项 会影响到所有表单项
componentProps: {
class: 'w-full',
}
},
schema: addModalSchema(),
showDefaultActions: false,
wrapperClass: 'grid-cols-2',
});
const { onBeforeClose, markInitialized, resetInitialized } = useBeforeCloseDiff(
{
initializedGetter: defaultFormValueGetter(formApi),
currentGetter: defaultFormValueGetter(formApi),
},
);
const [BasicModal, modalApi] = useVbenModal({
// 在这里更改宽度
class: 'w-[550px]',
fullscreenButton: false,
onBeforeClose,
onClosed: handleClosed,
onConfirm: handleConfirm,
onOpenChange: async (isOpen) => {
if (!isOpen) {
return null;
}
modalApi.modalLoading(true);
const { id } = modalApi.getData() as { id?: number | string };
await markInitialized();
modalApi.modalLoading(false);
},
});
async function handleConfirm() {
try {
modalApi.lock(true);
const { valid } = await formApi.validate();
if (!valid) {
return;
}
// getValues获取为一个readonly的对象 需要修改必须先深拷贝一次
const data = cloneDeep(await formApi.getValues());
await carChargeAdd(data);
resetInitialized();
emit('reload');
modalApi.close();
} catch (error) {
console.error(error);
} finally {
modalApi.lock(false);
}
}
async function handleClosed() {
await formApi.resetForm();
resetInitialized();
}
</script>
<template>
<BasicModal title="创建收费">
<BasicForm />
</BasicModal>
</template>

View File

@@ -0,0 +1,101 @@
<script setup lang="ts">
import { computed, ref } from 'vue';
import { useVbenModal } from '@vben/common-ui';
import { $t } from '@vben/locales';
import { cloneDeep } from '@vben/utils';
import { useVbenForm } from '#/adapter/form';
import { carChargeAdd, carChargeInfo, carChargeUpdate } from '#/api/property/carCharge';
import { defaultFormValueGetter, useBeforeCloseDiff } from '#/utils/popup';
import { modalSchema } from './data';
const emit = defineEmits<{ reload: [] }>();
const isUpdate = ref(false);
const title = computed(() => {
return isUpdate.value ? $t('pages.common.edit') : $t('pages.common.add');
});
const [BasicForm, formApi] = useVbenForm({
commonConfig: {
// 默认占满两列
formItemClass: 'col-span-2',
// 默认label宽度 px
labelWidth: 80,
// 通用配置项 会影响到所有表单项
componentProps: {
class: 'w-full',
}
},
schema: modalSchema(),
showDefaultActions: false,
wrapperClass: 'grid-cols-2',
});
const { onBeforeClose, markInitialized, resetInitialized } = useBeforeCloseDiff(
{
initializedGetter: defaultFormValueGetter(formApi),
currentGetter: defaultFormValueGetter(formApi),
},
);
const [BasicModal, modalApi] = useVbenModal({
// 在这里更改宽度
class: 'w-[550px]',
fullscreenButton: false,
onBeforeClose,
onClosed: handleClosed,
onConfirm: handleConfirm,
onOpenChange: async (isOpen) => {
if (!isOpen) {
return null;
}
modalApi.modalLoading(true);
const { id } = modalApi.getData() as { id?: number | string };
isUpdate.value = !!id;
if (isUpdate.value && id) {
const record = await carChargeInfo(id);
await formApi.setValues(record);
}
await markInitialized();
modalApi.modalLoading(false);
},
});
async function handleConfirm() {
try {
modalApi.lock(true);
const { valid } = await formApi.validate();
if (!valid) {
return;
}
// getValues获取为一个readonly的对象 需要修改必须先深拷贝一次
const data = cloneDeep(await formApi.getValues());
await (isUpdate.value ? carChargeUpdate(data) : carChargeAdd(data));
resetInitialized();
emit('reload');
modalApi.close();
} catch (error) {
console.error(error);
} finally {
modalApi.lock(false);
}
}
async function handleClosed() {
await formApi.resetForm();
resetInitialized();
}
</script>
<template>
<BasicModal :title="title">
<BasicForm />
</BasicModal>
</template>

View File

@@ -0,0 +1,89 @@
<script setup lang="ts">
import { computed, ref } from 'vue';
import { useVbenModal } from '@vben/common-ui';
import { $t } from '@vben/locales';
import { cloneDeep } from '@vben/utils';
import { useVbenForm } from '#/adapter/form';
import { carChargeAdd, carChargeInfo, carChargeUpdate } from '#/api/property/carCharge';
import { defaultFormValueGetter, useBeforeCloseDiff } from '#/utils/popup';
import { payModalSchema } from './data';
const emit = defineEmits<{ reload: [] }>();
const [BasicForm, formApi] = useVbenForm({
commonConfig: {
formItemClass: 'col-span-1',
// 默认label宽度 px
labelWidth: 1400,
// 通用配置项 会影响到所有表单项
componentProps: {
class: 'w-full',
}
},
schema: payModalSchema(),
showDefaultActions: false,
wrapperClass: 'grid-cols-2',
});
const { onBeforeClose, markInitialized, resetInitialized } = useBeforeCloseDiff(
{
initializedGetter: defaultFormValueGetter(formApi),
currentGetter: defaultFormValueGetter(formApi),
},
);
const [BasicModal, modalApi] = useVbenModal({
// 在这里更改宽度
class: 'w-[70%]',
fullscreenButton: false,
onBeforeClose,
onClosed: handleClosed,
onConfirm: handleConfirm,
onOpenChange: async (isOpen) => {
if (!isOpen) {
return null;
}
modalApi.modalLoading(true);
const { id } = modalApi.getData() as { id?: number | string };
await markInitialized();
modalApi.modalLoading(false);
},
});
async function handleConfirm() {
try {
modalApi.lock(true);
const { valid } = await formApi.validate();
if (!valid) {
return;
}
// getValues获取为一个readonly的对象 需要修改必须先深拷贝一次
const data = cloneDeep(await formApi.getValues());
await carChargeAdd(data);
resetInitialized();
emit('reload');
modalApi.close();
} catch (error) {
console.error(error);
} finally {
modalApi.lock(false);
}
}
async function handleClosed() {
await formApi.resetForm();
resetInitialized();
}
</script>
<template>
<BasicModal title="缴费">
<BasicForm />
</BasicModal>
</template>

View File

@@ -0,0 +1,350 @@
import type { FormSchemaGetter } from '#/adapter/form';
import type { VxeGridProps } from '#/adapter/vxe-table';
import { getDictOptions } from '#/utils/dict';
import { renderDict } from '#/utils/render';
export const querySchema: FormSchemaGetter = () => [
{
component: 'Input',
fieldName: 'carNumber',
label: '车牌号',
},
{
component: 'Input',
fieldName: 'personId',
label: '业主',
},
{
component: 'Select',
componentProps: {
// 可选从DictEnum中获取 DictEnum.WY_CSZT 便于维护
options: getDictOptions('wy_cszt'),
},
fieldName: 'state',
label: '状态',
},
];
// 需要使用i18n注意这里要改成getter形式 否则切换语言不会刷新
// export const columns: () => VxeGridProps['columns'] = () => [
export const columns: VxeGridProps['columns'] = [
{ type: 'checkbox', width: 60 },
{
title: '序号',
field: 'id',
slots: {
default: ({ rowIndex }) => {
return (rowIndex + 1).toString();
},
},
},
{
title: '车牌号',
field: 'carNumber',
},
{
title: '车位',
field: 'location',
},
{
title: '业主',
field: 'personId',
},
{
title: '状态',
field: 'state',
slots: {
default: ({ row }) => {
// 可选从DictEnum中获取 DictEnum.WY_CSZT 便于维护
return renderDict(row.state, 'wy_cszt');
},
},
},
{
title: '收费项目',
field: 'costItemsId',
},
{
title: '计费开始时间',
field: 'starTime',
},
{
title: '计费结束时间',
field: 'endTime',
},
{
title: '说明',
field: 'remark',
},
{
field: 'action',
fixed: 'right',
slots: { default: 'action' },
title: '操作',
width: 180,
},
];
//详情
export const modalSchema: FormSchemaGetter = () => [
{
label: '主键',
fieldName: 'id',
component: 'Input',
dependencies: {
show: () => false,
triggerFields: [''],
},
},
{
label: '车牌号',
fieldName: 'carNumber',
component: 'Input',
rules: 'required',
},
{
label: '业主',
fieldName: 'personId',
component: 'Input',
},
{
label: '楼层',
fieldName: 'floorId',
component: 'Input',
rules: 'required',
},
{
label: '车位',
fieldName: 'location',
component: 'Input',
},
{
label: '状态',
fieldName: 'state',
component: 'Select',
componentProps: {
// 可选从DictEnum中获取 DictEnum.WY_CSZT 便于维护
options: getDictOptions('wy_cszt'),
},
},
{
label: '收费项目',
fieldName: 'costItemsId',
component: 'Input',
},
{
label: '计费开始时间',
fieldName: 'starTime',
component: 'DatePicker',
componentProps: {
showTime: true,
format: 'YYYY-MM-DD HH:mm:ss',
valueFormat: 'YYYY-MM-DD HH:mm:ss',
},
},
{
label: '计费结束时间',
fieldName: 'endTime',
component: 'DatePicker',
componentProps: {
showTime: true,
format: 'YYYY-MM-DD HH:mm:ss',
valueFormat: 'YYYY-MM-DD HH:mm:ss',
},
},
{
label: '说明',
fieldName: 'remark',
component: 'Input',
},
{
label: '搜索值',
fieldName: 'searchValue',
component: 'Input',
},
];
//创建
export const addModalSchema: FormSchemaGetter = () => [
{
label: '主键',
fieldName: 'id',
component: 'Input',
dependencies: {
show: () => false,
triggerFields: [''],
},
},
{
label: '车牌号',
fieldName: 'carNumber',
component: 'Input',
rules: 'required',
},
// {
// label: '费用类型',//一个费用下有对各费用项目
// fieldName: 'personId',
// component: 'Input',
// },
{
label: '收费项目',//一个费用收费项目对应一个费用类型
fieldName: 'costItemsId',
component: 'Input',
rules: 'required',
},
{
label: '计费开始时间',
fieldName: 'starTime',
component: 'DatePicker',
rules: 'required',
componentProps: {
showTime: true,
format: 'YYYY-MM-DD HH:mm:ss',
valueFormat: 'YYYY-MM-DD HH:mm:ss',
},
},
{
label: '计费结束时间',
fieldName: 'endTime',
component: 'DatePicker',
rules:'required',
componentProps: {
showTime: true,
format: 'YYYY-MM-DD HH:mm:ss',
valueFormat: 'YYYY-MM-DD HH:mm:ss',
},
},
{
label: '说明',
fieldName: 'remark',
component: 'Input',
},
];
//缴费
export const payModalSchema: FormSchemaGetter = () => [
{
label: '主键',
fieldName: 'id',
component: 'Input',
dependencies: {
show: () => false,
triggerFields: [''],
},
},
{
label: '车牌号',
fieldName: 'carNumber',
component: 'Input',
rules: 'required',
},
// {
// label: '费用类型',//一个费用下有对各费用项目
// fieldName: 'personId',
// component: 'Input',
// },
{
label: '收费项目',//一个费用收费项目对应一个费用类型
fieldName: 'costItemsId',
component: 'Input',
rules: 'required',
},
{
label: '计费开始时间',
fieldName: 'starTime',
component: 'DatePicker',
rules: 'required',
componentProps: {
showTime: true,
format: 'YYYY-MM-DD HH:mm:ss',
valueFormat: 'YYYY-MM-DD HH:mm:ss',
},
},
{
label: '计费结束时间',
fieldName: 'endTime',
component: 'DatePicker',
rules:'required',
componentProps: {
showTime: true,
format: 'YYYY-MM-DD HH:mm:ss',
valueFormat: 'YYYY-MM-DD HH:mm:ss',
},
},
{
label: '说明',
fieldName: 'remark',
component: 'Input',
},
{
label: '支付方式',
fieldName: 'carNumber',
component: 'Input',
rules: 'required',
},
{
label: '缴费周期',
fieldName: 'personId',
component: 'Input',
},
{
label: '实收金额',
fieldName: 'costItemsId',
component: 'Input',
},
{
label: '自定义周期',
fieldName: 'remark',
component: 'Input',
},
];
export const detailColumns: VxeGridProps['columns'] = [
{
title: '序号',
field: 'id',
slots: {
default: ({ rowIndex }) => {
return (rowIndex + 1).toString();
},
},
},
{
title: '费用项目',
field: 'carNumber',
},
{
title: '费用标识',
field: 'location',
},
{
title: '应收金额',
field: 'personId',
},
{
title: '状态',
field: 'state',
slots: {
default: ({ row }) => {
// 可选从DictEnum中获取 DictEnum.WY_CSZT 便于维护
return renderDict(row.state, 'wy_cszt');
},
},
},
{
title: '建帐时间',
field: 'starTime',
},
{
title: '应收时间',
field: 'endTime',
},
{
title: '说明',
field: 'remark',
},
{
field: 'action',
fixed: 'right',
slots: { default: 'action' },
title: '操作',
width: 180,
},
];

View File

@@ -0,0 +1,173 @@
<script setup lang="ts">
import type { Recordable } from '@vben/types';
import { ref } from 'vue';
import { Page, useVbenModal, type VbenFormProps } from '@vben/common-ui';
import { getVxePopupContainer } from '@vben/utils';
import { Modal, Popconfirm, Space } from 'ant-design-vue';
import dayjs from 'dayjs';
import {
useVbenVxeGrid,
vxeCheckboxChecked,
type VxeGridProps
} from '#/adapter/vxe-table';
import {
carChargeExport,
carChargeList,
carChargeRemove,
} from '#/api/property/carCharge';
import type { CarChargeForm } from '#/api/property/carCharge/model';
import { commonDownloadExcel } from '#/utils/file/download';
import carChargeDetailModal from './carCharge-detail-modal.vue';// 详情弹窗
import carChargePayModal from './carCharge-pay-modal.vue';//缴费弹窗
import carCharfeAddModal from './carCharge-add-modal.vue';//创建费用弹窗
import { columns, querySchema } from './data';
const formOptions: VbenFormProps = {
commonConfig: {
labelWidth: 80,
componentProps: {
allowClear: true,
},
},
schema: querySchema(),
wrapperClass: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4',
// 处理区间选择器RangePicker时间格式 将一个字段映射为两个字段 搜索/导出会用到
// 不需要直接删除
// fieldMappingTime: [
// [
// 'createTime',
// ['params[beginTime]', 'params[endTime]'],
// ['YYYY-MM-DD 00:00:00', 'YYYY-MM-DD 23:59:59'],
// ],
// ],
};
const gridOptions: VxeGridProps = {
checkboxConfig: {
// 高亮
highlight: true,
// 翻页时保留选中状态
reserve: true,
// 点击行选中
// trigger: 'row',
},
// 需要使用i18n注意这里要改成getter形式 否则切换语言不会刷新
// columns: columns(),
columns,
height: 'auto',
keepSource: true,
pagerConfig: {},
proxyConfig: {
ajax: {
query: async ({ page }, formValues = {}) => {
return await carChargeList({
pageNum: page.currentPage,
pageSize: page.pageSize,
...formValues,
});
},
},
},
rowConfig: {
keyField: 'id',
},
// 表格全局唯一表示 保存列配置需要用到
id: 'property-carCharge-index'
};
const [BasicTable, tableApi] = useVbenVxeGrid({
formOptions,
gridOptions,
});
// 详情弹窗
const [CarChargeDetailModal, modalApi] = useVbenModal({
connectedComponent: carChargeDetailModal,
});
// 创建费用弹窗
const [CarCharfeAddModal, addModalApi] = useVbenModal({
connectedComponent: carCharfeAddModal,
});
// 缴费弹窗
const [CarChargePayModal, payModalApi] = useVbenModal({
connectedComponent: carChargePayModal,
});
//打开创建费用弹窗
function handleAdd() {
addModalApi.setData({});
addModalApi.open();
}
//打开详情
async function handleEdit(row: Required<CarChargeForm>) {
modalApi.setData({ id: row.id });
modalApi.open();
}
//打开缴费
async function handleSave(row: Required<CarChargeForm>) {
payModalApi.setData({ id: row.id });
payModalApi.open();
}
async function handleDelete(row: Required<CarChargeForm>) {
await carChargeRemove(row.id);
await tableApi.query();
}
</script>
<template>
<Page :auto-content-height="true">
<BasicTable table-title="费用-车辆收费列表">
<template #toolbar-tools>
<Space>
<a-button
type="primary"
v-access:code="['property:carCharge:add']"
@click="handleAdd"
>
创建费用
</a-button>
</Space>
</template>
<template #action="{ row }">
<Space>
<ghost-button
v-access:code="['property:carCharge:edit']"
@click.stop="handleSave(row)"
>
缴费
</ghost-button>
<Popconfirm
:get-popup-container="getVxePopupContainer"
placement="left"
title="确认删除?"
@confirm="handleDelete(row)"
>
<ghost-button
danger
v-access:code="['property:carCharge:remove']"
@click.stop=""
>
{{ $t('pages.common.delete') }}
</ghost-button>
</Popconfirm>
<ghost-button
v-access:code="['property:carCharge:edit']"
@click.stop="handleEdit(row)"
>
详情
</ghost-button>
</Space>
</template>
</BasicTable>
<!-- 详情弹窗 -->
<CarChargeDetailModal @reload="tableApi.query()" />
<CarCharfeAddModal @reload="tableApi.query()" />
<CarChargePayModal @reload="tableApi.query()" />
</Page>
</template>

View File

@@ -0,0 +1,101 @@
<script setup lang="ts">
import { computed, ref } from 'vue';
import { useVbenModal } from '@vben/common-ui';
import { $t } from '@vben/locales';
import { cloneDeep } from '@vben/utils';
import { useVbenForm } from '#/adapter/form';
import { costMeterWaterAdd, costMeterWaterInfo, costMeterWaterUpdate } from '#/api/property/costMeterWater';
import { defaultFormValueGetter, useBeforeCloseDiff } from '#/utils/popup';
import { modalSchema } from './data';
const emit = defineEmits<{ reload: [] }>();
const isUpdate = ref(false);
const title = computed(() => {
return isUpdate.value ? $t('pages.common.edit') : $t('pages.common.add');
});
const [BasicForm, formApi] = useVbenForm({
commonConfig: {
// 默认占满两列
formItemClass: 'col-span-2',
// 默认label宽度 px
labelWidth: 80,
// 通用配置项 会影响到所有表单项
componentProps: {
class: 'w-full',
}
},
schema: modalSchema(),
showDefaultActions: false,
wrapperClass: 'grid-cols-2',
});
const { onBeforeClose, markInitialized, resetInitialized } = useBeforeCloseDiff(
{
initializedGetter: defaultFormValueGetter(formApi),
currentGetter: defaultFormValueGetter(formApi),
},
);
const [BasicModal, modalApi] = useVbenModal({
// 在这里更改宽度
class: 'w-[550px]',
fullscreenButton: false,
onBeforeClose,
onClosed: handleClosed,
onConfirm: handleConfirm,
onOpenChange: async (isOpen) => {
if (!isOpen) {
return null;
}
modalApi.modalLoading(true);
const { id } = modalApi.getData() as { id?: number | string };
isUpdate.value = !!id;
if (isUpdate.value && id) {
const record = await costMeterWaterInfo(id);
await formApi.setValues(record);
}
await markInitialized();
modalApi.modalLoading(false);
},
});
async function handleConfirm() {
try {
modalApi.lock(true);
const { valid } = await formApi.validate();
if (!valid) {
return;
}
// getValues获取为一个readonly的对象 需要修改必须先深拷贝一次
const data = cloneDeep(await formApi.getValues());
await (isUpdate.value ? costMeterWaterUpdate(data) : costMeterWaterAdd(data));
resetInitialized();
emit('reload');
modalApi.close();
} catch (error) {
console.error(error);
} finally {
modalApi.lock(false);
}
}
async function handleClosed() {
await formApi.resetForm();
resetInitialized();
}
</script>
<template>
<BasicModal :title="title">
<BasicForm />
</BasicModal>
</template>

View File

@@ -0,0 +1,183 @@
import type { FormSchemaGetter } from '#/adapter/form';
import type { VxeGridProps } from '#/adapter/vxe-table';
export const querySchema: FormSchemaGetter = () => [
{
component: 'Input',
fieldName: 'itemId',
label: '费用类型id',
},
{
component: 'Input',
fieldName: 'meterTypeId',
label: '抄表类型id',
},
{
component: 'Input',
fieldName: 'objName',
label: '对象名称',
},
{
component: 'Input',
fieldName: 'curDegrees',
label: '本期度数',
},
{
component: 'Input',
fieldName: 'preDegrees',
label: '上期度数',
},
{
component: 'DatePicker',
componentProps: {
showTime: true,
format: 'YYYY-MM-DD HH:mm:ss',
valueFormat: 'YYYY-MM-DD HH:mm:ss',
},
fieldName: 'preReadingTime',
label: '上期读表时间',
},
{
component: 'DatePicker',
componentProps: {
showTime: true,
format: 'YYYY-MM-DD HH:mm:ss',
valueFormat: 'YYYY-MM-DD HH:mm:ss',
},
fieldName: 'curReadingTime',
label: '本期读表时间',
},
{
component: 'Input',
fieldName: 'searchValue',
label: '搜索值',
},
];
// 需要使用i18n注意这里要改成getter形式 否则切换语言不会刷新
// export const columns: () => VxeGridProps['columns'] = () => [
export const columns: VxeGridProps['columns'] = [
{ type: 'checkbox', width: 60 },
{
title: '主键',
field: 'id',
},
{
title: '费用类型id',
field: 'itemId',
},
{
title: '抄表类型id',
field: 'meterTypeId',
},
{
title: '对象名称',
field: 'objName',
},
{
title: '本期度数',
field: 'curDegrees',
},
{
title: '上期度数',
field: 'preDegrees',
},
{
title: '上期读表时间',
field: 'preReadingTime',
},
{
title: '本期读表时间',
field: 'curReadingTime',
},
{
title: '备注',
field: 'remark',
},
{
title: '搜索值',
field: 'searchValue',
},
{
field: 'action',
fixed: 'right',
slots: { default: 'action' },
title: '操作',
width: 180,
},
];
export const modalSchema: FormSchemaGetter = () => [
{
label: '主键',
fieldName: 'id',
component: 'Input',
dependencies: {
show: () => false,
triggerFields: [''],
},
},
{
label: '费用类型id',
fieldName: 'itemId',
component: 'Input',
rules: 'required',
},
{
label: '抄表类型id',
fieldName: 'meterTypeId',
component: 'Input',
rules: 'required',
},
{
label: '对象名称',
fieldName: 'objName',
component: 'Input',
rules: 'required',
},
{
label: '本期度数',
fieldName: 'curDegrees',
component: 'Input',
rules: 'required',
},
{
label: '上期度数',
fieldName: 'preDegrees',
component: 'Input',
rules: 'required',
},
{
label: '上期读表时间',
fieldName: 'preReadingTime',
component: 'DatePicker',
componentProps: {
showTime: true,
format: 'YYYY-MM-DD HH:mm:ss',
valueFormat: 'YYYY-MM-DD HH:mm:ss',
},
rules: 'required',
},
{
label: '本期读表时间',
fieldName: 'curReadingTime',
component: 'DatePicker',
componentProps: {
showTime: true,
format: 'YYYY-MM-DD HH:mm:ss',
valueFormat: 'YYYY-MM-DD HH:mm:ss',
},
rules: 'required',
},
{
label: '备注',
fieldName: 'remark',
component: 'Textarea',
},
{
label: '搜索值',
fieldName: 'searchValue',
component: 'Input',
},
];

View File

@@ -0,0 +1,182 @@
<script setup lang="ts">
import type { Recordable } from '@vben/types';
import { ref } from 'vue';
import { Page, useVbenModal, type VbenFormProps } from '@vben/common-ui';
import { getVxePopupContainer } from '@vben/utils';
import { Modal, Popconfirm, Space } from 'ant-design-vue';
import dayjs from 'dayjs';
import {
useVbenVxeGrid,
vxeCheckboxChecked,
type VxeGridProps
} from '#/adapter/vxe-table';
import {
costMeterWaterExport,
costMeterWaterList,
costMeterWaterRemove,
} from '#/api/property/costMeterWater';
import type { CostMeterWaterForm } from '#/api/property/costMeterWater/model';
import { commonDownloadExcel } from '#/utils/file/download';
import costMeterWaterModal from './costMeterWater-modal.vue';
import { columns, querySchema } from './data';
const formOptions: VbenFormProps = {
commonConfig: {
labelWidth: 80,
componentProps: {
allowClear: true,
},
},
schema: querySchema(),
wrapperClass: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4',
// 处理区间选择器RangePicker时间格式 将一个字段映射为两个字段 搜索/导出会用到
// 不需要直接删除
// fieldMappingTime: [
// [
// 'createTime',
// ['params[beginTime]', 'params[endTime]'],
// ['YYYY-MM-DD 00:00:00', 'YYYY-MM-DD 23:59:59'],
// ],
// ],
};
const gridOptions: VxeGridProps = {
checkboxConfig: {
// 高亮
highlight: true,
// 翻页时保留选中状态
reserve: true,
// 点击行选中
// trigger: 'row',
},
// 需要使用i18n注意这里要改成getter形式 否则切换语言不会刷新
// columns: columns(),
columns,
height: 'auto',
keepSource: true,
pagerConfig: {},
proxyConfig: {
ajax: {
query: async ({ page }, formValues = {}) => {
return await costMeterWaterList({
pageNum: page.currentPage,
pageSize: page.pageSize,
...formValues,
});
},
},
},
rowConfig: {
keyField: 'id',
},
// 表格全局唯一表示 保存列配置需要用到
id: 'property-costMeterWater-index'
};
const [BasicTable, tableApi] = useVbenVxeGrid({
formOptions,
gridOptions,
});
const [CostMeterWaterModal, modalApi] = useVbenModal({
connectedComponent: costMeterWaterModal,
});
function handleAdd() {
modalApi.setData({});
modalApi.open();
}
async function handleEdit(row: Required<CostMeterWaterForm>) {
modalApi.setData({ id: row.id });
modalApi.open();
}
async function handleDelete(row: Required<CostMeterWaterForm>) {
await costMeterWaterRemove(row.id);
await tableApi.query();
}
function handleMultiDelete() {
const rows = tableApi.grid.getCheckboxRecords();
const ids = rows.map((row: Required<CostMeterWaterForm>) => row.id);
Modal.confirm({
title: '提示',
okType: 'danger',
content: `确认删除选中的${ids.length}条记录吗?`,
onOk: async () => {
await costMeterWaterRemove(ids);
await tableApi.query();
},
});
}
function handleDownloadExcel() {
commonDownloadExcel(costMeterWaterExport, '费用-水电抄数据', tableApi.formApi.form.values, {
fieldMappingTime: formOptions.fieldMappingTime,
});
}
</script>
<template>
<Page :auto-content-height="true">
<BasicTable table-title="费用-水电抄列表">
<template #toolbar-tools>
<Space>
<a-button
v-access:code="['property:costMeterWater:export']"
@click="handleDownloadExcel"
>
{{ $t('pages.common.export') }}
</a-button>
<a-button
:disabled="!vxeCheckboxChecked(tableApi)"
danger
type="primary"
v-access:code="['property:costMeterWater:remove']"
@click="handleMultiDelete">
{{ $t('pages.common.delete') }}
</a-button>
<a-button
type="primary"
v-access:code="['property:costMeterWater:add']"
@click="handleAdd"
>
{{ $t('pages.common.add') }}
</a-button>
</Space>
</template>
<template #action="{ row }">
<Space>
<ghost-button
v-access:code="['property:costMeterWater:edit']"
@click.stop="handleEdit(row)"
>
{{ $t('pages.common.edit') }}
</ghost-button>
<Popconfirm
:get-popup-container="getVxePopupContainer"
placement="left"
title="确认删除?"
@confirm="handleDelete(row)"
>
<ghost-button
danger
v-access:code="['property:costMeterWater:remove']"
@click.stop=""
>
{{ $t('pages.common.delete') }}
</ghost-button>
</Popconfirm>
</Space>
</template>
</BasicTable>
<CostMeterWaterModal @reload="tableApi.query()" />
</Page>
</template>

View File

@@ -0,0 +1,181 @@
import type {FormSchemaGetter} from '#/adapter/form';
import type {VxeGridProps} from '#/adapter/vxe-table';
import {getDictOptions} from "#/utils/dict";
import {renderDict} from "#/utils/render";
import {costItemSettingList} from "#/api/property/costManagement/costItemSetting";
import { h } from 'vue';
export const querySchema: FormSchemaGetter = () => [
{
component: 'ApiSelect',
componentProps: {
api:async ()=>{
return (await costItemSettingList({pageSize: 1000, pageNum: 1}))?.rows
},
afterFetch: (data: { chargeItem: string; id: string }[]) => {
return data.map((item: any) => ({
label: item.chargeItem,
value: item.id,
}));
},
},
fieldName: 'costItemsId',
label: '收费项目',
},
{
component: 'Select',
fieldName: 'state',
label: '状态',
componentProps: {
options: getDictOptions('wy_fysfzt')
},
},
];
export const columns: VxeGridProps['columns'] = [
{type: 'checkbox', width: 60},
{
title: '房屋',
field: 'roomId',
minWidth: 150,
},
{
title: '收费项目',
field: 'costItemsId',
width: 150,
},
{
title: '应收金额',
field: 'amountReceivable',
width: 150,
},
{
title: '计费开始时间',
field: 'startTime',
width: 150,
},
{
title: '计费结束时间',
field: 'endTime',
width: 150,
},
{
title: '状态',
field: 'state',
width: 150,
slots: {
default: ({row}) => {
return renderDict(row.state, 'wy_fysfzt')
}
}
},
{
title: '说明',
field: 'remark',
width: 150,
},
{
field: 'action',
fixed: 'right',
slots: {default: 'action'},
title: '操作',
width: 180,
},
];
export const modalSchema: FormSchemaGetter = () => [
{
label: '主键',
fieldName: 'id',
component: 'Input',
dependencies: {
show: () => false,
triggerFields: [''],
},
},
{
label: '房屋',
fieldName: 'roomId',
component: 'TreeSelect',
componentProps: {
},
rules: 'selectRequired',
},
{
label: '费用类型',
fieldName: 'costType',
component: 'Select',
componentProps: {
},
rules: 'selectRequired',
},
{
label: '收费项目',
fieldName: 'costItemsId',
component: 'ApiSelect',
componentProps: {},
rules: 'selectRequired',
},
{
label: '应收金额',
fieldName: 'amountReceivable',
component: 'Input',
dependencies: {
show: () => false,
triggerFields: [''],
},
},
{
label: '计费时间',
fieldName: 'chargeTime',
component: 'RangePicker',
componentProps: {
format: 'YYYY-MM-DD',
valueFormat: 'YYYY-MM-DD',
},
rules: 'selectRequired',
},
{
label: '说明',
fieldName: 'remark',
component: 'Textarea',
formItemClass: 'col-span-2',
dependencies: {
show: () => false,
triggerFields: [''],
},
},
];
export const modalSchemaUpdate: FormSchemaGetter = () => [
{
label: '主键',
fieldName: 'id',
component: 'Input',
dependencies: {
show: () => false,
triggerFields: [''],
},
},
{
label: '支付方式',
fieldName: 'payType',
component: 'Select',
componentProps: {
options:getDictOptions('wy_zffs')
},
rules: 'selectRequired',
},
{
label: '缴费周期',
fieldName: 'chargeCycle',
component: 'InputNumber',
componentProps: {
min:1,
precision:0,
placeholder:'请输入缴费周期(月)'
},
suffix: () => h('span', { style: {fontSize: '0.875rem',fontWeight:500,} }, '月'),
rules: 'selectRequired',
},
]

View File

@@ -0,0 +1,91 @@
<script setup lang="ts">
import {ref, shallowRef} from 'vue';
import {useVbenModal} from '@vben/common-ui';
import {Descriptions, DescriptionsItem} from 'ant-design-vue';
import dayjs from 'dayjs';
import duration from 'dayjs/plugin/duration';
import relativeTime from 'dayjs/plugin/relativeTime';
import {renderDict} from "#/utils/render";
dayjs.extend(duration);
dayjs.extend(relativeTime);
import {houseChargeInfo} from "#/api/property/costManagement/houseCharge";
import type {HouseChargeVO} from "#/api/property/costManagement/houseCharge/model";
import type {RoomVO} from "#/api/property/room/model";
import type {CostItemSettingVO} from "#/api/property/costManagement/costItemSetting/model";
const [BasicModal, modalApi] = useVbenModal({
onOpenChange: handleOpenChange,
onClosed() {
houseChargeDetail.value = null;
},
});
const houseChargeDetail = shallowRef<null | HouseChargeVO>(null);
const room=ref<RoomVO>();
const costItem=ref<CostItemSettingVO>();
async function handleOpenChange(open: boolean) {
if (!open) {
return null;
}
modalApi.modalLoading(true);
const {id} = modalApi.getData() as { id: number | string };
houseChargeDetail.value = await houseChargeInfo(id);
if(houseChargeDetail.value){
room.value=houseChargeDetail.value.roomVo
costItem.value=houseChargeDetail.value.costItemsVo
}
modalApi.modalLoading(false);
}
</script>
<template>
<BasicModal :footer="false" :fullscreen-button="false" title="房屋收费详情" class="w-[70%]">
<Descriptions v-if="houseChargeDetail" size="small" :column="2" bordered
:labelStyle="{width:'100px'}">
<DescriptionsItem label="费用编号">
{{ costItem?.id }}
</DescriptionsItem>
<DescriptionsItem label="费用项目">
{{ costItem?.chargeItem }}
</DescriptionsItem>
<DescriptionsItem label="费用类型">
<component v-if="costItem"
:is="renderDict(costItem.costType,'pro_expense_type')"
/>
</DescriptionsItem>
<DescriptionsItem label="计费时间">
{{ houseChargeDetail.startTime+' 至 '+houseChargeDetail.endTime }}
</DescriptionsItem>
<DescriptionsItem label="房间">
{{room?.roomNumber}}
</DescriptionsItem>
<DescriptionsItem label="房间面积">
{{`建筑面积:${room?.area} 套内面积:${room?.insideInArea}`}}
</DescriptionsItem>
<DescriptionsItem label="单价">
{{ costItem?.unitPrice }}
</DescriptionsItem>
<DescriptionsItem label="附加费">
{{costItem?.surcharge}}
</DescriptionsItem>
<DescriptionsItem label="应收金额">
<span style="font-size: 16px;font-weight: 600;color: red" v-if="houseChargeDetail.amountReceivable">
{{houseChargeDetail.amountReceivable}}
</span>
</DescriptionsItem>
<DescriptionsItem label="支付方式" v-if="houseChargeDetail.payType">
<component
:is="renderDict(houseChargeDetail.payType,'wy_zffs')"
/>
</DescriptionsItem>
<DescriptionsItem label="缴费周期" v-if="houseChargeDetail.chargeCycle">
{{houseChargeDetail.chargeCycle}}
</DescriptionsItem>
<DescriptionsItem label="说明" :span="2">
{{houseChargeDetail.remark}}
</DescriptionsItem>
</Descriptions>
</BasicModal>
</template>

View File

@@ -0,0 +1,201 @@
<script setup lang="ts">
import {computed, ref} from 'vue';
import {useVbenModal} from '@vben/common-ui';
import {$t} from '@vben/locales';
import {cloneDeep, handleNode} from '@vben/utils';
import {useVbenForm} from '#/adapter/form';
import {
houseChargeAdd,
houseChargeInfo,
houseChargeUpdate
} from '#/api/property/costManagement/houseCharge';
import {defaultFormValueGetter, useBeforeCloseDiff} from '#/utils/popup';
import {modalSchema} from './data';
import {communityTree} from "#/api/property/community";
import {costItemSettingList} from "#/api/property/costManagement/costItemSetting";
import type {CostItemSettingVO} from "#/api/property/costManagement/costItemSetting/model";
import {getDictOptions} from "#/utils/dict";
const emit = defineEmits<{ reload: [] }>();
const isUpdate = ref(false);
const costItemOptions = ref<CostItemSettingVO[]>([]);
const title = computed(() => {
return isUpdate.value ? $t('pages.common.edit') : $t('pages.common.add');
});
const [BasicForm, formApi] = useVbenForm({
commonConfig: {
// 默认占满两列
formItemClass: 'col-span-2',
// 默认label宽度 px
labelWidth: 80,
// 通用配置项 会影响到所有表单项
componentProps: {
class: 'w-full',
}
},
schema: modalSchema(),
showDefaultActions: false,
wrapperClass: 'grid-cols-2',
});
const {onBeforeClose, markInitialized, resetInitialized} = useBeforeCloseDiff(
{
initializedGetter: defaultFormValueGetter(formApi),
currentGetter: defaultFormValueGetter(formApi),
},
);
const [BasicModal, modalApi] = useVbenModal({
// 在这里更改宽度
class: 'w-[550px]',
fullscreenButton: false,
onBeforeClose,
onClosed: handleClosed,
onConfirm: handleConfirm,
onOpenChange: async (isOpen) => {
if (!isOpen) {
return null;
}
modalApi.modalLoading(true);
await initRoomOptions()
await queryCostItemOptions()
await initCostTypeOptions()
const {id} = modalApi.getData() as { id?: number | string };
isUpdate.value = !!id;
if (isUpdate.value && id) {
const record = await houseChargeInfo(id);
record.chargeTime = [record.startTime, record.endTime]
await formApi.setValues(record);
}
await markInitialized();
modalApi.modalLoading(false);
},
});
async function handleConfirm() {
try {
modalApi.lock(true);
const {valid} = await formApi.validate();
if (!valid) {
return;
}
// getValues获取为一个readonly的对象 需要修改必须先深拷贝一次
const data = cloneDeep(await formApi.getValues());
if (data.chargeTime && data.chargeTime.length) {
data.startTime = data.chargeTime[0]
data.endTime = data.chargeTime[1]
}
await (isUpdate.value ? houseChargeUpdate(data) : houseChargeAdd(data));
resetInitialized();
emit('reload');
modalApi.close();
} catch (error) {
console.error(error);
} finally {
modalApi.lock(false);
}
}
async function handleClosed() {
await formApi.resetForm();
resetInitialized();
}
/**
* 房间数据
*/
async function initRoomOptions() {
const roomList = await communityTree(5);
const splitStr = '/';
handleNode(roomList, 'label', splitStr, function (node: any) {
if (node.level != 5) {
node.disabled = true;
}
});
formApi.updateSchema([
{
componentProps: () => ({
class: 'w-full',
fieldNames: {
key: 'id',
label: 'label',
value: 'code',
children: 'children',
},
placeholder: '请选择房间',
showSearch: true,
treeData: roomList,
treeDefaultExpandAll: true,
treeLine: {showLeafIcon: false},
// 筛选的字段
treeNodeFilterProp: 'label',
// 选中后显示在输入框的值
treeNodeLabelProp: 'fullName',
}),
fieldName: 'roomId',
},
]);
}
/**
* 查询费用项设置
*/
async function queryCostItemOptions(costType:string) {
let params = {
pageSize: 1000,
pageNum: 1,
costType
}
const res = await costItemSettingList(params)
costItemOptions.value = res.rows
formApi.updateSchema([{
componentProps: {
options: costItemOptions.value,
fieldNames: {label: 'chargeItem', value: 'id'},
showSearch: true,
optionFilterProp: 'chargeItem',
onChange: async (value: string) => {
if (value) {
const costItem = costItemOptions.value.find(item => item.id == value)
if(costItem){
await formApi.setFieldValue('remark', `单价:${costItem.unitPrice} 附加费:${costItem.surcharge}`);
}
}
}
},
fieldName: 'costItemsId'
}])
}
/**
* 初始化费用类型
*/
async function initCostTypeOptions(){
formApi.updateSchema([{
componentProps: {
options: getDictOptions('pro_expense_type'),
onChange: async (value: string) => {
if (value) {
await queryCostItemOptions(value)
await formApi.setFieldValue('costItemsId', null)
}
}
},
fieldName: 'costType'
}])
}
</script>
<template>
<BasicModal :title="title">
<BasicForm/>
</BasicModal>
</template>

View File

@@ -0,0 +1,147 @@
<script setup lang="ts">
import {ref} from 'vue';
import {useVbenModal} from '@vben/common-ui';
import {cloneDeep} from '@vben/utils';
import {useVbenForm} from '#/adapter/form';
import {
houseChargeAdd,
houseChargeInfo,
houseChargeUpdate
} from '#/api/property/costManagement/houseCharge';
import {defaultFormValueGetter, useBeforeCloseDiff} from '#/utils/popup';
import {modalSchemaUpdate} from './data';
import {renderDict} from "#/utils/render";
import {Descriptions, DescriptionsItem, Divider} from "ant-design-vue";
import type {HouseChargeVO} from "#/api/property/costManagement/houseCharge/model";
import type {RoomVO} from "#/api/property/room/model";
import type {CostItemSettingVO} from "#/api/property/costManagement/costItemSetting/model";
const emit = defineEmits<{ reload: [] }>();
const isUpdate = ref(false);
const record = ref<HouseChargeVO>();
const room = ref<RoomVO>();
const costItem = ref<CostItemSettingVO>();
const [BasicForm, formApi] = useVbenForm({
commonConfig: {
// 默认占满两列
formItemClass: 'col-span-2',
// 默认label宽度 px
labelWidth: 80,
// 通用配置项 会影响到所有表单项
componentProps: {
class: 'w-full',
}
},
schema: modalSchemaUpdate(),
showDefaultActions: false,
wrapperClass: 'grid-cols-2',
});
const {onBeforeClose, markInitialized, resetInitialized} = useBeforeCloseDiff(
{
initializedGetter: defaultFormValueGetter(formApi),
currentGetter: defaultFormValueGetter(formApi),
},
);
const [BasicModal, modalApi] = useVbenModal({
// 在这里更改宽度
class: 'w-[550px]',
fullscreenButton: false,
onBeforeClose,
onClosed: handleClosed,
onConfirm: handleConfirm,
onOpenChange: async (isOpen) => {
if (!isOpen) {
return null;
}
modalApi.modalLoading(true);
const {id} = modalApi.getData() as { id?: number | string };
isUpdate.value = !!id;
record.value = await houseChargeInfo(id);
if (record.value) {
room.value = record.value.roomVo
costItem.value = record.value.costItemsVo
}
await formApi.setValues(record.value);
await markInitialized();
modalApi.modalLoading(false);
},
});
async function handleConfirm() {
try {
modalApi.lock(true);
const {valid} = await formApi.validate();
if (!valid) {
return;
}
// getValues获取为一个readonly的对象 需要修改必须先深拷贝一次
const data = cloneDeep(await formApi.getValues());
record.value.payType = data.payType
record.value.chargeCycle = data.chargeCycle
await houseChargeUpdate(record.value) ;
resetInitialized();
emit('reload');
modalApi.close();
} catch (error) {
console.error(error);
} finally {
modalApi.lock(false);
}
}
async function handleClosed() {
await formApi.resetForm();
resetInitialized();
}
</script>
<template>
<BasicModal title="缴费">
<Descriptions v-if="record" size="small" :column="2"
:labelStyle="{width:'80px'}">
<DescriptionsItem label="费用编号">
{{ costItem?.id }}
</DescriptionsItem>
<DescriptionsItem label="费用项目">
{{ costItem?.chargeItem }}
</DescriptionsItem>
<DescriptionsItem label="费用类型">
<component
v-if="costItem"
:is="renderDict(costItem?.costType,'pro_expense_type')"
/>
</DescriptionsItem>
<DescriptionsItem label="计费起始">
{{ record.startTime }}
</DescriptionsItem>
<DescriptionsItem label="房间">
{{ room.roomNumber }}
</DescriptionsItem>
<DescriptionsItem label="面积(㎡)">
{{ `${room?.area} (套内面积:${room?.insideInArea}` }}
</DescriptionsItem>
<DescriptionsItem label="单价">
{{ costItem?.unitPrice }}
</DescriptionsItem>
<DescriptionsItem label="附加费">
{{ costItem?.surcharge }}
</DescriptionsItem>
<DescriptionsItem label="应收金额" :span="2">
<span style="font-size: 16px;font-weight: 600;color: red" v-if="record.amountReceivable">
{{ record.amountReceivable }}
</span>
</DescriptionsItem>
</Descriptions>
<Divider/>
<BasicForm/>
</BasicModal>
</template>

View File

@@ -0,0 +1,189 @@
<script setup lang="ts">
import { Page, useVbenModal, type VbenFormProps } from '@vben/common-ui';
import { getVxePopupContainer } from '@vben/utils';
import { Modal, Popconfirm, Space } from 'ant-design-vue';
import {
useVbenVxeGrid,
vxeCheckboxChecked,
type VxeGridProps
} from '#/adapter/vxe-table';
import {
houseChargeExport,
houseChargeList,
houseChargeRemove,
} from '#/api/property/costManagement/houseCharge';
import type { HouseChargeForm } from '#/api/property/costManagement/houseCharge/model';
import { commonDownloadExcel } from '#/utils/file/download';
import houseChargeAdd from './houseCharge-add.vue';
import houseChargeUpdate from './houseCharge-update.vue';
import houseChargeDetail from './house-charge-detail.vue';
import { columns, querySchema } from './data';
const formOptions: VbenFormProps = {
commonConfig: {
labelWidth: 80,
componentProps: {
allowClear: true,
},
},
schema: querySchema(),
wrapperClass: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4',
};
const gridOptions: VxeGridProps = {
checkboxConfig: {
// 高亮
highlight: true,
// 翻页时保留选中状态
reserve: true,
// 点击行选中
// trigger: 'row',
},
// 需要使用i18n注意这里要改成getter形式 否则切换语言不会刷新
// columns: columns(),
columns,
height: 'auto',
keepSource: true,
pagerConfig: {},
proxyConfig: {
ajax: {
query: async ({ page }, formValues = {}) => {
return await houseChargeList({
pageNum: page.currentPage,
pageSize: page.pageSize,
...formValues,
});
},
},
},
rowConfig: {
keyField: 'id',
},
// 表格全局唯一表示 保存列配置需要用到
id: 'property-houseCharge-index'
};
const [BasicTable, tableApi] = useVbenVxeGrid({
formOptions,
gridOptions,
});
const [HouseChargeAdd, modalApi] = useVbenModal({
connectedComponent: houseChargeAdd,
});
const [HouseChargeUpdate, updateApi] = useVbenModal({
connectedComponent: houseChargeUpdate,
});
const [HouseChargeDetail, detailApi] = useVbenModal({
connectedComponent: houseChargeDetail,
});
function handleAdd() {
modalApi.setData({});
modalApi.open();
}
async function handleEdit(row: Required<HouseChargeForm>) {
updateApi.setData({ id: row.id });
updateApi.open();
}
async function handleInfo(row: Required<HouseChargeForm>) {
detailApi.setData({ id: row.id });
detailApi.open();
}
async function handleDelete(row: Required<HouseChargeForm>) {
await houseChargeRemove(row.id);
await tableApi.query();
}
function handleMultiDelete() {
const rows = tableApi.grid.getCheckboxRecords();
const ids = rows.map((row: Required<HouseChargeForm>) => row.id);
Modal.confirm({
title: '提示',
okType: 'danger',
content: `确认删除选中的${ids.length}条记录吗?`,
onOk: async () => {
await houseChargeRemove(ids);
await tableApi.query();
},
});
}
function handleDownloadExcel() {
commonDownloadExcel(houseChargeExport, '房屋收费数据', tableApi.formApi.form.values, {
fieldMappingTime: formOptions.fieldMappingTime,
});
}
</script>
<template>
<Page :auto-content-height="true">
<BasicTable table-title="房屋收费列表">
<template #toolbar-tools>
<Space>
<a-button
v-access:code="['property:houseCharge:export']"
@click="handleDownloadExcel"
>
{{ $t('pages.common.export') }}
</a-button>
<a-button
:disabled="!vxeCheckboxChecked(tableApi)"
danger
type="primary"
v-access:code="['property:houseCharge:remove']"
@click="handleMultiDelete">
取消
</a-button>
<a-button
type="primary"
v-access:code="['property:houseCharge:add']"
@click="handleAdd"
>
{{ $t('pages.common.add') }}
</a-button>
</Space>
</template>
<template #action="{ row }">
<Space>
<ghost-button
v-access:code="['property:houseCharge:info']"
@click.stop="handleInfo(row)"
>
{{ $t('pages.common.info') }}
</ghost-button>
<ghost-button
v-access:code="['property:houseCharge:edit']"
@click.stop="handleEdit(row)"
>
缴费
</ghost-button>
<Popconfirm
:get-popup-container="getVxePopupContainer"
placement="left"
title="确认取消?"
@confirm="handleDelete(row)"
>
<ghost-button
danger
v-access:code="['property:houseCharge:remove']"
@click.stop=""
>
取消
</ghost-button>
</Popconfirm>
</Space>
</template>
</BasicTable>
<HouseChargeAdd @reload="tableApi.query()" />
<HouseChargeUpdate @reload="tableApi.query()" />
<HouseChargeDetail/>
</Page>
</template>

View File

@@ -0,0 +1,103 @@
import type { FormSchemaGetter } from '#/adapter/form';
import type { VxeGridProps } from '#/adapter/vxe-table';
import {getDictOptions} from "#/utils/dict";
import {renderDict} from "#/utils/render";
export const querySchema: FormSchemaGetter = () => [
{
component: 'Input',
fieldName: 'returnNo',
label: '退款单号',
},
{
component: 'Select',
componentProps:{
options:getDictOptions('wy_tfshzt')
},
fieldName: 'state',
label: '审核状态',
},
];
export const columns: VxeGridProps['columns'] = [
{ type: 'checkbox', width: 60 },
{
title: '退款单号',
field: 'returnNo',
width: 180,
},
{
title: '支付单号',
field: 'payNo',
width: 180,
},
{
title: '支付金额',
field: 'payAcount',
width: 100,
},
{
title: '支付时间',
field: 'payTime',
width: 180,
},
{
title: '退款原因',
field: 'reason',
minWidth: 180,
},
{
title: '审核状态',
field: 'state',
width: 150,
slots:{
default:({row})=>{
return renderDict(row.state,'wy_tfshzt')
}
}
},
{
title: '审核意见',
field: 'remark',
width: 180,
},
{
field: 'action',
fixed: 'right',
slots: { default: 'action' },
title: '操作',
width: 180,
},
];
export const stateOptions = [
{ label: '审核通过', value: '1' },
{ label: '审核不通过', value: '2' },
];
export const modalSchema: FormSchemaGetter = () => [
{
label: '主键',
fieldName: 'id',
component: 'Input',
dependencies: {
show: () => false,
triggerFields: [''],
},
},
{
label: '审核状态',
fieldName: 'state',
component: 'RadioGroup',
componentProps: {
buttonStyle: 'solid',
options: stateOptions,
},
rules:'required'
},
{
label: '审核意见',
fieldName: 'remark',
component: 'Textarea',
},
];

View File

@@ -0,0 +1,172 @@
<script setup lang="ts">
import {Page, useVbenModal, type VbenFormProps} from '@vben/common-ui';
import {Modal, Popconfirm, Space} from 'ant-design-vue';
import {
useVbenVxeGrid,
vxeCheckboxChecked,
type VxeGridProps
} from '#/adapter/vxe-table';
import {
returnPayFeeExport,
returnPayFeeList,
returnPayFeeRemove,
} from '#/api/property/costManagement/returnPayFee';
import type {ReturnPayFeeForm} from '#/api/property/costManagement/returnPayFee/model';
import {commonDownloadExcel} from '#/utils/file/download';
import returnPayFeeModal from './returnPayFee-modal.vue';
import returnPayFeeDetail from './return-pay-detail.vue';
import {columns, querySchema} from './data';
const formOptions: VbenFormProps = {
commonConfig: {
labelWidth: 80,
componentProps: {
allowClear: true,
},
},
schema: querySchema(),
wrapperClass: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4',
};
const gridOptions: VxeGridProps = {
checkboxConfig: {
// 高亮
highlight: true,
// 翻页时保留选中状态
reserve: true,
// 点击行选中
// trigger: 'row',
},
// 需要使用i18n注意这里要改成getter形式 否则切换语言不会刷新
// columns: columns(),
columns,
height: 'auto',
keepSource: true,
pagerConfig: {},
proxyConfig: {
ajax: {
query: async ({page}, formValues = {}) => {
return await returnPayFeeList({
pageNum: page.currentPage,
pageSize: page.pageSize,
...formValues,
});
},
},
},
rowConfig: {
keyField: 'id',
},
// 表格全局唯一表示 保存列配置需要用到
id: 'property-returnPayFee-index'
};
const [BasicTable, tableApi] = useVbenVxeGrid({
formOptions,
gridOptions,
});
const [ReturnPayFeeModal, modalApi] = useVbenModal({
connectedComponent: returnPayFeeModal,
});
const [ReturnPayFeeDetail, detailApi] = useVbenModal({
connectedComponent: returnPayFeeDetail,
});
function handleAdd() {
modalApi.setData({});
modalApi.open();
}
async function handleEdit(row: Required<ReturnPayFeeForm>) {
modalApi.setData({id: row.id});
modalApi.open();
}
async function handleInfo(row: Required<ReturnPayFeeForm>) {
detailApi.setData({id: row.id});
detailApi.open();
}
async function handleDelete(row: Required<ReturnPayFeeForm>) {
await returnPayFeeRemove(row.id);
await tableApi.query();
}
function handleMultiDelete() {
const rows = tableApi.grid.getCheckboxRecords();
const ids = rows.map((row: Required<ReturnPayFeeForm>) => row.id);
Modal.confirm({
title: '提示',
okType: 'danger',
content: `确认删除选中的${ids.length}条记录吗?`,
onOk: async () => {
await returnPayFeeRemove(ids);
await tableApi.query();
},
});
}
function handleDownloadExcel() {
commonDownloadExcel(returnPayFeeExport, '退费审核数据', tableApi.formApi.form.values, {
fieldMappingTime: formOptions.fieldMappingTime,
});
}
</script>
<template>
<Page :auto-content-height="true">
<BasicTable table-title="退费审核列表">
<template #toolbar-tools>
<Space>
<a-button
v-access:code="['property:returnPayFee:export']"
@click="handleDownloadExcel"
>
{{ $t('pages.common.export') }}
</a-button>
<!-- <a-button-->
<!-- :disabled="!vxeCheckboxChecked(tableApi)"-->
<!-- danger-->
<!-- type="primary"-->
<!-- v-access:code="['property:returnPayFee:remove']"-->
<!-- @click="handleMultiDelete">-->
<!-- {{ $t('pages.common.delete') }}-->
<!-- </a-button>-->
<!-- <a-button-->
<!-- type="primary"-->
<!-- v-access:code="['property:returnPayFee:add']"-->
<!-- @click="handleAdd"-->
<!-- >-->
<!-- {{ $t('pages.common.add') }}-->
<!-- </a-button>-->
</Space>
</template>
<template #action="{ row }">
<Space>
<ghost-button
:disabled="row.state!='0'"
v-access:code="['property:returnPayFee:edit']"
@click.stop="handleEdit(row)"
>
审核
</ghost-button>
<ghost-button
v-access:code="['property:returnPayFee:info']"
@click.stop="handleInfo(row)"
>
{{ $t('pages.common.info') }}
</ghost-button>
</Space>
</template>
</BasicTable>
<ReturnPayFeeModal @reload="tableApi.query()"/>
<ReturnPayFeeDetail/>
</Page>
</template>

View File

@@ -0,0 +1,64 @@
<script setup lang="ts">
import {shallowRef} from 'vue';
import {useVbenModal} from '@vben/common-ui';
import {Descriptions, DescriptionsItem} from 'ant-design-vue';
import dayjs from 'dayjs';
import duration from 'dayjs/plugin/duration';
import relativeTime from 'dayjs/plugin/relativeTime';
import {renderDict} from "#/utils/render";
dayjs.extend(duration);
dayjs.extend(relativeTime);
import {returnPayFeeInfo} from "#/api/property/costManagement/returnPayFee";
import type {ReturnPayFeeVO} from "#/api/property/costManagement/returnPayFee/model";
const [BasicModal, modalApi] = useVbenModal({
onOpenChange: handleOpenChange,
onClosed() {
returnPayDetail.value = null;
},
});
const returnPayDetail = shallowRef<null | ReturnPayFeeVO>(null);
async function handleOpenChange(open: boolean) {
if (!open) {
return null;
}
modalApi.modalLoading(true);
const {id} = modalApi.getData() as { id: number | string };
returnPayDetail.value = await returnPayFeeInfo(id);
modalApi.modalLoading(false);
}
</script>
<template>
<BasicModal :footer="false" :fullscreen-button="false" title="退费审核详情" class="w-[70%]">
<Descriptions v-if="returnPayDetail" size="small" :column="2" bordered
:labelStyle="{width:'100px'}">
<DescriptionsItem label="退款单号">
{{ returnPayDetail.returnNo }}
</DescriptionsItem>
<DescriptionsItem label="支付单号">
{{ returnPayDetail.payNo }}
</DescriptionsItem>
<DescriptionsItem label="支付金额">
{{returnPayDetail.payAcount}}
</DescriptionsItem>
<DescriptionsItem label="支付时间">
{{ returnPayDetail.payTime }}
</DescriptionsItem>
<DescriptionsItem label="退款原因" :span="2">
{{returnPayDetail.reason}}
</DescriptionsItem>
<DescriptionsItem label="审核状态" :span="2">
<component
:is="renderDict(returnPayDetail.state,'wy_tfshzt')"
/>
</DescriptionsItem>
<DescriptionsItem label="审核意见" :span="2">
{{returnPayDetail.remark}}
</DescriptionsItem>
</Descriptions>
</BasicModal>
</template>

View File

@@ -0,0 +1,108 @@
<script setup lang="ts">
import {ref} from 'vue';
import {useVbenModal} from '@vben/common-ui';
import {cloneDeep} from '@vben/utils';
import {useVbenForm} from '#/adapter/form';
import {
returnPayFeeInfo,
returnPayFeeUpdate
} from '#/api/property/costManagement/returnPayFee';
import {defaultFormValueGetter, useBeforeCloseDiff} from '#/utils/popup';
import {modalSchema} from './data';
import type {ReturnPayFeeVO} from "#/api/property/costManagement/returnPayFee/model";
const emit = defineEmits<{ reload: [] }>();
const isUpdate = ref(false);
const record = ref<ReturnPayFeeVO>({
id:'',
state:'1',
remark:''
})
const [BasicForm, formApi] = useVbenForm({
commonConfig: {
// 默认占满两列
formItemClass: 'col-span-2',
// 默认label宽度 px
labelWidth: 80,
// 通用配置项 会影响到所有表单项
componentProps: {
class: 'w-full',
}
},
schema: modalSchema(),
showDefaultActions: false,
wrapperClass: 'grid-cols-2',
});
const {onBeforeClose, markInitialized, resetInitialized} = useBeforeCloseDiff(
{
initializedGetter: defaultFormValueGetter(formApi),
currentGetter: defaultFormValueGetter(formApi),
},
);
const [BasicModal, modalApi] = useVbenModal({
// 在这里更改宽度
class: 'w-[550px]',
fullscreenButton: false,
onBeforeClose,
onClosed: handleClosed,
onConfirm: handleConfirm,
onOpenChange: async (isOpen) => {
if (!isOpen) {
return null;
}
modalApi.modalLoading(true);
const {id} = modalApi.getData() as { id?: number | string };
isUpdate.value = !!id;
if (isUpdate.value && id) {
record.value = await returnPayFeeInfo(id);
record.value.state = '1'
await formApi.setValues(record.value);
}
await markInitialized();
modalApi.modalLoading(false);
},
});
async function handleConfirm() {
try {
modalApi.lock(true);
const {valid} = await formApi.validate();
if (!valid) {
return;
}
// getValues获取为一个readonly的对象 需要修改必须先深拷贝一次
const data = cloneDeep(await formApi.getValues());
record.value.state=data.state
record.value.remark=data.remark
await returnPayFeeUpdate(record.value);
resetInitialized();
emit('reload');
modalApi.close();
} catch (error) {
console.error(error);
} finally {
modalApi.lock(false);
}
}
async function handleClosed() {
await formApi.resetForm();
resetInitialized();
}
</script>
<template>
<BasicModal title="审核">
<BasicForm/>
</BasicModal>
</template>

View File

@@ -42,16 +42,16 @@ export const columns: VxeGridProps['columns'] = [
field: 'machineBrand',
width:100
},
{
title: '设备类型',
field: 'machineTypeId',
width:100
},
{
title: '位置详情',
field: 'locationId',
width:100
},
// {
// title: '设备类型',
// field: 'machineTypeId',
// width:100
// },
// {
// title: '位置详情',
// field: 'locationId',
// width:100
// },
{
title: '采购价格',
field: 'purchasePrice',
@@ -92,11 +92,11 @@ export const columns: VxeGridProps['columns'] = [
}
}
},
{
title: '责任人',
field: 'personId',
width:100
},
// {
// title: '责任人',
// field: 'personId',
// width:100
// },
{
field: 'action',
fixed: 'right',

View File

@@ -24,7 +24,7 @@ import MachineTypeTree from '../components/machine-type-tree.vue'
import machineDetail from './machine-detail.vue'
import {ref} from "vue";
const selectTypeId = ref('')
const selectTypeId = ref([])
const formOptions: VbenFormProps = {
commonConfig: {
@@ -36,8 +36,8 @@ const formOptions: VbenFormProps = {
schema: querySchema(),
wrapperClass: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4',
handleReset: async () => {
selectTypeId.value = '';
const { formApi, reload } = tableApi;
selectTypeId.value = [];
const {formApi, reload} = tableApi;
await formApi.resetForm();
const formValues = formApi.form.values;
formApi.setLatestSubmissionValues(formValues);
@@ -61,7 +61,11 @@ const gridOptions: VxeGridProps = {
proxyConfig: {
ajax: {
query: async ({page}, formValues = {}) => {
formValues.machineTypeId = selectTypeId.value
if (selectTypeId.value && selectTypeId.value.length) {
formValues.machineTypeId = selectTypeId.value[0]
}else {
formValues.machineTypeId =[]
}
return await machineList({
pageNum: page.currentPage,
pageSize: page.pageSize,
@@ -135,32 +139,32 @@ function handleDownloadExcel() {
<Page :auto-content-height="true">
<div class="flex h-full gap-[8px]">
<MachineTypeTree
v-model:select-dept-id="selectTypeId"
class="w-[260px]"
@reload="() => tableApi.reload()"
@select="() => tableApi.reload()"
v-model:select-dept-id="selectTypeId"
class="w-[260px]"
@reload="() => tableApi.reload()"
@select="() => tableApi.reload()"
/>
<BasicTable class="flex-1 overflow-hidden" table-title="设备列表列表">
<template #toolbar-tools>
<Space>
<a-button
v-access:code="['property:machine:export']"
@click="handleDownloadExcel"
v-access:code="['property:machine:export']"
@click="handleDownloadExcel"
>
{{ $t('pages.common.export') }}
</a-button>
<a-button
:disabled="!vxeCheckboxChecked(tableApi)"
danger
type="primary"
v-access:code="['property:machine:remove']"
@click="handleMultiDelete">
:disabled="!vxeCheckboxChecked(tableApi)"
danger
type="primary"
v-access:code="['property:machine:remove']"
@click="handleMultiDelete">
{{ $t('pages.common.delete') }}
</a-button>
<a-button
type="primary"
v-access:code="['property:machine:add']"
@click="handleAdd"
type="primary"
v-access:code="['property:machine:add']"
@click="handleAdd"
>
{{ $t('pages.common.add') }}
</a-button>
@@ -169,27 +173,27 @@ function handleDownloadExcel() {
<template #action="{ row }">
<Space>
<ghost-button
v-access:code="['property:machine:info']"
@click.stop="handleInfo(row)"
v-access:code="['property:machine:info']"
@click.stop="handleInfo(row)"
>
{{ $t('pages.common.info') }}
</ghost-button>
<ghost-button
v-access:code="['property:machine:edit']"
@click.stop="handleEdit(row)"
v-access:code="['property:machine:edit']"
@click.stop="handleEdit(row)"
>
{{ $t('pages.common.edit') }}
</ghost-button>
<Popconfirm
:get-popup-container="getVxePopupContainer"
placement="left"
title="确认删除?"
@confirm="handleDelete(row)"
:get-popup-container="getVxePopupContainer"
placement="left"
title="确认删除?"
@confirm="handleDelete(row)"
>
<ghost-button
danger
v-access:code="['property:machine:remove']"
@click.stop=""
danger
v-access:code="['property:machine:remove']"
@click.stop=""
>
{{ $t('pages.common.delete') }}
</ghost-button>

View File

@@ -2,6 +2,7 @@ import type {FormSchemaGetter} from '#/adapter/form';
import type {VxeGridProps} from '#/adapter/vxe-table';
import {getDictOptions} from "#/utils/dict";
import {renderDict} from "#/utils/render";
import {z} from "#/adapter/form";
export const querySchema: FormSchemaGetter = () => [
@@ -22,10 +23,6 @@ export const querySchema: FormSchemaGetter = () => [
export const columns: VxeGridProps['columns'] = [
{type: 'checkbox', width: 60},
{
title: '主键',
field: 'id',
},
{
title: '计划名称',
field: 'planName',
@@ -34,10 +31,10 @@ export const columns: VxeGridProps['columns'] = [
title: '计划编号',
field: 'planNo',
},
{
title: '设备类型',
field: 'machineTypeId',
},
// {
// title: '设备类型',
// field: 'machineTypeId',
// },
{
title: '保养周期',
field: 'planPeriod',
@@ -179,31 +176,14 @@ export const modalSchema: FormSchemaGetter = () => [
},
rules:'required'
},
// {
// label: '开始时间',
// fieldName: 'startDate',
// component: 'DatePicker',
// componentProps: {
// showTime: true,
// format: 'YYYY-MM-DD HH:mm:ss',
// valueFormat: 'YYYY-MM-DD HH:mm:ss',
// },
// rules:'required'
// },
// {
// label: '结束时间',
// fieldName: 'endDate',
// component: 'DatePicker',
// componentProps: {
// showTime: true,
// format: 'YYYY-MM-DD HH:mm:ss',
// valueFormat: 'YYYY-MM-DD HH:mm:ss',
// },
// rules:'required'
// },
// {
// label: '状态(0启用,1停用)',
// fieldName: 'state',
// component: 'Input',
// },
{
label: '巡检人员',
fieldName: 'userId',
component: 'ApiSelect',
componentProps:{
mode: 'multiple',
},
rules: z.array(z.string()).min(1, { message: '请选择巡检人员' }),
formItemClass: 'col-span-2'
},
];

View File

@@ -182,8 +182,8 @@ function handleDownloadExcel() {
</template>
<template #state="{row}">
<TableSwitch
:checkedValue="1"
:unCheckedValue="0"
checkedValue="1"
unCheckedValue="0"
v-model:value="row.state"
:api="() => maintainPlanUpdate(row)"
:disabled="!hasAccessByCodes(['property:depot:edit'])"

View File

@@ -15,6 +15,8 @@ import {defaultFormValueGetter, useBeforeCloseDiff} from '#/utils/popup';
import {modalSchema} from './data';
import {getMachineTypeTree} from "#/api/property/machineType";
import {personList} from "#/api/property/resident/person";
import {renderDictValue} from "#/utils/render";
const emit = defineEmits<{ reload: [] }>();
@@ -62,12 +64,16 @@ const [BasicModal, modalApi] = useVbenModal({
const {id} = modalApi.getData() as { id?: number | string };
isUpdate.value = !!id;
await setupTypeSelect();
await queryPersonData()
if (isUpdate.value && id) {
const record = await maintainPlanInfo(id);
record.planDate = [record.startDate, record.endDate]
if (record.planPeriod == '1') {
record.maintainanceMonth = record.maintainanceMonth?.split(',')
record.maintainanceDay = record.maintainanceDay?.split(',')
record.maintainMonth = record.maintainMonth?.split(',')
record.maintainDay = record.maintainDay?.split(',')
}
if (record.machineMaintainPlanStaffBoList) {
record.userId = record.machineMaintainPlanStaffBoList.map(item=>item.userId)
}
await formApi.setValues(record);
}
@@ -91,13 +97,19 @@ async function handleConfirm() {
data.endDate = data.planDate[1]
}
if (data.planPeriod == '1') {
data.maintainanceMonth = data.maintainanceMonth?.join(',')
data.maintainanceDay = data.maintainanceDay?.join(',')
data.maintainanceEveryday = undefined
data.maintainMonth = data.maintainMonth?.join(',')
data.maintainDay = data.maintainDay?.join(',')
data.maintainEveryday = undefined
} else {
data.maintainanceMonth = undefined
data.maintainanceDay = undefined
data.maintainMonth = undefined
data.maintainDay = undefined
}
data.machineMaintainPlanStaffBoList = []
data.userId.forEach((item: string) => {
data.machineMaintainPlanStaffBoList.push({
userId: item
})
})
await (isUpdate.value ? maintainPlanUpdate(data) : maintainPlanAdd(data));
resetInitialized();
emit('reload');
@@ -143,6 +155,29 @@ async function setupTypeSelect() {
},
]);
}
async function queryPersonData() {
let params = {
pageSize: 1000,
pageNum: 1,
}
const res = await personList(params);
const options = res.rows.map((user) => ({
label: user.userName + '-' + renderDictValue(user.gender, 'sys_user_sex')
+ '-' + user.phone + '-' + user.unitName,
value: user.id,
}));
formApi.updateSchema([{
componentProps: () => ({
options: options,
showSearch: true,
optionFilterProp: 'label',
optionLabelProp: 'label',
mode: 'multiple',
}),
fieldName: 'userId',
}])
}
</script>
<template>

View File

@@ -25,35 +25,34 @@ export const querySchema: FormSchemaGetter = () => [
// export const columns: () => VxeGridProps['columns'] = () => [
export const columns: VxeGridProps['columns'] = [
{ type: 'checkbox', width: 60 },
{
title: '设备名称',
field: 'machineId',
},
{
title: '设备编号',
field: 'machineId',
},
// {
// title: '设备名称',
// field: 'machineId',
// },
// {
// title: '设备编号',
// field: 'machineId',
// },
{
title: '位置编号',
field: 'machineId',
},
{
title: '计划名称',
field: 'machineId',
},
{
title: '计划保养人',
field: 'machineId',
},
{
title: '计划保养时间',
field: 'machineId',
},
{
title: '实际保养时间',
field: 'machineId',
},
// {
// title: '计划名称',
// field: 'machineId',
// },
// {
// title: '计划保养人',
// field: 'machineId',
// },
// {
// title: '计划保养时间',
// field: 'machineId',
// },
// {
// title: '实际保养时间',
// field: 'machineId',
// },
{
title: '保养情况',
field: 'sendFlag',

View File

@@ -43,9 +43,13 @@ export const columns: VxeGridProps['columns'] = [
field: 'roomTypeName',
},
{
title: '面积',
title: '建筑面积',
field: 'area',
},
{
title: '套内面积',
field: 'insideInArea',
},
{
title: '户型',
field: 'layout',
@@ -110,10 +114,18 @@ export const modalSchema: FormSchemaGetter = () => [
},
},
{
label: '面积',
label: '建筑面积',
fieldName: 'area',
component: 'Input',
},
{
label: '套内面积',
fieldName: 'insideInArea',
component: 'InputNumber',
componentProps:{
min:0,
}
},
{
label: '户型',
fieldName: 'layout',