From ceb0e2bf14b3fd251d3719de72176646f605f91d Mon Sep 17 00:00:00 2001 From: xyx Date: Mon, 13 Jul 2026 16:11:53 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E6=B7=BB=E5=8A=A0=E9=BB=98=E8=AE=A4?= =?UTF-8?q?=E5=BA=8A=E4=BD=8D=E7=94=9F=E6=88=90=E9=80=BB=E8=BE=91=E5=B9=B6?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=BA=8A=E4=BD=8D=E6=B7=BB=E5=8A=A0=E9=AA=8C?= =?UTF-8?q?=E8=AF=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/admin/src/pages/Rooms/index.tsx | 21 ++++++++++++------ apps/server/src/rooms/rooms.service.ts | 30 ++++++++++++++++++++++++-- 2 files changed, 42 insertions(+), 9 deletions(-) diff --git a/apps/admin/src/pages/Rooms/index.tsx b/apps/admin/src/pages/Rooms/index.tsx index df2140a..e27ce95 100644 --- a/apps/admin/src/pages/Rooms/index.tsx +++ b/apps/admin/src/pages/Rooms/index.tsx @@ -156,6 +156,11 @@ const RoomsPage: React.FC = () => { if (filterStatus) result = result.filter((r: Record) => r.status === filterStatus); return result; }, [data, searchText, filterBuilding, filterStatus]); + const remainingBedSlots = useMemo(() => { + const capacity = Number(drawerRoom?.capacity) || 0; + return Math.max(capacity - beds.length, 0); + }, [drawerRoom?.capacity, beds.length]); + const defaultBatchBedCount = Math.min(4, Math.max(remainingBedSlots, 1)); const handleSave = async () => { const values = await form.validateFields(); @@ -167,7 +172,7 @@ const RoomsPage: React.FC = () => { message.success('更新成功'); } else { await api.post('/rooms', payload); - message.success('创建成功'); + message.success(`创建成功,已自动生成 ${values.capacity} 张床位`); } setModalOpen(false); form.resetFields(); @@ -634,24 +639,26 @@ const RoomsPage: React.FC = () => { type="primary" size="small" icon={} - disabled={drawerRoom?.status === 'archived'} + disabled={drawerRoom?.status === 'archived' || remainingBedSlots === 0} onClick={() => { setBedEditing(null); bedForm.resetFields(); setBedModalOpen(true); }} > 添加床位 0 ? '批量生成床位' : '床位已达到额定人数'} description={ - + remainingBedSlots > 0 + ? + : '如需增加床位,请先调整宿舍额定人数' } onConfirm={() => { const input = document.getElementById('batch-bed-count') as HTMLInputElement; - handleBatchBeds(input ? parseInt(input.value) || 4 : 4); + handleBatchBeds(input ? parseInt(input.value) || defaultBatchBedCount : defaultBatchBedCount); }} okText="生成" - disabled={drawerRoom?.status === 'archived'} + disabled={drawerRoom?.status === 'archived' || remainingBedSlots === 0} > - + { const match = b.bedNumber.match(/^\d+/); return match ? parseInt(match[0]) : 0; @@ -399,6 +404,27 @@ export class RoomsService { return this.bedRepo.save(beds); } + private async createDefaultBeds(roomId: number, capacity: number): Promise { + const count = Math.max(capacity ?? 0, 0); + if (count === 0) return; + const beds = Array.from({ length: count }, (_, index) => + this.bedRepo.create({ roomId, bedNumber: `${index + 1}号床` }), + ); + await this.bedRepo.save(beds); + } + + private async assertCanAddBeds(room: Room, count: number): Promise { + const existingCount = await this.bedRepo.count({ where: { roomId: room.id } }); + this.assertCanAddBedsFromCount(room, existingCount, count); + } + + private assertCanAddBedsFromCount(room: Room, existingCount: number, count: number): void { + const remaining = Math.max((room.capacity ?? 0) - existingCount, 0); + if (count > remaining) { + throw new BadRequestException(`床位不能超过额定人数,当前已有 ${existingCount} 张,额定 ${room.capacity} 张,最多还能添加 ${remaining} 张`); + } + } + // ── 柜子管理 ── async getRoomLockers(roomId: number): Promise {