library-picturebook-activity/backend/prisma/schema.prisma
zhangxiaohua f6b292bebf 新增预设评语功能及评审相关优化
- 新增预设评语表(PresetComment)及相关API
- 新增预设评语管理页面
- 优化评审作品弹框,支持预设评语选择
- 优化赛果发布列表页面
- 更新路由和菜单配置

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-23 14:46:25 +08:00

1126 lines
62 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
}
/// 租户表
model Tenant {
id Int @id @default(autoincrement())
name String /// 租户名称
code String @unique /// 租户编码(唯一,用于访问链接)
domain String? @unique /// 租户域名(可选,用于子域名访问)
description String? /// 租户描述
isSuper Int @default(0) @map("is_super") /// 是否为超级租户0-否1-是
validState Int @default(1) @map("valid_state") /// 有效状态1-有效2-失效
creator Int? /// 创建人ID超级租户的用户ID
modifier Int? /// 修改人ID
createTime DateTime @default(now()) @map("create_time") /// 创建时间
modifyTime DateTime @updatedAt @map("modify_time") /// 修改时间
users User[]
roles Role[]
menus TenantMenu[]
permissions Permission[]
dicts Dict[]
configs Config[]
school School? /// 学校信息(一对一)
grades Grade[] /// 年级
departments Department[] /// 部门
classes Class[] /// 班级
teachers Teacher[] /// 教师
students Student[] /// 学生
contestTeams ContestTeam[] /// 赛事团队
contestTeamMembers ContestTeamMember[] /// 团队成员
contestRegistrations ContestRegistration[] /// 赛事报名
contestRegistrationTeachers ContestRegistrationTeacher[] /// 报名指导老师关联
contestWorks ContestWork[] /// 参赛作品
contestWorkAttachments ContestWorkAttachment[] /// 作品附件
contestWorkScores ContestWorkScore[] /// 作品评分
contestReviewRules ContestReviewRule[] /// 评审规则
// 作业管理关联
homeworks Homework[] /// 作业
homeworkSubmissions HomeworkSubmission[] /// 作业提交记录
homeworkReviewRules HomeworkReviewRule[] /// 作业评审规则
homeworkScores HomeworkScore[] /// 作业评分
// AI 3D 生成关联
ai3dTasks AI3DTask[] /// AI 3D 生成任务
creatorUser User? @relation("TenantCreator", fields: [creator], references: [id], onDelete: SetNull)
modifierUser User? @relation("TenantModifier", fields: [modifier], references: [id], onDelete: SetNull)
@@map("tenants")
}
/// 用户表
model User {
id Int @id @default(autoincrement())
tenantId Int @map("tenant_id") /// 租户ID
username String /// 用户名(在租户内唯一)
password String /// 密码(加密存储)
nickname String /// 昵称
email String? /// 邮箱(在租户内唯一,可选)
phone String? /// 联系方式/手机号
gender String? /// 性别male-男female-女
avatar String? /// 头像URL
organization String? /// 所属单位(用于评委等独立用户)
status String @default("enabled") /// 账号状态enabled-启用disabled-停用
validState Int @default(1) @map("valid_state") /// 有效状态1-有效2-失效
creator Int? @map("creator") /// 创建人ID
modifier Int? @map("modifier") /// 修改人ID
createTime DateTime @default(now()) @map("create_time") /// 创建时间
modifyTime DateTime @updatedAt @map("modify_time") /// 修改时间
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
roles UserRole[]
logs Log[]
createdBy User? @relation("UserCreator", fields: [creator], references: [id], onDelete: SetNull)
modifiedBy User? @relation("UserModifier", fields: [modifier], references: [id], onDelete: SetNull)
createdUsers User[] @relation("UserCreator")
modifiedUsers User[] @relation("UserModifier")
createdRoles Role[] @relation("RoleCreator")
modifiedRoles Role[] @relation("RoleModifier")
createdPermissions Permission[] @relation("PermissionCreator")
modifiedPermissions Permission[] @relation("PermissionModifier")
createdMenus Menu[] @relation("MenuCreator")
modifiedMenus Menu[] @relation("MenuModifier")
createdDicts Dict[] @relation("DictCreator")
modifiedDicts Dict[] @relation("DictModifier")
createdDictItems DictItem[] @relation("DictItemCreator")
modifiedDictItems DictItem[] @relation("DictItemModifier")
createdConfigs Config[] @relation("ConfigCreator")
modifiedConfigs Config[] @relation("ConfigModifier")
createdTenants Tenant[] @relation("TenantCreator")
modifiedTenants Tenant[] @relation("TenantModifier")
teacher Teacher? /// 教师信息(一对一)
student Student? /// 学生信息(一对一)
createdSchools School[] @relation("SchoolCreator")
modifiedSchools School[] @relation("SchoolModifier")
createdGrades Grade[] @relation("GradeCreator")
modifiedGrades Grade[] @relation("GradeModifier")
createdDepartments Department[] @relation("DepartmentCreator")
modifiedDepartments Department[] @relation("DepartmentModifier")
createdClasses Class[] @relation("ClassCreator")
modifiedClasses Class[] @relation("ClassModifier")
createdTeachers Teacher[] @relation("TeacherCreator")
modifiedTeachers Teacher[] @relation("TeacherModifier")
createdStudents Student[] @relation("StudentCreator")
modifiedStudents Student[] @relation("StudentModifier")
// 赛事相关关联
createdContests Contest[] @relation("ContestCreator")
modifiedContests Contest[] @relation("ContestModifier")
createdContestAttachments ContestAttachment[] @relation("ContestAttachmentCreator")
modifiedContestAttachments ContestAttachment[] @relation("ContestAttachmentModifier")
createdContestReviewRules ContestReviewRule[] @relation("ContestReviewRuleCreator")
modifiedContestReviewRules ContestReviewRule[] @relation("ContestReviewRuleModifier")
createdContestTeams ContestTeam[] @relation("ContestTeamCreator")
modifiedContestTeams ContestTeam[] @relation("ContestTeamModifier")
ledContestTeams ContestTeam[] @relation("ContestTeamLeader")
createdContestTeamMembers ContestTeamMember[] @relation("ContestTeamMemberCreator")
modifiedContestTeamMembers ContestTeamMember[] @relation("ContestTeamMemberModifier")
contestTeamMembers ContestTeamMember[] @relation("ContestTeamMemberUser")
createdContestRegistrations ContestRegistration[] @relation("ContestRegistrationCreator")
modifiedContestRegistrations ContestRegistration[] @relation("ContestRegistrationModifier")
contestRegistrations ContestRegistration[] @relation("ContestRegistrationUser")
createdContestWorks ContestWork[] @relation("ContestWorkCreator")
modifiedContestWorks ContestWork[] @relation("ContestWorkModifier")
createdContestWorkAttachments ContestWorkAttachment[] @relation("ContestWorkAttachmentCreator")
modifiedContestWorkAttachments ContestWorkAttachment[] @relation("ContestWorkAttachmentModifier")
createdContestWorkJudgeAssignments ContestWorkJudgeAssignment[] @relation("ContestWorkJudgeAssignmentCreator")
modifiedContestWorkJudgeAssignments ContestWorkJudgeAssignment[] @relation("ContestWorkJudgeAssignmentModifier")
assignedContestWorks ContestWorkJudgeAssignment[] @relation("ContestWorkJudgeAssignmentJudge")
createdContestWorkScores ContestWorkScore[] @relation("ContestWorkScoreCreator")
modifiedContestWorkScores ContestWorkScore[] @relation("ContestWorkScoreModifier")
scoredContestWorks ContestWorkScore[] @relation("ContestWorkScoreJudge")
createdContestNotices ContestNotice[] @relation("ContestNoticeCreator")
modifiedContestNotices ContestNotice[] @relation("ContestNoticeModifier")
contestJudges ContestJudge[] @relation("ContestJudgeUser")
createdContestJudges ContestJudge[] @relation("ContestJudgeCreator")
modifiedContestJudges ContestJudge[] @relation("ContestJudgeModifier")
contestRegistrationTeachers ContestRegistrationTeacher[] @relation("ContestRegistrationTeacherUser")
createdContestRegistrationTeachers ContestRegistrationTeacher[] @relation("ContestRegistrationTeacherCreator")
modifiedContestRegistrationTeachers ContestRegistrationTeacher[] @relation("ContestRegistrationTeacherModifier")
// 作业管理关联
createdHomeworks Homework[] @relation("HomeworkCreator")
modifiedHomeworks Homework[] @relation("HomeworkModifier")
homeworkSubmissions HomeworkSubmission[] @relation("HomeworkSubmissionStudent")
createdHomeworkSubmissions HomeworkSubmission[] @relation("HomeworkSubmissionCreator")
modifiedHomeworkSubmissions HomeworkSubmission[] @relation("HomeworkSubmissionModifier")
createdHomeworkReviewRules HomeworkReviewRule[] @relation("HomeworkReviewRuleCreator")
modifiedHomeworkReviewRules HomeworkReviewRule[] @relation("HomeworkReviewRuleModifier")
homeworkScoresAsReviewer HomeworkScore[] @relation("HomeworkScoreReviewer")
createdHomeworkScores HomeworkScore[] @relation("HomeworkScoreCreator")
modifiedHomeworkScores HomeworkScore[] @relation("HomeworkScoreModifier")
// AI 3D 生成关联
ai3dTasks AI3DTask[] @relation("AI3DTaskUser") /// 用户的 AI 3D 生成任务
// 预设评语关联
presetComments PresetComment[] @relation("PresetCommentJudge") /// 评委的预设评语
@@unique([tenantId, username])
@@unique([tenantId, email])
@@map("users")
}
/// 角色表
model Role {
id Int @id @default(autoincrement())
tenantId Int @map("tenant_id") /// 租户ID
name String /// 角色名称(在租户内唯一)
code String /// 角色编码(在租户内唯一)
description String? /// 角色描述
validState Int @default(1) @map("valid_state") /// 有效状态1-有效2-失效
creator Int? /// 创建人ID
modifier Int? /// 修改人ID
createTime DateTime @default(now()) @map("create_time") /// 创建时间
modifyTime DateTime @updatedAt @map("modify_time") /// 修改时间
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
users UserRole[]
permissions RolePermission[]
creatorUser User? @relation("RoleCreator", fields: [creator], references: [id], onDelete: SetNull)
modifierUser User? @relation("RoleModifier", fields: [modifier], references: [id], onDelete: SetNull)
@@unique([tenantId, name])
@@unique([tenantId, code])
@@map("roles")
}
/// 用户角色关联表
model UserRole {
id Int @id @default(autoincrement())
userId Int @map("user_id") /// 用户ID
roleId Int @map("role_id") /// 角色ID
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
role Role @relation(fields: [roleId], references: [id], onDelete: Cascade)
@@unique([userId, roleId])
@@map("user_roles")
}
/// 权限表
model Permission {
id Int @id @default(autoincrement())
tenantId Int @map("tenant_id") /// 租户ID
name String /// 权限名称
code String /// 权限编码(在租户内唯一)
resource String /// 资源名称,如 user, role, menu
action String /// 操作类型,如 create, read, update, delete
description String? /// 权限描述
validState Int @default(1) @map("valid_state") /// 有效状态1-有效2-失效
creator Int? /// 创建人ID
modifier Int? /// 修改人ID
createTime DateTime @default(now()) @map("create_time") /// 创建时间
modifyTime DateTime @updatedAt @map("modify_time") /// 修改时间
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
roles RolePermission[]
creatorUser User? @relation("PermissionCreator", fields: [creator], references: [id], onDelete: SetNull)
modifierUser User? @relation("PermissionModifier", fields: [modifier], references: [id], onDelete: SetNull)
@@unique([tenantId, resource, action])
@@unique([tenantId, code])
@@map("permissions")
}
/// 角色权限关联表
model RolePermission {
id Int @id @default(autoincrement())
roleId Int @map("role_id") /// 角色ID
permissionId Int @map("permission_id") /// 权限ID
role Role @relation(fields: [roleId], references: [id], onDelete: Cascade)
permission Permission @relation(fields: [permissionId], references: [id], onDelete: Cascade)
@@unique([roleId, permissionId])
@@map("role_permissions")
}
/// 菜单表(全局菜单模板,超级租户管理)
model Menu {
id Int @id @default(autoincrement())
name String /// 菜单名称
path String? /// 路由路径
icon String? /// 图标
component String? /// 组件路径
parentId Int? @map("parent_id") /// 父菜单ID
permission String? /// 权限编码用于控制菜单显示menu:read
sort Int @default(0) /// 排序
validState Int @default(1) @map("valid_state") /// 有效状态1-有效2-失效
creator Int? @map("creator") /// 创建人ID
modifier Int? @map("modifier") /// 修改人ID
createTime DateTime @default(now()) @map("create_time") /// 创建时间
modifyTime DateTime @updatedAt @map("modify_time") /// 修改时间
parent Menu? @relation("MenuTree", fields: [parentId], references: [id])
children Menu[] @relation("MenuTree")
tenantMenus TenantMenu[] /// 租户菜单关联
creatorUser User? @relation("MenuCreator", fields: [creator], references: [id], onDelete: SetNull)
modifierUser User? @relation("MenuModifier", fields: [modifier], references: [id], onDelete: SetNull)
@@map("menus")
}
/// 租户菜单关联表(租户分配的菜单)
model TenantMenu {
id Int @id @default(autoincrement())
tenantId Int @map("tenant_id") /// 租户ID
menuId Int @map("menu_id") /// 菜单ID
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
menu Menu @relation(fields: [menuId], references: [id], onDelete: Cascade)
@@unique([tenantId, menuId])
@@map("tenant_menus")
}
/// 数据字典表
model Dict {
id Int @id @default(autoincrement())
tenantId Int @map("tenant_id") /// 租户ID
name String /// 字典名称
code String /// 字典编码(在租户内唯一)
description String? /// 字典描述
validState Int @default(1) @map("valid_state") /// 有效状态1-有效2-失效
creator Int? /// 创建人ID
modifier Int? /// 修改人ID
createTime DateTime @default(now()) @map("create_time") /// 创建时间
modifyTime DateTime @updatedAt @map("modify_time") /// 修改时间
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
items DictItem[]
creatorUser User? @relation("DictCreator", fields: [creator], references: [id], onDelete: SetNull)
modifierUser User? @relation("DictModifier", fields: [modifier], references: [id], onDelete: SetNull)
@@unique([tenantId, code])
@@map("dicts")
}
/// 字典项表
model DictItem {
id Int @id @default(autoincrement())
dictId Int @map("dict_id") /// 字典ID
label String /// 标签
value String /// 值
sort Int @default(0) /// 排序
validState Int @default(1) @map("valid_state") /// 有效状态1-有效2-失效
creator Int? @map("creator") /// 创建人ID
modifier Int? @map("modifier") /// 修改人ID
createTime DateTime @default(now()) @map("create_time") /// 创建时间
modifyTime DateTime @updatedAt @map("modify_time") /// 修改时间
dict Dict @relation(fields: [dictId], references: [id], onDelete: Cascade)
creatorUser User? @relation("DictItemCreator", fields: [creator], references: [id], onDelete: SetNull)
modifierUser User? @relation("DictItemModifier", fields: [modifier], references: [id], onDelete: SetNull)
@@map("dict_items")
}
/// 系统配置表
model Config {
id Int @id @default(autoincrement())
tenantId Int @map("tenant_id") /// 租户ID
key String /// 配置键(在租户内唯一)
value String /// 配置值
description String? /// 配置描述
creator Int? /// 创建人ID
modifier Int? /// 修改人ID
createTime DateTime @default(now()) @map("create_time") /// 创建时间
modifyTime DateTime @updatedAt @map("modify_time") /// 修改时间
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
creatorUser User? @relation("ConfigCreator", fields: [creator], references: [id], onDelete: SetNull)
modifierUser User? @relation("ConfigModifier", fields: [modifier], references: [id], onDelete: SetNull)
@@unique([tenantId, key])
@@map("configs")
}
/// 日志记录表
model Log {
id Int @id @default(autoincrement())
userId Int? @map("user_id") /// 用户ID
action String /// 操作类型
content String? @db.Text /// 操作内容(使用 TEXT 类型支持长文本)
ip String? /// IP地址
userAgent String? @map("user_agent") /// 用户代理
createTime DateTime @default(now()) @map("create_time") /// 创建时间
user User? @relation(fields: [userId], references: [id], onDelete: SetNull)
@@map("logs")
}
/// 学校信息表(扩展租户信息)
model School {
id Int @id @default(autoincrement())
tenantId Int @unique @map("tenant_id") /// 租户ID一对一
address String? /// 学校地址
phone String? /// 联系电话
principal String? /// 校长姓名
established DateTime? /// 建校时间
description String? @db.Text /// 学校描述
logo String? /// 学校Logo URL
website String? /// 学校网站
creator Int? /// 创建人ID
modifier Int? /// 修改人ID
createTime DateTime @default(now()) @map("create_time") /// 创建时间
modifyTime DateTime @updatedAt @map("modify_time") /// 修改时间
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
creatorUser User? @relation("SchoolCreator", fields: [creator], references: [id], onDelete: SetNull)
modifierUser User? @relation("SchoolModifier", fields: [modifier], references: [id], onDelete: SetNull)
@@map("schools")
}
/// 年级表
model Grade {
id Int @id @default(autoincrement())
tenantId Int @map("tenant_id") /// 租户ID
name String /// 年级名称(如:一年级、二年级)
code String /// 年级编码在租户内唯一grade_1, grade_2
level Int /// 年级级别用于排序1, 2, 3
description String? /// 年级描述
validState Int @default(1) @map("valid_state") /// 有效状态1-有效2-失效
creator Int? /// 创建人ID
modifier Int? /// 修改人ID
createTime DateTime @default(now()) @map("create_time") /// 创建时间
modifyTime DateTime @updatedAt @map("modify_time") /// 修改时间
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
classes Class[] /// 班级
creatorUser User? @relation("GradeCreator", fields: [creator], references: [id], onDelete: SetNull)
modifierUser User? @relation("GradeModifier", fields: [modifier], references: [id], onDelete: SetNull)
@@unique([tenantId, code])
@@unique([tenantId, level])
@@map("grades")
}
/// 部门表(支持树形结构)
model Department {
id Int @id @default(autoincrement())
tenantId Int @map("tenant_id") /// 租户ID
name String /// 部门名称
code String /// 部门编码(在租户内唯一)
parentId Int? @map("parent_id") /// 父部门ID支持树形结构
description String? /// 部门描述
sort Int @default(0) /// 排序
validState Int @default(1) @map("valid_state") /// 有效状态1-有效2-失效
creator Int? /// 创建人ID
modifier Int? /// 修改人ID
createTime DateTime @default(now()) @map("create_time") /// 创建时间
modifyTime DateTime @updatedAt @map("modify_time") /// 修改时间
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
parent Department? @relation("DepartmentTree", fields: [parentId], references: [id])
children Department[] @relation("DepartmentTree")
teachers Teacher[] /// 教师
creatorUser User? @relation("DepartmentCreator", fields: [creator], references: [id], onDelete: SetNull)
modifierUser User? @relation("DepartmentModifier", fields: [modifier], references: [id], onDelete: SetNull)
@@unique([tenantId, code])
@@map("departments")
}
/// 班级表
model Class {
id Int @id @default(autoincrement())
tenantId Int @map("tenant_id") /// 租户ID
gradeId Int @map("grade_id") /// 年级ID
name String /// 班级名称一年级1班、二年级2班
code String /// 班级编码(在租户内唯一)
type Int @default(1) @map("type") /// 班级类型1-行政班级教学班级2-兴趣班
capacity Int? /// 班级容量(可选)
description String? /// 班级描述
validState Int @default(1) @map("valid_state") /// 有效状态1-有效2-失效
creator Int? /// 创建人ID
modifier Int? /// 修改人ID
createTime DateTime @default(now()) @map("create_time") /// 创建时间
modifyTime DateTime @updatedAt @map("modify_time") /// 修改时间
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
grade Grade @relation(fields: [gradeId], references: [id], onDelete: Cascade)
students Student[] /// 学生(行政班级)
studentInterestClasses StudentInterestClass[] /// 学生兴趣班关联
creatorUser User? @relation("ClassCreator", fields: [creator], references: [id], onDelete: SetNull)
modifierUser User? @relation("ClassModifier", fields: [modifier], references: [id], onDelete: SetNull)
@@unique([tenantId, code])
@@map("classes")
}
/// 教师表
model Teacher {
id Int @id @default(autoincrement())
userId Int @unique @map("user_id") /// 用户ID一对一
tenantId Int @map("tenant_id") /// 租户ID
departmentId Int @map("department_id") /// 部门ID
employeeNo String? @map("employee_no") /// 工号(在租户内唯一)
phone String? /// 联系电话
idCard String? @map("id_card") /// 身份证号
gender Int? /// 性别1-男2-女
birthDate DateTime? @map("birth_date") /// 出生日期
hireDate DateTime? @map("hire_date") /// 入职日期
subject String? /// 任教科目(可选,如:语文、数学)
title String? /// 职称(可选,如:高级教师、一级教师)
description String? @db.Text /// 教师描述
validState Int @default(1) @map("valid_state") /// 有效状态1-有效2-失效
creator Int? /// 创建人ID
modifier Int? /// 修改人ID
createTime DateTime @default(now()) @map("create_time") /// 创建时间
modifyTime DateTime @updatedAt @map("modify_time") /// 修改时间
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
department Department @relation(fields: [departmentId], references: [id], onDelete: Restrict)
creatorUser User? @relation("TeacherCreator", fields: [creator], references: [id], onDelete: SetNull)
modifierUser User? @relation("TeacherModifier", fields: [modifier], references: [id], onDelete: SetNull)
@@unique([tenantId, employeeNo])
@@map("teachers")
}
/// 学生表
model Student {
id Int @id @default(autoincrement())
userId Int @unique @map("user_id") /// 用户ID一对一
tenantId Int @map("tenant_id") /// 租户ID
classId Int @map("class_id") /// 行政班级ID
studentNo String? @map("student_no") /// 学号(在租户内唯一)
phone String? /// 联系电话
idCard String? @map("id_card") /// 身份证号
gender Int? /// 性别1-男2-女
birthDate DateTime? @map("birth_date") /// 出生日期
enrollmentDate DateTime? @map("enrollment_date") /// 入学日期
parentName String? @map("parent_name") /// 家长姓名
parentPhone String? @map("parent_phone") /// 家长电话
address String? /// 家庭地址
description String? @db.Text /// 学生描述
validState Int @default(1) @map("valid_state") /// 有效状态1-有效2-失效
creator Int? /// 创建人ID
modifier Int? /// 修改人ID
createTime DateTime @default(now()) @map("create_time") /// 创建时间
modifyTime DateTime @updatedAt @map("modify_time") /// 修改时间
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
class Class @relation(fields: [classId], references: [id], onDelete: Restrict)
interestClasses StudentInterestClass[] /// 兴趣班关联
creatorUser User? @relation("StudentCreator", fields: [creator], references: [id], onDelete: SetNull)
modifierUser User? @relation("StudentModifier", fields: [modifier], references: [id], onDelete: SetNull)
@@unique([tenantId, studentNo])
@@map("students")
}
/// 学生兴趣班关联表(多对多)
model StudentInterestClass {
id Int @id @default(autoincrement())
studentId Int @map("student_id") /// 学生ID
classId Int @map("class_id") /// 兴趣班ID
student Student @relation(fields: [studentId], references: [id], onDelete: Cascade)
class Class @relation(fields: [classId], references: [id], onDelete: Cascade)
@@unique([studentId, classId])
@@map("student_interest_classes")
}
// ============================================
// 赛事管理模块
// ============================================
/// 赛事表
model Contest {
id Int @id @default(autoincrement())
contestName String @map("contest_name") /// 赛事名称
contestType String @map("contest_type") /// 赛事类型individual/team
contestState String @default("unpublished") @map("contest_state") /// 赛事状态unpublished/published
status String @default("ongoing") /// 赛事进度状态ongoing/finished
startTime DateTime @map("start_time") /// 赛事开始时间
endTime DateTime @map("end_time") /// 赛事结束时间
address String? /// 线下地址
content String? @db.Text /// 赛事详情
contestTenants Json? @map("contest_tenants") /// 授权租户ID数组
coverUrl String? @map("cover_url") /// 封面url
posterUrl String? @map("poster_url") /// 海报url
contactName String? @map("contact_name") /// 联系人
contactPhone String? @map("contact_phone") /// 联系电话
contactQrcode String? @map("contact_qrcode") /// 联系人二维码
organizers Json? /// 主办单位数组
coOrganizers Json? @map("co_organizers") /// 协办单位数组
sponsors Json? /// 赞助单位数组
// 报名配置
registerStartTime DateTime @map("register_start_time") /// 报名开始时间
registerEndTime DateTime @map("register_end_time") /// 报名结束时间
registerState String? @map("register_state") /// 报名任务状态started/closed
requireAudit Boolean @default(true) @map("require_audit") /// 报名是否需要审核
allowedGrades Json? @map("allowed_grades") /// 允许报名的年级ID数组
allowedClasses Json? @map("allowed_classes") /// 允许报名的班级ID数组
teamMinMembers Int? @map("team_min_members") /// 团队最少成员数
teamMaxMembers Int? @map("team_max_members") /// 团队最多成员数
// 作品配置
submitRule String @default("once") @map("submit_rule") /// 提交规则once/resubmit
submitStartTime DateTime @map("submit_start_time") /// 作品提交开始时间
submitEndTime DateTime @map("submit_end_time") /// 作品提交结束时间
workType String? @map("work_type") /// 作品类型image/video/document/code
workRequirement String? @map("work_requirement") @db.Text /// 作品要求说明
// 评审配置
reviewRuleId Int? @map("review_rule_id") /// 评审规则id
reviewStartTime DateTime @map("review_start_time") /// 评审开始时间
reviewEndTime DateTime @map("review_end_time") /// 评审结束时间
// 赛果配置
resultState String @default("unpublished") @map("result_state") /// 赛果状态unpublished/published
resultPublishTime DateTime? @map("result_publish_time") /// 结果发布时间
creator Int? /// 创建人ID
modifier Int? /// 修改人ID
createTime DateTime @default(now()) @map("create_time") /// 创建时间
modifyTime DateTime @updatedAt @map("modify_time") /// 更新时间
validState Int @default(1) @map("valid_state") /// 有效状态1-有效2-失效
attachments ContestAttachment[] /// 赛事附件
reviewRule ContestReviewRule? @relation("ContestReviewRuleContest", fields: [reviewRuleId], references: [id], onDelete: SetNull)
teams ContestTeam[] /// 赛事团队
registrations ContestRegistration[] /// 报名记录
works ContestWork[] /// 参赛作品
judges ContestJudge[] /// 比赛评委
workAssignments ContestWorkJudgeAssignment[] @relation("ContestWorkJudgeAssignmentContest") /// 作品分配
workScores ContestWorkScore[] @relation("ContestWorkScoreContest") /// 作品评分
notices ContestNotice[] /// 赛事公告
presetComments PresetComment[] /// 预设评语
creatorUser User? @relation("ContestCreator", fields: [creator], references: [id], onDelete: SetNull)
modifierUser User? @relation("ContestModifier", fields: [modifier], references: [id], onDelete: SetNull)
@@unique([contestName])
@@index([contestState])
@@index([startTime, endTime])
@@index([reviewRuleId])
@@map("t_contest")
}
/// 赛事附件表
model ContestAttachment {
id Int @id @default(autoincrement())
contestId Int @map("contest_id") /// 赛事id
fileName String @map("file_name") /// 文件名
fileUrl String @map("file_url") /// 文件路径
format String? /// 文件类型png,mp4
fileType String? @map("file_type") /// 素材类型image,video
size String @default("0") /// 文件大小
creator Int? /// 创建人ID
modifier Int? /// 修改人ID
createTime DateTime @default(now()) @map("create_time") /// 创建时间
modifyTime DateTime @updatedAt @map("modify_time") /// 更新时间
validState Int @default(1) @map("valid_state") /// 有效状态1-有效2-失效
contest Contest @relation(fields: [contestId], references: [id], onDelete: Cascade)
creatorUser User? @relation("ContestAttachmentCreator", fields: [creator], references: [id], onDelete: SetNull)
modifierUser User? @relation("ContestAttachmentModifier", fields: [modifier], references: [id], onDelete: SetNull)
@@index([contestId])
@@map("t_contest_attachment")
}
/// 评审规则表(独立存在,可被多个赛事使用)
model ContestReviewRule {
id Int @id @default(autoincrement())
tenantId Int @map("tenant_id") /// 租户ID
ruleName String @map("rule_name") /// 规则名称
ruleDescription String? @map("rule_description") @db.Text /// 规则说明
judgeCount Int? @map("judge_count") /// 评委数量
dimensions Json /// 评分维度配置JSON
calculationRule String @default("average") @map("calculation_rule") /// 计算规则average/remove_max_min/remove_min
creator Int? /// 创建人ID
modifier Int? /// 修改人ID
createTime DateTime @default(now()) @map("create_time") /// 创建时间
modifyTime DateTime @updatedAt @map("modify_time") /// 更新时间
validState Int @default(1) @map("valid_state") /// 有效状态1-有效2-失效
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
contests Contest[] @relation("ContestReviewRuleContest") /// 使用此规则的赛事列表
creatorUser User? @relation("ContestReviewRuleCreator", fields: [creator], references: [id], onDelete: SetNull)
modifierUser User? @relation("ContestReviewRuleModifier", fields: [modifier], references: [id], onDelete: SetNull)
@@index([tenantId])
@@map("t_contest_review_rule")
}
/// 赛事团队表
model ContestTeam {
id Int @id @default(autoincrement())
tenantId Int @map("tenant_id") /// 团队所属租户ID
contestId Int @map("contest_id") /// 赛事id
teamName String @map("team_name") /// 团队名称(租户内唯一)
leaderUserId Int @map("leader_user_id") /// 团队负责人用户id
maxMembers Int? @map("max_members") /// 团队最大成员数
creator Int? /// 创建人ID
modifier Int? /// 修改人ID
createTime DateTime @default(now()) @map("create_time") /// 创建时间
modifyTime DateTime @updatedAt @map("modify_time") /// 更新时间
validState Int @default(1) @map("valid_state") /// 有效状态1-有效2-失效
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
contest Contest @relation(fields: [contestId], references: [id], onDelete: Cascade)
leader User @relation("ContestTeamLeader", fields: [leaderUserId], references: [id], onDelete: Restrict)
members ContestTeamMember[] /// 团队成员
registrations ContestRegistration[] /// 报名记录
creatorUser User? @relation("ContestTeamCreator", fields: [creator], references: [id], onDelete: SetNull)
modifierUser User? @relation("ContestTeamModifier", fields: [modifier], references: [id], onDelete: SetNull)
@@unique([tenantId, contestId, teamName])
@@index([contestId])
@@index([leaderUserId])
@@map("t_contest_team")
}
/// 团队成员表
model ContestTeamMember {
id Int @id @default(autoincrement())
tenantId Int @map("tenant_id") /// 成员所属租户ID
teamId Int @map("team_id") /// 团队id
userId Int @map("user_id") /// 成员用户id
role String @default("member") /// 成员角色member/leader/mentor
creator Int? /// 创建人ID
modifier Int? /// 修改人ID
createTime DateTime @default(now()) @map("create_time") /// 创建时间
modifyTime DateTime @updatedAt @map("modify_time") /// 更新时间
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
team ContestTeam @relation(fields: [teamId], references: [id], onDelete: Cascade)
user User @relation("ContestTeamMemberUser", fields: [userId], references: [id], onDelete: Cascade)
creatorUser User? @relation("ContestTeamMemberCreator", fields: [creator], references: [id], onDelete: SetNull)
modifierUser User? @relation("ContestTeamMemberModifier", fields: [modifier], references: [id], onDelete: SetNull)
@@unique([tenantId, teamId, userId])
@@index([teamId])
@@index([userId])
@@map("t_contest_team_member")
}
/// 赛事报名表
model ContestRegistration {
id Int @id @default(autoincrement())
contestId Int @map("contest_id") /// 赛事id
tenantId Int @map("tenant_id") /// 所属租户ID
registrationType String? @map("registration_type") /// 报名类型individual/team
teamId Int? @map("team_id") /// 团队id
teamName String? @map("team_name") /// 团队名称快照(团队赛)
userId Int @map("user_id") /// 账号id
accountNo String @map("account_no") /// 报名账号(记录报名快照)
accountName String @map("account_name") /// 报名账号名称(记录报名快照)
role String? /// 报名角色快照leader/member/mentor
registrationState String @default("pending") @map("registration_state") /// 报名状态pending/passed/rejected/withdrawn
registrant Int? /// 实际报名人用户ID
registrationTime DateTime @map("registration_time") /// 报名时间
reason String? @db.VarChar(1023) /// 审核理由
operator Int? /// 审核人用户ID
operationDate DateTime? @map("operation_date") /// 审核时间
creator Int? /// 创建人ID
modifier Int? /// 修改人ID
createTime DateTime @default(now()) @map("create_time") /// 创建时间
modifyTime DateTime @updatedAt @map("modify_time") /// 更新时间
contest Contest @relation(fields: [contestId], references: [id], onDelete: Cascade)
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
team ContestTeam? @relation(fields: [teamId], references: [id], onDelete: SetNull)
user User @relation("ContestRegistrationUser", fields: [userId], references: [id], onDelete: Restrict)
works ContestWork[] /// 参赛作品
creatorUser User? @relation("ContestRegistrationCreator", fields: [creator], references: [id], onDelete: SetNull)
modifierUser User? @relation("ContestRegistrationModifier", fields: [modifier], references: [id], onDelete: SetNull)
teachers ContestRegistrationTeacher[] /// 指导老师关联
@@index([contestId, tenantId])
@@index([userId, contestId])
@@index([teamId])
@@index([registrationState])
@@map("t_contest_registration")
}
/// 报名指导老师关联表
model ContestRegistrationTeacher {
id Int @id @default(autoincrement())
registrationId Int @map("registration_id") /// 报名记录ID
tenantId Int @map("tenant_id") /// 租户ID
userId Int @map("user_id") /// 指导老师用户ID
isDefault Boolean @default(false) @map("is_default") /// 是否为默认指导老师(报名时自动添加的,不能移除)
creator Int? /// 创建人ID
modifier Int? /// 修改人ID
createTime DateTime @default(now()) @map("create_time") /// 创建时间
modifyTime DateTime @updatedAt @map("modify_time") /// 更新时间
registration ContestRegistration @relation(fields: [registrationId], references: [id], onDelete: Cascade)
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
user User @relation("ContestRegistrationTeacherUser", fields: [userId], references: [id], onDelete: Cascade)
creatorUser User? @relation("ContestRegistrationTeacherCreator", fields: [creator], references: [id], onDelete: SetNull)
modifierUser User? @relation("ContestRegistrationTeacherModifier", fields: [modifier], references: [id], onDelete: SetNull)
@@unique([tenantId, registrationId, userId])
@@index([registrationId])
@@index([userId])
@@map("t_contest_registration_teacher")
}
/// 参赛作品表
model ContestWork {
id Int @id @default(autoincrement())
tenantId Int @map("tenant_id") /// 作品所属租户ID
contestId Int @map("contest_id") /// 赛事id
registrationId Int @map("registration_id") /// 报名记录id
workNo String? @unique @map("work_no") /// 作品编号(展示用唯一编号)
title String /// 作品标题
description String? @db.Text /// 作品说明
files Json? /// 作品文件列表(简易场景)
version Int @default(1) /// 作品版本号(递增)
isLatest Boolean @default(true) @map("is_latest") /// 是否最新版本
status String @default("submitted") /// 作品状态submitted/locked/reviewing/rejected/accepted
submitTime DateTime @default(now()) @map("submit_time") /// 提交时间
submitterUserId Int? @map("submitter_user_id") /// 提交人用户id
submitterAccountNo String? @map("submitter_account_no") /// 提交人账号
submitSource String @default("teacher") @map("submit_source") /// 提交来源teacher/student/team_leader
previewUrl String? @map("preview_url") @db.Text /// 作品预览URL兼容单预览图
previewUrls Json? @map("preview_urls") /// 作品预览图URL列表多模型场景
aiModelMeta Json? @map("ai_model_meta") /// AI建模元数据
// 赛果相关字段
finalScore Decimal? @map("final_score") @db.Decimal(10, 2) /// 最终得分(根据规则计算)
rank Int? /// 排名
awardLevel String? @map("award_level") /// 奖项等级first/second/third/excellent/none
awardName String? @map("award_name") /// 奖项名称(如:一等奖、金奖)
certificateUrl String? @map("certificate_url") /// 证书URL
creator Int? /// 创建人ID
modifier Int? /// 修改人ID
createTime DateTime @default(now()) @map("create_time") /// 创建时间
modifyTime DateTime @updatedAt @map("modify_time") /// 更新时间
validState Int @default(1) @map("valid_state") /// 有效状态1-有效2-失效
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
contest Contest @relation(fields: [contestId], references: [id], onDelete: Cascade)
registration ContestRegistration @relation(fields: [registrationId], references: [id], onDelete: Restrict)
attachments ContestWorkAttachment[] /// 作品附件
assignments ContestWorkJudgeAssignment[] /// 作品分配
scores ContestWorkScore[] /// 作品评分
creatorUser User? @relation("ContestWorkCreator", fields: [creator], references: [id], onDelete: SetNull)
modifierUser User? @relation("ContestWorkModifier", fields: [modifier], references: [id], onDelete: SetNull)
@@index([tenantId, contestId, isLatest])
@@index([registrationId])
@@index([tenantId, contestId, submitTime, status])
@@index([contestId, status])
@@map("t_contest_work")
}
/// 作品附件文件表
model ContestWorkAttachment {
id Int @id @default(autoincrement())
tenantId Int @map("tenant_id") /// 所属租户ID
contestId Int @map("contest_id") /// 赛事id
workId Int @map("work_id") /// 作品id
fileName String @map("file_name") /// 文件名
fileUrl String @map("file_url") /// 文件路径
format String? /// 文件类型png,mp4
fileType String? @map("file_type") /// 素材类型image,video
size String @default("0") /// 文件大小
creator Int? /// 创建人ID
modifier Int? /// 修改人ID
createTime DateTime @default(now()) @map("create_time") /// 创建时间
modifyTime DateTime @updatedAt @map("modify_time") /// 更新时间
work ContestWork @relation(fields: [workId], references: [id], onDelete: Cascade)
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
creatorUser User? @relation("ContestWorkAttachmentCreator", fields: [creator], references: [id], onDelete: SetNull)
modifierUser User? @relation("ContestWorkAttachmentModifier", fields: [modifier], references: [id], onDelete: SetNull)
@@index([tenantId, contestId, workId])
@@map("t_contest_work_attachment")
}
/// 比赛评委关联表(比赛与评委的多对多关系)
model ContestJudge {
id Int @id @default(autoincrement())
contestId Int @map("contest_id") /// 比赛id
judgeId Int @map("judge_id") /// 评委用户id
specialty String? /// 评审专业领域(可选)
weight Decimal? @db.Decimal(3, 2) /// 评审权重(可选,用于加权平均计算)
description String? @db.Text /// 评委在该比赛中的说明
creator Int? /// 创建人ID
modifier Int? /// 修改人ID
createTime DateTime @default(now()) @map("create_time") /// 创建时间
modifyTime DateTime @updatedAt @map("modify_time") /// 更新时间
validState Int @default(1) @map("valid_state") /// 有效状态1-有效2-失效
contest Contest @relation(fields: [contestId], references: [id], onDelete: Cascade)
judge User @relation("ContestJudgeUser", fields: [judgeId], references: [id], onDelete: Cascade)
creatorUser User? @relation("ContestJudgeCreator", fields: [creator], references: [id], onDelete: SetNull)
modifierUser User? @relation("ContestJudgeModifier", fields: [modifier], references: [id], onDelete: SetNull)
@@unique([contestId, judgeId])
@@index([contestId])
@@index([judgeId])
@@map("t_contest_judge")
}
/// 作品分配表(评委分配作品)
model ContestWorkJudgeAssignment {
id Int @id @default(autoincrement())
contestId Int @map("contest_id") /// 赛事id
workId Int @map("work_id") /// 作品id
judgeId Int @map("judge_id") /// 评委用户id
assignmentTime DateTime @default(now()) @map("assignment_time") /// 分配时间
status String @default("assigned") /// 分配状态assigned/reviewing/completed
creator Int? /// 创建人ID
modifier Int? /// 修改人ID
createTime DateTime @default(now()) @map("create_time") /// 创建时间
modifyTime DateTime @updatedAt @map("modify_time") /// 更新时间
contest Contest @relation("ContestWorkJudgeAssignmentContest", fields: [contestId], references: [id], onDelete: Cascade)
work ContestWork @relation(fields: [workId], references: [id], onDelete: Cascade)
judge User @relation("ContestWorkJudgeAssignmentJudge", fields: [judgeId], references: [id], onDelete: Restrict)
scores ContestWorkScore[] /// 评分记录
creatorUser User? @relation("ContestWorkJudgeAssignmentCreator", fields: [creator], references: [id], onDelete: SetNull)
modifierUser User? @relation("ContestWorkJudgeAssignmentModifier", fields: [modifier], references: [id], onDelete: SetNull)
@@unique([workId, judgeId])
@@index([contestId, judgeId])
@@index([workId])
@@index([status])
@@map("t_contest_work_judge_assignment")
}
/// 作品评分表
model ContestWorkScore {
id Int @id @default(autoincrement())
tenantId Int @map("tenant_id") /// 所属租户ID
contestId Int @map("contest_id") /// 赛事id
workId Int @map("work_id") /// 作品id
assignmentId Int @map("assignment_id") /// 分配记录id
judgeId Int @map("judge_id") /// 评委用户id
judgeName String @map("judge_name") /// 评委姓名
dimensionScores Json @map("dimension_scores") /// 各维度评分JSON
totalScore Decimal @map("total_score") @db.Decimal(10, 2) /// 总分
comments String? @db.Text /// 评语
scoreTime DateTime @map("score_time") /// 评分时间
creator Int? /// 创建人ID
modifier Int? /// 修改人ID
createTime DateTime @default(now()) @map("create_time") /// 创建时间
modifyTime DateTime @updatedAt @map("modify_time") /// 更新时间
validState Int @default(1) @map("valid_state") /// 有效状态1-有效2-失效
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
contest Contest @relation("ContestWorkScoreContest", fields: [contestId], references: [id], onDelete: Cascade)
work ContestWork @relation(fields: [workId], references: [id], onDelete: Cascade)
assignment ContestWorkJudgeAssignment @relation(fields: [assignmentId], references: [id], onDelete: Restrict)
judge User @relation("ContestWorkScoreJudge", fields: [judgeId], references: [id], onDelete: Restrict)
creatorUser User? @relation("ContestWorkScoreCreator", fields: [creator], references: [id], onDelete: SetNull)
modifierUser User? @relation("ContestWorkScoreModifier", fields: [modifier], references: [id], onDelete: SetNull)
@@index([contestId, workId, judgeId])
@@index([workId])
@@index([assignmentId])
@@map("t_contest_work_score")
}
/// 赛事公告表
model ContestNotice {
id Int @id @default(autoincrement())
contestId Int @map("contest_id") /// 赛事id
title String /// 公告标题
content String @db.Text /// 公告内容
noticeType String @default("manual") @map("notice_type") /// 公告类型system/manual/urgent
priority Int @default(0) /// 优先级(数字越大优先级越高)
publishTime DateTime? @map("publish_time") /// 发布时间
creator Int? /// 创建人ID
modifier Int? /// 修改人ID
createTime DateTime @default(now()) @map("create_time") /// 创建时间
modifyTime DateTime @updatedAt @map("modify_time") /// 更新时间
validState Int @default(1) @map("valid_state") /// 有效状态1-有效2-失效
contest Contest @relation(fields: [contestId], references: [id], onDelete: Cascade)
creatorUser User? @relation("ContestNoticeCreator", fields: [creator], references: [id], onDelete: SetNull)
modifierUser User? @relation("ContestNoticeModifier", fields: [modifier], references: [id], onDelete: SetNull)
@@index([contestId])
@@index([publishTime])
@@index([noticeType])
@@map("t_contest_notice")
}
// ============================================
// 作业管理模块
// ============================================
/// 作业表
model Homework {
id Int @id @default(autoincrement())
tenantId Int @map("tenant_id") /// 租户ID
name String /// 作业名称
content String? @db.Text /// 作业内容(富文本)
status String @default("unpublished") /// 作业状态unpublished/published
publishTime DateTime? @map("publish_time") /// 发布时间
submitStartTime DateTime @map("submit_start_time") /// 提交开始时间
submitEndTime DateTime @map("submit_end_time") /// 提交结束时间
attachments Json? /// 附件列表 [{fileName, fileUrl, size}]
publishScope Json? @map("publish_scope") /// 公开范围班级ID数组
reviewRuleId Int? @map("review_rule_id") /// 评审规则ID
creator Int? /// 创建人ID
modifier Int? /// 修改人ID
createTime DateTime @default(now()) @map("create_time") /// 创建时间
modifyTime DateTime @updatedAt @map("modify_time") /// 更新时间
validState Int @default(1) @map("valid_state") /// 有效状态1-有效2-失效
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
reviewRule HomeworkReviewRule? @relation(fields: [reviewRuleId], references: [id], onDelete: SetNull)
submissions HomeworkSubmission[] /// 作业提交记录
creatorUser User? @relation("HomeworkCreator", fields: [creator], references: [id], onDelete: SetNull)
modifierUser User? @relation("HomeworkModifier", fields: [modifier], references: [id], onDelete: SetNull)
@@index([tenantId, status])
@@index([tenantId, submitStartTime, submitEndTime])
@@map("t_homework")
}
/// 作业提交表
model HomeworkSubmission {
id Int @id @default(autoincrement())
tenantId Int @map("tenant_id") /// 租户ID
homeworkId Int @map("homework_id") /// 作业ID
studentId Int @map("student_id") /// 学生用户ID
workNo String? @map("work_no") /// 作品编号
workName String @map("work_name") /// 作品名称
workDescription String? @map("work_description") @db.Text /// 作品介绍
files Json? /// 作品文件列表
attachments Json? /// 附件列表
submitTime DateTime @default(now()) @map("submit_time") /// 提交时间
status String @default("pending") /// 状态pending/reviewed/rejected
totalScore Decimal? @map("total_score") @db.Decimal(10, 2) /// 总分
creator Int? /// 创建人ID
modifier Int? /// 修改人ID
createTime DateTime @default(now()) @map("create_time") /// 创建时间
modifyTime DateTime @updatedAt @map("modify_time") /// 更新时间
validState Int @default(1) @map("valid_state") /// 有效状态1-有效2-失效
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
homework Homework @relation(fields: [homeworkId], references: [id], onDelete: Cascade)
student User @relation("HomeworkSubmissionStudent", fields: [studentId], references: [id], onDelete: Cascade)
scores HomeworkScore[] /// 评分记录
creatorUser User? @relation("HomeworkSubmissionCreator", fields: [creator], references: [id], onDelete: SetNull)
modifierUser User? @relation("HomeworkSubmissionModifier", fields: [modifier], references: [id], onDelete: SetNull)
@@unique([homeworkId, studentId])
@@index([tenantId, homeworkId])
@@index([studentId])
@@index([status])
@@map("t_homework_submission")
}
/// 作业评审规则表
model HomeworkReviewRule {
id Int @id @default(autoincrement())
tenantId Int @map("tenant_id") /// 租户ID
name String /// 规则名称
description String? @db.Text /// 规则描述
criteria Json /// 评分标准 [{name, maxScore, description}]
creator Int? /// 创建人ID
modifier Int? /// 修改人ID
createTime DateTime @default(now()) @map("create_time") /// 创建时间
modifyTime DateTime @updatedAt @map("modify_time") /// 更新时间
validState Int @default(1) @map("valid_state") /// 有效状态1-有效2-失效
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
homeworks Homework[] /// 关联的作业
creatorUser User? @relation("HomeworkReviewRuleCreator", fields: [creator], references: [id], onDelete: SetNull)
modifierUser User? @relation("HomeworkReviewRuleModifier", fields: [modifier], references: [id], onDelete: SetNull)
@@index([tenantId])
@@map("t_homework_review_rule")
}
/// 作业评分表
model HomeworkScore {
id Int @id @default(autoincrement())
tenantId Int @map("tenant_id") /// 租户ID
submissionId Int @map("submission_id") /// 提交记录ID
reviewerId Int @map("reviewer_id") /// 评审人ID
dimensionScores Json @map("dimension_scores") /// 各维度评分
totalScore Decimal @map("total_score") @db.Decimal(10, 2) /// 总分
comments String? @db.Text /// 评语
scoreTime DateTime @default(now()) @map("score_time") /// 评分时间
creator Int? /// 创建人ID
modifier Int? /// 修改人ID
createTime DateTime @default(now()) @map("create_time") /// 创建时间
modifyTime DateTime @updatedAt @map("modify_time") /// 更新时间
validState Int @default(1) @map("valid_state") /// 有效状态1-有效2-失效
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
submission HomeworkSubmission @relation(fields: [submissionId], references: [id], onDelete: Cascade)
reviewer User @relation("HomeworkScoreReviewer", fields: [reviewerId], references: [id], onDelete: Restrict)
creatorUser User? @relation("HomeworkScoreCreator", fields: [creator], references: [id], onDelete: SetNull)
modifierUser User? @relation("HomeworkScoreModifier", fields: [modifier], references: [id], onDelete: SetNull)
@@unique([submissionId, reviewerId])
@@index([tenantId, submissionId])
@@index([reviewerId])
@@map("t_homework_score")
}
// ============================================
// AI 3D 模型生成模块
// ============================================
/// AI 3D 生成任务表
model AI3DTask {
id Int @id @default(autoincrement())
tenantId Int @map("tenant_id") /// 租户ID
userId Int @map("user_id") /// 用户ID任务归属用户
inputType String @map("input_type") /// 输入类型text | image
inputContent String @map("input_content") @db.Text /// 输入内容文字描述或图片URL
generateType String @default("Normal") @map("generate_type") /// 生成类型Normal(带纹理) | Geometry(白模) | LowPoly(低多边形) | Sketch(草图)
status String @default("pending") /// 任务状态pending | processing | completed | failed | timeout
resultUrl String? @map("result_url") @db.Text /// 生成的3D模型URL单个结果兼容旧数据
previewUrl String? @map("preview_url") @db.Text /// 预览图URL单个结果兼容旧数据
resultUrls Json? @map("result_urls") /// 生成的3D模型URL数组多个结果文生3D生成4个
previewUrls Json? @map("preview_urls") /// 预览图URL数组多个结果
errorMessage String? @map("error_message") @db.Text /// 失败时的错误信息
externalTaskId String? @map("external_task_id") /// 外部AI服务的任务ID
retryCount Int @default(0) @map("retry_count") /// 已重试次数
createTime DateTime @default(now()) @map("create_time") /// 创建时间
completeTime DateTime? @map("complete_time") /// 完成时间
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
user User @relation("AI3DTaskUser", fields: [userId], references: [id], onDelete: Cascade)
@@index([userId])
@@index([tenantId])
@@index([status])
@@index([createTime])
@@map("t_ai_3d_task")
}
/// 预设评语表
model PresetComment {
id Int @id @default(autoincrement())
contestId Int @map("contest_id") /// 赛事ID
judgeId Int @map("judge_id") /// 评委用户ID
content String @db.Text /// 评语内容
score Decimal? @db.Decimal(10, 2) /// 关联评审分数
sortOrder Int @default(0) @map("sort_order") /// 排序顺序
useCount Int @default(0) @map("use_count") /// 使用次数
validState Int @default(1) @map("valid_state") /// 有效状态1-有效2-失效
creator Int? /// 创建人ID
modifier Int? /// 修改人ID
createTime DateTime @default(now()) @map("create_time") /// 创建时间
modifyTime DateTime @updatedAt @map("modify_time") /// 修改时间
contest Contest @relation(fields: [contestId], references: [id], onDelete: Cascade)
judge User @relation("PresetCommentJudge", fields: [judgeId], references: [id], onDelete: Cascade)
@@index([contestId, judgeId])
@@map("t_preset_comment")
}