This commit is contained in:
2026-06-16 07:51:38 -06:00
parent 8b0e4df43d
commit dcec78d4b7
7 changed files with 87 additions and 10 deletions

View File

@@ -18,6 +18,42 @@ function createBookWithDesign(filename = '1.md'): { data: TeachingBook; design:
return { data, design }
}
function generatedMarkdownWithAdditionalSection(topic: string): string {
return [
`# ${topic} 教学设计`,
'| | |',
'|:---|:---|',
`| **课题** | **${topic}** |`,
'| **课时** | 1课时40分钟 |',
'| **教学目标** | **知识目标**:理解概念。<br>**技能目标**:完成任务。<br>**素养目标**:规范表达。 |',
'| **教学重难点** | **重点**:任务流程。<br>**难点**:问题定位。 |',
'| **教学资源准备** | 机房、示例文件。 |',
'',
'## 教学过程',
'',
'| 教学环节 | 教学内容 | 教师活动 | 学生活动 | 设计意图 |',
'|:---|:---|:---|:---|:---|',
'| **1. 导入**<br>5分钟 | 引出任务。 | **情境导入**<br>展示案例。 | **观察思考**<br>回答问题。 | 明确目标。 |',
'',
'## 板书设计',
'',
'```text',
`${topic}`,
'```',
'',
'## 教学成效与反思',
'',
'| | |',
'|:---|:---|',
'| **教学成效** | 学生完成任务。 |',
'| **教学反思** | 后续加强练习。 |',
'',
'## 附加说明',
'',
'这是模型额外生成的内容。',
].join('\n')
}
describe('useTeachingBook', () => {
beforeEach(() => {
vi.clearAllMocks()
@@ -140,6 +176,25 @@ describe('useTeachingBook', () => {
expect(store.book.value.selectedId).toBe(store.book.value.designs[0]?.id)
})
it('generateLesson discards unclassified additional content from AI output', async () => {
mockGetBook(createEmptyBook())
vi.mocked(booksApi.generateLesson).mockResolvedValue({
filename: 'css-flex.md',
markdown: generatedMarkdownWithAdditionalSection('CSS 弹性布局'),
})
const store = useTeachingBook('b1')
await flushPromises()
const result = await store.generateLesson('CSS 弹性布局')
expect(result).toEqual({ ok: true })
expect(store.book.value.designs[0]?.additionalContent).toBe('')
expect(store.book.value.designs[0]?.warnings).not.toContainEqual(
expect.objectContaining({ code: 'unclassified-content' }),
)
})
it('generateLesson returns an error when the API call fails', async () => {
mockGetBook(createEmptyBook())
vi.mocked(booksApi.generateLesson).mockRejectedValue(new Error('Deepseek 请求失败。'))

View File

@@ -244,10 +244,18 @@ export function useTeachingBook(bookId: string): TeachingBookStore {
touch()
}
function removeGeneratedAdditionalContent(design: TeachingDesign): TeachingDesign {
design.additionalContent = ''
design.warnings = design.warnings.filter((warning) => warning.code !== 'unclassified-content')
return design
}
async function generateLesson(topic: string): Promise<GenerateLessonResult> {
try {
const result = await booksApi.generateLesson(topic)
const design = parseTeachingDesign(result.filename, result.markdown)
const design = removeGeneratedAdditionalContent(
parseTeachingDesign(result.filename, result.markdown),
)
book.value.designs.push(design)
book.value.selectedId = design.id
touch()
@@ -299,7 +307,9 @@ export function useTeachingBook(bookId: string): TeachingBookStore {
try {
const result = await booksApi.generateLesson(topic)
results[index] = parseTeachingDesign(result.filename, result.markdown)
results[index] = removeGeneratedAdditionalContent(
parseTeachingDesign(result.filename, result.markdown),
)
appendReadyLessons()
} catch (error) {
firstError = error instanceof Error ? error.message : '生成失败。'
@@ -322,7 +332,9 @@ export function useTeachingBook(bookId: string): TeachingBookStore {
const topic = existing.originalFilename.replace(/\.md$/i, '')
try {
const result = await booksApi.generateLesson(topic)
const newDesign = parseTeachingDesign(result.filename, result.markdown)
const newDesign = removeGeneratedAdditionalContent(
parseTeachingDesign(result.filename, result.markdown),
)
const index = book.value.designs.findIndex((d) => d.id === id)
if (index !== -1) {
book.value.designs.splice(index, 1, newDesign)