feat(courseware,docs): 完善课件传输与岛编辑并统一全仓文档
- 增加课件上传、班级可见范围、设备补收与传输进度 - 整合自定义灵动岛编辑器和相关客户端交互 - 同步三端契约、数据库迁移、部署配置与隔离回归 - 按源码统一文档与官网说明,移除过时任务书和审查记录 - 保持产品版本为 1.4.0
This commit is contained in:
1 parent
536379036a
commit
c7f215a09c
127 files changed
+4334
-8482
No files matched your search
@@ -0,0 +1,35 @@
|
||||
CREATE TABLE "Courseware" (
|
||||
"id" TEXT NOT NULL PRIMARY KEY, "ownerId" TEXT NOT NULL, "name" TEXT NOT NULL,
|
||||
"size" INTEGER NOT NULL, "category" TEXT NOT NULL, "extension" TEXT NOT NULL,
|
||||
"archiveDate" TEXT NOT NULL, "storagePath" TEXT NOT NULL, "sha256" TEXT NOT NULL,
|
||||
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
CONSTRAINT "Courseware_ownerId_fkey" FOREIGN KEY ("ownerId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE
|
||||
);
|
||||
CREATE UNIQUE INDEX "Courseware_storagePath_key" ON "Courseware"("storagePath");
|
||||
CREATE INDEX "Courseware_ownerId_createdAt_idx" ON "Courseware"("ownerId", "createdAt");
|
||||
CREATE TABLE "CoursewareVisibility" (
|
||||
"coursewareId" TEXT NOT NULL, "classId" TEXT NOT NULL, PRIMARY KEY ("coursewareId", "classId"),
|
||||
FOREIGN KEY ("coursewareId") REFERENCES "Courseware"("id") ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
FOREIGN KEY ("classId") REFERENCES "Class"("id") ON DELETE CASCADE ON UPDATE CASCADE
|
||||
);
|
||||
CREATE INDEX "CoursewareVisibility_classId_idx" ON "CoursewareVisibility"("classId");
|
||||
CREATE TABLE "CoursewarePush" (
|
||||
"id" TEXT NOT NULL PRIMARY KEY, "coursewareId" TEXT NOT NULL, "classId" TEXT NOT NULL,
|
||||
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY ("coursewareId") REFERENCES "Courseware"("id") ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
FOREIGN KEY ("classId") REFERENCES "Class"("id") ON DELETE CASCADE ON UPDATE CASCADE
|
||||
);
|
||||
CREATE INDEX "CoursewarePush_classId_createdAt_idx" ON "CoursewarePush"("classId", "createdAt");
|
||||
CREATE TABLE "CoursewareReceipt" (
|
||||
"pushId" TEXT NOT NULL, "deviceId" TEXT NOT NULL, "completedAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY ("pushId", "deviceId"),
|
||||
FOREIGN KEY ("pushId") REFERENCES "CoursewarePush"("id") ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
FOREIGN KEY ("deviceId") REFERENCES "ClientDevice"("id") ON DELETE CASCADE ON UPDATE CASCADE
|
||||
);
|
||||
-- 仅为旧默认组和内置教学岗位补充新能力;自定义组仍需管理员按需授权。
|
||||
INSERT INTO "PermissionGroupItem" ("id", "groupId", "key")
|
||||
SELECT 'cw-read-' || "id", "id", 'courseware:read' FROM "PermissionGroup"
|
||||
WHERE "defaultRole" IN ('ADMIN', 'TEACHER') OR "id" IN ('builtin-head', 'builtin-teacher');
|
||||
INSERT INTO "PermissionGroupItem" ("id", "groupId", "key")
|
||||
SELECT 'cw-write-' || "id", "id", 'courseware:write' FROM "PermissionGroup"
|
||||
WHERE "defaultRole" IN ('ADMIN', 'TEACHER') OR "id" IN ('builtin-head', 'builtin-teacher');
|
||||
@@ -34,6 +34,7 @@ datasource db {
|
||||
|
||||
/// 账号:管理员 / 教师 / ClassHelper 班级端。**学生不在这里**(见 Student)。
|
||||
model User {
|
||||
coursewares Courseware[]
|
||||
id String @id @default(cuid())
|
||||
/// 登录名:教师即**工号**,班级端即班级码
|
||||
username String @unique
|
||||
@@ -201,6 +202,8 @@ model TermWeek {
|
||||
/// `grade`(高一/高二/高三)表示**当前年级**,学年升级时批量改它即可 ——
|
||||
/// 升级只动这一个字段,班级记录、学生名单、作业与成绩全部沿用,**不归档**。
|
||||
model Class {
|
||||
coursewares CoursewareVisibility[]
|
||||
coursewarePushes CoursewarePush[]
|
||||
id String @id @default(cuid())
|
||||
/// 班级称呼:由 enrollmentYear + classIndex 生成,如「2026级1班」
|
||||
name String
|
||||
@@ -501,6 +504,7 @@ model AppSetting {
|
||||
/// 服务端由此知道**每台机器在哪个班、版本多少、是否在线**,并把更新与远控
|
||||
/// 指令按「查库 + 心跳拉取」的范式下发,不新增长连接握手。
|
||||
model ClientDevice {
|
||||
coursewareReceipts CoursewareReceipt[]
|
||||
id String @id @default(cuid())
|
||||
/// 该设备当前登录的班级(未登录时为空)
|
||||
classId String?
|
||||
@@ -717,3 +721,50 @@ model PromotionRun {
|
||||
createdAt DateTime @default(now())
|
||||
finishedAt DateTime?
|
||||
}
|
||||
/// 课件只在完整接收并计算摘要后入库;存储路径不对客户端暴露。
|
||||
model Courseware {
|
||||
id String @id @default(cuid())
|
||||
ownerId String
|
||||
name String
|
||||
size Int
|
||||
category String
|
||||
extension String
|
||||
archiveDate String
|
||||
storagePath String @unique
|
||||
sha256 String
|
||||
createdAt DateTime @default(now())
|
||||
owner User @relation(fields: [ownerId], references: [id], onDelete: Restrict)
|
||||
visibility CoursewareVisibility[]
|
||||
pushes CoursewarePush[]
|
||||
@@index([ownerId, createdAt])
|
||||
}
|
||||
|
||||
model CoursewareVisibility {
|
||||
coursewareId String
|
||||
classId String
|
||||
courseware Courseware @relation(fields: [coursewareId], references: [id], onDelete: Cascade)
|
||||
class Class @relation(fields: [classId], references: [id], onDelete: Cascade)
|
||||
@@id([coursewareId, classId])
|
||||
@@index([classId])
|
||||
}
|
||||
|
||||
/// 下发持久化,班级离线时不丢失;每台设备完成下载后单独回执。
|
||||
model CoursewarePush {
|
||||
id String @id @default(cuid())
|
||||
coursewareId String
|
||||
classId String
|
||||
createdAt DateTime @default(now())
|
||||
courseware Courseware @relation(fields: [coursewareId], references: [id], onDelete: Cascade)
|
||||
class Class @relation(fields: [classId], references: [id], onDelete: Cascade)
|
||||
receipts CoursewareReceipt[]
|
||||
@@index([classId, createdAt])
|
||||
}
|
||||
|
||||
model CoursewareReceipt {
|
||||
pushId String
|
||||
deviceId String
|
||||
completedAt DateTime @default(now())
|
||||
push CoursewarePush @relation(fields: [pushId], references: [id], onDelete: Cascade)
|
||||
device ClientDevice @relation(fields: [deviceId], references: [id], onDelete: Cascade)
|
||||
@@id([pushId, deviceId])
|
||||
}
|
||||
@@ -78,6 +78,7 @@ async function resetDatabase(): Promise<void> {
|
||||
await prisma.clientCommand.deleteMany();
|
||||
await prisma.clientDevice.deleteMany();
|
||||
await prisma.clientRelease.deleteMany();
|
||||
await prisma.courseware.deleteMany();
|
||||
await prisma.aiAudit.deleteMany();
|
||||
await prisma.userPermissionGroup.deleteMany();
|
||||
await prisma.permissionGroupItem.deleteMany();
|
||||
|
||||
Reference in new issue
Block a user