|
<template> |
|
<div class="templates"> |
|
<div class="catalogs"> |
|
<div class="catalog" |
|
:class="{ 'active': activeCatalog === item.id }" |
|
v-for="item in templates" |
|
:key="item.id" |
|
@click="changeCatalog(item.id)" |
|
>{{ item.name }}</div> |
|
</div> |
|
<div class="content"> |
|
<div class="header"> |
|
<div class="types"> |
|
<div class="type" |
|
:class="{ 'active': activeType === item.value }" |
|
v-for="item in types" |
|
:key="item.value" |
|
@click="activeType = item.value" |
|
>{{ item.label }}</div> |
|
</div> |
|
<div class="insert-all" @click="insertTemplates(slides)">插入全部</div> |
|
</div> |
|
<div class="list" ref="listRef"> |
|
<template v-for="slide in slides" :key="slide.id"> |
|
<div |
|
class="slide-item" |
|
v-if="slide.type === activeType || activeType === 'all'" |
|
> |
|
<ThumbnailSlide class="thumbnail" :slide="slide" :size="180" /> |
|
|
|
<div class="btns"> |
|
<Button class="btn" type="primary" size="small" @click="insertTemplate(slide)">插入模板</Button> |
|
</div> |
|
</div> |
|
</template> |
|
</div> |
|
</div> |
|
</div> |
|
</template> |
|
|
|
<script lang="ts" setup> |
|
import { ref, onMounted } from 'vue' |
|
import { storeToRefs } from 'pinia' |
|
import { useSlidesStore } from '@/store' |
|
import type { Slide } from '@/types/slides' |
|
import api from '@/services' |
|
|
|
import ThumbnailSlide from '@/views/components/ThumbnailSlide/index.vue' |
|
import Button from '@/components/Button.vue' |
|
|
|
const emit = defineEmits<{ |
|
(event: 'select', payload: Slide): void |
|
(event: 'selectAll', payload: Slide[]): void |
|
}>() |
|
|
|
const slidesStore = useSlidesStore() |
|
const { templates } = storeToRefs(slidesStore) |
|
const slides = ref<Slide[]>([]) |
|
const listRef = ref<HTMLElement>() |
|
const types = ref<{ |
|
label: string |
|
value: string |
|
}[]>([ |
|
{ label: '全部', value: 'all' }, |
|
{ label: '封面', value: 'cover' }, |
|
{ label: '目录', value: 'contents' }, |
|
{ label: '过渡', value: 'transition' }, |
|
{ label: '内容', value: 'content' }, |
|
{ label: '结束', value: 'end' }, |
|
]) |
|
const activeType = ref('all') |
|
|
|
const activeCatalog = ref('') |
|
|
|
const insertTemplate = (slide: Slide) => { |
|
emit('select', slide) |
|
} |
|
|
|
const insertTemplates = (slides: Slide[]) => { |
|
emit('selectAll', slides) |
|
} |
|
|
|
const changeCatalog = (id: string) => { |
|
activeCatalog.value = id |
|
api.getFileData(activeCatalog.value).then(ret => { |
|
slides.value = ret.slides |
|
|
|
if (listRef.value) listRef.value.scrollTo(0, 0) |
|
}) |
|
} |
|
|
|
onMounted(() => { |
|
changeCatalog(templates.value[0].id) |
|
}) |
|
</script> |
|
|
|
<style lang="scss" scoped> |
|
.templates { |
|
width: 500px; |
|
height: 500px; |
|
display: flex; |
|
user-select: none; |
|
} |
|
.catalogs { |
|
width: 108px; |
|
margin-right: 10px; |
|
padding-right: 10px; |
|
border-right: 1px solid $borderColor; |
|
overflow: auto; |
|
|
|
.catalog { |
|
padding: 7px 8px; |
|
border-radius: $borderRadius; |
|
cursor: pointer; |
|
|
|
&:hover { |
|
background-color: #f5f5f5; |
|
} |
|
|
|
&.active { |
|
color: $themeColor; |
|
background-color: rgba($color: $themeColor, $alpha: .05); |
|
border-right: 2px solid $themeColor; |
|
font-weight: 700; |
|
} |
|
|
|
& + .catalog { |
|
margin-top: 3px; |
|
} |
|
} |
|
} |
|
.content { |
|
display: flex; |
|
flex-direction: column; |
|
} |
|
.header { |
|
display: flex; |
|
justify-content: space-between; |
|
align-items: center; |
|
margin-bottom: 10px; |
|
padding-right: 4px; |
|
|
|
&:hover .insert-all { |
|
opacity: 1; |
|
transition: opacity $transitionDelay; |
|
} |
|
} |
|
.types { |
|
display: flex; |
|
|
|
.type { |
|
border-radius: $borderRadius; |
|
padding: 3px 8px; |
|
font-size: 12px; |
|
cursor: pointer; |
|
|
|
& +.type { |
|
margin-left: 4px; |
|
} |
|
|
|
&.active { |
|
color: $themeColor; |
|
background-color: rgba($color: $themeColor, $alpha:.05); |
|
font-weight: 700; |
|
} |
|
|
|
&:hover { |
|
background-color: #f5f5f5; |
|
} |
|
} |
|
} |
|
.insert-all { |
|
opacity: 0; |
|
font-size: 12px; |
|
color: $themeColor; |
|
text-decoration: underline; |
|
cursor: pointer; |
|
} |
|
.list { |
|
width: 392px; |
|
padding: 2px; |
|
margin-right: -10px; |
|
padding-right: 10px; |
|
overflow: auto; |
|
@include flex-grid-layout(); |
|
} |
|
.slide-item { |
|
position: relative; |
|
@include flex-grid-layout-children(2, 48%); |
|
|
|
&:hover .btns { |
|
opacity: 1; |
|
} |
|
|
|
&:hover .thumbnail { |
|
outline-color: $themeColor; |
|
} |
|
|
|
.btns { |
|
@include absolute-0(); |
|
|
|
flex-direction: column; |
|
justify-content: center; |
|
align-items: center; |
|
display: flex; |
|
background-color: rgba($color: #000, $alpha: .25); |
|
opacity: 0; |
|
transition: opacity $transitionDelay; |
|
} |
|
|
|
.thumbnail { |
|
outline: 2px solid $borderColor; |
|
transition: outline $transitionDelay; |
|
border-radius: $borderRadius; |
|
cursor: pointer; |
|
} |
|
} |
|
</style> |