This commit is contained in:
Rao 2025-03-11 22:36:54 +08:00
parent 7fd2173dd2
commit 4dcccff01e
6 changed files with 167 additions and 12 deletions

View File

@ -5,7 +5,6 @@ import { TrainSituationController } from './trainSituation.controller';
import { TrainSituationRouter } from './trainSituation.router'; import { TrainSituationRouter } from './trainSituation.router';
import { TrpcService } from '@server/trpc/trpc.service'; import { TrpcService } from '@server/trpc/trpc.service';
@Module({ @Module({
imports: [StaffModule], imports: [StaffModule],
controllers: [TrainSituationController], controllers: [TrainSituationController],

View File

@ -5,7 +5,8 @@ import { z, ZodType } from "zod";
import { Prisma } from "@nice/common"; import { Prisma } from "@nice/common";
const TrainSituationArgsSchema:ZodType<Prisma.TrainSituationCreateArgs> = z.any() const TrainSituationArgsSchema:ZodType<Prisma.TrainSituationCreateArgs> = z.any()
const TrainSituationUpdateArgsSchema:ZodType<Prisma.TrainSituationUpdateArgs> = z.any()
const TrainSituationFindManyArgsSchema:ZodType<Prisma.TrainSituationFindManyArgs> = z.any()
@Injectable() @Injectable()
export class TrainSituationRouter { export class TrainSituationRouter {
@ -18,8 +19,27 @@ export class TrainSituationRouter {
create:this.trpc.protectProcedure create:this.trpc.protectProcedure
.input(TrainSituationArgsSchema) .input(TrainSituationArgsSchema)
.mutation(async ({ input }) => { .mutation(async ({ input }) => {
this.trainSituationService.create(input) return this.trainSituationService.create(input)
}), }),
update:this.trpc.protectProcedure
.input(TrainSituationUpdateArgsSchema)
.mutation(async ({ input }) => {
return this.trainSituationService.update(input)
}),
findMany:this.trpc.protectProcedure
.input(TrainSituationFindManyArgsSchema)
.mutation(async ({input}) =>{
return this.trainSituationService.findMany(input)
}),
findManyByDepId:this.trpc.protectProcedure
.input(z.object({
deptId: z.string().optional(),
domainId: z.string().optional(),
trainContentId: z.string().optional()
}))
.mutation(async ({input}) => {
return this.trainSituationService.findManyByDeptId(input)
})
}) })
} }

View File

@ -2,13 +2,16 @@ import { Injectable } from "@nestjs/common";
import { BaseService } from "../base/base.service"; import { BaseService } from "../base/base.service";
import { db, ObjectType, Prisma, UserProfile } from "@nice/common"; import { db, ObjectType, Prisma, UserProfile } from "@nice/common";
import EventBus, { CrudOperation } from "@server/utils/event-bus"; import EventBus, { CrudOperation } from "@server/utils/event-bus";
import { DefaultArgs } from "@prisma/client/runtime/library";
import { StaffService } from "../staff/staff.service";
@Injectable() @Injectable()
export class TrainSituationService extends BaseService<Prisma.TrainSituationDelegate> { export class TrainSituationService extends BaseService<Prisma.TrainSituationDelegate> {
constructor() { constructor(private readonly staffService:StaffService) {
super(db,ObjectType.TRAIN_SITUATION,false); super(db,ObjectType.TRAIN_SITUATION,false);
} }
// 创建培训情况
async create( async create(
args: Prisma.TrainSituationCreateArgs, args: Prisma.TrainSituationCreateArgs,
){ ){
@ -17,7 +20,55 @@ export class TrainSituationService extends BaseService<Prisma.TrainSituationDele
this.emitDataChanged(CrudOperation.CREATED, result); this.emitDataChanged(CrudOperation.CREATED, result);
return result; return result;
} }
// 更新培训情况
async update(
args: Prisma.TrainSituationUpdateArgs,
){
const result = await super.update(args);
this.emitDataChanged(CrudOperation.UPDATED, result);
return result;
}
// 查找培训情况
async findMany(args: Prisma.TrainSituationFindManyArgs): Promise<{
id: string;
staffId: string;
trainContentId: string;
mustTrainTime: number;
alreadyTrainTime: number;
score: number;
}[]>
{
const result = await super.findMany(args);
return result;
}
// 查找某一单位所有人员的培训情况
async findManyByDeptId(args:{
deptId?:string,
domainId?:string,
trainContentId?:string
}):Promise<{
id: string;
staffId: string;
trainContentId: string;
mustTrainTime: number;
alreadyTrainTime: number;
score: number;
}[]>
{
const staffs = await this.staffService.findByDept({deptId:args.deptId,domainId:args.domainId})
const result = await super.findMany({
where:{
staffId:{
in:staffs.map(staff=>staff.id)
},
...(args.trainContentId ? {trainContentId:args.trainContentId} : {})
}
})
return result
}
// 发送数据变化事件
private emitDataChanged(operation: CrudOperation, data: any) { private emitDataChanged(operation: CrudOperation, data: any) {
EventBus.emit('dataChanged', { EventBus.emit('dataChanged', {
type:ObjectType.TRAIN_SITUATION, type:ObjectType.TRAIN_SITUATION,

View File

@ -49,10 +49,11 @@ export class GenDevService {
try { try {
await this.calculateCounts(); await this.calculateCounts();
await this.generateDepartments(3, 6); await this.generateDepartments(3, 6);
await this.generateTerms(2, 6); //await this.generateTerms(2, 6);
await this.generateStaffs(4); await this.generateStaffs(4);
await this.generateCourses(8); //await this.generateCourses(8);
await this.generateTrainContent(2,6) await this.generateTrainContent(2,6)
await this.generateTrainSituations()
} catch (err) { } catch (err) {
this.logger.error(err); this.logger.error(err);
} }
@ -209,7 +210,7 @@ export class GenDevService {
} }
} }
} }
private async generateStaffs(countPerDept: number = 3) { private async generateStaffs(countPerDept: number = 2) {
if (this.counts.staffCount === 1) { if (this.counts.staffCount === 1) {
this.logger.log('Generating staffs...'); this.logger.log('Generating staffs...');
// Calculate the total number of staffs to be generated // Calculate the total number of staffs to be generated
@ -344,7 +345,7 @@ export class GenDevService {
await createTermTree(null, 1); await createTermTree(null, 1);
} }
// 生成培训内容
private async createTrainContent( private async createTrainContent(
type:string, type:string,
title:string, title:string,
@ -359,7 +360,7 @@ export class GenDevService {
}); });
return trainContent; return trainContent;
} }
// 生成培训内容
private async generateTrainContent(depth:number=3,count:number=6){ private async generateTrainContent(depth:number=3,count:number=6){
if(this.counts.trainContentCount !== 0) return; if(this.counts.trainContentCount !== 0) return;
const totalTrainContent = this.calculateTotalTrainContent(depth,count) const totalTrainContent = this.calculateTotalTrainContent(depth,count)
@ -368,6 +369,7 @@ export class GenDevService {
this.trainContents = await db.trainContent.findMany() this.trainContents = await db.trainContent.findMany()
this.logger.log(`Completed: Generated ${this.trainContents.length} departments.`); this.logger.log(`Completed: Generated ${this.trainContents.length} departments.`);
} }
// 生成培训内容子内容
private async generateSubTrainContent( private async generateSubTrainContent(
parentId: string | null, parentId: string | null,
currentDepth:number, currentDepth:number,
@ -404,4 +406,47 @@ export class GenDevService {
} }
return total; return total;
} }
}
private async createTrainSituation(staffId:string,trainContentId:string){
const trainSituation = await db.trainSituation.create({
data:{
staffId,
trainContentId,
mustTrainTime:Math.floor(Math.random()*100),
alreadyTrainTime:Math.floor(Math.random()*100),
score:Math.floor(Math.random()*100),
}
})
return trainSituation
}
private async generateTrainSituations(probability: number = 0.7){
this.logger.log("Start generating train situations...")
const allTrainContents = await db.trainContent.findMany();
// 这里相当于两次遍历 找到没有parentID的即是
const leafNodes = allTrainContents.filter((item)=>item.parentId !== null)
console.log(leafNodes.length)
const staffs = await db.staff.findMany()
let situationCount = 0
const totalPossibleSituations = leafNodes.length * staffs.length
for (const staff of staffs){
for(const leaf of leafNodes){
if(Math.random() < probability){
await this.createTrainSituation(staff.id,leaf.id)
situationCount++
if (situationCount % 100 === 0) {
this.logger.log(
`Generated ${situationCount} train situations`
);
}
}
}
}
this.logger.log(
`Completed: Generated ${situationCount} train situations out of ${totalPossibleSituations} possible combinations.`
);
}
}

View File

@ -360,12 +360,20 @@ model TrainSituation {
trainContent TrainContent @relation(fields: [trainContentId], references: [id]) trainContent TrainContent @relation(fields: [trainContentId], references: [id])
score Float @default(0.0) @map("score") score Float @default(0.0) @map("score")
mustTrainTime String @map("must_train_time") mustTrainTime Float @map("must_train_time")
alreadyTrainTime String @map("already_train_time") alreadyTrainTime Float @map("already_train_time")
@@map("train_situation") @@map("train_situation")
} }
model DailyTrainTime {
id String @id @default(cuid())
trainTime Float @default(0.0)@map("trainTime")
createdAt DateTime @default(now()) @map("created_at")
@@map("daily_train_situation")
}
model Position { model Position {
id String @id @default(cuid()) @map("id") id String @id @default(cuid()) @map("id")
type String @map("type") type String @map("type")

View File

@ -135,3 +135,35 @@ export const lectureDetailSelect: Prisma.PostSelect = {
meta: true, meta: true,
}; };
export const trainSituationDetailSelect: Prisma.TrainSituationSelect = {
id: true,
staffId: true,
trainContentId: true,
mustTrainTime: true,
alreadyTrainTime: true,
score: true,
staff: {
select: {
id: true,
showname: true,
avatar: true,
department: {
select: {
id: true,
name: true,
},
},
age: true,
sex: true,
absent: true,
},
},
trainContent: {
select: {
id: true,
title: true,
},
},
};