library-picturebook-activity/backend/prisma/schema.prisma

1165 lines
62 KiB
Plaintext
Raw Normal View History

2025-11-23 14:04:20 +08:00
// 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-是
tenantType String @default("other") @map("tenant_type") /// 租户类型platform/library/kindergarten/school/institution/other
2025-11-23 14:04:20 +08:00
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") /// 修改时间
2026-01-13 14:01:17 +08:00
users User[]
roles Role[]
menus TenantMenu[]
permissions Permission[]
dicts Dict[]
configs Config[]
contestTeams ContestTeam[] /// 赛事团队
contestTeamMembers ContestTeamMember[] /// 团队成员
contestRegistrations ContestRegistration[] /// 赛事报名
2026-01-09 18:14:35 +08:00
contestRegistrationTeachers ContestRegistrationTeacher[] /// 报名指导老师关联
2026-01-13 14:01:17 +08:00
contestWorks ContestWork[] /// 参赛作品
contestWorkAttachments ContestWorkAttachment[] /// 作品附件
contestWorkScores ContestWorkScore[] /// 作品评分
contestReviewRules ContestReviewRule[] /// 评审规则
2026-01-09 18:14:35 +08:00
// 作业管理关联
2026-01-13 14:01:17 +08:00
homeworks Homework[] /// 作业
homeworkSubmissions HomeworkSubmission[] /// 作业提交记录
homeworkReviewRules HomeworkReviewRule[] /// 作业评审规则
homeworkScores HomeworkScore[] /// 作业评分
creatorUser User? @relation("TenantCreator", fields: [creator], references: [id], onDelete: SetNull)
modifierUser User? @relation("TenantModifier", fields: [modifier], references: [id], onDelete: SetNull)
2025-11-23 14:04:20 +08:00
@@index([tenantType])
2025-11-23 14:04:20 +08:00
@@map("tenants")
}
/// 用户表
model User {
2026-01-12 16:06:34 +08:00
id Int @id @default(autoincrement())
tenantId Int @map("tenant_id") /// 租户ID
username String /// 用户名(在租户内唯一)
password String /// 密码(加密存储)
nickname String /// 昵称
email String? /// 邮箱(在租户内唯一,可选)
phone String? @unique /// 手机号(全局唯一,用于手机号登录)
wxOpenid String? @unique @map("wx_openid") /// 微信OpenID
wxUnionid String? @map("wx_unionid") /// 微信UnionID
userSource String @default("admin_created") @map("user_source") /// 用户来源admin_created/self_registered/child_migrated
userType String @default("adult") @map("user_type") /// 用户类型adult/child
city String? /// 所在城市
birthday DateTime? @db.Date /// 出生日期
2026-01-12 16:06:34 +08:00
gender String? /// 性别male-男female-女
avatar String? /// 头像URL
organization String? /// 所属单位(用于评委等独立用户)
status String @default("enabled") /// 账号状态enabled-启用disabled-停用
validState Int @default(1) @map("valid_state") /// 有效状态1-有效2-失效
2026-01-13 14:01:17 +08:00
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")
2025-12-09 11:10:36 +08:00
// 赛事相关关联
2026-01-13 14:01:17 +08:00
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")
2025-12-09 11:10:36 +08:00
modifiedContestWorkJudgeAssignments ContestWorkJudgeAssignment[] @relation("ContestWorkJudgeAssignmentModifier")
2026-01-13 14:01:17 +08:00
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")
2026-01-09 18:14:35 +08:00
modifiedContestRegistrationTeachers ContestRegistrationTeacher[] @relation("ContestRegistrationTeacherModifier")
// 作业管理关联
2026-01-13 14:01:17 +08:00
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")
// 预设评语关联
presetComments PresetComment[] @relation("PresetCommentJudge") /// 评委的预设评语
// 子女关联
children Child[] @relation("ChildParent") /// 子女信息
// 家长-子女账号关系
parentRelations UserParentChild[] @relation("ParentUser") /// 作为家长关联的子女
childRelations UserParentChild[] @relation("ChildUser") /// 作为子女关联的家长
// UGC 作品关联
userWorks UserWork[] @relation("UserWorkCreator") /// 用户创作的作品
userWorkLikes UserWorkLike[] @relation("UserWorkLikeUser")
userWorkFavorites UserWorkFavorite[] @relation("UserWorkFavoriteUser")
userWorkComments UserWorkComment[] @relation("UserWorkCommentUser")
contentReviewLogs ContentReviewLog[] @relation("ContentReviewLogOperator")
// 举报关联
reportsMade UserWorkReport[] @relation("UserWorkReportReporter")
reportsReceived UserWorkReport[] @relation("UserWorkReportTarget")
2025-11-23 14:04:20 +08:00
@@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") /// 修改时间
2025-12-09 11:10:36 +08:00
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
2025-11-23 14:04:20 +08:00
users UserRole[]
permissions RolePermission[]
2025-12-09 11:10:36 +08:00
creatorUser User? @relation("RoleCreator", fields: [creator], references: [id], onDelete: SetNull)
modifierUser User? @relation("RoleModifier", fields: [modifier], references: [id], onDelete: SetNull)
2025-11-23 14:04:20 +08:00
@@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") /// 修改时间
2025-12-09 11:10:36 +08:00
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
2025-11-23 14:04:20 +08:00
roles RolePermission[]
2025-12-09 11:10:36 +08:00
creatorUser User? @relation("PermissionCreator", fields: [creator], references: [id], onDelete: SetNull)
modifierUser User? @relation("PermissionModifier", fields: [modifier], references: [id], onDelete: SetNull)
2025-11-23 14:04:20 +08:00
@@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") /// 修改时间
2025-12-09 11:10:36 +08:00
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)
2025-11-23 14:04:20 +08:00
@@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") /// 修改时间
2025-12-09 11:10:36 +08:00
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)
2025-11-23 14:04:20 +08:00
@@unique([tenantId, key])
@@map("configs")
}
/// 日志记录表
model Log {
id Int @id @default(autoincrement())
userId Int? @map("user_id") /// 用户ID
action String /// 操作类型
2025-12-09 11:10:36 +08:00
content String? @db.Text /// 操作内容(使用 TEXT 类型支持长文本)
2025-11-23 14:04:20 +08:00
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")
}
2025-12-09 11:10:36 +08:00
// ============================================
// 赛事管理模块
// ============================================
/// 赛事表
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
2026-01-08 09:17:46 +08:00
status String @default("ongoing") /// 赛事进度状态ongoing/finished
2025-12-09 11:10:36 +08:00
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? /// 赞助单位数组
2026-01-08 09:17:46 +08:00
// 报名配置
2025-12-09 11:10:36 +08:00
registerStartTime DateTime @map("register_start_time") /// 报名开始时间
registerEndTime DateTime @map("register_end_time") /// 报名结束时间
registerState String? @map("register_state") /// 报名任务状态started/closed
2026-01-08 09:17:46 +08:00
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") /// 团队最多成员数
// 定向推送条件visibility='targeted'时使用)
targetCities Json? @map("target_cities") /// 目标城市列表
ageMin Int? @map("age_min") /// 最小年龄限制
ageMax Int? @map("age_max") /// 最大年龄限制
2026-01-08 09:17:46 +08:00
// 作品配置
2025-12-09 11:10:36 +08:00
submitRule String @default("once") @map("submit_rule") /// 提交规则once/resubmit
submitStartTime DateTime @map("submit_start_time") /// 作品提交开始时间
submitEndTime DateTime @map("submit_end_time") /// 作品提交结束时间
2026-01-08 09:17:46 +08:00
workType String? @map("work_type") /// 作品类型image/video/document/code
2026-01-13 14:01:17 +08:00
workRequirement String? @map("work_requirement") @db.Text /// 作品要求说明
2026-01-08 09:17:46 +08:00
// 评审配置
2025-12-09 11:10:36 +08:00
reviewRuleId Int? @map("review_rule_id") /// 评审规则id
reviewStartTime DateTime @map("review_start_time") /// 评审开始时间
reviewEndTime DateTime @map("review_end_time") /// 评审结束时间
2026-01-08 09:17:46 +08:00
// 赛果配置
resultState String @default("unpublished") @map("result_state") /// 赛果状态unpublished/published
2025-12-09 11:10:36 +08:00
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") /// 更新时间
visibility String @default("designated") /// 可见范围public-公开/designated-指定机构/internal-仅内部
2025-12-09 11:10:36 +08:00
validState Int @default(1) @map("valid_state") /// 有效状态1-有效2-失效
2026-01-13 14:01:17 +08:00
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[] /// 预设评语
2026-01-13 14:01:17 +08:00
creatorUser User? @relation("ContestCreator", fields: [creator], references: [id], onDelete: SetNull)
modifierUser User? @relation("ContestModifier", fields: [modifier], references: [id], onDelete: SetNull)
2025-12-09 11:10:36 +08:00
@@unique([contestName])
@@index([contestState])
@@index([startTime, endTime])
@@index([reviewRuleId])
@@map("t_contest")
}
/// 赛事附件表
model ContestAttachment {
2026-01-13 14:01:17 +08:00
id Int @id @default(autoincrement())
contestId Int @map("contest_id") /// 赛事id
fileName String @map("file_name") /// 文件名
fileUrl String @map("file_url") /// 文件路径
2025-12-09 11:10:36 +08:00
format String? /// 文件类型png,mp4
2026-01-13 14:01:17 +08:00
fileType String? @map("file_type") /// 素材类型image,video
size String @default("0") /// 文件大小
2025-12-09 11:10:36 +08:00
creator Int? /// 创建人ID
modifier Int? /// 修改人ID
2026-01-13 14:01:17 +08:00
createTime DateTime @default(now()) @map("create_time") /// 创建时间
modifyTime DateTime @updatedAt @map("modify_time") /// 更新时间
validState Int @default(1) @map("valid_state") /// 有效状态1-有效2-失效
2025-12-09 11:10:36 +08:00
2026-01-13 14:01:17 +08:00
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)
2025-12-09 11:10:36 +08:00
@@index([contestId])
@@map("t_contest_attachment")
}
2026-01-08 09:17:46 +08:00
/// 评审规则表(独立存在,可被多个赛事使用)
2025-12-09 11:10:36 +08:00
model ContestReviewRule {
2026-01-13 14:01:17 +08:00
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") /// 评委数量
2025-12-09 11:10:36 +08:00
dimensions Json /// 评分维度配置JSON
2026-01-13 14:01:17 +08:00
calculationRule String @default("average") @map("calculation_rule") /// 计算规则average/remove_max_min/remove_min
2025-12-09 11:10:36 +08:00
creator Int? /// 创建人ID
modifier Int? /// 修改人ID
2026-01-13 14:01:17 +08:00
createTime DateTime @default(now()) @map("create_time") /// 创建时间
modifyTime DateTime @updatedAt @map("modify_time") /// 更新时间
validState Int @default(1) @map("valid_state") /// 有效状态1-有效2-失效
2025-12-09 11:10:36 +08:00
2026-01-08 09:17:46 +08:00
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)
2025-12-09 11:10:36 +08:00
2026-01-08 09:17:46 +08:00
@@index([tenantId])
2025-12-09 11:10:36 +08:00
@@map("t_contest_review_rule")
}
/// 赛事团队表
model ContestTeam {
2026-01-13 14:01:17 +08:00
id Int @id @default(autoincrement())
tenantId Int @map("tenant_id") /// 团队所属租户ID
contestId Int @map("contest_id") /// 赛事id
teamName String @map("team_name") /// 团队名称(租户内唯一)
2025-12-09 11:10:36 +08:00
leaderUserId Int @map("leader_user_id") /// 团队负责人用户id
2026-01-13 14:01:17 +08:00
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-失效
2025-12-09 11:10:36 +08:00
2026-01-13 14:01:17 +08:00
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[] /// 团队成员
2025-12-09 11:10:36 +08:00
registrations ContestRegistration[] /// 报名记录
2026-01-13 14:01:17 +08:00
creatorUser User? @relation("ContestTeamCreator", fields: [creator], references: [id], onDelete: SetNull)
modifierUser User? @relation("ContestTeamModifier", fields: [modifier], references: [id], onDelete: SetNull)
2025-12-09 11:10:36 +08:00
@@unique([tenantId, contestId, teamName])
@@index([contestId])
@@index([leaderUserId])
@@map("t_contest_team")
}
/// 团队成员表
model ContestTeamMember {
2026-01-13 14:01:17 +08:00
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)
2025-12-09 11:10:36 +08:00
@@unique([tenantId, teamId, userId])
@@index([teamId])
@@index([userId])
@@map("t_contest_team_member")
}
/// 赛事报名表
model ContestRegistration {
2026-01-13 14:01:17 +08:00
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
participantType String @default("self") @map("participant_type") /// 参与者类型self-自己/child-代子女报名
childId Int? @map("child_id") /// 子女ID代子女报名时填写
2026-01-13 14:01:17 +08:00
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)
child Child? @relation("ContestRegistrationChild", fields: [childId], references: [id], onDelete: SetNull)
2025-12-09 11:10:36 +08:00
works ContestWork[] /// 参赛作品
2026-01-13 14:01:17 +08:00
creatorUser User? @relation("ContestRegistrationCreator", fields: [creator], references: [id], onDelete: SetNull)
modifierUser User? @relation("ContestRegistrationModifier", fields: [modifier], references: [id], onDelete: SetNull)
2025-12-09 11:10:36 +08:00
2026-01-09 18:14:35 +08:00
teachers ContestRegistrationTeacher[] /// 指导老师关联
2025-12-09 11:10:36 +08:00
@@index([contestId, tenantId])
@@index([userId, contestId])
@@index([teamId])
@@index([registrationState])
@@index([participantType])
@@index([childId])
2025-12-09 11:10:36 +08:00
@@map("t_contest_registration")
}
2026-01-09 18:14:35 +08:00
/// 报名指导老师关联表
model ContestRegistrationTeacher {
2026-01-13 14:01:17 +08:00
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") /// 更新时间
2026-01-09 18:14:35 +08:00
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")
}
2025-12-09 11:10:36 +08:00
/// 参赛作品表
model ContestWork {
2026-01-13 14:01:17 +08:00
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
2026-01-16 14:18:32 +08:00
previewUrl String? @map("preview_url") @db.Text /// 作品预览URL兼容单预览图
previewUrls Json? @map("preview_urls") /// 作品预览图URL列表多模型场景
2026-01-13 14:01:17 +08:00
aiModelMeta Json? @map("ai_model_meta") /// AI建模元数据
userWorkId Int? @map("user_work_id") /// 关联用户作品库(从作品库选择提交时)
2026-01-08 09:17:46 +08:00
// 赛果相关字段
2026-01-13 14:01:17 +08:00
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)
userWork UserWork? @relation("ContestWorkUserWork", fields: [userWorkId], references: [id], onDelete: SetNull)
2026-01-13 14:01:17 +08:00
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)
2025-12-09 11:10:36 +08:00
@@index([tenantId, contestId, isLatest])
@@index([registrationId])
@@index([tenantId, contestId, submitTime, status])
@@index([contestId, status])
@@map("t_contest_work")
}
/// 作品附件文件表
model ContestWorkAttachment {
2026-01-13 14:01:17 +08:00
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") /// 文件路径
2025-12-09 11:10:36 +08:00
format String? /// 文件类型png,mp4
2026-01-13 14:01:17 +08:00
fileType String? @map("file_type") /// 素材类型image,video
size String @default("0") /// 文件大小
2025-12-09 11:10:36 +08:00
creator Int? /// 创建人ID
modifier Int? /// 修改人ID
2026-01-13 14:01:17 +08:00
createTime DateTime @default(now()) @map("create_time") /// 创建时间
modifyTime DateTime @updatedAt @map("modify_time") /// 更新时间
2025-12-09 11:10:36 +08:00
2026-01-13 14:01:17 +08:00
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)
2025-12-09 11:10:36 +08:00
@@index([tenantId, contestId, workId])
@@map("t_contest_work_attachment")
}
/// 比赛评委关联表(比赛与评委的多对多关系)
model ContestJudge {
2026-01-13 14:01:17 +08:00
id Int @id @default(autoincrement())
contestId Int @map("contest_id") /// 比赛id
judgeId Int @map("judge_id") /// 评委用户id
2025-12-09 11:10:36 +08:00
specialty String? /// 评审专业领域(可选)
2026-01-13 14:01:17 +08:00
weight Decimal? @db.Decimal(3, 2) /// 评审权重(可选,用于加权平均计算)
description String? @db.Text /// 评委在该比赛中的说明
2025-12-09 11:10:36 +08:00
creator Int? /// 创建人ID
modifier Int? /// 修改人ID
2026-01-13 14:01:17 +08:00
createTime DateTime @default(now()) @map("create_time") /// 创建时间
modifyTime DateTime @updatedAt @map("modify_time") /// 更新时间
validState Int @default(1) @map("valid_state") /// 有效状态1-有效2-失效
2025-12-09 11:10:36 +08:00
2026-01-13 14:01:17 +08:00
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)
2025-12-09 11:10:36 +08:00
@@unique([contestId, judgeId])
@@index([contestId])
@@index([judgeId])
@@map("t_contest_judge")
}
/// 作品分配表(评委分配作品)
model ContestWorkJudgeAssignment {
2026-01-13 14:01:17 +08:00
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
2025-12-09 11:10:36 +08:00
creator Int? /// 创建人ID
modifier Int? /// 修改人ID
2026-01-13 14:01:17 +08:00
createTime DateTime @default(now()) @map("create_time") /// 创建时间
modifyTime DateTime @updatedAt @map("modify_time") /// 更新时间
2025-12-09 11:10:36 +08:00
2026-01-13 14:01:17 +08:00
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)
2025-12-09 11:10:36 +08:00
@@unique([workId, judgeId])
@@index([contestId, judgeId])
@@index([workId])
@@index([status])
@@map("t_contest_work_judge_assignment")
}
/// 作品评分表
model ContestWorkScore {
2026-01-13 14:01:17 +08:00
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") /// 评分时间
2025-12-09 11:10:36 +08:00
creator Int? /// 创建人ID
modifier Int? /// 修改人ID
2026-01-13 14:01:17 +08:00
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)
2025-12-09 11:10:36 +08:00
@@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-失效
2026-01-13 14:01:17 +08:00
contest Contest @relation(fields: [contestId], references: [id], onDelete: Cascade)
creatorUser User? @relation("ContestNoticeCreator", fields: [creator], references: [id], onDelete: SetNull)
2025-12-09 11:10:36 +08:00
modifierUser User? @relation("ContestNoticeModifier", fields: [modifier], references: [id], onDelete: SetNull)
@@index([contestId])
@@index([publishTime])
@@index([noticeType])
@@map("t_contest_notice")
}
2026-01-09 18:14:35 +08:00
// ============================================
// 作业管理模块
// ============================================
/// 作业表
model Homework {
id Int @id @default(autoincrement())
tenantId Int @map("tenant_id") /// 租户ID
2026-01-13 14:01:17 +08:00
name String /// 作业名称
2026-01-09 18:14:35 +08:00
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") /// 提交结束时间
2026-01-13 14:01:17 +08:00
attachments Json? /// 附件列表 [{fileName, fileUrl, size}]
2026-01-09 18:14:35 +08:00
publishScope Json? @map("publish_scope") /// 公开范围班级ID数组
reviewRuleId Int? @map("review_rule_id") /// 评审规则ID
2026-01-13 14:01:17 +08:00
creator Int? /// 创建人ID
modifier Int? /// 修改人ID
2026-01-09 18:14:35 +08:00
createTime DateTime @default(now()) @map("create_time") /// 创建时间
modifyTime DateTime @updatedAt @map("modify_time") /// 更新时间
validState Int @default(1) @map("valid_state") /// 有效状态1-有效2-失效
2026-01-13 14:01:17 +08:00
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
reviewRule HomeworkReviewRule? @relation(fields: [reviewRuleId], references: [id], onDelete: SetNull)
2026-01-09 18:14:35 +08:00
submissions HomeworkSubmission[] /// 作业提交记录
2026-01-13 14:01:17 +08:00
creatorUser User? @relation("HomeworkCreator", fields: [creator], references: [id], onDelete: SetNull)
modifierUser User? @relation("HomeworkModifier", fields: [modifier], references: [id], onDelete: SetNull)
2026-01-09 18:14:35 +08:00
@@index([tenantId, status])
@@index([tenantId, submitStartTime, submitEndTime])
@@map("t_homework")
}
/// 作业提交表
model HomeworkSubmission {
2026-01-13 14:01:17 +08:00
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-失效
2026-01-09 18:14:35 +08:00
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 {
2026-01-13 14:01:17 +08:00
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-失效
2026-01-09 18:14:35 +08:00
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 {
2026-01-13 14:01:17 +08:00
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-失效
2026-01-09 18:14:35 +08:00
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")
}
2026-01-13 14:01:17 +08:00
// ============================================
// AI 3D 模型生成模块
// ============================================
/// 预设评语表
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")
}
/// 子女信息表
model Child {
id Int @id @default(autoincrement())
parentId Int @map("parent_id") /// 家长用户ID
name String @db.VarChar(50) /// 子女姓名
gender String? @db.VarChar(10) /// 性别male/female
birthday DateTime? @db.Date /// 出生日期
grade String? @db.VarChar(20) /// 年级
city String? @db.VarChar(50) /// 所在城市
schoolName String? @map("school_name") @db.VarChar(100) /// 学校/幼儿园名称
avatar String? @db.VarChar(500) /// 头像URL
isDeleted Int @default(0) @map("is_deleted") /// 软删除标记
createTime DateTime @default(now()) @map("create_time") /// 创建时间
modifyTime DateTime @updatedAt @map("modify_time") /// 修改时间
parent User @relation("ChildParent", fields: [parentId], references: [id], onDelete: Cascade)
registrations ContestRegistration[] @relation("ContestRegistrationChild")
@@index([parentId])
@@map("children")
}
// ==================== 家长-子女账号关系 ====================
/// 家长-子女独立账号管理关系
model UserParentChild {
id Int @id @default(autoincrement())
parentUserId Int @map("parent_user_id") /// 家长 User.id
childUserId Int @map("child_user_id") /// 子女 User.id
relationship String? @db.VarChar(20) /// 关系father/mother/guardian
controlMode String @default("open") @map("control_mode") /// 管控模式open(子女自主)/restricted(需家长确认)
createTime DateTime @default(now()) @map("create_time")
parent User @relation("ParentUser", fields: [parentUserId], references: [id], onDelete: Cascade)
child User @relation("ChildUser", fields: [childUserId], references: [id], onDelete: Cascade)
@@unique([parentUserId, childUserId])
@@index([childUserId])
@@map("user_parent_child")
}
// ==================== UGC 用户作品 ====================
/// 用户作品主表
model UserWork {
id Int @id @default(autoincrement())
userId Int @map("user_id") /// 创作者 User.id
title String @db.VarChar(200) /// 作品名称
coverUrl String? @map("cover_url") @db.Text /// 封面图 URL
description String? @db.Text /// 作品简介
visibility String @default("private") /// 可见性public/private/friends
status String @default("draft") /// 状态draft/pending_review/published/rejected/taken_down
reviewNote String? @map("review_note") @db.Text /// 审核备注/拒绝原因
reviewTime DateTime? @map("review_time") /// 审核时间
reviewerId Int? @map("reviewer_id") /// 审核人 ID
machineReviewResult String? @map("machine_review_result") /// 机器预审结果safe/suspicious
machineReviewNote String? @map("machine_review_note") @db.Text /// 机器预审备注
isRecommended Boolean @default(false) @map("is_recommended") /// 是否推荐
// 统计字段(冗余,提升查询性能)
viewCount Int @default(0) @map("view_count")
likeCount Int @default(0) @map("like_count")
favoriteCount Int @default(0) @map("favorite_count")
commentCount Int @default(0) @map("comment_count")
shareCount Int @default(0) @map("share_count")
// AI 创作元数据
originalImageUrl String? @map("original_image_url") @db.Text /// 用户原画 URL
voiceInputUrl String? @map("voice_input_url") @db.Text /// 语音输入 URL
textInput String? @map("text_input") @db.Text /// 文字描述输入
aiMeta Json? @map("ai_meta") /// AI 生成的元数据(模型/参数等)
// 通用字段
publishTime DateTime? @map("publish_time") /// 发布时间
isDeleted Int @default(0) @map("is_deleted") /// 软删除标记
createTime DateTime @default(now()) @map("create_time")
modifyTime DateTime @updatedAt @map("modify_time")
creator User @relation("UserWorkCreator", fields: [userId], references: [id], onDelete: Cascade)
pages UserWorkPage[] @relation("UserWorkPages")
tags WorkTagRelation[] @relation("UserWorkTags")
likes UserWorkLike[] @relation("UserWorkLikes")
favorites UserWorkFavorite[] @relation("UserWorkFavorites")
comments UserWorkComment[] @relation("UserWorkComments")
reports UserWorkReport[] @relation("UserWorkReports")
reviewLogs ContentReviewLog[] @relation("ContentReviewLogWork")
contestWorks ContestWork[] @relation("ContestWorkUserWork") /// 关联的活动参赛作品
@@index([userId, status])
@@index([status, publishTime])
@@index([isRecommended, publishTime])
@@map("user_works")
}
/// 绘本分页内容
model UserWorkPage {
id Int @id @default(autoincrement())
workId Int @map("work_id") /// 作品 ID
pageNo Int @map("page_no") /// 页码(从 1 开始)
imageUrl String? @map("image_url") @db.Text /// 页面插图 URL
text String? @db.Text /// 页面文字
audioUrl String? @map("audio_url") @db.Text /// 页面配音 URL
work UserWork @relation("UserWorkPages", fields: [workId], references: [id], onDelete: Cascade)
@@unique([workId, pageNo])
@@map("user_work_pages")
}
// ==================== 标签体系 ====================
/// 作品标签
model WorkTag {
id Int @id @default(autoincrement())
name String @unique @db.VarChar(50) /// 标签名称
category String? @db.VarChar(50) /// 所属分类(如:主题/风格/情感)
color String? @db.VarChar(20) /// 标签颜色(如:#6366f1
sort Int @default(0) /// 排序权重
status String @default("enabled") /// 状态enabled/disabled
usageCount Int @default(0) @map("usage_count") /// 使用次数(冗余)
createTime DateTime @default(now()) @map("create_time")
modifyTime DateTime @updatedAt @map("modify_time")
works WorkTagRelation[] @relation("WorkTagRelations")
@@index([category, sort])
@@map("work_tags")
}
/// 作品-标签关联
model WorkTagRelation {
id Int @id @default(autoincrement())
workId Int @map("work_id")
tagId Int @map("tag_id")
work UserWork @relation("UserWorkTags", fields: [workId], references: [id], onDelete: Cascade)
tag WorkTag @relation("WorkTagRelations", fields: [tagId], references: [id], onDelete: Cascade)
@@unique([workId, tagId])
@@map("work_tag_relations")
}
// ==================== 社区互动 ====================
/// 作品点赞
model UserWorkLike {
id Int @id @default(autoincrement())
userId Int @map("user_id")
workId Int @map("work_id")
createTime DateTime @default(now()) @map("create_time")
user User @relation("UserWorkLikeUser", fields: [userId], references: [id], onDelete: Cascade)
work UserWork @relation("UserWorkLikes", fields: [workId], references: [id], onDelete: Cascade)
@@unique([userId, workId])
@@map("user_work_likes")
}
/// 作品收藏
model UserWorkFavorite {
id Int @id @default(autoincrement())
userId Int @map("user_id")
workId Int @map("work_id")
createTime DateTime @default(now()) @map("create_time")
user User @relation("UserWorkFavoriteUser", fields: [userId], references: [id], onDelete: Cascade)
work UserWork @relation("UserWorkFavorites", fields: [workId], references: [id], onDelete: Cascade)
@@unique([userId, workId])
@@map("user_work_favorites")
}
/// 作品评论
model UserWorkComment {
id Int @id @default(autoincrement())
workId Int @map("work_id")
userId Int @map("user_id")
parentId Int? @map("parent_id") /// 父评论 ID支持回复嵌套
content String @db.Text /// 评论内容
status String @default("pending") /// 状态pending/approved/rejected
createTime DateTime @default(now()) @map("create_time")
user User @relation("UserWorkCommentUser", fields: [userId], references: [id], onDelete: Cascade)
work UserWork @relation("UserWorkComments", fields: [workId], references: [id], onDelete: Cascade)
parent UserWorkComment? @relation("CommentReplies", fields: [parentId], references: [id], onDelete: SetNull)
replies UserWorkComment[] @relation("CommentReplies")
@@index([workId, status, createTime])
@@map("user_work_comments")
}
/// 作品举报
model UserWorkReport {
id Int @id @default(autoincrement())
reporterId Int @map("reporter_id") /// 举报人
targetType String @map("target_type") /// 举报类型work/comment/user
targetId Int @map("target_id") /// 被举报对象 ID
targetUserId Int? @map("target_user_id") /// 被举报人 User.id
reason String @db.VarChar(200) /// 举报原因
description String? @db.Text /// 详细描述
status String @default("pending") /// 状态pending/handled/ignored
handleAction String? @map("handle_action") /// 处理操作takedown/warn/ban/ignore
handleNote String? @map("handle_note") @db.Text /// 处理备注
handlerId Int? @map("handler_id") /// 处理人 ID
handleTime DateTime? @map("handle_time") /// 处理时间
createTime DateTime @default(now()) @map("create_time")
reporter User @relation("UserWorkReportReporter", fields: [reporterId], references: [id], onDelete: Cascade)
targetUser User? @relation("UserWorkReportTarget", fields: [targetUserId], references: [id], onDelete: SetNull)
work UserWork? @relation("UserWorkReports", fields: [targetId], references: [id], onDelete: Cascade)
@@index([status, createTime])
@@index([targetType, targetId])
@@map("user_work_reports")
}
// ==================== 内容审核日志 ====================
/// 审核操作日志
model ContentReviewLog {
id Int @id @default(autoincrement())
targetType String @map("target_type") /// 审核类型work/comment
targetId Int @map("target_id") /// 审核对象 ID
workId Int? @map("work_id") /// 关联作品 ID方便查询
action String /// 操作approve/reject/takedown/restore
reason String? @db.Text /// 原因
note String? @db.Text /// 备注
operatorId Int @map("operator_id") /// 操作人 ID
createTime DateTime @default(now()) @map("create_time")
operator User @relation("ContentReviewLogOperator", fields: [operatorId], references: [id], onDelete: Cascade)
work UserWork? @relation("ContentReviewLogWork", fields: [workId], references: [id], onDelete: SetNull)
@@index([targetType, targetId])
@@index([workId])
@@map("content_review_logs")
}