refactor: RBAC权限系统重构 + UI组件拆分 + 测试修复 + 架构文档
Some checks failed
CI / build-deploy (push) Has been cancelled
Some checks failed
CI / build-deploy (push) Has been cancelled
- RBAC: 新增30个权限点、DataScope行级权限、requirePermission守卫,所有57+ Server Action接入权限校验 - UI拆分: exam-form(1623行→11文件)、textbook-reader(744行→7文件),均降至300行以内 - 测试: 新增5个单元测试文件(19用例),修复4个集成测试文件(38用例全部通过) - 架构文档: 新增架构影响地图(004/005)、标准功能清单(006)、差距审计报告(007) - 项目规则: 架构图优先规则,改码必同步图 - 安全: rehype-sanitize净化、AES加密API Key、权限路由守卫 - 无障碍: skip-link、aria-label、prefers-reduced-motion - 性能: next/font优化、next/image、代码分割
This commit is contained in:
148
src/modules/textbooks/components/knowledge-point-dialogs.tsx
Normal file
148
src/modules/textbooks/components/knowledge-point-dialogs.tsx
Normal file
@@ -0,0 +1,148 @@
|
||||
"use client"
|
||||
|
||||
import type { KnowledgePoint } from "../types"
|
||||
import { Button } from "@/shared/components/ui/button"
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from "@/shared/components/ui/dialog"
|
||||
import { Input } from "@/shared/components/ui/input"
|
||||
import { Label } from "@/shared/components/ui/label"
|
||||
import { Textarea } from "@/shared/components/ui/textarea"
|
||||
import { CreateQuestionDialog } from "@/modules/questions/components/create-question-dialog"
|
||||
|
||||
interface KnowledgePointDialogsProps {
|
||||
// Create KP dialog
|
||||
createDialogOpen: boolean
|
||||
setCreateDialogOpen: (open: boolean) => void
|
||||
selectedText: string
|
||||
isCreating: boolean
|
||||
onCreateKnowledgePoint: (formData: FormData) => Promise<boolean | void>
|
||||
|
||||
// Edit KP dialog
|
||||
editKpDialogOpen: boolean
|
||||
setEditKpDialogOpen: (open: boolean) => void
|
||||
editingKp: KnowledgePoint | null
|
||||
isUpdatingKp: boolean
|
||||
onUpdateKnowledgePoint: (formData: FormData) => Promise<void>
|
||||
|
||||
// Question dialog
|
||||
questionDialogOpen: boolean
|
||||
setQuestionDialogOpen: (open: boolean) => void
|
||||
targetKpForQuestion: KnowledgePoint | null
|
||||
}
|
||||
|
||||
export function KnowledgePointDialogs({
|
||||
createDialogOpen,
|
||||
setCreateDialogOpen,
|
||||
selectedText,
|
||||
isCreating,
|
||||
onCreateKnowledgePoint,
|
||||
editKpDialogOpen,
|
||||
setEditKpDialogOpen,
|
||||
editingKp,
|
||||
isUpdatingKp,
|
||||
onUpdateKnowledgePoint,
|
||||
questionDialogOpen,
|
||||
setQuestionDialogOpen,
|
||||
targetKpForQuestion,
|
||||
}: KnowledgePointDialogsProps) {
|
||||
return (
|
||||
<>
|
||||
<Dialog open={createDialogOpen} onOpenChange={setCreateDialogOpen}>
|
||||
<DialogContent>
|
||||
<DialogHeader>
|
||||
<DialogTitle>添加知识点</DialogTitle>
|
||||
<DialogDescription>
|
||||
从选中的文本创建知识点。
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<form action={onCreateKnowledgePoint as (formData: FormData) => void}>
|
||||
<div className="grid gap-4 py-4">
|
||||
<div className="grid gap-2">
|
||||
<Label htmlFor="name">名称</Label>
|
||||
<Input id="name" name="name" defaultValue={selectedText} required />
|
||||
</div>
|
||||
<div className="grid gap-2">
|
||||
<Label htmlFor="description">描述(可选)</Label>
|
||||
<Textarea id="description" name="description" placeholder="请输入描述..." />
|
||||
</div>
|
||||
</div>
|
||||
<DialogFooter>
|
||||
<Button type="button" variant="outline" onClick={() => setCreateDialogOpen(false)} disabled={isCreating}>
|
||||
取消
|
||||
</Button>
|
||||
<Button type="submit" disabled={isCreating}>
|
||||
{isCreating ? "创建中..." : "创建"}
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</form>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
||||
<Dialog open={editKpDialogOpen} onOpenChange={setEditKpDialogOpen}>
|
||||
<DialogContent>
|
||||
<DialogHeader>
|
||||
<DialogTitle>编辑知识点</DialogTitle>
|
||||
<DialogDescription>
|
||||
修改知识点的名称和描述。
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<form action={onUpdateKnowledgePoint}>
|
||||
<div className="grid gap-4 py-4">
|
||||
<div className="grid gap-2">
|
||||
<Label htmlFor="edit-name">显示名称</Label>
|
||||
<Input id="edit-name" name="name" defaultValue={editingKp?.name} required />
|
||||
</div>
|
||||
<div className="grid gap-2">
|
||||
<Label htmlFor="edit-description">描述(可选)</Label>
|
||||
<Textarea id="edit-description" name="description" defaultValue={editingKp?.description || ""} placeholder="请输入描述..." />
|
||||
</div>
|
||||
|
||||
<div className="space-y-2 border rounded-md p-3 bg-muted/20">
|
||||
<div className="flex items-center justify-between">
|
||||
<Label htmlFor="edit-anchorText" className="text-muted-foreground text-xs flex items-center gap-1">
|
||||
高级:关联文本 (影响文中高亮)
|
||||
</Label>
|
||||
</div>
|
||||
<div className="pt-2">
|
||||
<Input
|
||||
key={editingKp?.id}
|
||||
id="edit-anchorText"
|
||||
name="anchorText"
|
||||
defaultValue={editingKp?.anchorText || editingKp?.name}
|
||||
className="text-sm font-mono"
|
||||
required
|
||||
/>
|
||||
<p className="text-[10px] text-muted-foreground mt-1">
|
||||
修改此字段会改变文中被高亮匹配的文字。通常保持与原文一致。
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<DialogFooter>
|
||||
<Button type="button" variant="outline" onClick={() => setEditKpDialogOpen(false)} disabled={isUpdatingKp}>
|
||||
取消
|
||||
</Button>
|
||||
<Button type="submit" disabled={isUpdatingKp}>
|
||||
{isUpdatingKp ? "保存中..." : "保存"}
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</form>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
||||
<CreateQuestionDialog
|
||||
open={questionDialogOpen}
|
||||
onOpenChange={setQuestionDialogOpen}
|
||||
defaultKnowledgePointIds={targetKpForQuestion ? [targetKpForQuestion.id] : []}
|
||||
defaultContent={targetKpForQuestion ? `Please explain the knowledge point: ${targetKpForQuestion.name}` : ""}
|
||||
defaultType="text"
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user