feat(lesson-preparation): 师生交互对话体 inline 渲染

This commit is contained in:
SpecialX
2026-07-04 11:28:16 +08:00
parent 8583e3e387
commit cbed4ef508

View File

@@ -0,0 +1,91 @@
"use client";
import { useTranslations } from "next-intl";
import type { InteractionBlockData, LessonPlanNode, QATurn } from "../../types";
import { useLessonPlanEditor } from "../../hooks/use-lesson-plan-editor";
interface Props {
node: LessonPlanNode;
}
/**
* V4 师生交互节点的 inline 对话体渲染。
* - 师/生 角色标签JetBrains Mono
* - 教师提问下方 italic 灰色 [预期:...]
* - 对话轮次之间 dashed 线分隔
*/
export function InlineQaDialog({ node }: Props) {
const t = useTranslations("lessonPreparation");
const toggleExpand = useLessonPlanEditor((s) => s.toggleExpand);
const data = node.data as InteractionBlockData;
return (
<div className="lp-inline-node">
<div className="lp-inline-node-head">
<span
style={{
width: 5,
height: 5,
borderRadius: "50%",
background: "var(--lp-dot-interaction)",
display: "inline-block",
}}
/>
<span>{t("v4.interaction.label")}</span>
<span style={{ marginLeft: "auto", fontFamily: "JetBrains Mono, monospace", fontSize: 9, color: "var(--lp-inline-node-meta)" }}>
{data.turns?.length ?? 0}
</span>
<button
type="button"
onClick={() => toggleExpand(node.id)}
style={{
cursor: "pointer",
padding: "2px 6px",
borderRadius: 3,
color: "var(--lp-inline-node-meta)",
fontSize: 11,
background: "transparent",
border: "none",
}}
>
{t("v4.contextMenu.collapseFromPaper")}
</button>
</div>
<h4 className="lp-inline-node-title">{node.title}</h4>
<div className="lp-inline-node-body">
{data.designIntent && (
<p style={{ fontSize: 13, marginBottom: 8 }}>{data.designIntent}</p>
)}
<div className="lp-qa-dialog">
{(data.turns ?? []).map((turn, idx) => (
<QaTurnView key={turn.id} turn={turn} index={idx} />
))}
{(!data.turns || data.turns.length === 0) && (
<p style={{ color: "var(--muted-foreground)", fontSize: 12 }}>
</p>
)}
</div>
</div>
</div>
);
}
function QaTurnView({ turn, index }: { turn: QATurn; index: number }) {
const t = useTranslations("lessonPreparation");
const roleClass = turn.role === "teacher" ? "teacher" : "student";
const roleLabel = turn.role === "teacher" ? t("v4.interaction.roleTeacher") : t("v4.interaction.roleStudent");
void index;
return (
<div className="lp-qa-turn">
<div className={`lp-qa-role ${roleClass}`}>{roleLabel}</div>
<div className="lp-qa-content">
{turn.content}
{turn.role === "teacher" && turn.expectedAnswer && (
<span className="lp-qa-prompt">[{turn.expectedAnswer}]</span>
)}
</div>
</div>
);
}