IntelliClass_FE/components/course/Section.vue

135 lines
3.5 KiB
Vue

<script lang="ts" setup>
import { toast } from 'vue-sonner'
import { addResourceToSection } from '~/api/course'
import type { FetchError, ICourseSection, IResource } from '~/types'
const props = defineProps<{
tag?: string
section: ICourseSection
}>()
const emit = defineEmits<{
'refresh': []
'delete-section': [sectionId: number]
'delete-resource': [resourceId: number]
}>()
const isUploadOpen = ref(false)
const handleDeleteSection = () => {
if (props.section.resources.length > 0) {
const confirmDelete = confirm(
'该小节下有资源,删除后将无法恢复,是否继续?',
)
if (!confirmDelete) return
}
emit('delete-section', props.section.id)
}
const onCreateResource = (resource: IResource) => {
toast.promise(
addResourceToSection({
sectionId: props.section.id,
resourceId: resource.id,
}),
{
loading: '添加资源中...',
success: () => {
isUploadOpen.value = false
return '添加资源成功'
},
error: (error: FetchError) => {
return `添加资源失败: ${error.message}`
},
finally: () => {
emit('refresh')
},
},
)
}
</script>
<template>
<div class="rounded-md border border-muted overflow-hidden">
<div
class="w-full px-4 py-2.5 bg-muted dark:bg-muted/50 flex justify-between items-center group/section"
>
<div class="flex items-center gap-2">
<div class="w-10 flex justify-center">
<Badge
variant="outline"
class="text-xs bg-background"
>
<span>
{{
tag || section.resources.length > 0
? section.resources.length
: 0
}}
</span>
</Badge>
</div>
<h2 class="inline-flex items-center gap-2 text-sm font-medium">
<!-- <span>1.1</span> -->
<span class="text-ellipsis line-clamp-1">{{ section.title }}</span>
</h2>
</div>
<div
class="flex items-center gap-2 mr-8 opacity-0 group-hover/section:opacity-100"
>
<Button
variant="link"
size="xs"
class="flex items-center gap-1 text-muted-foreground"
@click="isUploadOpen = true"
>
<Icon
name="tabler:plus"
size="16px"
/>
<span>添加资源</span>
</Button>
<Button
variant="link"
size="xs"
class="flex items-center gap-1 text-red-500"
@click="handleDeleteSection"
>
<Icon
name="tabler:trash"
size="16px"
/>
<span>删除</span>
</Button>
</div>
</div>
<div
v-if="section.resources.length > 0"
class="flex flex-col gap-2 py-2"
>
<!-- Resource -->
<CourseResource
v-for="resource in section.resources"
:key="resource.id"
:resource="resource"
@refresh="emit('refresh')"
@delete-resource="emit('delete-resource', resource.id)"
/>
</div>
<!-- <div
v-else
class="py-4 flex items-center justify-center gap-2 text-muted-foreground"
>
<Icon name="tabler:circle-minus" size="16px" />
<span class="text-sm">该小节下暂无资源</span>
</div> -->
<ResourceUploader
v-model="isUploadOpen"
@refresh="emit('refresh')"
@on-create="onCreateResource"
/>
</div>
</template>
<style scoped></style>