feat(exams,homework): add rich text exam editor and scan-based grading
- Add Tiptap-based rich text editor with custom extensions (dotted-mark, blank-node, image-node, group-block, question-block) for exam creation - Add AI auto-marking action to convert pasted exam text to structured editor doc - Add resizable split-panel layout for editor + live preview - Add student scan upload (photo of paper answers) with drag-drop and reorder - Add scan image viewer with zoom/rotate/fullscreen for teachers - Add scan grading view with side-by-side questions and scan images - Add /teacher/exams/new and /teacher/homework/submissions/[id]/scan-grading routes - Fix getScansAction to support both teacher (HOMEWORK_GRADE) and student (HOMEWORK_SUBMIT) permission scopes - Add i18n keys for rich editor, scan upload, and scan grading (zh-CN/en) - Sync architecture diagrams (004/005) with new modules, routes, and deps
This commit is contained in:
@@ -1,7 +1,11 @@
|
||||
import type { JSX } from "react"
|
||||
import Link from "next/link"
|
||||
import { notFound } from "next/navigation"
|
||||
import { getTranslations } from "next-intl/server"
|
||||
import { getHomeworkSubmissionDetails } from "@/modules/homework/data-access"
|
||||
import { HomeworkGradingView } from "@/modules/homework/components/homework-grading-view"
|
||||
import { Button } from "@/shared/components/ui/button"
|
||||
import { ScanLine } from "lucide-react"
|
||||
import { formatDate } from "@/shared/lib/utils"
|
||||
import {
|
||||
AiClientProvider,
|
||||
@@ -37,6 +41,7 @@ function createAiClientService(): AiClientService {
|
||||
|
||||
export default async function HomeworkSubmissionGradingPage({ params }: { params: Promise<{ submissionId: string }> }): Promise<JSX.Element> {
|
||||
const { submissionId } = await params
|
||||
const t = await getTranslations("examHomework")
|
||||
const submission = await getHomeworkSubmissionDetails(submissionId)
|
||||
|
||||
if (!submission) return notFound()
|
||||
@@ -58,6 +63,12 @@ export default async function HomeworkSubmissionGradingPage({ params }: { params
|
||||
<span className="capitalize">Status: {submission.status}</span>
|
||||
</div>
|
||||
</div>
|
||||
<Button asChild variant="outline" size="sm">
|
||||
<Link href={`/teacher/homework/submissions/${submissionId}/scan-grading`}>
|
||||
<ScanLine className="mr-2 h-4 w-4" />
|
||||
{t("homework.grade.scanGrading")}
|
||||
</Link>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<AiClientProvider service={aiClientService}>
|
||||
|
||||
Reference in New Issue
Block a user