chore: remove dead code and tune frontend chunks
This commit is contained in:
@@ -1,16 +0,0 @@
|
|||||||
import { describe, expect, it } from 'vitest';
|
|
||||||
import { CLASSROOM_VISIBLE_FIELDS } from './classroom-fields';
|
|
||||||
|
|
||||||
describe('classroom visible fields', () => {
|
|
||||||
it('excludes obsolete course and supervisor metadata', () => {
|
|
||||||
expect(CLASSROOM_VISIBLE_FIELDS).toEqual([
|
|
||||||
'name',
|
|
||||||
'building',
|
|
||||||
'floor',
|
|
||||||
'roomType',
|
|
||||||
'capacity',
|
|
||||||
'status',
|
|
||||||
'notes',
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
export const CLASSROOM_VISIBLE_FIELDS = [
|
|
||||||
'name',
|
|
||||||
'building',
|
|
||||||
'floor',
|
|
||||||
'roomType',
|
|
||||||
'capacity',
|
|
||||||
'status',
|
|
||||||
'notes',
|
|
||||||
] as const;
|
|
||||||
@@ -18,13 +18,13 @@ export default defineConfig({
|
|||||||
name: 'echarts',
|
name: 'echarts',
|
||||||
test: /node_modules[\\/](echarts|zrender)[\\/]/,
|
test: /node_modules[\\/](echarts|zrender)[\\/]/,
|
||||||
priority: 20,
|
priority: 20,
|
||||||
maxSize: 300_000,
|
maxSize: 600_000,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'antd',
|
name: 'antd',
|
||||||
test: /node_modules[\\/](@ant-design|antd|rc-[^\\/]+)[\\/]/,
|
test: /node_modules[\\/](@ant-design|antd|rc-[^\\/]+)[\\/]/,
|
||||||
priority: 10,
|
priority: 10,
|
||||||
maxSize: 300_000,
|
maxSize: 600_000,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ describe('AttendanceController — DingTalk import scope', () => {
|
|||||||
attendanceService.getTeacherClassDingUserIds.mockResolvedValue(['ding-1', 'ding-2']);
|
attendanceService.getTeacherClassDingUserIds.mockResolvedValue(['ding-1', 'ding-2']);
|
||||||
|
|
||||||
await controller.importFromDingTalk(
|
await controller.importFromDingTalk(
|
||||||
{ start: '2026-07-01', end: '2026-07-02', classId: 8, autoMatch: true },
|
{ start: '2026-07-01', end: '2026-07-02', classId: 8 },
|
||||||
{ user: { id: 21, username: 'teacher', permissions: [], isSuperAdmin: false } } as never,
|
{ user: { id: 21, username: 'teacher', permissions: [], isSuperAdmin: false } } as never,
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -79,7 +79,7 @@ describe('AttendanceController — DingTalk import scope', () => {
|
|||||||
it('does not allow a teacher to supply arbitrary DingTalk user IDs', async () => {
|
it('does not allow a teacher to supply arbitrary DingTalk user IDs', async () => {
|
||||||
await expect(
|
await expect(
|
||||||
controller.importFromDingTalk(
|
controller.importFromDingTalk(
|
||||||
{ start: '2026-07-01', end: '2026-07-02', users: 'someone-else', autoMatch: true },
|
{ start: '2026-07-01', end: '2026-07-02', users: 'someone-else' },
|
||||||
{ user: { id: 21, username: 'teacher', permissions: [], isSuperAdmin: false } } as never,
|
{ user: { id: 21, username: 'teacher', permissions: [], isSuperAdmin: false } } as never,
|
||||||
),
|
),
|
||||||
).rejects.toBeInstanceOf(ForbiddenException);
|
).rejects.toBeInstanceOf(ForbiddenException);
|
||||||
@@ -89,7 +89,7 @@ describe('AttendanceController — DingTalk import scope', () => {
|
|||||||
|
|
||||||
it('requires teachers to select one of their classes', async () => {
|
it('requires teachers to select one of their classes', async () => {
|
||||||
await expect(
|
await expect(
|
||||||
controller.importFromDingTalk({ start: '2026-07-01', end: '2026-07-02', autoMatch: true }, {
|
controller.importFromDingTalk({ start: '2026-07-01', end: '2026-07-02' }, {
|
||||||
user: { id: 21, username: 'teacher', permissions: [], isSuperAdmin: false },
|
user: { id: 21, username: 'teacher', permissions: [], isSuperAdmin: false },
|
||||||
} as never),
|
} as never),
|
||||||
).rejects.toBeInstanceOf(BadRequestException);
|
).rejects.toBeInstanceOf(BadRequestException);
|
||||||
@@ -106,11 +106,11 @@ describe('AttendanceController — DingTalk import scope', () => {
|
|||||||
expect(attendanceService.getImportableClasses).toHaveBeenCalledWith(21, false);
|
expect(attendanceService.getImportableClasses).toHaveBeenCalledWith(21, false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('always auto-matches class-scoped imports even if an old client sends autoMatch=false', async () => {
|
it('always auto-matches class-scoped imports', async () => {
|
||||||
attendanceService.getTeacherClassDingUserIds.mockResolvedValue(['ding-1']);
|
attendanceService.getTeacherClassDingUserIds.mockResolvedValue(['ding-1']);
|
||||||
|
|
||||||
await controller.importFromDingTalk(
|
await controller.importFromDingTalk(
|
||||||
{ start: '2026-07-01', end: '2026-07-02', classId: 8, autoMatch: false },
|
{ start: '2026-07-01', end: '2026-07-02', classId: 8 },
|
||||||
{ user: { id: 21, username: 'teacher', permissions: [], isSuperAdmin: false } } as never,
|
{ user: { id: 21, username: 'teacher', permissions: [], isSuperAdmin: false } } as never,
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -137,7 +137,7 @@ describe('AttendanceController — DingTalk import scope', () => {
|
|||||||
expect(attendanceService.getImportableClasses).toHaveBeenCalledWith(7, true);
|
expect(attendanceService.getImportableClasses).toHaveBeenCalledWith(7, true);
|
||||||
|
|
||||||
await controller.importFromDingTalk(
|
await controller.importFromDingTalk(
|
||||||
{ start: '2026-07-01', end: '2026-07-02', users: 'ding-1,ding-2', autoMatch: true },
|
{ start: '2026-07-01', end: '2026-07-02', users: 'ding-1,ding-2' },
|
||||||
{
|
{
|
||||||
user: {
|
user: {
|
||||||
id: 7,
|
id: 7,
|
||||||
|
|||||||
@@ -27,11 +27,6 @@ export class DingTalkImportDto {
|
|||||||
@IsOptional()
|
@IsOptional()
|
||||||
@IsString()
|
@IsString()
|
||||||
users?: string;
|
users?: string;
|
||||||
|
|
||||||
/** @deprecated Imports are always matched through DingTalk user mappings. */
|
|
||||||
@IsOptional()
|
|
||||||
@Type(() => Boolean)
|
|
||||||
autoMatch?: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { ArrayNotEmpty, IsArray, IsIn, IsInt, IsNotEmpty, IsOptional, IsString, Matches, MaxLength } from 'class-validator';
|
import { IsIn, IsNotEmpty, IsOptional, IsString, Matches, MaxLength } from 'class-validator';
|
||||||
|
|
||||||
export class GenerateBillsDto {
|
export class GenerateBillsDto {
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@@ -36,10 +36,3 @@ export class CancelBillDto {
|
|||||||
@MaxLength(300)
|
@MaxLength(300)
|
||||||
reason: string;
|
reason: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class BatchUpdateBillStatusDto extends UpdateBillStatusDto {
|
|
||||||
@IsArray()
|
|
||||||
@ArrayNotEmpty()
|
|
||||||
@IsInt({ each: true })
|
|
||||||
ids: number[];
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,7 +1,13 @@
|
|||||||
import { CLASSROOM_TEMPLATE_HEADERS } from './classroom-template';
|
import { CLASSROOM_TEMPLATE_COLUMNS } from './classroom-template';
|
||||||
|
|
||||||
describe('classroom import template', () => {
|
describe('classroom import template', () => {
|
||||||
it('contains only classroom fields used by the product', () => {
|
it('contains only classroom fields used by the product', () => {
|
||||||
expect(CLASSROOM_TEMPLATE_HEADERS).toEqual(['教室名', '楼栋', '楼层', '类型', '容量']);
|
expect(CLASSROOM_TEMPLATE_COLUMNS.map(({ header }) => header)).toEqual([
|
||||||
|
'教室名',
|
||||||
|
'楼栋',
|
||||||
|
'楼层',
|
||||||
|
'类型',
|
||||||
|
'容量',
|
||||||
|
]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -5,5 +5,3 @@ export const CLASSROOM_TEMPLATE_COLUMNS = [
|
|||||||
{ header: '类型', key: 'roomType', width: 10 },
|
{ header: '类型', key: 'roomType', width: 10 },
|
||||||
{ header: '容量', key: 'capacity', width: 10 },
|
{ header: '容量', key: 'capacity', width: 10 },
|
||||||
];
|
];
|
||||||
|
|
||||||
export const CLASSROOM_TEMPLATE_HEADERS = CLASSROOM_TEMPLATE_COLUMNS.map(({ header }) => header);
|
|
||||||
|
|||||||
@@ -16,11 +16,6 @@ export interface JinshujuFieldMapping {
|
|||||||
studentNo?: string;
|
studentNo?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DEFAULT_MAPPING: JinshujuFieldMapping = {
|
|
||||||
name: 'field_1',
|
|
||||||
phone: 'field_2',
|
|
||||||
};
|
|
||||||
|
|
||||||
const mappingTransformer = {
|
const mappingTransformer = {
|
||||||
to(value: JinshujuFieldMapping): string {
|
to(value: JinshujuFieldMapping): string {
|
||||||
return JSON.stringify(value);
|
return JSON.stringify(value);
|
||||||
|
|||||||
@@ -915,11 +915,6 @@ export class DingTalkService {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
private delay(requestIndex: number): Promise<void> {
|
|
||||||
const ms = requestIndex % 10 === 0 ? 200 : DingTalkService.MIN_INTERVAL;
|
|
||||||
return this.sleep(ms);
|
|
||||||
}
|
|
||||||
|
|
||||||
private sleep(ms: number): Promise<void> {
|
private sleep(ms: number): Promise<void> {
|
||||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { NestFactory } from '@nestjs/core';
|
import { NestFactory } from '@nestjs/core';
|
||||||
import { ValidationPipe } from '@nestjs/common';
|
|
||||||
import { AppModule } from './app.module';
|
import { AppModule } from './app.module';
|
||||||
import { runMigrationsOnStartup } from './migration-runner';
|
import { runMigrationsOnStartup } from './migration-runner';
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user