<script lang="ts" setup> import type { AIGeneratedContent } from '.' defineProps<{ data?: AIGeneratedContent | null }>() defineEmits<{ (e: 'delete', itemIndex: number): void (e: 'regenerate', itemIndex: number, conversationId: string): void (e: 'regenerateAll' | 'download' | 'save'): void }>() </script> <template> <div v-if="data" class="flex flex-col gap-4 rounded-md border p-4 overflow-hidden relative" > <!-- header --> <div class="flex justify-between items-start gap-2"> <div class="flex items-center gap-2"> <Icon name="mage:stars-c-fill" class="text-xl text-amber-500" /> <h1 class="text-lg font-medium"> {{ data.title }} </h1> </div> <div class="flex items-center gap-2"> <Button variant="outline" size="sm" @click="$emit('regenerateAll')" > <Icon name="tabler:reload" /> 重新生成 </Button> <Button variant="outline" size="sm" @click="$emit('download')" > <Icon name="tabler:download" /> 下载 </Button> <Button size="sm" @click="$emit('save')" > <Icon name="tabler:copy" /> 存入教案库 </Button> </div> </div> <!-- items --> <div v-for="(item, i) in data.sections" :key="i" class="flex flex-col rounded-md border overflow-hidden" > <div class="flex justify-between items-center gap-2 p-2 px-4 bg-gradient-to-r from-primary/15 to-muted text-background" > <span class="text-sm text-foreground font-medium"> {{ item.title }} </span> <div class="flex items-center"> <Button variant="link" size="xs" class="text-muted-foreground" @click="$emit('regenerate', i, data.conversationId)" > <Icon name="tabler:reload" /> 重新生成 </Button> <Button variant="link" size="xs" class="text-muted-foreground" @click="$emit('delete', i)" > <Icon name="tabler:trash" /> 删除 </Button> </div> </div> <div class="p-4 py-2 bg-background"> <MarkdownRenderer :source="item.content" /> </div> </div> </div> <slot v-else name="empty" > <div class="flex flex-col justify-center items-center gap-2 py-8 rounded-md border" > <Icon name="lucide:text-cursor-input" class="text-3xl opacity-50" /> <span class="text-xs font-medium opacity-50">等待生成内容</span> </div> </slot> </template> <style scoped></style>