diff --git a/apps/server/src/models/train-content/trainContent.controller.ts b/apps/server/src/models/train-content/trainContent.controller.ts new file mode 100644 index 0000000..4e9acbe --- /dev/null +++ b/apps/server/src/models/train-content/trainContent.controller.ts @@ -0,0 +1,9 @@ +import { Controller, UseGuards } from "@nestjs/common"; +import { TrainContentService } from "./trainContent.service"; +import { AuthGuard } from '@server/auth/auth.guard'; + +@Controller('train-content') +export class TrainContentController { + constructor(private readonly trainContentService: TrainContentService) {} + //@UseGuards(AuthGuard) +} \ No newline at end of file diff --git a/apps/server/src/models/train-content/trainContent.module.ts b/apps/server/src/models/train-content/trainContent.module.ts new file mode 100644 index 0000000..b436d0f --- /dev/null +++ b/apps/server/src/models/train-content/trainContent.module.ts @@ -0,0 +1,15 @@ +import { Module } from '@nestjs/common'; +import { TrainContentService } from './trainContent.service'; +import { StaffModule } from '../staff/staff.module'; +import { TrainContentController } from './trainContent.controller'; +import { TrainContentRouter } from './trainContent.router'; +import { TrpcService } from '@server/trpc/trpc.service'; + + +@Module({ + imports: [StaffModule], + controllers: [TrainContentController], + providers: [TrainContentService,TrainContentRouter,TrpcService], + exports: [TrainContentService,TrainContentRouter], +}) +export class TrainContentModule {} \ No newline at end of file diff --git a/apps/server/src/models/train-content/trainContent.router.ts b/apps/server/src/models/train-content/trainContent.router.ts new file mode 100644 index 0000000..cdb2b8f --- /dev/null +++ b/apps/server/src/models/train-content/trainContent.router.ts @@ -0,0 +1,16 @@ +import { Injectable } from "@nestjs/common"; +import { TrpcService } from "@server/trpc/trpc.service"; +import { TrainContentService } from "./trainContent.service"; + +@Injectable() +export class TrainContentRouter { + constructor( + private readonly trpc: TrpcService, + private readonly trainContentService: TrainContentService, + ) { } + + router = this.trpc.router({ + + }) + +} \ No newline at end of file diff --git a/apps/server/src/models/train-content/trainContent.service.ts b/apps/server/src/models/train-content/trainContent.service.ts new file mode 100644 index 0000000..8015cf2 --- /dev/null +++ b/apps/server/src/models/train-content/trainContent.service.ts @@ -0,0 +1,12 @@ +import { Injectable } from "@nestjs/common"; +import { BaseService } from "../base/base.service"; +import { db, ObjectType, Prisma, UserProfile } from "@nice/common"; + + +@Injectable() +export class TrainContentService extends BaseService { + constructor() { + super(db,ObjectType.TRAIN_CONTENT,true); + } + +} \ No newline at end of file diff --git a/apps/server/src/models/train-situation/trainSituation.controller.ts b/apps/server/src/models/train-situation/trainSituation.controller.ts new file mode 100644 index 0000000..94f9ad0 --- /dev/null +++ b/apps/server/src/models/train-situation/trainSituation.controller.ts @@ -0,0 +1,9 @@ +import { Controller, UseGuards } from "@nestjs/common"; +import { TrainSituationService } from "./trainSituation.service"; +import { AuthGuard } from '@server/auth/auth.guard'; + +@Controller('train-situation') +export class TrainSituationController { + constructor(private readonly trainContentService: TrainSituationService) {} + //@UseGuards(AuthGuard) +} \ No newline at end of file diff --git a/apps/server/src/models/train-situation/trainSituation.module.ts b/apps/server/src/models/train-situation/trainSituation.module.ts new file mode 100644 index 0000000..ae21bbd --- /dev/null +++ b/apps/server/src/models/train-situation/trainSituation.module.ts @@ -0,0 +1,15 @@ +import { Module } from '@nestjs/common'; +import { TrainSituationService } from './trainSituation.service'; +import { StaffModule } from '../staff/staff.module'; +import { TrainSituationController } from './trainSituation.controller'; +import { TrainSituationRouter } from './trainSituation.router'; +import { TrpcService } from '@server/trpc/trpc.service'; + + +@Module({ + imports: [StaffModule], + controllers: [TrainSituationController], + providers: [TrainSituationService,TrainSituationRouter,TrpcService], + exports: [TrainSituationService,TrainSituationRouter], +}) +export class TrainSituationModule {} \ No newline at end of file diff --git a/apps/server/src/models/train-situation/trainSituation.router.ts b/apps/server/src/models/train-situation/trainSituation.router.ts new file mode 100644 index 0000000..5cb374a --- /dev/null +++ b/apps/server/src/models/train-situation/trainSituation.router.ts @@ -0,0 +1,25 @@ +import { Injectable } from "@nestjs/common"; +import { TrpcService } from "@server/trpc/trpc.service"; +import { TrainSituationService } from "./trainSituation.service"; +import { z, ZodType } from "zod"; +import { Prisma } from "@nice/common"; + +const TrainSituationArgsSchema:ZodType = z.any() + + +@Injectable() +export class TrainSituationRouter { + constructor( + private readonly trpc: TrpcService, + private readonly trainSituationService: TrainSituationService, + ) { } + + router = this.trpc.router({ + create:this.trpc.protectProcedure + .input(TrainSituationArgsSchema) + .mutation(async ({ input }) => { + this.trainSituationService.create(input) + }), + }) + +} \ No newline at end of file diff --git a/apps/server/src/models/train-situation/trainSituation.service.ts b/apps/server/src/models/train-situation/trainSituation.service.ts new file mode 100644 index 0000000..1b54509 --- /dev/null +++ b/apps/server/src/models/train-situation/trainSituation.service.ts @@ -0,0 +1,28 @@ +import { Injectable } from "@nestjs/common"; +import { BaseService } from "../base/base.service"; +import { db, ObjectType, Prisma, UserProfile } from "@nice/common"; +import EventBus, { CrudOperation } from "@server/utils/event-bus"; + + +@Injectable() +export class TrainSituationService extends BaseService { + constructor() { + super(db,ObjectType.TRAIN_SITUATION,false); + } + async create( + args: Prisma.TrainSituationCreateArgs, + ){ + console.log(args) + const result = await super.create(args); + this.emitDataChanged(CrudOperation.CREATED, result); + return result; + } + + private emitDataChanged(operation: CrudOperation, data: any) { + EventBus.emit('dataChanged', { + type:ObjectType.TRAIN_SITUATION, + operation, + data, + }); + } +} \ No newline at end of file diff --git a/apps/server/src/tasks/init/gendev.service.ts b/apps/server/src/tasks/init/gendev.service.ts index e5c3f9f..441ef91 100755 --- a/apps/server/src/tasks/init/gendev.service.ts +++ b/apps/server/src/tasks/init/gendev.service.ts @@ -11,11 +11,14 @@ import { Staff, TaxonomySlug, Term, + TrainContent, } from '@nice/common'; import EventBus from '@server/utils/event-bus'; import { capitalizeFirstLetter, DevDataCounts, getCounts } from './utils'; import { StaffService } from '@server/models/staff/staff.service'; import dayjs from 'dayjs'; +import { TrainContentType } from '@nice/common'; + @Injectable() export class GenDevService { private readonly logger = new Logger(GenDevService.name); @@ -30,8 +33,10 @@ export class GenDevService { domains: Department[] = []; domainDepts: Record = {}; staffs: Staff[] = []; + trainContents: TrainContent[] = []; deptGeneratedCount = 0; courseGeneratedCount = 1; + trainContentGeneratedCount = 0; constructor( private readonly appConfigService: AppConfigService, @@ -47,6 +52,7 @@ export class GenDevService { await this.generateTerms(2, 6); await this.generateStaffs(4); await this.generateCourses(8); + await this.generateTrainContent(2,6) } catch (err) { this.logger.error(err); } @@ -338,4 +344,64 @@ export class GenDevService { await createTermTree(null, 1); } + + private async createTrainContent( + type:string, + title:string, + parentId:string|null + ){ + const trainContent = await db.trainContent.create({ + data: { + type, + title, + parentId + }, + }); + return trainContent; + } + + private async generateTrainContent(depth:number=3,count:number=6){ + if(this.counts.trainContentCount !== 0) return; + const totalTrainContent = this.calculateTotalTrainContent(depth,count) + this.logger.log("Start generating train content...") + await this.generateSubTrainContent(null,1,depth,count,totalTrainContent) + this.trainContents = await db.trainContent.findMany() + this.logger.log(`Completed: Generated ${this.trainContents.length} departments.`); + } + private async generateSubTrainContent( + parentId: string | null, + currentDepth:number, + maxDepth:number, + count:number, + total:number, + ){ + if(currentDepth > maxDepth) return; + const contentType = [TrainContentType.SUBJECTS,TrainContentType.COURSE] + for(let i = 0 ; i < count ; i++){ + const trainContentTitle = `${parentId?.slice(0,6) || '根'}公司${currentDepth}-${i}` + const newTrainContent = await this.createTrainContent( + contentType[currentDepth-1], + trainContentTitle, + parentId + ) + this.trainContentGeneratedCount++; + this.logger.log( + `Generated ${this.trainContentGeneratedCount}/${total} train contents` + ) + await this.generateSubTrainContent( + newTrainContent.id, + currentDepth+1, + maxDepth, + count, + total + ) + } + } + private calculateTotalTrainContent(depth:number,count:number):number{ + let total = 0; + for(let i = 1 ; i<=depth;i++){ + total += Math.pow(count,i); + } + return total; + } } diff --git a/apps/server/src/tasks/init/utils.ts b/apps/server/src/tasks/init/utils.ts index d55dcec..0126cc0 100755 --- a/apps/server/src/tasks/init/utils.ts +++ b/apps/server/src/tasks/init/utils.ts @@ -8,7 +8,7 @@ import { import dayjs from 'dayjs'; export interface DevDataCounts { deptCount: number; - + trainContentCount: number; staffCount: number; termCount: number; courseCount: number; @@ -16,7 +16,7 @@ export interface DevDataCounts { export async function getCounts(): Promise { const counts = { deptCount: await db.department.count(), - + trainContentCount:await db.trainContent.count(), staffCount: await db.staff.count(), termCount: await db.term.count(), courseCount: await db.post.count({ diff --git a/apps/server/src/trpc/trpc.module.ts b/apps/server/src/trpc/trpc.module.ts index 222c9c9..dff231d 100755 --- a/apps/server/src/trpc/trpc.module.ts +++ b/apps/server/src/trpc/trpc.module.ts @@ -14,8 +14,9 @@ import { VisitModule } from '@server/models/visit/visit.module'; import { WebSocketModule } from '@server/socket/websocket.module'; import { RoleMapModule } from '@server/models/rbac/rbac.module'; import { TransformModule } from '@server/models/transform/transform.module'; - +import { TrainContentModule } from '@server/models/train-content/trainContent.module'; import { ResourceModule } from '@server/models/resource/resource.module'; +import { TrainSituationModule } from '@server/models/train-situation/trainSituation.module'; @Module({ imports: [ @@ -33,6 +34,8 @@ import { ResourceModule } from '@server/models/resource/resource.module'; VisitModule, WebSocketModule, ResourceModule, + TrainContentModule, + TrainSituationModule ], controllers: [], providers: [TrpcService, TrpcRouter, Logger], diff --git a/apps/server/src/trpc/trpc.router.ts b/apps/server/src/trpc/trpc.router.ts index 7550867..4556791 100755 --- a/apps/server/src/trpc/trpc.router.ts +++ b/apps/server/src/trpc/trpc.router.ts @@ -14,6 +14,8 @@ import { RoleMapRouter } from '@server/models/rbac/rolemap.router'; import { TransformRouter } from '@server/models/transform/transform.router'; import { RoleRouter } from '@server/models/rbac/role.router'; import { ResourceRouter } from '../models/resource/resource.router'; +import { TrainContentRouter } from '@server/models/train-content/trainContent.router'; +import { TrainSituationRouter } from '@server/models/train-situation/trainSituation.router'; @Injectable() export class TrpcRouter { @@ -32,6 +34,8 @@ export class TrpcRouter { private readonly message: MessageRouter, private readonly visitor: VisitRouter, private readonly resource: ResourceRouter, + private readonly trainContent: TrainContentRouter, + private readonly trainSituation:TrainSituationRouter, ) {} getRouter() { return; @@ -49,6 +53,8 @@ export class TrpcRouter { app_config: this.app_config.router, visitor: this.visitor.router, resource: this.resource.router, + trainContent:this.trainContent.router, + trainSituation:this.trainSituation.router }); wss: WebSocketServer = undefined; diff --git a/apps/web/src/app/main/home/components/CategorySection.tsx b/apps/web/src/app/main/home/components/CategorySection.tsx index 6630e1b..7bddcf2 100755 --- a/apps/web/src/app/main/home/components/CategorySection.tsx +++ b/apps/web/src/app/main/home/components/CategorySection.tsx @@ -1,11 +1,12 @@ import React, { useState, useCallback, useEffect, useMemo } from "react"; import { Typography, Skeleton } from "antd"; import { stringToColor, TaxonomySlug, TermDto } from "@nice/common"; -import { api } from "@nice/client"; +import { api, useTrainSituation } from "@nice/client"; import LookForMore from "./LookForMore"; import CategorySectionCard from "./CategorySectionCard"; import { useNavigate } from "react-router-dom"; import { useMainContext } from "../../layout/MainProvider"; +import { useAuth } from "@web/src/providers/auth-provider"; const { Title, Text } = Typography; const CategorySection = () => { @@ -41,6 +42,26 @@ const CategorySection = () => { navigate("/courses"); window.scrollTo({ top: 0, behavior: "smooth" }); }, []); + + + const {user} = useAuth() + const {create} = useTrainSituation() + useEffect(() => { + if (user?.id) { + create.mutate({ + data: { + //staffId: user.id, // 确保类型匹配 + mustTrainTime: "1", + alreadyTrainTime: "1", + //trainContentId: "cm83w52dr00ff3jc8ep4uf4a4", + staff: { connect: { id: user.id } }, + trainContent: { connect: { id: "cm847lcc805ne123v81l5h13e" } } + } + }); + console.log("create score time") + } + }, []); + return (
diff --git a/apps/web/src/app/main/home/components/HeroSection.tsx b/apps/web/src/app/main/home/components/HeroSection.tsx index f4c21fd..07b775e 100755 --- a/apps/web/src/app/main/home/components/HeroSection.tsx +++ b/apps/web/src/app/main/home/components/HeroSection.tsx @@ -15,7 +15,7 @@ import { EyeOutlined, } from "@ant-design/icons"; import type { CarouselRef } from "antd/es/carousel"; -import { useAppConfig } from "@nice/client"; +import { api, useAppConfig } from "@nice/client"; import { useNavigate } from "react-router-dom"; interface PlatformStat { @@ -70,6 +70,13 @@ const HeroSection = () => { console.log(count); setCountStatistics(count); }, [statistics]); + + + + + + + return (
diff --git a/config/nginx/conf.d/web.conf b/config/nginx/conf.d/web.conf index 88fa2c9..8f5da09 100755 --- a/config/nginx/conf.d/web.conf +++ b/config/nginx/conf.d/web.conf @@ -2,7 +2,7 @@ server { # 监听80端口 listen 80; # 服务器域名/IP地址,使用环境变量 - server_name host.docker.internal; + server_name 192.168.43.206; # 基础性能优化配置 # 启用tcp_nopush以优化数据发送 @@ -100,7 +100,7 @@ server { # 仅供内部使用 internal; # 代理到认证服务 - proxy_pass http://host.docker.internal:3006/auth/file; + proxy_pass http://192.168.43.206:3001/auth/file; # 请求优化:不传递请求体 proxy_pass_request_body off; diff --git a/packages/client/src/api/hooks/index.ts b/packages/client/src/api/hooks/index.ts index 73b516d..3f8b54a 100755 --- a/packages/client/src/api/hooks/index.ts +++ b/packages/client/src/api/hooks/index.ts @@ -10,3 +10,4 @@ export * from "./useVisitor" export * from "./useMessage" export * from "./usePost" export * from "./useEntity" +export * from "./useTrainSituation" diff --git a/packages/client/src/api/hooks/useTrainSituation.ts b/packages/client/src/api/hooks/useTrainSituation.ts new file mode 100644 index 0000000..441e113 --- /dev/null +++ b/packages/client/src/api/hooks/useTrainSituation.ts @@ -0,0 +1,23 @@ +import { getQueryKey } from "@trpc/react-query"; +import { api } from "../trpc"; // Adjust path as necessary +import { useQueryClient } from "@tanstack/react-query"; +import { ObjectType, Staff } from "@nice/common"; +import { findQueryData } from "../utils"; +import { CrudOperation, emitDataChange } from "../../event"; + + +export function useTrainSituation(){ + const queryClient = useQueryClient(); + const queryKey = getQueryKey(api.trainSituation); + + const create = api.trainSituation.create.useMutation({ + onSuccess: (res:any) => { + queryClient.invalidateQueries({ queryKey }); + emitDataChange(ObjectType.TRAIN_SITUATION, res, CrudOperation.CREATED); + }, + }); + + return { + create + } +} \ No newline at end of file diff --git a/packages/common/prisma/schema.prisma b/packages/common/prisma/schema.prisma index fc3118e..66d7ef4 100755 --- a/packages/common/prisma/schema.prisma +++ b/packages/common/prisma/schema.prisma @@ -67,80 +67,9 @@ model TermAncestry { @@map("term_ancestry") } -model Staff { - id String @id @default(cuid()) - showname String? @map("showname") - username String @unique @map("username") - avatar String? @map("avatar") - password String? @map("password") - phoneNumber String? @unique @map("phone_number") - age Int? @map("age") - sex Boolean? @map("sex") - absent Boolean? @map("absent") - - domainId String? @map("domain_id") - deptId String? @map("dept_id") - - domain Department? @relation("DomainStaff", fields: [domainId], references: [id]) - department Department? @relation("DeptStaff", fields: [deptId], references: [id]) - order Float? - - createdAt DateTime @default(now()) @map("created_at") - updatedAt DateTime @updatedAt @map("updated_at") - enabled Boolean? @default(true) - deletedAt DateTime? @map("deleted_at") - officerId String? @map("officer_id") - - // watchedPost Post[] @relation("post_watch_staff") - visits Visit[] - posts Post[] - learningPosts Post[] @relation("post_student") - sentMsgs Message[] @relation("message_sender") - receivedMsgs Message[] @relation("message_receiver") - registerToken String? - enrollments Enrollment[] - teachedPosts PostInstructor[] - ownedResources Resource[] - traincontent TrainContent[] @relation("StaffTrainContent") - - @@index([officerId]) - @@index([deptId]) - @@index([domainId]) - @@index([username]) - @@index([order]) - @@map("staff") -} - -model Department { - id String @id @default(cuid()) - name String - order Float? - posts Post[] @relation("post_dept") - ancestors DeptAncestry[] @relation("DescendantToAncestor") - descendants DeptAncestry[] @relation("AncestorToDescendant") - parentId String? @map("parent_id") - parent Department? @relation("ChildParent", fields: [parentId], references: [id]) - children Department[] @relation("ChildParent") - domainId String? @map("domain_id") - domainTerms Term[] @relation("TermDom") - deletedAt DateTime? @map("deleted_at") - isDomain Boolean? @default(false) @map("is_domain") - domainStaffs Staff[] @relation("DomainStaff") - deptStaffs Staff[] @relation("DeptStaff") - terms Term[] @relation("department_term") - - // watchedPost Post[] @relation("post_watch_dept") - hasChildren Boolean? @default(false) @map("has_children") - - @@index([parentId]) - @@index([isDomain]) - @@index([name]) - @@index([order]) - @@map("department") -} model DeptAncestry { id String @id @default(cuid()) @@ -196,45 +125,45 @@ model AppConfig { model Post { // 字符串类型字段 - id String @id @default(cuid()) // 帖子唯一标识,使用 cuid() 生成默认值 - type String? // Post类型,课程、章节、小节、讨论都用Post实现 - level String? - state String? - title String? // 帖子标题,可为空 - subTitle String? - content String? // 帖子内容,可为空 - important Boolean? //是否重要/精选/突出 - domainId String? @map("domain_id") - terms Term[] @relation("post_term") - order Float? @default(0) @map("order") - duration Int? - rating Int? @default(0) - students Staff[] @relation("post_student") - depts Department[] @relation("post_dept") - views Int @default(0) @map("views") - hates Int @default(0) @map("hates") - likes Int @default(0) @map("likes") + id String @id @default(cuid()) // 帖子唯一标识,使用 cuid() 生成默认值 + type String? // Post类型,课程、章节、小节、讨论都用Post实现 + level String? + state String? + title String? // 帖子标题,可为空 + subTitle String? + content String? // 帖子内容,可为空 + important Boolean? //是否重要/精选/突出 + domainId String? @map("domain_id") + terms Term[] @relation("post_term") + order Float? @default(0) @map("order") + duration Int? + rating Int? @default(0) + students Staff[] @relation("post_student") + depts Department[] @relation("post_dept") + views Int @default(0) @map("views") + hates Int @default(0) @map("hates") + likes Int @default(0) @map("likes") // 索引 // 日期时间类型字段 - createdAt DateTime @default(now()) @map("created_at") - publishedAt DateTime? @map("published_at") // 发布时间 - updatedAt DateTime @map("updated_at") - deletedAt DateTime? @map("deleted_at") // 删除时间,可为空 - instructors PostInstructor[] + createdAt DateTime @default(now()) @map("created_at") + publishedAt DateTime? @map("published_at") // 发布时间 + updatedAt DateTime @map("updated_at") + deletedAt DateTime? @map("deleted_at") // 删除时间,可为空 + instructors PostInstructor[] // 关系类型字段 - authorId String? @map("author_id") - author Staff? @relation(fields: [authorId], references: [id]) // 帖子作者,关联 Staff 模型 - enrollments Enrollment[] // 学生报名记录 - visits Visit[] // 访问记录,关联 Visit 模型 - parentId String? @map("parent_id") - parent Post? @relation("PostChildren", fields: [parentId], references: [id]) // 父级帖子,关联 Post 模型 - children Post[] @relation("PostChildren") // 子级帖子列表,关联 Post 模型 - hasChildren Boolean? @default(false) @map("has_children") + authorId String? @map("author_id") + author Staff? @relation(fields: [authorId], references: [id]) // 帖子作者,关联 Staff 模型 + enrollments Enrollment[] // 学生报名记录 + visits Visit[] // 访问记录,关联 Visit 模型 + parentId String? @map("parent_id") + parent Post? @relation("PostChildren", fields: [parentId], references: [id]) // 父级帖子,关联 Post 模型 + children Post[] @relation("PostChildren") // 子级帖子列表,关联 Post 模型 + hasChildren Boolean? @default(false) @map("has_children") // 闭包表关系 - ancestors PostAncestry[] @relation("DescendantPosts") - descendants PostAncestry[] @relation("AncestorPosts") - resources Resource[] // 附件列表 - meta Json? // 封面url 视频url objectives具体的学习目标 rating评分Int + ancestors PostAncestry[] @relation("DescendantPosts") + descendants PostAncestry[] @relation("AncestorPosts") + resources Resource[] // 附件列表 + meta Json? // 封面url 视频url objectives具体的学习目标 rating评分Int // 索引 @@index([type, domainId]) @@ -252,12 +181,13 @@ model Post { } model PostAncestry { - id String @id @default(cuid()) - ancestorId String? @map("ancestor_id") - descendantId String @map("descendant_id") - relDepth Int @map("rel_depth") - ancestor Post? @relation("AncestorPosts", fields: [ancestorId], references: [id]) - descendant Post @relation("DescendantPosts", fields: [descendantId], references: [id]) + id String @id @default(cuid()) + ancestorId String? @map("ancestor_id") + descendantId String @map("descendant_id") + relDepth Int @map("rel_depth") + ancestor Post? @relation("AncestorPosts", fields: [ancestorId], references: [id]) + descendant Post @relation("DescendantPosts", fields: [descendantId], references: [id]) + // 复合索引优化 // 索引建议 @@index([ancestorId]) // 针对祖先的查询 @@ -281,23 +211,24 @@ model Message { visits Visit[] createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime? @updatedAt @map("updated_at") + @@index([type, createdAt]) @@map("message") } model Visit { - id String @id @default(cuid()) @map("id") + id String @id @default(cuid()) @map("id") type String? - views Int @default(1) @map("views") + views Int @default(1) @map("views") // sourceIP String? @map("source_ip") // 关联关系 visitorId String? @map("visitor_id") visitor Staff? @relation(fields: [visitorId], references: [id]) - postId String? @map("post_id") - post Post? @relation(fields: [postId], references: [id]) - message Message? @relation(fields: [messageId], references: [id]) - messageId String? @map("message_id") - lectureId String? @map("lecture_id") // 课时ID + postId String? @map("post_id") + post Post? @relation(fields: [postId], references: [id]) + message Message? @relation(fields: [messageId], references: [id]) + messageId String? @map("message_id") + lectureId String? @map("lecture_id") // 课时ID createdAt DateTime @default(now()) @map("created_at") // 创建时间 updatedAt DateTime @updatedAt @map("updated_at") // 更新时间 deletedAt DateTime? @map("deleted_at") // 删除时间,可为空 @@ -408,44 +339,127 @@ model NodeEdge { @@index([targetId]) @@map("node_edge") } -model Animal { - id String @id @default(cuid()) - name String - age Int - gender Boolean - personId String? - person Person? @relation(fields: [personId], references: [id]) -} -model Person { - id String @id @default(cuid()) - name String - age Int - gender Boolean - animals Animal[] -} + + + + + + + model TrainContent { - id String @id @default(cuid()) - title String @map("title") - score Float? @map("score") - mustTrainTime String @map("must_train_time") - alreadyTrainTime String @map("already_train_time") - - type String @map("type") - - parentId String? @map("parent_id") - parent TrainContent? @relation("ContentParent", fields: [parentId], references: [id]) // 指向自身 - children TrainContent[] @relation("ContentParent") // 指向自身 - - staff Staff[] @relation("StaffTrainContent") - - - deletedAt DateTime? @map("deleted_at") - createdAt DateTime @default(now()) @map("created_at") - updatedAt DateTime @updatedAt @map("updated_at") + id String @id @default(cuid()) + title String @map("title") + trainSituations TrainSituation[] + type String @map("type") + parentId String? @map("parent_id") + parent TrainContent? @relation("ContentParent", fields: [parentId], references: [id]) // 指向自身 + children TrainContent[] @relation("ContentParent") // 指向自身 + deletedAt DateTime? @map("deleted_at") + createdAt DateTime @default(now()) @map("created_at") + updatedAt DateTime @updatedAt @map("updated_at") @@map("train_content") +} + +model TrainSituation { + id String @id @default(cuid()) + staffId String @map("staff_id") + staff Staff @relation(fields: [staffId], references: [id]) + trainContentId String @map("train_content_id") + trainContent TrainContent @relation(fields: [trainContentId], references: [id]) + + mustTrainTime String @map("must_train_time") + alreadyTrainTime String @map("already_train_time") + @@map("train_situation") +} + +model Position { + id String @id @default(cuid()) @map("id") + type String @map("type") + + staff Staff[] @relation("StaffPosition") + createdAt DateTime @default(now()) @map("created_at") + updatedAt DateTime @updatedAt @map("updated_at") + + @@map("position") +} + +model Department { + id String @id @default(cuid()) + name String + order Float? + posts Post[] @relation("post_dept") + ancestors DeptAncestry[] @relation("DescendantToAncestor") + descendants DeptAncestry[] @relation("AncestorToDescendant") + parentId String? @map("parent_id") + parent Department? @relation("ChildParent", fields: [parentId], references: [id]) + children Department[] @relation("ChildParent") + domainId String? @map("domain_id") + domainTerms Term[] @relation("TermDom") + deletedAt DateTime? @map("deleted_at") + isDomain Boolean? @default(false) @map("is_domain") + domainStaffs Staff[] @relation("DomainStaff") + deptStaffs Staff[] @relation("DeptStaff") + terms Term[] @relation("department_term") + + // watchedPost Post[] @relation("post_watch_dept") + hasChildren Boolean? @default(false) @map("has_children") + + @@index([parentId]) + @@index([isDomain]) + @@index([name]) + @@index([order]) + @@map("department") +} + +model Staff { + id String @id @default(cuid()) + showname String? @map("showname") + username String @unique @map("username") + avatar String? @map("avatar") + password String? @map("password") + phoneNumber String? @unique @map("phone_number") + age Int? @map("age") + sex Boolean? @map("sex") + absent Boolean? @map("absent") + + trainSituations TrainSituation[] + position Position? @relation("StaffPosition", fields: [positionId], references: [id]) + positionId String? @map("position_id") + + domainId String? @map("domain_id") + deptId String? @map("dept_id") + + domain Department? @relation("DomainStaff", fields: [domainId], references: [id]) + department Department? @relation("DeptStaff", fields: [deptId], references: [id]) + order Float? + + createdAt DateTime @default(now()) @map("created_at") + updatedAt DateTime @updatedAt @map("updated_at") + enabled Boolean? @default(true) + deletedAt DateTime? @map("deleted_at") + officerId String? @map("officer_id") + + // watchedPost Post[] @relation("post_watch_staff") + visits Visit[] + posts Post[] + + learningPosts Post[] @relation("post_student") + sentMsgs Message[] @relation("message_sender") + receivedMsgs Message[] @relation("message_receiver") + registerToken String? + enrollments Enrollment[] + teachedPosts PostInstructor[] + ownedResources Resource[] + + @@index([officerId]) + @@index([deptId]) + @@index([domainId]) + @@index([username]) + @@index([order]) + @@map("staff") } \ No newline at end of file diff --git a/packages/common/src/enum.ts b/packages/common/src/enum.ts index 309ef6d..9028b44 100755 --- a/packages/common/src/enum.ts +++ b/packages/common/src/enum.ts @@ -59,6 +59,8 @@ export enum ObjectType { LECTURE = "lecture", ENROLLMENT = "enrollment", RESOURCE = "resource", + TRAIN_CONTENT = "trainContent", + TRAIN_SITUATION = "trainSituation" } export enum RolePerms { // Create Permissions 创建权限 @@ -201,3 +203,8 @@ export const LessonTypeLabel = { [LessonType.QUIZ]: "测验", [LessonType.ASSIGNMENT]: "作业", }; + +export enum TrainContentType { + SUBJECTS = "科目", + COURSE = "课目" +} \ No newline at end of file