feat(题库生成): 重构参数配置为教材、知识点和题型
This commit is contained in:
parent
18ca189d56
commit
b993a94385
|
|
@ -24,25 +24,81 @@ const rawContent = ref("");
|
||||||
const cancelTokenSource = ref(null);
|
const cancelTokenSource = ref(null);
|
||||||
|
|
||||||
// ── 参数配置 ──
|
// ── 参数配置 ──
|
||||||
const questionType = ref("choice"); // 'choice' | 'fillBlank' | 'translation' | 'reading'
|
|
||||||
const difficulty = ref("medium"); // 'easy' | 'medium' | 'hard'
|
const difficulty = ref("medium"); // 'easy' | 'medium' | 'hard'
|
||||||
const questionCount = ref(5);
|
const questionCount = ref(5);
|
||||||
const topicInput = ref("");
|
|
||||||
|
// 新增维度:教材章节、知识点、题型
|
||||||
|
const textbookChapter = ref(""); // 教材章节(预设)
|
||||||
|
const customTextbookChapter = ref(""); // 自定义教材章节输入
|
||||||
|
const selectedKnowledgePoints = ref([]); // 选中的知识点
|
||||||
|
const customKnowledgePoint = ref(""); // 自定义知识点输入
|
||||||
|
const questionFormat = ref("单项选择"); // 题型(预设)
|
||||||
|
const customQuestionFormat = ref(""); // 自定义题型输入
|
||||||
|
|
||||||
// ── 配置选项 ──
|
// ── 配置选项 ──
|
||||||
const TYPE_OPTIONS = [
|
const DIFFICULTY_OPTIONS = [
|
||||||
{ value: "choice", label: "选择题", desc: "单项选择题" },
|
{ value: "very_easy", label: "容易", color: "#10b981" },
|
||||||
{ value: "fillBlank", label: "填空题", desc: "根据语境填空" },
|
{ value: "easy", label: "较易", color: "#34d399" },
|
||||||
{ value: "translation", label: "翻译题", desc: "英汉互译" },
|
{ value: "medium", label: "适中", color: "#f59e0b" },
|
||||||
{ value: "reading", label: "阅读理解", desc: "阅读文章并回答问题" },
|
{ value: "hard", label: "较难", color: "#f97316" },
|
||||||
|
{ value: "very_hard", label: "困难", color: "#ef4444" },
|
||||||
];
|
];
|
||||||
|
|
||||||
const DIFFICULTY_OPTIONS = [
|
// 教材章节预设选项
|
||||||
{ value: "easy", label: "简单", color: "#10b981" },
|
const CHAPTER_OPTIONS = [
|
||||||
{ value: "medium", label: "中等", color: "#f59e0b" },
|
{ value: "Starter Unit1 You and Me", label: "Starter Unit1 You and Me" },
|
||||||
{ value: "hard", label: "困难", color: "#ef4444" },
|
{ value: "Starter Unit2 Keep Tidy", label: "Starter Unit2 Keep Tidy" },
|
||||||
|
{ value: "Starter Unit3 Welcome!", label: "Starter Unit3 Welcome!" },
|
||||||
|
{ value: "Unit 1 You and Me", label: "Unit 1 You and Me" },
|
||||||
|
{ value: "Unit 2 We're Family!", label: "Unit 2 We're Family!" },
|
||||||
|
{ value: "Unit 3 My School", label: "Unit 3 My School" },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// 知识点预设选项
|
||||||
|
const KNOWLEDGE_POINT_OPTIONS = [
|
||||||
|
{ value: "语法", label: "语法" },
|
||||||
|
{ value: "词汇", label: "词汇" },
|
||||||
|
{ value: "冠词", label: "冠词" },
|
||||||
|
{ value: "不定冠词", label: "不定冠词" },
|
||||||
|
{ value: "定冠词", label: "定冠词" },
|
||||||
|
{ value: "名词", label: "名词" },
|
||||||
|
{ value: "动词", label: "动词" },
|
||||||
|
{ value: "形容词", label: "形容词" },
|
||||||
|
{ value: "代词", label: "代词" },
|
||||||
|
{ value: "介词", label: "介词" },
|
||||||
|
{ value: "时态", label: "时态" },
|
||||||
|
{ value: "一般现在时", label: "一般现在时" },
|
||||||
|
{ value: "现在进行时", label: "现在进行时" },
|
||||||
|
{ value: "一般过去时", label: "一般过去时" },
|
||||||
|
{ value: "句型结构", label: "句型结构" },
|
||||||
|
{ value: "阅读理解", label: "阅读理解" },
|
||||||
|
{ value: "写作", label: "写作" },
|
||||||
|
];
|
||||||
|
|
||||||
|
// 题型预设选项
|
||||||
|
const FORMAT_OPTIONS = [
|
||||||
|
{ value: "单项选择", label: "单项选择" },
|
||||||
|
{ value: "完形填空", label: "完形填空" },
|
||||||
|
{ value: "句型转换", label: "句型转换" },
|
||||||
|
{ value: "词汇运用", label: "词汇运用" },
|
||||||
|
{ value: "翻译句子", label: "翻译句子" },
|
||||||
|
{ value: "阅读理解", label: "阅读理解" },
|
||||||
|
{ value: "书面表达", label: "书面表达" },
|
||||||
|
{ value: "短文填空", label: "短文填空" },
|
||||||
|
{ value: "语法填空", label: "语法填空" },
|
||||||
|
{ value: "选词填空", label: "选词填空" },
|
||||||
|
];
|
||||||
|
|
||||||
|
// 切换知识点选中状态
|
||||||
|
const toggleKnowledgePoint = (value) => {
|
||||||
|
const index = selectedKnowledgePoints.value.indexOf(value);
|
||||||
|
if (index > -1) {
|
||||||
|
selectedKnowledgePoints.value.splice(index, 1);
|
||||||
|
} else {
|
||||||
|
selectedKnowledgePoints.value.push(value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// ── 解析试题内容 ──
|
// ── 解析试题内容 ──
|
||||||
const parsedQuestions = computed(() => {
|
const parsedQuestions = computed(() => {
|
||||||
const raw = rawContent.value;
|
const raw = rawContent.value;
|
||||||
|
|
@ -111,19 +167,30 @@ function extractOptions(text) {
|
||||||
|
|
||||||
// ── 构建请求体 ──
|
// ── 构建请求体 ──
|
||||||
const buildRequestBody = () => {
|
const buildRequestBody = () => {
|
||||||
const typeLabel = TYPE_OPTIONS.find((t) => t.value === questionType.value)?.label || "选择题";
|
|
||||||
const difficultyLabel =
|
const difficultyLabel =
|
||||||
DIFFICULTY_OPTIONS.find((d) => d.value === difficulty.value)?.label || "中等";
|
DIFFICULTY_OPTIONS.find((d) => d.value === difficulty.value)?.label || "中等";
|
||||||
|
|
||||||
const userPrompt = `请生成 ${questionCount.value} 道${difficultyLabel}难度的英语${typeLabel}${
|
// 构建知识点字符串:预设选项 + 自定义输入
|
||||||
topicInput.value ? `,主题为:${topicInput.value}` : ""
|
const allKnowledgePoints = [
|
||||||
}。
|
...selectedKnowledgePoints.value,
|
||||||
|
...(customKnowledgePoint.value ? [customKnowledgePoint.value] : []),
|
||||||
|
];
|
||||||
|
const knowledgePointStr = allKnowledgePoints.length > 0 ? allKnowledgePoints.join("、") : "";
|
||||||
|
|
||||||
|
// 教材章节:优先使用自定义输入,否则使用预设选择
|
||||||
|
const chapterStr = customTextbookChapter.value || textbookChapter.value || "";
|
||||||
|
|
||||||
|
// 题型:优先使用自定义输入,否则使用预设选择
|
||||||
|
const formatStr = customQuestionFormat.value || questionFormat.value || "";
|
||||||
|
|
||||||
|
const userPrompt = `请生成 ${questionCount.value} 道${difficultyLabel}难度的英语试题。
|
||||||
|
|
||||||
要求:
|
要求:
|
||||||
1. 题目类型:${typeLabel}
|
1. 题型:${formatStr}
|
||||||
2. 难度等级:${difficultyLabel}
|
2. 难度等级:${difficultyLabel}
|
||||||
3. 题目数量:${questionCount.value} 道
|
3. 题目数量:${questionCount.value} 道
|
||||||
${topicInput.value ? `4. 主题/知识点:${topicInput.value}` : ""}
|
${chapterStr ? `4. 教材章节:${chapterStr}` : ""}
|
||||||
|
${knowledgePointStr ? `5. 知识点:${knowledgePointStr}` : ""}
|
||||||
|
|
||||||
请严格按照指定的输出格式生成试题。`;
|
请严格按照指定的输出格式生成试题。`;
|
||||||
|
|
||||||
|
|
@ -218,10 +285,14 @@ const resetAll = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const loadExample = () => {
|
const loadExample = () => {
|
||||||
questionType.value = "choice";
|
|
||||||
difficulty.value = "medium";
|
difficulty.value = "medium";
|
||||||
questionCount.value = 3;
|
questionCount.value = 3;
|
||||||
topicInput.value = "一般现在时";
|
textbookChapter.value = "Starter Unit2 Keep Tidy";
|
||||||
|
customTextbookChapter.value = "";
|
||||||
|
selectedKnowledgePoints.value = ["语法", "冠词", "不定冠词"];
|
||||||
|
customKnowledgePoint.value = "";
|
||||||
|
questionFormat.value = "句型转换";
|
||||||
|
customQuestionFormat.value = "";
|
||||||
};
|
};
|
||||||
|
|
||||||
const goBack = () => router.back();
|
const goBack = () => router.back();
|
||||||
|
|
@ -287,24 +358,6 @@ onUnmounted(() => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="config-body">
|
<div class="config-body">
|
||||||
<!-- 题目类型 -->
|
|
||||||
<div class="config-item">
|
|
||||||
<label class="config-label">题目类型</label>
|
|
||||||
<div class="type-grid">
|
|
||||||
<button
|
|
||||||
v-for="opt in TYPE_OPTIONS"
|
|
||||||
:key="opt.value"
|
|
||||||
class="type-btn"
|
|
||||||
:class="{ active: questionType === opt.value }"
|
|
||||||
@click="questionType = opt.value"
|
|
||||||
:disabled="status === 'generating'"
|
|
||||||
>
|
|
||||||
<div class="type-label">{{ opt.label }}</div>
|
|
||||||
<div class="type-desc">{{ opt.desc }}</div>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 难度等级 -->
|
<!-- 难度等级 -->
|
||||||
<div class="config-item">
|
<div class="config-item">
|
||||||
<label class="config-label">难度等级</label>
|
<label class="config-label">难度等级</label>
|
||||||
|
|
@ -344,14 +397,77 @@ onUnmounted(() => {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 知识点/主题 -->
|
<!-- 教材章节 -->
|
||||||
<div class="config-item">
|
<div class="config-item">
|
||||||
<label class="config-label">知识点/主题(可选)</label>
|
<label class="config-label">教材章节(可选)</label>
|
||||||
|
<select
|
||||||
|
v-model="textbookChapter"
|
||||||
|
class="select-input"
|
||||||
|
:disabled="status === 'generating'"
|
||||||
|
>
|
||||||
|
<option value="">请选择教材章节</option>
|
||||||
|
<option
|
||||||
|
v-for="opt in CHAPTER_OPTIONS"
|
||||||
|
:key="opt.value"
|
||||||
|
:value="opt.value"
|
||||||
|
>
|
||||||
|
{{ opt.label }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
v-model="topicInput"
|
v-model="customTextbookChapter"
|
||||||
class="topic-input"
|
class="topic-input mt-2"
|
||||||
placeholder="例如:一般现在时、定语从句、商务英语..."
|
placeholder="或输入自定义教材章节..."
|
||||||
|
:disabled="status === 'generating'"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 知识点 -->
|
||||||
|
<div class="config-item">
|
||||||
|
<label class="config-label">知识点(可多选)</label>
|
||||||
|
<div class="knowledge-grid">
|
||||||
|
<button
|
||||||
|
v-for="opt in KNOWLEDGE_POINT_OPTIONS"
|
||||||
|
:key="opt.value"
|
||||||
|
class="knowledge-btn"
|
||||||
|
:class="{ active: selectedKnowledgePoints.includes(opt.value) }"
|
||||||
|
@click="toggleKnowledgePoint(opt.value)"
|
||||||
|
:disabled="status === 'generating'"
|
||||||
|
>
|
||||||
|
{{ opt.label }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
v-model="customKnowledgePoint"
|
||||||
|
class="topic-input mt-2"
|
||||||
|
placeholder="或输入自定义知识点..."
|
||||||
|
:disabled="status === 'generating'"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 题型 -->
|
||||||
|
<div class="config-item">
|
||||||
|
<label class="config-label">题型</label>
|
||||||
|
<select
|
||||||
|
v-model="questionFormat"
|
||||||
|
class="select-input"
|
||||||
|
:disabled="status === 'generating'"
|
||||||
|
>
|
||||||
|
<option
|
||||||
|
v-for="opt in FORMAT_OPTIONS"
|
||||||
|
:key="opt.value"
|
||||||
|
:value="opt.value"
|
||||||
|
>
|
||||||
|
{{ opt.label }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
v-model="customQuestionFormat"
|
||||||
|
class="topic-input mt-2"
|
||||||
|
placeholder="或输入自定义题型..."
|
||||||
:disabled="status === 'generating'"
|
:disabled="status === 'generating'"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -750,6 +866,27 @@ onUnmounted(() => {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 1.5rem;
|
gap: 1.5rem;
|
||||||
|
overflow-y: auto;
|
||||||
|
min-height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.config-body::-webkit-scrollbar {
|
||||||
|
width: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.config-body::-webkit-scrollbar-track {
|
||||||
|
background: rgba(0, 0, 0, 0.1);
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.config-body::-webkit-scrollbar-thumb {
|
||||||
|
background: rgba(16, 185, 129, 0.3);
|
||||||
|
border-radius: 3px;
|
||||||
|
transition: background 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.config-body::-webkit-scrollbar-thumb:hover {
|
||||||
|
background: rgba(16, 185, 129, 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
.config-item {
|
.config-item {
|
||||||
|
|
@ -773,50 +910,6 @@ onUnmounted(() => {
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Type Selection */
|
|
||||||
.type-grid {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 1fr 1fr;
|
|
||||||
gap: 0.75rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.type-btn {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
gap: 0.25rem;
|
|
||||||
padding: 1rem;
|
|
||||||
background: rgba(255, 255, 255, 0.02);
|
|
||||||
border: 1px solid rgba(255, 255, 255, 0.08);
|
|
||||||
border-radius: 12px;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: all 0.2s;
|
|
||||||
}
|
|
||||||
.type-btn:hover:not(:disabled) {
|
|
||||||
background: rgba(16, 185, 129, 0.06);
|
|
||||||
border-color: rgba(16, 185, 129, 0.3);
|
|
||||||
}
|
|
||||||
.type-btn.active {
|
|
||||||
background: rgba(16, 185, 129, 0.12);
|
|
||||||
border-color: #10b981;
|
|
||||||
}
|
|
||||||
.type-btn:disabled {
|
|
||||||
opacity: 0.4;
|
|
||||||
cursor: not-allowed;
|
|
||||||
}
|
|
||||||
.type-label {
|
|
||||||
font-size: 0.95rem;
|
|
||||||
font-weight: 600;
|
|
||||||
color: var(--text-primary);
|
|
||||||
}
|
|
||||||
.type-desc {
|
|
||||||
font-size: 0.75rem;
|
|
||||||
color: var(--text-secondary);
|
|
||||||
}
|
|
||||||
.type-btn.active .type-label {
|
|
||||||
color: #10b981;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Difficulty Selection */
|
/* Difficulty Selection */
|
||||||
.difficulty-group {
|
.difficulty-group {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
@ -858,6 +951,7 @@ onUnmounted(() => {
|
||||||
outline: none;
|
outline: none;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
-webkit-appearance: none;
|
-webkit-appearance: none;
|
||||||
|
appearance: none;
|
||||||
}
|
}
|
||||||
.range-slider::-webkit-slider-thumb {
|
.range-slider::-webkit-slider-thumb {
|
||||||
-webkit-appearance: none;
|
-webkit-appearance: none;
|
||||||
|
|
@ -910,6 +1004,74 @@ onUnmounted(() => {
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Select Input */
|
||||||
|
.select-input {
|
||||||
|
width: 100%;
|
||||||
|
padding: 0.875rem 1rem;
|
||||||
|
background: rgba(0, 0, 0, 0.2);
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||||
|
border-radius: 10px;
|
||||||
|
color: var(--text-primary);
|
||||||
|
font-size: 0.9rem;
|
||||||
|
outline: none;
|
||||||
|
transition: border-color 0.2s, box-shadow 0.2s;
|
||||||
|
box-sizing: border-box;
|
||||||
|
cursor: pointer;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%2310b981' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: right 1rem center;
|
||||||
|
padding-right: 2.5rem;
|
||||||
|
}
|
||||||
|
.select-input:focus {
|
||||||
|
border-color: rgba(16, 185, 129, 0.5);
|
||||||
|
box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.1);
|
||||||
|
}
|
||||||
|
.select-input:disabled {
|
||||||
|
opacity: 0.4;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
.select-input option {
|
||||||
|
background: #1a1a2e;
|
||||||
|
color: var(--text-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Knowledge Points Grid */
|
||||||
|
.knowledge-grid {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
.knowledge-btn {
|
||||||
|
padding: 0.5rem 0.875rem;
|
||||||
|
background: rgba(255, 255, 255, 0.02);
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||||
|
border-radius: 8px;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
font-size: 0.8rem;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.2s;
|
||||||
|
}
|
||||||
|
.knowledge-btn:hover:not(:disabled) {
|
||||||
|
background: rgba(16, 185, 129, 0.1);
|
||||||
|
border-color: rgba(16, 185, 129, 0.3);
|
||||||
|
color: #10b981;
|
||||||
|
}
|
||||||
|
.knowledge-btn.active {
|
||||||
|
background: rgba(16, 185, 129, 0.15);
|
||||||
|
border-color: #10b981;
|
||||||
|
color: #10b981;
|
||||||
|
}
|
||||||
|
.knowledge-btn:disabled {
|
||||||
|
opacity: 0.4;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mt-2 {
|
||||||
|
margin-top: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
/* Example Button */
|
/* Example Button */
|
||||||
.example-btn {
|
.example-btn {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
@ -1275,9 +1437,6 @@ onUnmounted(() => {
|
||||||
.right-panel {
|
.right-panel {
|
||||||
padding: 1.25rem 1rem;
|
padding: 1.25rem 1rem;
|
||||||
}
|
}
|
||||||
.type-grid {
|
|
||||||
grid-template-columns: 1fr;
|
|
||||||
}
|
|
||||||
.options-grid {
|
.options-grid {
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue