diff --git a/CLAUDE.md b/CLAUDE.md
index 9919bfb..afbf642 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -5,7 +5,7 @@
## Current Status
-**Phase 1b in progress.** Category CRUD + Question CRUD done. Remaining: 知识卡编辑、题目状态流转 UI 完善、批量导入。
+**Phase 1b in progress.** Category CRUD + Question CRUD + 知识卡编辑 done. Remaining: 题目状态流转 UI 完善、批量导入。
Development follows the phased roadmap in [dev-spec.md](./dev-spec.md) §九.
@@ -38,7 +38,7 @@ src/
│ ├── layout/ # Sidebar, Header, AdminLayout
│ ├── charts/ # StatsCard, chart wrappers
│ ├── category/ # Category CRUD (columns, dialogs)
-│ ├── question/ # Question CRUD (columns, form, StatusBadge, DistractorEditor)
+│ ├── question/ # Question CRUD (columns, form, StatusBadge, DistractorEditor, KnowledgeCardFields)
├── lib/
│ ├── api-client.ts # HTTP client for /admin/* endpoints
│ ├── auth.ts # Admin JWT token management
diff --git a/src/components/question/KnowledgeCardFields.tsx b/src/components/question/KnowledgeCardFields.tsx
new file mode 100644
index 0000000..6551ae7
--- /dev/null
+++ b/src/components/question/KnowledgeCardFields.tsx
@@ -0,0 +1,178 @@
+import { useState } from "react"
+import type { UseFormRegisterReturn } from "react-hook-form"
+import { Button } from "@/components/ui/button"
+import { Input } from "@/components/ui/input"
+import { Label } from "@/components/ui/label"
+import { Textarea } from "@/components/ui/textarea"
+import {
+ Card,
+ CardContent,
+ CardDescription,
+ CardHeader,
+ CardTitle,
+} from "@/components/ui/card"
+import { Badge } from "@/components/ui/badge"
+
+const BASIC_MAX = 100
+const DEEP_MAX = 300
+
+interface KnowledgeCardFieldsProps {
+ basicRegister: UseFormRegisterReturn
+ deepRegister: UseFormRegisterReturn
+ sourceRefRegister: UseFormRegisterReturn
+ basicError?: string
+ deepError?: string
+ watchBasic: string
+ watchDeep: string
+}
+
+export function KnowledgeCardFields({
+ basicRegister,
+ deepRegister,
+ sourceRefRegister,
+ basicError,
+ deepError,
+ watchBasic,
+ watchDeep,
+}: KnowledgeCardFieldsProps) {
+ const [showPreview, setShowPreview] = useState(false)
+ const [deepExpanded, setDeepExpanded] = useState(!!watchDeep)
+
+ const basicCount = watchBasic.length
+ const deepCount = watchDeep.length
+ const basicOver = basicCount > BASIC_MAX
+ const deepOver = deepCount > DEEP_MAX
+
+ return (
+
+ {/* 基础版 */}
+
+
+
+
+ 所有用户可见
+
+
+
+ 2-3 句趣味解读,让用户答完题后学到新知识
+
+
+
+ {basicError && (
+
{basicError}
+ )}
+
+ {basicCount}/{BASIC_MAX}
+
+
+
+
+ {/* 深度版 */}
+
+
+
+ {deepExpanded && (
+ <>
+
+ 扩展背景故事、趣味延伸,给 Pro 用户更深层的内容体验
+
+
+
+ {deepError && (
+
{deepError}
+ )}
+
+ {deepCount}/{DEEP_MAX}
+
+
+ >
+ )}
+
+
+ {/* 来源参考 */}
+
+
+
+
+
+ {/* 预览切换 */}
+
+
+ {showPreview && (
+
+
+ 知识卡预览
+
+ 用户答完题后看到的知识卡效果
+
+
+
+ {watchBasic ? (
+ {watchBasic}
+ ) : (
+
+ (基础版内容为空)
+
+ )}
+ {watchDeep && (
+ <>
+
+
+
+ Pro
+
+
+ 深度解读
+
+
+
+ {watchDeep}
+
+
+ >
+ )}
+
+
+ )}
+
+ )
+}
diff --git a/src/components/question/QuestionForm.tsx b/src/components/question/QuestionForm.tsx
index ced8e81..b7e0f4c 100644
--- a/src/components/question/QuestionForm.tsx
+++ b/src/components/question/QuestionForm.tsx
@@ -16,6 +16,7 @@ import {
SelectValue,
} from "@/components/ui/select"
import { DistractorEditor } from "@/components/question/DistractorEditor"
+import { KnowledgeCardFields } from "@/components/question/KnowledgeCardFields"
import { fetchCategories } from "@/lib/api/category-api"
import { DIFFICULTY_LABELS, QUESTION_STATUSES } from "@/lib/constants"
import type { Question, Difficulty, QuestionStatus } from "@/types/question"
@@ -33,6 +34,7 @@ const questionSchema = z.object({
status: z.enum(["draft", "reviewing", "published", "archived"]),
knowledgeCardBasic: z.string().min(1, "请填写基础知识卡").max(100),
knowledgeCardDeep: z.string().max(300).optional(),
+ sourceRef: z.string().max(500).optional(),
})
type FormValues = z.infer
@@ -65,6 +67,7 @@ export function QuestionForm({ question }: QuestionFormProps) {
status: question.status,
knowledgeCardBasic: question.knowledgeCardBasic,
knowledgeCardDeep: question.knowledgeCardDeep ?? "",
+ sourceRef: question.sourceRef ?? "",
}
: {
stem: "",
@@ -75,6 +78,7 @@ export function QuestionForm({ question }: QuestionFormProps) {
status: "draft",
knowledgeCardBasic: "",
knowledgeCardDeep: "",
+ sourceRef: "",
},
})
@@ -208,40 +212,16 @@ export function QuestionForm({ question }: QuestionFormProps) {
- {/* 知识卡(基础版) */}
-
-
-
- {errors.knowledgeCardBasic && (
-
- {errors.knowledgeCardBasic.message}
-
- )}
-
-
- {/* 知识卡(深度版) */}
-
-
-
- {errors.knowledgeCardDeep && (
-
- {errors.knowledgeCardDeep.message}
-
- )}
-
+ {/* 知识卡 */}
+
{/* 提交 */}
diff --git a/src/types/question.ts b/src/types/question.ts
index 9c243ca..263928b 100644
--- a/src/types/question.ts
+++ b/src/types/question.ts
@@ -11,6 +11,7 @@ export interface Question {
status: QuestionStatus
knowledgeCardBasic: string
knowledgeCardDeep?: string
+ sourceRef?: string
source: "system" | "ugc"
stats: {
timesAnswered: number
@@ -30,4 +31,5 @@ export interface QuestionFormData {
status: QuestionStatus
knowledgeCardBasic: string
knowledgeCardDeep?: string
+ sourceRef?: string
}