uploadPaperFigure 存 public/exam/<卷>/<uuid>.ext;编辑器预览/移除; quiz-block 渲染 q.figure;compose 挂 exam-figures 卷防重建丢失。 Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Haiku 4.5
parent
890e7ef3ac
commit
c706f485cc
@@ -1,6 +1,8 @@
|
||||
"use server";
|
||||
|
||||
import crypto from "node:crypto";
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import { and, eq, sql } from "drizzle-orm";
|
||||
import { revalidatePath } from "next/cache";
|
||||
import { z } from "zod";
|
||||
@@ -392,3 +394,25 @@ export async function deleteExamPaper(paperId: string): Promise<void> {
|
||||
revalidatePath("/parent/exams");
|
||||
revalidatePath("/exam");
|
||||
}
|
||||
|
||||
// xuchao: 上传试卷题目配图(几何体等)——存 public/exam/<paperId>/<uuid>.<ext>,返回文件名写回 q.figure
|
||||
// 生产容器 public/exam 挂卷持久化(compose volumes: exam-figures),重建不丢
|
||||
export async function uploadPaperFigure(
|
||||
paperId: string,
|
||||
file: File,
|
||||
): Promise<{ filename?: string; error?: string }> {
|
||||
const parent = await getSessionUser();
|
||||
if (!parent || parent.role !== "parent") return { error: "请先以家长身份登录" };
|
||||
if (!/^[a-z0-9-]+$/.test(paperId)) return { error: "试卷编号不合法" };
|
||||
if (!file.type.startsWith("image/")) return { error: "只能上传图片文件" };
|
||||
const ext = file.name.toLowerCase().split(".").pop();
|
||||
if (!["png", "jpg", "jpeg", "webp"].includes(ext ?? "")) return { error: "只支持 png/jpg/webp 图片" };
|
||||
if (file.size > 8 * 1024 * 1024) return { error: "图片不能超过 8MB" };
|
||||
|
||||
const buf = Buffer.from(await file.arrayBuffer());
|
||||
const filename = `${crypto.randomUUID()}.${ext}`;
|
||||
const dir = path.join(process.cwd(), "public", "exam", paperId);
|
||||
fs.mkdirSync(dir, { recursive: true });
|
||||
fs.writeFileSync(path.join(dir, filename), buf);
|
||||
return { filename };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user