forked from wangziqi/gongxue-base
chore: commit oxfmt formatting changes and verify artifacts
This commit is contained in:
@@ -1,4 +1,9 @@
|
||||
import { Injectable, NotFoundException, BadRequestException, ConflictException } from '@nestjs/common';
|
||||
import {
|
||||
Injectable,
|
||||
NotFoundException,
|
||||
BadRequestException,
|
||||
ConflictException,
|
||||
} from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { Repository, Not } from 'typeorm';
|
||||
import { ClassroomRental } from '../entities/classroom-rental.entity';
|
||||
@@ -10,8 +15,16 @@ import * as fs from 'fs';
|
||||
|
||||
// 预设色板(与 tenants.service 保持一致,作为颜色兜底)
|
||||
const COLOR_PALETTE = [
|
||||
'#ff7875', '#ffa940', '#ffc53d', '#73d13d', '#36cfc9',
|
||||
'#40a9ff', '#597ef7', '#9254de', '#f759ab', '#8c8c8c',
|
||||
'#ff7875',
|
||||
'#ffa940',
|
||||
'#ffc53d',
|
||||
'#73d13d',
|
||||
'#36cfc9',
|
||||
'#40a9ff',
|
||||
'#597ef7',
|
||||
'#9254de',
|
||||
'#f759ab',
|
||||
'#8c8c8c',
|
||||
];
|
||||
|
||||
@Injectable()
|
||||
@@ -33,8 +46,14 @@ export class ClassroomRentalsService {
|
||||
}
|
||||
}
|
||||
|
||||
async findAll(query?: { classroomId?: number; tenantId?: number; month?: string; includeEnded?: boolean }) {
|
||||
const qb = this.repo.createQueryBuilder('r')
|
||||
async findAll(query?: {
|
||||
classroomId?: number;
|
||||
tenantId?: number;
|
||||
month?: string;
|
||||
includeEnded?: boolean;
|
||||
}) {
|
||||
const qb = this.repo
|
||||
.createQueryBuilder('r')
|
||||
.leftJoinAndSelect('r.classroom', 'classroom')
|
||||
.leftJoinAndSelect('r.tenant', 'tenant')
|
||||
.orderBy('r.startDate', 'DESC');
|
||||
@@ -63,7 +82,8 @@ export class ClassroomRentalsService {
|
||||
* 重叠判定:start1 <= end2 AND start2 <= end1
|
||||
*/
|
||||
async findConflicts(classroomId: number, startDate: string, endDate: string, excludeId?: number) {
|
||||
const qb = this.repo.createQueryBuilder('r')
|
||||
const qb = this.repo
|
||||
.createQueryBuilder('r')
|
||||
.leftJoinAndSelect('r.tenant', 'tenant')
|
||||
.where('r.classroomId = :cid', { cid: classroomId })
|
||||
.andWhere('r.status != :cancelled', { cancelled: 'cancelled' })
|
||||
@@ -84,7 +104,12 @@ export class ClassroomRentalsService {
|
||||
if (conflicts.length > 0) {
|
||||
throw new ConflictException({
|
||||
message: '该教室在此时间段已有租赁',
|
||||
conflicts: conflicts.map(c => ({ id: c.id, startDate: c.startDate, endDate: c.endDate, tenantName: c.tenant?.name })),
|
||||
conflicts: conflicts.map((c) => ({
|
||||
id: c.id,
|
||||
startDate: c.startDate,
|
||||
endDate: c.endDate,
|
||||
tenantName: c.tenant?.name,
|
||||
})),
|
||||
});
|
||||
}
|
||||
return this.repo.save(this.repo.create({ ...dto, createdBy: userId, status: 'active' }));
|
||||
@@ -102,7 +127,12 @@ export class ClassroomRentalsService {
|
||||
if (conflicts.length > 0) {
|
||||
throw new ConflictException({
|
||||
message: '修改后时间段与已有租赁冲突',
|
||||
conflicts: conflicts.map(c => ({ id: c.id, startDate: c.startDate, endDate: c.endDate, tenantName: c.tenant?.name })),
|
||||
conflicts: conflicts.map((c) => ({
|
||||
id: c.id,
|
||||
startDate: c.startDate,
|
||||
endDate: c.endDate,
|
||||
tenantName: c.tenant?.name,
|
||||
})),
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -116,7 +146,11 @@ export class ClassroomRentalsService {
|
||||
if (rental.contractPath) {
|
||||
const full = path.join(this.uploadDir, rental.contractPath);
|
||||
if (fs.existsSync(full)) {
|
||||
try { fs.unlinkSync(full); } catch { /* ignore */ }
|
||||
try {
|
||||
fs.unlinkSync(full);
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
}
|
||||
}
|
||||
await this.repo.delete(id);
|
||||
@@ -133,7 +167,9 @@ export class ClassroomRentalsService {
|
||||
const ext = path.extname(file.originalname).toLowerCase();
|
||||
if (ext !== '.pdf') throw new BadRequestException('文件扩展名必须为 .pdf');
|
||||
// UUID 文件名
|
||||
const uuid = (globalThis as any).crypto?.randomUUID?.() || require('crypto').randomBytes(16).toString('hex');
|
||||
const uuid =
|
||||
(globalThis as any).crypto?.randomUUID?.() ||
|
||||
require('crypto').randomBytes(16).toString('hex');
|
||||
const filename = `${uuid}.pdf`;
|
||||
const fullPath = path.join(this.uploadDir, filename);
|
||||
// 路径遍历防护
|
||||
@@ -142,7 +178,11 @@ export class ClassroomRentalsService {
|
||||
if (rental.contractPath) {
|
||||
const oldPath = path.join(this.uploadDir, rental.contractPath);
|
||||
if (fs.existsSync(oldPath)) {
|
||||
try { fs.unlinkSync(oldPath); } catch { /* ignore */ }
|
||||
try {
|
||||
fs.unlinkSync(oldPath);
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
}
|
||||
}
|
||||
fs.writeFileSync(fullPath, file.buffer);
|
||||
@@ -158,7 +198,11 @@ export class ClassroomRentalsService {
|
||||
if (!rental.contractPath) throw new BadRequestException('该租赁未上传合同');
|
||||
const fullPath = path.join(this.uploadDir, rental.contractPath);
|
||||
if (fs.existsSync(fullPath)) {
|
||||
try { fs.unlinkSync(fullPath); } catch { /* ignore */ }
|
||||
try {
|
||||
fs.unlinkSync(fullPath);
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
}
|
||||
await this.repo.update(id, { contractPath: null as any, contractOriginalName: null as any });
|
||||
return { message: '合同已删除' };
|
||||
@@ -188,7 +232,8 @@ export class ClassroomRentalsService {
|
||||
where: { status: Not('archived') },
|
||||
order: { building: 'ASC', name: 'ASC' },
|
||||
});
|
||||
const rentals = await this.repo.createQueryBuilder('r')
|
||||
const rentals = await this.repo
|
||||
.createQueryBuilder('r')
|
||||
.leftJoinAndSelect('r.tenant', 'tenant')
|
||||
.leftJoinAndSelect('r.classroom', 'classroom')
|
||||
.where('r.status != :cancelled', { cancelled: 'cancelled' })
|
||||
@@ -197,7 +242,10 @@ export class ClassroomRentalsService {
|
||||
|
||||
const tenantMap = new Map<number, any>();
|
||||
const matrix: Record<number, Record<number, any>> = {};
|
||||
const summary: Record<number, { totalDays: number; rentedDays: number; idleDays: number; occupancyRate: number }> = {};
|
||||
const summary: Record<
|
||||
number,
|
||||
{ totalDays: number; rentedDays: number; idleDays: number; occupancyRate: number }
|
||||
> = {};
|
||||
|
||||
for (const cls of classrooms) {
|
||||
matrix[cls.id] = {};
|
||||
@@ -225,7 +273,8 @@ export class ClassroomRentalsService {
|
||||
rentalId: rental.id,
|
||||
tenantId: rental.tenantId,
|
||||
tenantName: rental.tenant?.name || '未知',
|
||||
color: rental.tenant?.color || COLOR_PALETTE[(rental.tenantId || 0) % COLOR_PALETTE.length],
|
||||
color:
|
||||
rental.tenant?.color || COLOR_PALETTE[(rental.tenantId || 0) % COLOR_PALETTE.length],
|
||||
hasContract: !!rental.contractPath,
|
||||
};
|
||||
}
|
||||
@@ -243,7 +292,15 @@ export class ClassroomRentalsService {
|
||||
year,
|
||||
month,
|
||||
days: lastDay,
|
||||
classrooms: classrooms.map(c => ({ id: c.id, name: c.name, building: c.building, floor: c.floor, roomType: c.roomType, capacity: c.capacity, supervisor: c.supervisor })),
|
||||
classrooms: classrooms.map((c) => ({
|
||||
id: c.id,
|
||||
name: c.name,
|
||||
building: c.building,
|
||||
floor: c.floor,
|
||||
roomType: c.roomType,
|
||||
capacity: c.capacity,
|
||||
supervisor: c.supervisor,
|
||||
})),
|
||||
tenants: Array.from(tenantMap.values()),
|
||||
matrix,
|
||||
summary,
|
||||
|
||||
Reference in New Issue
Block a user