diff --git a/apps/server/src/init/init.service.ts b/apps/server/src/init/init.service.ts index 653f0f6..405f913 100644 --- a/apps/server/src/init/init.service.ts +++ b/apps/server/src/init/init.service.ts @@ -8,7 +8,6 @@ export class InitService { constructor(private readonly authService: AuthService) { } private async createRoles() { this.logger.log('Checking existing system roles'); - for (const role of InitRoles) { const existingRole = await db.role.findUnique({ where: { name: role.name }, @@ -26,10 +25,8 @@ export class InitService { } private async createTaxonomy() { this.logger.log('Checking existing taxonomies'); - const existingTaxonomies = await db.taxonomy.findMany(); const existingTaxonomyNames = existingTaxonomies.map(taxonomy => taxonomy.name); - for (const [index, taxonomy] of InitTaxonomies.entries()) { if (!existingTaxonomyNames.includes(taxonomy.name)) { this.logger.log(`Creating taxonomy: ${taxonomy.name}`); diff --git a/apps/server/src/socket/socket.gateway.spec.ts b/apps/server/src/socket/socket.gateway.spec.ts deleted file mode 100644 index 8cf8bf5..0000000 --- a/apps/server/src/socket/socket.gateway.spec.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { SocketGateway } from './socket.gateway'; - -describe('SocketGateway', () => { - let gateway: SocketGateway; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [SocketGateway], - }).compile(); - - gateway = module.get(SocketGateway); - }); - - it('should be defined', () => { - expect(gateway).toBeDefined(); - }); -}); diff --git a/apps/server/src/transform/transform.controller.spec.ts b/apps/server/src/transform/transform.controller.spec.ts deleted file mode 100644 index 78829ae..0000000 --- a/apps/server/src/transform/transform.controller.spec.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { TransformController } from './transform.controller'; - -describe('TransformController', () => { - let controller: TransformController; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - controllers: [TransformController], - }).compile(); - - controller = module.get(TransformController); - }); - - it('should be defined', () => { - expect(controller).toBeDefined(); - }); -}); diff --git a/apps/server/src/transform/transform.controller.ts b/apps/server/src/transform/transform.controller.ts deleted file mode 100644 index 998f77e..0000000 --- a/apps/server/src/transform/transform.controller.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { - Controller, - Post, - UseInterceptors, - UploadedFile, - Body, -} from '@nestjs/common'; -import { FileInterceptor } from '@nestjs/platform-express'; -@Controller('transform') -export class TransformController { - @Post('import') - @UseInterceptors(FileInterceptor('file')) - async uploadFile(@UploadedFile() file: Express.Multer.File, @Body('type') type: string) { - console.log(file); - let result = 'test'; - switch (type) { - default: - throw new Error(`Unsupported import type: ${type}`); - } - - return result; - } -} diff --git a/apps/server/src/transform/transform.router.ts b/apps/server/src/transform/transform.router.ts new file mode 100644 index 0000000..9a9dade --- /dev/null +++ b/apps/server/src/transform/transform.router.ts @@ -0,0 +1,13 @@ +import { Injectable } from '@nestjs/common'; +import { TrpcService } from '@server/trpc/trpc.service'; +import { TransformService } from './transform.service'; + + +@Injectable() +export class TransformRouter { + constructor(private readonly trpc: TrpcService, private readonly transformService: TransformService) { } + + router = this.trpc.router({ + + }); +} diff --git a/apps/server/src/transform/transform.service.spec.ts b/apps/server/src/transform/transform.service.spec.ts deleted file mode 100644 index 686f2c8..0000000 --- a/apps/server/src/transform/transform.service.spec.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { TransformService } from './transform.service'; - -describe('TransformService', () => { - let service: TransformService; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [TransformService], - }).compile(); - - service = module.get(TransformService); - }); - - it('should be defined', () => { - expect(service).toBeDefined(); - }); -}); diff --git a/apps/server/src/trpc/trpc.router.ts b/apps/server/src/trpc/trpc.router.ts index bbc6944..032b8cd 100644 --- a/apps/server/src/trpc/trpc.router.ts +++ b/apps/server/src/trpc/trpc.router.ts @@ -1,12 +1,23 @@ import { INestApplication, Injectable } from '@nestjs/common'; import { AuthRouter } from '@server/auth/auth.router'; +import { DepartmentRouter } from '@server/models/department/department.router'; +import { StaffRouter } from '@server/models/staff/staff.router'; import { TrpcService } from '@server/trpc/trpc.service'; import * as trpcExpress from '@trpc/server/adapters/express'; +import { TransformRouter } from '../transform/transform.router'; @Injectable() export class TrpcRouter { - constructor(private readonly trpc: TrpcService, private readonly auth: AuthRouter) { } + constructor(private readonly trpc: TrpcService, + private readonly auth: AuthRouter, + private readonly staff: StaffRouter, + private readonly department: DepartmentRouter, + private readonly transform: TransformRouter + ) { } appRouter = this.trpc.router({ - auth: this.auth.router + auth: this.auth.router, + staff: this.staff.router, + department: this.department.router, + transform: this.transform.router }); async applyMiddleware(app: INestApplication) { app.use( diff --git a/apps/web/src/main.tsx b/apps/web/src/main.tsx index 973961b..d97b57e 100644 --- a/apps/web/src/main.tsx +++ b/apps/web/src/main.tsx @@ -1,3 +1,4 @@ +import "@web/src/polyfills" import React from 'react' import ReactDOM from 'react-dom/client' import App from './App.js' diff --git a/apps/web/src/polyfills/index.ts b/apps/web/src/polyfills/index.ts new file mode 100644 index 0000000..454fa17 --- /dev/null +++ b/apps/web/src/polyfills/index.ts @@ -0,0 +1,7 @@ +if (!AbortSignal.prototype.throwIfAborted) { + AbortSignal.prototype.throwIfAborted = function () { + if (this.aborted) { + throw new DOMException("The operation was aborted.", "AbortError"); + } + }; +} diff --git a/apps/web/src/utils/general.ts b/apps/web/src/utils/general.ts new file mode 100755 index 0000000..a27ba6a --- /dev/null +++ b/apps/web/src/utils/general.ts @@ -0,0 +1,70 @@ +import { QueryClient } from "@tanstack/react-query"; +import { getQueryKey } from "@trpc/react-query"; +export const handleDownload = (url: string | undefined) => { + if (url) { + const link = document.createElement('a'); + link.href = url; + link.download = url.split('/').pop() || ''; + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + } +}; + +/** + * 根据查询客户端缓存生成唯一数据列表的函数。 + * + * @template T - 数据类型 + * @param {QueryClient} client - 查询客户端实例 + * @param {any} trpcQueryKey - 用于获取查询键的参数 + * @param {string} uniqueField - 唯一字段的名称,默认为 'id' + * @returns {T[]} - 返回唯一的数据列表 + */ +export function getCacheDataFromQuery(client: QueryClient, trpcQueryKey: any, uniqueField: string = 'id'): T[] { + // 获取查询缓存数据 + const cacheData = client.getQueriesData({ queryKey: getQueryKey(trpcQueryKey) }); + // 提取并整理缓存数据 + const data = cacheData + .flatMap(cache => cache.slice(1)) + .flat() + .filter(item => item !== undefined) as T[]; + + // 使用 Map 进行去重 + const uniqueDataMap = new Map(); + data.forEach((item: T) => { + if (item && item[uniqueField]) { + uniqueDataMap.set(item[uniqueField], item); + } + }); + + // 转换为数组返回唯一的数据列表 + return Array.from(uniqueDataMap.values()); +} + +/** + * 查找唯一数据列表中的匹配对象。 + * + * @template T - 数据类型 + * @param {T[]} uniqueData - 唯一数据列表 + * @param {string} key - 唯一字段的键值 + * @param {string} uniqueField - 唯一字段的名称,默认为 'id' + * @returns {T | undefined} - 返回匹配的对象,如果没有找到则返回 undefined + */ +export function findDataByKey(uniqueData: T[], key: string | number, uniqueField: string = 'id'): T | undefined { + return uniqueData.find(item => item[uniqueField] === key); +} + +/** + * 综合使用生成唯一数据和查找数据的功能。 + * + * @template T - 数据类型 + * @param {QueryClient} client - 查询客户端实例 + * @param {any} trpcQueryKey - 用于获取查询键的参数 + * @param {string} key - 唯一字段的键值 + * @param {string} uniqueField - 唯一字段的名称,默认为 'id' + * @returns {T | undefined} - 返回匹配的对象,如果没有找到则返回 undefined + */ +export function findQueryData(client: QueryClient, trpcQueryKey: any, key: string | number, uniqueField: string = 'id'): T | undefined { + const uniqueData = getCacheDataFromQuery(client, trpcQueryKey, uniqueField); + return findDataByKey(uniqueData, key, uniqueField); +} diff --git a/tsconfig.json b/tsconfig.json index ad7f37c..c5894dd 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -6,10 +6,12 @@ "incremental": true, "skipLibCheck": true, "strictNullChecks": true, - "noImplicitAny": true, + "noImplicitAny": false, "strictBindCallApply": true, "forceConsistentCasingInFileNames": true, "noFallthroughCasesInSwitch": true, + "noUnusedLocals": false, // 关闭未使用局部变量的警告 + "noUnusedParameters": false, // 关闭未使用函数参数的警告 "paths": { "@server/*": [ "./apps/server/src/*"