09032029
This commit is contained in:
parent
312cfbb658
commit
0b01572389
|
@ -8,7 +8,6 @@ export class InitService {
|
||||||
constructor(private readonly authService: AuthService) { }
|
constructor(private readonly authService: AuthService) { }
|
||||||
private async createRoles() {
|
private async createRoles() {
|
||||||
this.logger.log('Checking existing system roles');
|
this.logger.log('Checking existing system roles');
|
||||||
|
|
||||||
for (const role of InitRoles) {
|
for (const role of InitRoles) {
|
||||||
const existingRole = await db.role.findUnique({
|
const existingRole = await db.role.findUnique({
|
||||||
where: { name: role.name },
|
where: { name: role.name },
|
||||||
|
@ -26,10 +25,8 @@ export class InitService {
|
||||||
}
|
}
|
||||||
private async createTaxonomy() {
|
private async createTaxonomy() {
|
||||||
this.logger.log('Checking existing taxonomies');
|
this.logger.log('Checking existing taxonomies');
|
||||||
|
|
||||||
const existingTaxonomies = await db.taxonomy.findMany();
|
const existingTaxonomies = await db.taxonomy.findMany();
|
||||||
const existingTaxonomyNames = existingTaxonomies.map(taxonomy => taxonomy.name);
|
const existingTaxonomyNames = existingTaxonomies.map(taxonomy => taxonomy.name);
|
||||||
|
|
||||||
for (const [index, taxonomy] of InitTaxonomies.entries()) {
|
for (const [index, taxonomy] of InitTaxonomies.entries()) {
|
||||||
if (!existingTaxonomyNames.includes(taxonomy.name)) {
|
if (!existingTaxonomyNames.includes(taxonomy.name)) {
|
||||||
this.logger.log(`Creating taxonomy: ${taxonomy.name}`);
|
this.logger.log(`Creating taxonomy: ${taxonomy.name}`);
|
||||||
|
|
|
@ -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>(SocketGateway);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should be defined', () => {
|
|
||||||
expect(gateway).toBeDefined();
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -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>(TransformController);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should be defined', () => {
|
|
||||||
expect(controller).toBeDefined();
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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({
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
|
@ -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>(TransformService);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should be defined', () => {
|
|
||||||
expect(service).toBeDefined();
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,12 +1,23 @@
|
||||||
import { INestApplication, Injectable } from '@nestjs/common';
|
import { INestApplication, Injectable } from '@nestjs/common';
|
||||||
import { AuthRouter } from '@server/auth/auth.router';
|
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 { TrpcService } from '@server/trpc/trpc.service';
|
||||||
import * as trpcExpress from '@trpc/server/adapters/express';
|
import * as trpcExpress from '@trpc/server/adapters/express';
|
||||||
|
import { TransformRouter } from '../transform/transform.router';
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class TrpcRouter {
|
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({
|
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) {
|
async applyMiddleware(app: INestApplication) {
|
||||||
app.use(
|
app.use(
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import "@web/src/polyfills"
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import ReactDOM from 'react-dom/client'
|
import ReactDOM from 'react-dom/client'
|
||||||
import App from './App.js'
|
import App from './App.js'
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
if (!AbortSignal.prototype.throwIfAborted) {
|
||||||
|
AbortSignal.prototype.throwIfAborted = function () {
|
||||||
|
if (this.aborted) {
|
||||||
|
throw new DOMException("The operation was aborted.", "AbortError");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
|
@ -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<T>(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<string, T>();
|
||||||
|
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<T>(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<T>(client: QueryClient, trpcQueryKey: any, key: string | number, uniqueField: string = 'id'): T | undefined {
|
||||||
|
const uniqueData = getCacheDataFromQuery<T>(client, trpcQueryKey, uniqueField);
|
||||||
|
return findDataByKey<T>(uniqueData, key, uniqueField);
|
||||||
|
}
|
|
@ -6,10 +6,12 @@
|
||||||
"incremental": true,
|
"incremental": true,
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
"strictNullChecks": true,
|
"strictNullChecks": true,
|
||||||
"noImplicitAny": true,
|
"noImplicitAny": false,
|
||||||
"strictBindCallApply": true,
|
"strictBindCallApply": true,
|
||||||
"forceConsistentCasingInFileNames": true,
|
"forceConsistentCasingInFileNames": true,
|
||||||
"noFallthroughCasesInSwitch": true,
|
"noFallthroughCasesInSwitch": true,
|
||||||
|
"noUnusedLocals": false, // 关闭未使用局部变量的警告
|
||||||
|
"noUnusedParameters": false, // 关闭未使用函数参数的警告
|
||||||
"paths": {
|
"paths": {
|
||||||
"@server/*": [
|
"@server/*": [
|
||||||
"./apps/server/src/*"
|
"./apps/server/src/*"
|
||||||
|
|
Loading…
Reference in New Issue