Merge branch 'remove-cover-page'
This commit is contained in:
27
src/components/A4Workspace.test.ts
Normal file
27
src/components/A4Workspace.test.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import { mount } from '@vue/test-utils'
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { createEmptyTeachingDesign } from '../domain/teachingDesign'
|
||||
import A4Workspace from './A4Workspace.vue'
|
||||
|
||||
describe('A4Workspace', () => {
|
||||
it('renders a selected lesson without cover state', () => {
|
||||
const design = createEmptyTeachingDesign('1.md')
|
||||
design.topic = 'CSS 弹性布局'
|
||||
|
||||
const wrapper = mount(A4Workspace, {
|
||||
props: { selectedDesign: design },
|
||||
})
|
||||
|
||||
expect(Object.keys(wrapper.props()).sort()).toEqual(['selectedDesign'])
|
||||
expect(wrapper.find('.cover-page').exists()).toBe(false)
|
||||
expect(wrapper.find('.teaching-design-page').exists()).toBe(true)
|
||||
})
|
||||
|
||||
it('renders no page when no lesson is selected', () => {
|
||||
const wrapper = mount(A4Workspace, {
|
||||
props: { selectedDesign: null },
|
||||
})
|
||||
|
||||
expect(wrapper.find('.page').exists()).toBe(false)
|
||||
})
|
||||
})
|
||||
@@ -1,16 +1,12 @@
|
||||
<script setup lang="ts">
|
||||
import type { BookCover, TeachingDesign } from '../domain/teachingDesign'
|
||||
import CoverPage from './CoverPage.vue'
|
||||
import type { TeachingDesign } from '../domain/teachingDesign'
|
||||
import TeachingDesignPage from './TeachingDesignPage.vue'
|
||||
|
||||
defineProps<{
|
||||
cover: BookCover
|
||||
selectedId: string
|
||||
selectedDesign: TeachingDesign | null
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
'update:cover': [patch: Partial<BookCover>]
|
||||
'update:design': [design: TeachingDesign]
|
||||
}>()
|
||||
</script>
|
||||
@@ -18,16 +14,8 @@ const emit = defineEmits<{
|
||||
<template>
|
||||
<div class="a4-workspace">
|
||||
<div class="a4-paper">
|
||||
<CoverPage
|
||||
v-if="selectedId === 'cover'"
|
||||
:course-name="cover.courseName"
|
||||
:teacher-name="cover.teacherName"
|
||||
:editable="true"
|
||||
@update:course-name="emit('update:cover', { courseName: $event })"
|
||||
@update:teacher-name="emit('update:cover', { teacherName: $event })"
|
||||
/>
|
||||
<TeachingDesignPage
|
||||
v-else-if="selectedDesign"
|
||||
v-if="selectedDesign"
|
||||
:design="selectedDesign"
|
||||
:editable="true"
|
||||
@update:design="emit('update:design', $event)"
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import EditableText from './EditableText.vue'
|
||||
|
||||
defineProps<{
|
||||
courseName: string
|
||||
teacherName: string
|
||||
editable: boolean
|
||||
}>()
|
||||
|
||||
defineEmits<{
|
||||
'update:courseName': [value: string]
|
||||
'update:teacherName': [value: string]
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<section class="page cover-page">
|
||||
<h1 class="cover-title">教学设计</h1>
|
||||
<div class="cover-field">
|
||||
<span class="cover-field-label">课程名称</span>
|
||||
<EditableText
|
||||
class="cover-field-value"
|
||||
:model-value="courseName"
|
||||
label="课程名称"
|
||||
:editable="editable"
|
||||
@update:model-value="$emit('update:courseName', $event)"
|
||||
/>
|
||||
</div>
|
||||
<div class="cover-field">
|
||||
<span class="cover-field-label">教师姓名</span>
|
||||
<EditableText
|
||||
class="cover-field-value"
|
||||
:model-value="teacherName"
|
||||
label="教师姓名"
|
||||
:editable="editable"
|
||||
@update:model-value="$emit('update:teacherName', $event)"
|
||||
/>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
@@ -7,7 +7,7 @@ describe('LessonSidebar', () => {
|
||||
it('emits a move when one lesson is dropped on another', async () => {
|
||||
const designs = [createEmptyTeachingDesign('1.md'), createEmptyTeachingDesign('2.md')]
|
||||
const wrapper = mount(LessonSidebar, {
|
||||
props: { designs, selectedId: designs[0]?.id ?? 'cover' },
|
||||
props: { designs, selectedId: designs[0]?.id ?? null },
|
||||
})
|
||||
|
||||
await wrapper.get('[data-index="0"]').trigger('dragstart')
|
||||
@@ -15,4 +15,14 @@ describe('LessonSidebar', () => {
|
||||
|
||||
expect(wrapper.emitted('move')?.[0]).toEqual([0, 1])
|
||||
})
|
||||
|
||||
it('does not render a cover navigation item', () => {
|
||||
const designs = [createEmptyTeachingDesign('1.md')]
|
||||
const wrapper = mount(LessonSidebar, {
|
||||
props: { designs, selectedId: null },
|
||||
})
|
||||
|
||||
expect(wrapper.text()).not.toContain('封面')
|
||||
expect(wrapper.find('.lesson-sidebar-cover').exists()).toBe(false)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -4,11 +4,11 @@ import type { DesignId, TeachingDesign } from '../domain/teachingDesign'
|
||||
|
||||
defineProps<{
|
||||
designs: TeachingDesign[]
|
||||
selectedId: 'cover' | DesignId
|
||||
selectedId: DesignId | null
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
select: [id: 'cover' | DesignId]
|
||||
select: [id: DesignId]
|
||||
remove: [id: DesignId]
|
||||
move: [from: number, to: number]
|
||||
}>()
|
||||
@@ -29,15 +29,6 @@ function onDrop(targetIndex: number): void {
|
||||
|
||||
<template>
|
||||
<nav class="lesson-sidebar" aria-label="教案目录">
|
||||
<button
|
||||
type="button"
|
||||
class="lesson-sidebar-item lesson-sidebar-cover"
|
||||
:class="{ 'lesson-sidebar-item--active': selectedId === 'cover' }"
|
||||
@click="emit('select', 'cover')"
|
||||
>
|
||||
封面
|
||||
</button>
|
||||
|
||||
<ul class="lesson-sidebar-list">
|
||||
<li
|
||||
v-for="(design, index) in designs"
|
||||
|
||||
@@ -74,6 +74,19 @@ describe('WorkspaceView', () => {
|
||||
expect(wrapper.text()).toContain('CSS 弹性布局')
|
||||
})
|
||||
|
||||
it('does not render cover navigation when lessons exist', async () => {
|
||||
const data = createEmptyBook()
|
||||
const design = createEmptyTeachingDesign('1.md')
|
||||
data.designs.push(design)
|
||||
data.selectedId = design.id
|
||||
mockBook(data)
|
||||
|
||||
const wrapper = mount(WorkspaceView, { props: { bookId: 'b1' } })
|
||||
await flushPromises()
|
||||
|
||||
expect(wrapper.text()).not.toContain('封面')
|
||||
})
|
||||
|
||||
it('clears the lessons after confirmation', async () => {
|
||||
const data = createEmptyBook()
|
||||
data.designs.push(createEmptyTeachingDesign('1.md'))
|
||||
|
||||
@@ -32,7 +32,6 @@ const {
|
||||
selectPage,
|
||||
moveDesign,
|
||||
removeDesign,
|
||||
updateCover,
|
||||
updateDesign,
|
||||
clearBook,
|
||||
generateLesson,
|
||||
@@ -299,10 +298,7 @@ function closeFixDialog(): void {
|
||||
@move="moveDesign"
|
||||
/>
|
||||
<A4Workspace
|
||||
:cover="book.cover"
|
||||
:selected-id="book.selectedId"
|
||||
:selected-design="selectedDesign"
|
||||
@update:cover="updateCover"
|
||||
@update:design="handleDesignUpdate"
|
||||
/>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user