From 620bf8dd17629802b4550b5e3e30fe67b5e3401a Mon Sep 17 00:00:00 2001 From: dev_ljl <2590379346@qq.com> Date: Fri, 11 Jul 2025 17:29:59 +0800 Subject: [PATCH 1/4] =?UTF-8?q?1=E3=80=81=E5=B7=A1=E6=A3=80=E8=AE=A1?= =?UTF-8?q?=E5=88=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../inspectionPlan/model.d.ts | 52 +++++- .../inspectionPlan/data.ts | 152 +++++++++++------- .../inspectionPlan/index.vue | 49 +++--- .../inspectionPlan/inspectionPlan-modal.vue | 129 +++++++++++++-- .../inspectionPlan/plan-detail.vue | 107 ++++++++++++ 5 files changed, 391 insertions(+), 98 deletions(-) create mode 100644 apps/web-antd/src/views/property/inspectionManagement/inspectionPlan/plan-detail.vue diff --git a/apps/web-antd/src/api/property/inspectionManagement/inspectionPlan/model.d.ts b/apps/web-antd/src/api/property/inspectionManagement/inspectionPlan/model.d.ts index 951a8553..c990b10e 100644 --- a/apps/web-antd/src/api/property/inspectionManagement/inspectionPlan/model.d.ts +++ b/apps/web-antd/src/api/property/inspectionManagement/inspectionPlan/model.d.ts @@ -1,4 +1,4 @@ -import type { PageQuery, BaseEntity } from '#/api/common'; +import type {PageQuery, BaseEntity} from '#/api/common'; export interface InspectionPlanVO { /** @@ -66,6 +66,28 @@ export interface InspectionPlanVO { */ remark: string; + /** + * 计划时间区间 + */ + planDate?: any[]; + + /** + * 巡检月 + */ + inspectionMonth?:string; + /** + * 巡检日 + */ + inspectionDay?:string; + /** + * 巡检周 + */ + inspectionWorkday?:string; + + /** + * 状态 + */ + state?:string } export interface InspectionPlanForm extends BaseEntity { @@ -133,6 +155,18 @@ export interface InspectionPlanForm extends BaseEntity { * 备注 */ remark?: string; + /** + * 巡检月 + */ + inspectionMonth?:string; + /** + * 巡检日 + */ + inspectionDay?:string; + /** + * 巡检周 + */ + inspectionWorkday?:string; } @@ -193,7 +227,19 @@ export interface InspectionPlanQuery extends PageQuery { userId?: string | number; /** - * 日期范围参数 - */ + * 日期范围参数 + */ params?: any; + /** + * 巡检月 + */ + inspectionMonth?:string; + /** + * 巡检日 + */ + inspectionDay?:string; + /** + * 巡检周 + */ + inspectionWorkday?:string; } diff --git a/apps/web-antd/src/views/property/inspectionManagement/inspectionPlan/data.ts b/apps/web-antd/src/views/property/inspectionManagement/inspectionPlan/data.ts index 1fed16ca..98fa9fe7 100644 --- a/apps/web-antd/src/views/property/inspectionManagement/inspectionPlan/data.ts +++ b/apps/web-antd/src/views/property/inspectionManagement/inspectionPlan/data.ts @@ -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 = () => [ @@ -32,71 +33,65 @@ export const querySchema: FormSchemaGetter = () => [ export const columns: VxeGridProps['columns'] = [ {type: 'checkbox', width: 60}, { - title: '主键id', - field: 'id', - }, - { - title: '巡检计划名称', + title: '计划名称', field: 'planName', + minWidth: 180, }, { title: '巡检路线', field: 'inspectionRouteId', + width: 180, }, { title: '巡检周期', field: 'inspectionPlanPeriod', slots: { - default: ({ row }) => { + default: ({row}) => { return renderDict(row.inspectionPlanPeriod, 'wy_xjzq'); }, }, + width: 100, }, { - title: '任务提前分组', + title: '任务提前分钟', field: 'beforeTime', + width: 120, }, { title: '开始日期', field: 'startDate', + width: 120, }, { title: '结束日期', field: 'endDate', - }, - { - title: '开始时间', - field: 'startTime', - }, - { - title: '结束时间', - field: 'endTime', + width: 120, }, { title: '签到方式', field: 'signType', slots: { - default: ({ row }) => { + default: ({row}) => { return renderDict(row.signType, 'wy_xjqdfs'); }, }, + width: 120, }, { title: '是否允许补检', field: 'canReexamine', slots: { - default: ({ row }) => { + default: ({row}) => { return renderDict(row.canReexamine, 'wy_sf'); }, }, + width: 120, }, { - title: '选择员工', - field: 'userId', - }, - { - title: '备注', - field: 'remark', + title: '状态', + field: 'state', + width: 120, + slots:{default: 'state'} }, { field: 'action', @@ -118,7 +113,7 @@ export const modalSchema: FormSchemaGetter = () => [ }, }, { - label: '巡检计划名称', + label: '计划名称', fieldName: 'planName', component: 'Input', rules: 'required', @@ -126,61 +121,80 @@ export const modalSchema: FormSchemaGetter = () => [ { label: '巡检路线', fieldName: 'inspectionRouteId', - component: 'Input', + component: 'ApiSelect', rules: 'required', }, { label: '巡检周期', fieldName: 'inspectionPlanPeriod', - component: 'Input', + component: 'Select', rules: 'required', componentProps: { options: getDictOptions('wy_xjzq'), }, }, { - label: '任务提前分组', + label: '任务提前', fieldName: 'beforeTime', component: 'Input', - rules: 'required', + rules: z.number({ + required_error: "请输入任务提前完成分钟数", + invalid_type_error: "请输入任务提前完成分钟数" + }), + slots: {default: 'beforeTime'}, }, { - label: '开始日期', - fieldName: 'startDate', - component: 'DatePicker', - componentProps: { - showTime: true, - format: 'YYYY-MM-DD HH:mm:ss', - valueFormat: 'YYYY-MM-DD HH:mm:ss', + label: '周', + fieldName: 'inspectionWorkday', + component: 'CheckboxGroup', + rules: 'selectRequired', + formItemClass: 'col-span-2', + dependencies: { + show: (formValue) => formValue.inspectionPlanPeriod == '2', + triggerFields: ['inspectionPlanPeriod'], }, - 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', + options: getDictOptions('wy_xq') + } }, { - label: '开始时间', - fieldName: 'startTime', - component: 'DatePicker', + label: '月', + fieldName: 'inspectionMonth', + component: 'CheckboxGroup', + rules: 'selectRequired', + formItemClass: 'col-span-2', + dependencies: { + show: (formValue) => formValue.inspectionPlanPeriod == '1', + triggerFields: ['inspectionPlanPeriod'], + }, componentProps: { - showTime: true, - format: 'YYYY-MM-DD HH:mm:ss', - valueFormat: 'YYYY-MM-DD HH:mm:ss', - }, - rules: 'required', + options: Array.from({ length: 12 }, (_, i) => ({ + label: `${i + 1}月`, + value: (i + 1).toString(), + })), + } }, { - label: '结束时间', - fieldName: 'endTime', - component: 'DatePicker', + label: '日', + fieldName: 'inspectionDay', + component: 'CheckboxGroup', + rules: 'selectRequired', + formItemClass: 'col-span-2', + dependencies: { + show: (formValue) => formValue.inspectionPlanPeriod == '1', + triggerFields: ['inspectionPlanPeriod'], + }, + componentProps: { + options: Array.from({ length: 31 }, (_, i) => ({ + label: `${i + 1}日`, + value: (i + 1).toString(), + })), + } + }, + { + label: '计划日期', + fieldName: 'planDate', + component: 'RangePicker', componentProps: { showTime: true, format: 'YYYY-MM-DD HH:mm:ss', @@ -200,21 +214,35 @@ export const modalSchema: FormSchemaGetter = () => [ { label: '允许补检', fieldName: 'canReexamine', - component: 'Select', + component: 'RadioGroup', componentProps: { options: getDictOptions('wy_sf'), + buttonStyle: 'solid', }, rules: 'selectRequired', }, { - label: '选择员工', + label: '巡检人员', fieldName: 'userId', - component: 'Input', - rules: 'required', + component: 'ApiSelect', + componentProps:{ + mode: 'multiple', + }, + rules: z.array(z.string()).min(1, { message: '请选择巡检人员' }), + formItemClass: 'col-span-2' }, { label: '备注', fieldName: 'remark', - component: 'Input', + component: 'Textarea', + formItemClass: 'col-span-2' }, ]; + +const weekOptions = (): any[] => { + let arr: any[] = [] + for (let i = 1; i <= 7; i++) { + arr.push({label: '星期' + '', value: i}) + } + return arr; +} diff --git a/apps/web-antd/src/views/property/inspectionManagement/inspectionPlan/index.vue b/apps/web-antd/src/views/property/inspectionManagement/inspectionPlan/index.vue index c8554f64..2881f7dc 100644 --- a/apps/web-antd/src/views/property/inspectionManagement/inspectionPlan/index.vue +++ b/apps/web-antd/src/views/property/inspectionManagement/inspectionPlan/index.vue @@ -1,14 +1,8 @@ @@ -154,6 +148,12 @@ function handleDownloadExcel() { + + {{ $t('pages.common.info') }} + + + tableApi.query()" + /> + + diff --git a/apps/web-antd/src/views/property/inspectionManagement/inspectionPlan/inspectionPlan-modal.vue b/apps/web-antd/src/views/property/inspectionManagement/inspectionPlan/inspectionPlan-modal.vue index 65fa155f..77604475 100644 --- a/apps/web-antd/src/views/property/inspectionManagement/inspectionPlan/inspectionPlan-modal.vue +++ b/apps/web-antd/src/views/property/inspectionManagement/inspectionPlan/inspectionPlan-modal.vue @@ -1,15 +1,23 @@ - + + + + + 分钟完成 + + + + diff --git a/apps/web-antd/src/views/property/inspectionManagement/inspectionPlan/plan-detail.vue b/apps/web-antd/src/views/property/inspectionManagement/inspectionPlan/plan-detail.vue new file mode 100644 index 00000000..0a46807f --- /dev/null +++ b/apps/web-antd/src/views/property/inspectionManagement/inspectionPlan/plan-detail.vue @@ -0,0 +1,107 @@ + + + + + + + {{ inspectionPlanDetail.planName }} + + + {{ inspectionPlanDetail.inspectionRouteId }} + + + + + + {{ inspectionPlanDetail.beforeTime + ' 分钟完成' }} + + + + + + + + + + + + {{ inspectionPlanDetail.startDate + '\xa0至\xa0' + inspectionPlanDetail.endDate }} + + + + + + + + + {{ inspectionPlanDetail.projectName }} + + + {{ inspectionPlanDetail.remark }} + + + {{ inspectionPlanDetail.state == '1' ? '停用' : '启用' }} + + + + From bce19bf9f832e4d712130fd91fc9f474d7775a97 Mon Sep 17 00:00:00 2001 From: zcxlsm Date: Fri, 11 Jul 2025 17:59:19 +0800 Subject: [PATCH 2/4] =?UTF-8?q?feat(sis):=20=E6=B7=BB=E5=8A=A0=E9=97=A8?= =?UTF-8?q?=E7=A6=81=E8=AE=BE=E5=A4=87=E5=90=8C=E6=AD=A5=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/api/sis/accessControl/index.ts | 30 ++++++++++++------- .../views/sis/accessControl/device/index.vue | 7 +++++ 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/apps/web-antd/src/api/sis/accessControl/index.ts b/apps/web-antd/src/api/sis/accessControl/index.ts index f4a2afc4..e6798260 100644 --- a/apps/web-antd/src/api/sis/accessControl/index.ts +++ b/apps/web-antd/src/api/sis/accessControl/index.ts @@ -2,12 +2,12 @@ import type { AccessControlForm, AccessControlQuery, AccessControlVO, -} from './model'; +} from './model' -import type { ID, IDS, PageResult, TreeNode } from '#/api/common'; +import type { ID, IDS, PageResult, TreeNode } from '#/api/common' -import { commonExport } from '#/api/helper'; -import { requestClient } from '#/api/request'; +import { commonExport } from '#/api/helper' +import { requestClient } from '#/api/request' /** * 查询门禁管理列表 @@ -18,7 +18,7 @@ export function accessControlList(params?: AccessControlQuery) { return requestClient.get>( '/sis/accessControl/list', { params }, - ); + ) } /** @@ -27,7 +27,7 @@ export function accessControlList(params?: AccessControlQuery) { * @returns 门禁管理列表 */ export function accessControlExport(params?: AccessControlQuery) { - return commonExport('/sis/accessControl/export', params ?? {}); + return commonExport('/sis/accessControl/export', params ?? {}) } /** @@ -36,7 +36,7 @@ export function accessControlExport(params?: AccessControlQuery) { * @returns 门禁管理详情 */ export function accessControlInfo(id: ID) { - return requestClient.get(`/sis/accessControl/${id}`); + return requestClient.get(`/sis/accessControl/${id}`) } /** @@ -45,7 +45,7 @@ export function accessControlInfo(id: ID) { * @returns void */ export function accessControlAdd(data: AccessControlForm) { - return requestClient.postWithMsg('/sis/accessControl', data); + return requestClient.postWithMsg('/sis/accessControl', data) } /** @@ -54,7 +54,7 @@ export function accessControlAdd(data: AccessControlForm) { * @returns void */ export function accessControlUpdate(data: AccessControlForm) { - return requestClient.putWithMsg('/sis/accessControl', data); + return requestClient.putWithMsg('/sis/accessControl', data) } /** @@ -63,7 +63,7 @@ export function accessControlUpdate(data: AccessControlForm) { * @returns void */ export function accessControlRemove(id: ID | IDS) { - return requestClient.deleteWithMsg(`/sis/accessControl/${id}`); + return requestClient.deleteWithMsg(`/sis/accessControl/${id}`) } /** @@ -71,5 +71,13 @@ export function accessControlRemove(id: ID | IDS) { * @returns void */ export function queryTree() { - return requestClient.get[]>(`/sis/accessControl/tree`); + return requestClient.get[]>(`/sis/accessControl/tree`) +} + +/** + * 同步E8门禁 + * @returns void + */ +export function accessControlSync() { + return requestClient.get(`/sis/accessControl/sync`) } diff --git a/apps/web-antd/src/views/sis/accessControl/device/index.vue b/apps/web-antd/src/views/sis/accessControl/device/index.vue index 8615c0a1..b59796bb 100644 --- a/apps/web-antd/src/views/sis/accessControl/device/index.vue +++ b/apps/web-antd/src/views/sis/accessControl/device/index.vue @@ -14,6 +14,7 @@ import { accessControlExport, accessControlList, accessControlRemove, + accessControlSync } from '#/api/sis/accessControl'; import type { AccessControlForm } from '#/api/sis/accessControl/model'; import { commonDownloadExcel } from '#/utils/file/download'; @@ -98,6 +99,11 @@ async function handleDelete(row: Required) { await tableApi.query(); } +async function handleSyncE8() { + await accessControlSync(); + await tableApi.query(); +} + function handleMultiDelete() { const rows = tableApi.grid.getCheckboxRecords(); const ids = rows.map((row: Required) => row.id); @@ -129,6 +135,7 @@ function handleDownloadExcel() { + 同步 Date: Mon, 14 Jul 2025 10:33:05 +0800 Subject: [PATCH 3/4] =?UTF-8?q?1=E3=80=81bug=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../property/inspectionManagement/inspectionPlan/data.ts | 9 +-------- .../inspectionPlan/inspectionPlan-modal.vue | 1 - .../inspectionManagement/inspectionPlan/plan-detail.vue | 4 ++-- apps/web-antd/src/views/system/user/data.tsx | 5 +---- 4 files changed, 4 insertions(+), 15 deletions(-) diff --git a/apps/web-antd/src/views/property/inspectionManagement/inspectionPlan/data.ts b/apps/web-antd/src/views/property/inspectionManagement/inspectionPlan/data.ts index 98fa9fe7..d9665527 100644 --- a/apps/web-antd/src/views/property/inspectionManagement/inspectionPlan/data.ts +++ b/apps/web-antd/src/views/property/inspectionManagement/inspectionPlan/data.ts @@ -220,6 +220,7 @@ export const modalSchema: FormSchemaGetter = () => [ buttonStyle: 'solid', }, rules: 'selectRequired', + defaultValue:'0' }, { label: '巡检人员', @@ -238,11 +239,3 @@ export const modalSchema: FormSchemaGetter = () => [ formItemClass: 'col-span-2' }, ]; - -const weekOptions = (): any[] => { - let arr: any[] = [] - for (let i = 1; i <= 7; i++) { - arr.push({label: '星期' + '', value: i}) - } - return arr; -} diff --git a/apps/web-antd/src/views/property/inspectionManagement/inspectionPlan/inspectionPlan-modal.vue b/apps/web-antd/src/views/property/inspectionManagement/inspectionPlan/inspectionPlan-modal.vue index 77604475..c0218032 100644 --- a/apps/web-antd/src/views/property/inspectionManagement/inspectionPlan/inspectionPlan-modal.vue +++ b/apps/web-antd/src/views/property/inspectionManagement/inspectionPlan/inspectionPlan-modal.vue @@ -65,7 +65,6 @@ const [BasicModal, modalApi] = useVbenModal({ await queryPersonData() const {id} = modalApi.getData() as { id?: number | string }; isUpdate.value = !!id; - if (isUpdate.value && id) { const record = await inspectionPlanInfo(id); record.planDate = [record.startDate, record.endDate] diff --git a/apps/web-antd/src/views/property/inspectionManagement/inspectionPlan/plan-detail.vue b/apps/web-antd/src/views/property/inspectionManagement/inspectionPlan/plan-detail.vue index 0a46807f..8838b2a0 100644 --- a/apps/web-antd/src/views/property/inspectionManagement/inspectionPlan/plan-detail.vue +++ b/apps/web-antd/src/views/property/inspectionManagement/inspectionPlan/plan-detail.vue @@ -73,7 +73,7 @@ const monthArr=Array.from({ length: 12 }, (_, i) => ({ :options="getDictOptions('wy_xq')"/> - @@ -88,7 +88,7 @@ const monthArr=Array.from({ length: 12 }, (_, i) => ({ :is="renderDict(inspectionPlanDetail.signType,'wy_xjqdfs')" /> - + diff --git a/apps/web-antd/src/views/system/user/data.tsx b/apps/web-antd/src/views/system/user/data.tsx index a84e0792..e13c13a5 100644 --- a/apps/web-antd/src/views/system/user/data.tsx +++ b/apps/web-antd/src/views/system/user/data.tsx @@ -130,12 +130,9 @@ export const drawerSchema: FormSchemaGetter = () => [ component: 'Input', fieldName: 'phonenumber', label: '手机号码', - defaultValue: undefined, rules: z .string() - .regex(/^1[3-9]\d{9}$/, '请输入正确的手机号码') - .optional() - .or(z.literal('')), + .regex(/^1[3-9]\d{9}$/, { message: '请输入正确的手机号' }), }, { component: 'Input', From c8b6d2faba4607667796c77b6d734bd978d00f4b Mon Sep 17 00:00:00 2001 From: fyy <2717885210@qq.com> Date: Mon, 14 Jul 2025 11:53:18 +0800 Subject: [PATCH 4/4] =?UTF-8?q?feat:=20=E4=BF=AE=E5=A4=8D=E4=BF=9D?= =?UTF-8?q?=E6=B4=81=E3=80=81=E7=BB=BF=E6=A4=8D=E3=80=81=E5=9B=AD=E5=8C=BA?= =?UTF-8?q?=E3=80=81=E7=B3=BB=E7=BB=9F=E7=94=A8=E6=88=B7=E7=9B=B8=E5=85=B3?= =?UTF-8?q?bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../property/community/community-modal.vue | 7 +- .../src/views/property/community/data.ts | 36 +- .../rentalPlan-detial-modal.vue | 24 +- .../rentalPlan-modal.vue | 19 +- .../reportStatistics/index.vue | 361 +++++++++--------- .../inspectionTask/data.ts | 17 +- .../inspectionTask/index.vue | 4 +- apps/web-antd/src/views/property/room/data.ts | 14 +- apps/web-antd/src/views/system/user/data.tsx | 3 +- .../src/plugins/extra-app-config.ts | 10 +- .../base/shared/src/constants/dict-enum.ts | 2 +- 11 files changed, 254 insertions(+), 243 deletions(-) diff --git a/apps/web-antd/src/views/property/community/community-modal.vue b/apps/web-antd/src/views/property/community/community-modal.vue index 606687f5..a2ffc793 100644 --- a/apps/web-antd/src/views/property/community/community-modal.vue +++ b/apps/web-antd/src/views/property/community/community-modal.vue @@ -65,7 +65,9 @@ const [BasicModal, modalApi] = useVbenModal({ if (isUpdate.value && id) { const record = await communityInfo(id); await formApi.setValues(record); + } + setupDeptSelect(); await markInitialized(); modalApi.modalLoading(false); @@ -83,7 +85,10 @@ async function handleConfirm() { } // getValues获取为一个readonly的对象 需要修改必须先深拷贝一次 const data: CommunityForm = cloneDeep(await formApi.getValues()); - data.cityFullName = currentSelectNode.fullName; + // data.cityFullName = currentSelectNode? currentSelectNode.fullName : data.cityFullName; + if (currentSelectNode?.fullName) { + data.cityFullName = currentSelectNode.fullName; + } await (isUpdate.value ? communityUpdate(data) : communityAdd(data)); resetInitialized(); emit('reload'); diff --git a/apps/web-antd/src/views/property/community/data.ts b/apps/web-antd/src/views/property/community/data.ts index 4a869a8b..1cc717ce 100644 --- a/apps/web-antd/src/views/property/community/data.ts +++ b/apps/web-antd/src/views/property/community/data.ts @@ -42,14 +42,14 @@ export const columns: VxeGridProps['columns'] = [ title: '地址', field: 'addr', }, - { - title: '经度', - field: 'lon', - }, - { - title: '维度', - field: 'lat', - }, + // { + // title: '经度', + // field: 'lon', + // }, + // { + // title: '维度', + // field: 'lat', + // }, { title: '占地面积', field: 'area', @@ -136,16 +136,16 @@ export const modalSchema: FormSchemaGetter = () => [ component: 'Input', rules: 'required', }, - { - label: '经度', - fieldName: 'lon', - component: 'Input', - }, - { - label: '维度', - fieldName: 'lat', - component: 'Input', - }, + // { + // label: '经度', + // fieldName: 'lon', + // component: 'Input', + // }, + // { + // label: '维度', + // fieldName: 'lat', + // component: 'Input', + // }, { label: '占地面积', fieldName: 'area', diff --git a/apps/web-antd/src/views/property/greenPlantRentalManagement/leasePogramManagement/rentalPlan-detial-modal.vue b/apps/web-antd/src/views/property/greenPlantRentalManagement/leasePogramManagement/rentalPlan-detial-modal.vue index f7af2e4f..e16c8d50 100644 --- a/apps/web-antd/src/views/property/greenPlantRentalManagement/leasePogramManagement/rentalPlan-detial-modal.vue +++ b/apps/web-antd/src/views/property/greenPlantRentalManagement/leasePogramManagement/rentalPlan-detial-modal.vue @@ -39,7 +39,29 @@ const detailSchema = [ api: async () => { const res = await plantsProductList({state:1,inventory:0}); plantListData = res.rows || []; - return res; + + // 获取当前模态框的数据,包含已添加的产品列表 + const modalData = modalApi.getData(); + const existingProducts = modalData?.existingProducts || []; + const currentProductId = modalData?.currentProductId; + + // 过滤掉已经添加到产品列表中的产品 + // 如果是编辑模式,需要排除当前正在编辑的产品 + const filteredRows = res.rows.filter((item: any) => { + // 如果是编辑模式且是当前正在编辑的产品,则保留 + if (currentProductId && item.id === currentProductId) { + return true; + } + // 过滤掉已添加的产品 + return !existingProducts.some((existing: any) => + existing.productId === item.id || existing.id === item.id + ); + }); + + return { + ...res, + rows: filteredRows + }; }, resultField: 'rows', labelField: 'plantName', diff --git a/apps/web-antd/src/views/property/greenPlantRentalManagement/leasePogramManagement/rentalPlan-modal.vue b/apps/web-antd/src/views/property/greenPlantRentalManagement/leasePogramManagement/rentalPlan-modal.vue index b6a9a9c2..55600aa4 100644 --- a/apps/web-antd/src/views/property/greenPlantRentalManagement/leasePogramManagement/rentalPlan-modal.vue +++ b/apps/web-antd/src/views/property/greenPlantRentalManagement/leasePogramManagement/rentalPlan-modal.vue @@ -29,10 +29,10 @@ const [BasicForm, formApi] = useVbenForm({ // 默认label宽度 px labelWidth: 120, // 通用配置项 会影响到所有表单项 - componentProps: computed(() => ({ + componentProps: { class: 'w-full', - disabled: isReadonly.value, - })), + disabled: isReadonly, + }, }, schema: modalSchema(), showDefaultActions: false, @@ -143,10 +143,13 @@ const detailColumns = [ title: '操作', key: 'action', fixed: 'right' as const, + width: 200, }, ]; function handleAddDetail() { - detailModalApi.setData({}); + detailModalApi.setData({ + existingProducts: detailTable.value + }); detailModalApi.open(); } //添加植物组合包产品 @@ -169,7 +172,13 @@ function handleViewDetail(record: any) { } // 编辑产品详情 function handleEditDetail(record: any, index: number) { - detailModalApi.setData({ ...record, index, readonly: false }); + detailModalApi.setData({ + ...record, + index, + readonly: false, + existingProducts: detailTable.value.filter((item: any, i: number) => i !== index), + currentProductId: record.productId || record.id + }); detailModalApi.open(); } //分类字典 diff --git a/apps/web-antd/src/views/property/greenPlantRentalManagement/reportStatistics/index.vue b/apps/web-antd/src/views/property/greenPlantRentalManagement/reportStatistics/index.vue index c2410298..1fcca068 100644 --- a/apps/web-antd/src/views/property/greenPlantRentalManagement/reportStatistics/index.vue +++ b/apps/web-antd/src/views/property/greenPlantRentalManagement/reportStatistics/index.vue @@ -5,7 +5,7 @@ import { onMounted, ref } from 'vue'; import { EchartsUI, useEcharts } from '@vben/plugins/echarts'; -import { Button,Radio } from 'ant-design-vue'; +import { Button,Radio,Spin } from 'ant-design-vue'; import type { RadioChangeEvent } from 'ant-design-vue'; import { statisticsByTime, @@ -44,42 +44,30 @@ const timeUnit = ref(1) const countOrderAndAmountDataAmount = ref(0); const countOrderAndAmountDataOrder = ref(0); const countAchievedRateData = ref(null); -const countCustomersData = ref(null); +const countCustomersData = ref(0); const xAxisData = ref([]); const seriesData = ref([]); -onMounted(async () => { - // 任务数 - const countOrderAndAmountData= await countOrderAndAmount(); +const loading = ref(false); +async function fetchOrderAndAmount() { + const countOrderAndAmountData = await countOrderAndAmount(); countOrderAndAmountDataAmount.value = countOrderAndAmountData.amount; countOrderAndAmountDataOrder.value = countOrderAndAmountData.num; - //活跃用户 +} + +async function fetchCustomers() { const countCustomersDataRes: any = await countCustomers(); countCustomersData.value = countCustomersDataRes.count; +} + +async function fetchAchievedRate() { const countAchievedRateDataRes: any = await countAchievedRate(); countAchievedRateData.value = countAchievedRateDataRes.rate; - // 查询订单数量趋势 +} + +async function fetchOrderTrend() { const res = await statisticsByTime({ timeUnit: timeUnit.value }); xAxisData.value = res?.time ?? []; seriesData.value = res?.counts ?? []; - // 租赁金额分布 - const data = await countByRentalType();//返回的内容是amount: 1, type: "单点" - // 转换字段名为value和name - const convertedData = data.map((item: { amount: number; type: string }) => ({ - value: item.amount, - name: item.type - })); - // 客户类型分配 - const countByCusTypeData:any = await countByCusType(); - //客户续租率趋势 - const countRenewRateData:any = await countRenewRate(); - // 养护任务完成情况 - const countAchievedData:any = await countAchieved(); - // 养护质量评分分布 - const countByCusScoreData:any = await countByCusScore(); - const countByCusScoreDataList = countByCusScoreData.map((item: { score: string; count: number }) => ({ - value: item.count, - name: item.score - })); renderEcharts({ tooltip: { trigger: 'axis' }, xAxis: { @@ -87,31 +75,34 @@ onMounted(async () => { data: xAxisData.value, boundaryGap: false, }, - yAxis: { type: 'value', - axisLabel: { - formatter: (value) => `${value * 100}%` - }, - }, + yAxis: { type: 'value', axisLabel: { formatter: (value) => `${value * 100}%` } }, series: [ { name: '订单趋势', type: 'line', - data: seriesData.value ||[], + data: seriesData.value || [], smooth: true, }, ], }); +} + +async function fetchLeasePie() { + const data = await countByRentalType(); + const convertedData = data.map((item: { amount: number; type: string }) => ({ + value: item.amount, + name: item.type, + })); renderLeasePie({ title: { text: '租赁金额分布', left: 'center' }, tooltip: { trigger: 'item' }, legend: { orient: 'vertical', left: 'left' }, series: [ { - // name: '金额', type: 'pie', radius: '60%', center: ['50%', '50%'], - data:convertedData || [], + data: convertedData || [], emphasis: { itemStyle: { shadowBlur: 10, @@ -126,20 +117,19 @@ onMounted(async () => { }, ], }); +} + +async function fetchCustomerTypesBar() { + const countByCusTypeData: any = await countByCusType(); renderCustomerTypesBar({ title: { text: '客户类型分布' }, tooltip: { trigger: 'axis' }, xAxis: { type: 'category', - data: ['企业客户','个人客户','政府机构','商业地产','其他'], + data: ['企业客户', '个人客户', '政府机构', '商业地产', '其他'], boundaryGap: true, }, - yAxis: { type: 'value', - axisLabel: { - // formatter: (value: number) => `${parseInt(value.toString())}` - }, - // interval: 0, - }, + yAxis: { type: 'value' }, series: [ { name: '客户数', @@ -148,16 +138,21 @@ onMounted(async () => { }, ], }); +} + +async function fetchCustomerRenewalLine() { + const countRenewRateData: any = await countRenewRate(); renderCustomerRenewalLine({ title: { text: '客户续租率趋势' }, - tooltip: { trigger: 'axis', - formatter: function(params:any) { + tooltip: { + trigger: 'axis', + formatter: function (params: any) { let result = params[0].axisValue + ''; - params.forEach((item:any) => { + params.forEach((item: any) => { result += item.marker + item.seriesName + ':' + item.data + '%'; }); return result; - } + }, }, xAxis: { type: 'category', @@ -165,10 +160,9 @@ onMounted(async () => { boundaryGap: false, }, yAxis: { - type: 'value', - axisLabel: { - formatter: '{value}%', - }, }, + type: 'value', + axisLabel: { formatter: '{value}%' }, + }, series: [ { name: '续租率', @@ -178,78 +172,55 @@ onMounted(async () => { }, ], }); +} + +async function fetchConservationTasksBar() { + const countAchievedData: any = await countAchieved(); renderConservationTasksBar({ title: { text: '养护任务完成情况' }, tooltip: { trigger: 'axis', axisPointer: { type: 'shadow' }, - formatter: function(params:any) { - // params 是一个数组,包含每个系列的当前项 - let result = params[0].axisValue + ''; - params.forEach((item:any) => { - if (item.seriesName === '完成率') { - // 假设原始数据是 80,显示为 80% - result += item.marker + item.seriesName + ':' + item.data + '%'; - } else { - result += item.marker + item.seriesName + ':' + item.data + ''; - } - }); - return result; - } - }, - legend: { - data: ['计划任务数', '已完成数', '完成率'], + formatter: function (params: any) { + let result = params[0].axisValue + ''; + params.forEach((item: any) => { + if (item.seriesName === '完成率') { + result += item.marker + item.seriesName + ':' + item.data + '%'; + } else { + result += item.marker + item.seriesName + ':' + item.data + ''; + } + }); + return result; + }, }, + legend: { data: ['计划任务数', '已完成数', '完成率'] }, xAxis: [ { type: 'category', - data: ['修剪整形','肥水管理','中耕除草','病虫害防治','越冬防寒'], + data: ['修剪整形', '肥水管理', '中耕除草', '病虫害防治', '越冬防寒'], }, ], yAxis: [ - { - type: 'value', - name: '任务数', - min: 0, - max: 200, - position: 'left', - }, - { - type: 'value', - name: '完成率', - min: 0, - max: 100, - position: 'right', - axisLabel: { - formatter: '{value}%', - }, - }, + { type: 'value', name: '任务数', min: 0, max: 200, position: 'left' }, + { type: 'value', name: '完成率', min: 0, max: 100, position: 'right', axisLabel: { formatter: '{value}%' } }, ], series: [ - { - name: '计划任务数', - type: 'bar', - data: countAchievedData.total || [], - }, - { - name: '已完成数', - type: 'bar', - data: countAchievedData.finish || [], - }, - { - name: '完成率', - type: 'line', - yAxisIndex: 1, - data: countAchievedData.rate || [], - }, + { name: '计划任务数', type: 'bar', data: countAchievedData.total || [] }, + { name: '已完成数', type: 'bar', data: countAchievedData.finish || [] }, + { name: '完成率', type: 'line', yAxisIndex: 1, data: countAchievedData.rate || [] }, ], }); +} + +async function fetchMaintenanceQualityScoresPei() { + const countByCusScoreData: any = await countByCusScore(); + const countByCusScoreDataList = countByCusScoreData.map((item: { score: string; count: number }) => ({ + value: item.count, + name: item.score, + })); renderMaintenanceQualityScoresPei({ title: { text: '养护质量评分分布', left: 'center' }, - tooltip: { - trigger: 'item', - formatter: '{b} : {d}%', - }, + tooltip: { trigger: 'item', formatter: '{b} : {d}%' }, legend: { orient: 'horizontal', left: 'center', @@ -263,13 +234,27 @@ onMounted(async () => { radius: '60%', center: ['50%', '50%'], data: countByCusScoreDataList || [], - label: { - formatter: '{b} {d}%', - show: true, - }, + label: { formatter: '{b} {d}%', show: true }, }, ], }); +} + +onMounted(async () => { + loading.value = true; + try { + await fetchOrderAndAmount(); + await fetchCustomers(); + await fetchAchievedRate(); + await fetchOrderTrend(); + await fetchLeasePie(); + await fetchCustomerTypesBar(); + await fetchCustomerRenewalLine(); + await fetchConservationTasksBar(); + await fetchMaintenanceQualityScoresPei(); + } finally { + loading.value = false; + } }); // 切换视图模式 async function handleViewModeChange(e: RadioChangeEvent): Promise { @@ -313,101 +298,103 @@ function formatNumber(num: number | string) { - - - 绿植租赁业务统计报表: - - - - 导出数据 - - - - - - - - 总订单数 - {{formatNumber(countOrderAndAmountDataAmount)}} - - - - 累计租赁金额 - {{ formatNumber(countOrderAndAmountDataOrder) }} - - - 当前活跃客户数 - {{ formatNumber(countCustomersData) }} - - - 绿植养护完成率 - {{ countAchievedRateData }} - - - - - - 订单数量趋势 - - - 日 - 周 - 月 - - + + + + 绿植租赁业务统计报表: + + + + 导出数据 + - - - - - - + + + + 总订单数 + {{formatNumber(countOrderAndAmountDataAmount)}} + + + + 累计租赁金额 + {{ formatNumber(countOrderAndAmountDataOrder) }} + + + 当前活跃客户数 + {{ formatNumber(countCustomersData) }} + + + 绿植养护完成率 + {{ countAchievedRateData || '0.00%' }} + + + + + + 订单数量趋势 + + + 日 + 周 + 月 + + + + + + + + + + + + + + + + + + - + - - - - - - - +