214 lines
5.8 KiB
Vue
214 lines
5.8 KiB
Vue
<script lang="ts" setup>
|
|
import { useFetchWrapped } from '~/composables/useFetchWrapped'
|
|
import GBTaskCard from '~/components/aigc/generation/GBTaskCard.vue'
|
|
import { useTourState } from '~/composables/useTourState'
|
|
import SlideCreateCourseGreen from '~/components/SlideCreateCourseGreen.vue'
|
|
|
|
const route = useRoute()
|
|
const overlay = useOverlay()
|
|
const slide = overlay.create(SlideCreateCourseGreen)
|
|
const toast = useToast()
|
|
const loginState = useLoginState()
|
|
const tourState = useTourState()
|
|
|
|
const page = ref(1)
|
|
const pageCount = ref(15)
|
|
const searchInput = ref('')
|
|
const debounceSearch = refDebounced(searchInput, 1000)
|
|
|
|
watch(debounceSearch, () => (page.value = 1))
|
|
|
|
const { data: videoList, refresh: refreshVideoList } = useAsyncData(
|
|
() =>
|
|
useFetchWrapped<
|
|
req.gen.GBVideoList & AuthedRequest,
|
|
BaseResponse<PagedData<GBVideoItem>>
|
|
>('App.Digital_VideoTask.GetList', {
|
|
token: loginState.token!,
|
|
user_id: loginState.user.id,
|
|
to_user_id: loginState.user.id,
|
|
page: page.value,
|
|
perpage: pageCount.value,
|
|
title: debounceSearch.value,
|
|
}),
|
|
{
|
|
watch: [page, pageCount, debounceSearch],
|
|
}
|
|
)
|
|
|
|
const onCreateCourseGreenClick = async () => {
|
|
const slideInst = slide.open()
|
|
await slideInst
|
|
refreshVideoList()
|
|
}
|
|
|
|
const onCourseGreenDelete = (task: GBVideoItem) => {
|
|
if (!task.task_id) return
|
|
useFetchWrapped<
|
|
req.gen.GBVideoDelete & AuthedRequest,
|
|
BaseResponse<resp.gen.GBVideoDelete>
|
|
>('App.Digital_VideoTask.Delete', {
|
|
token: loginState.token!,
|
|
user_id: loginState.user.id,
|
|
task_id: task.task_id,
|
|
}).then((res) => {
|
|
if (res.data.code === 1) {
|
|
refreshVideoList()
|
|
toast.add({
|
|
title: '删除成功',
|
|
description: '已删除任务记录',
|
|
color: 'success',
|
|
icon: 'i-tabler-check',
|
|
})
|
|
} else {
|
|
toast.add({
|
|
title: '删除失败',
|
|
description: res.msg || '未知错误',
|
|
color: 'error',
|
|
icon: 'i-tabler-alert-triangle',
|
|
})
|
|
}
|
|
})
|
|
}
|
|
|
|
const beforeLeave = (el: any) => {
|
|
el.style.width = `${el.offsetWidth}px`
|
|
el.style.height = `${el.offsetHeight}px`
|
|
}
|
|
|
|
const leave = (el: any, done: Function) => {
|
|
el.style.position = 'absolute'
|
|
el.style.transition = 'none' // 取消过渡动画
|
|
el.style.opacity = 0 // 立即隐藏元素
|
|
done()
|
|
}
|
|
|
|
onMounted(() => {
|
|
const i = setInterval(refreshVideoList, 1000 * 5)
|
|
onBeforeUnmount(() => clearInterval(i))
|
|
|
|
const driver = useDriver({
|
|
showProgress: true,
|
|
animate: true,
|
|
smoothScroll: true,
|
|
disableActiveInteraction: true,
|
|
popoverOffset: 12,
|
|
progressText: '{{current}} / {{total}}',
|
|
prevBtnText: '上一步',
|
|
nextBtnText: '下一步',
|
|
doneBtnText: '完成',
|
|
steps: [
|
|
{
|
|
element: '#button-create',
|
|
popover: {
|
|
title: '新建视频',
|
|
description: '点击这里开始新建绿幕视频',
|
|
},
|
|
},
|
|
{
|
|
element: '#input-search',
|
|
popover: {
|
|
title: '搜索生成记录',
|
|
description: '在这里输入视频标题,可以搜索符合条件的生成记录',
|
|
},
|
|
},
|
|
],
|
|
})
|
|
|
|
tourState.autoDriveTour(route.fullPath, driver)
|
|
})
|
|
</script>
|
|
|
|
<template>
|
|
<div class="h-full">
|
|
<div class="p-4 pb-0">
|
|
<BubbleTitle
|
|
:subtitle="!debounceSearch ? 'GB VIDEOS' : 'SEARCH...'"
|
|
:title="
|
|
!debounceSearch
|
|
? '我的绿幕视频'
|
|
: `标题搜索:${debounceSearch.toLocaleUpperCase()}`
|
|
"
|
|
>
|
|
<template #action>
|
|
<UFieldGroup size="md">
|
|
<UInput
|
|
id="input-search"
|
|
v-model="searchInput"
|
|
:autofocus="false"
|
|
autocomplete="off"
|
|
placeholder="标题搜索"
|
|
variant="outline"
|
|
>
|
|
<template #trailing>
|
|
<UButton
|
|
v-show="searchInput !== ''"
|
|
:padded="false"
|
|
color="neutral"
|
|
icon="i-tabler-x"
|
|
variant="link"
|
|
@click="searchInput = ''"
|
|
/>
|
|
</template>
|
|
</UInput>
|
|
</UFieldGroup>
|
|
<UButton
|
|
id="button-create"
|
|
:trailing="false"
|
|
color="primary"
|
|
icon="i-tabler-plus"
|
|
label="新建"
|
|
size="md"
|
|
variant="solid"
|
|
@click="onCreateCourseGreenClick"
|
|
/>
|
|
</template>
|
|
</BubbleTitle>
|
|
<GradientDivider />
|
|
</div>
|
|
|
|
<Transition name="loading-screen">
|
|
<div
|
|
v-if="videoList?.data.items.length === 0"
|
|
class="flex w-full flex-col items-center justify-center gap-2 py-20"
|
|
>
|
|
<Icon
|
|
class="text-7xl text-neutral-300 dark:text-neutral-700"
|
|
name="i-tabler-photo-hexagon"
|
|
/>
|
|
<p class="text-sm text-neutral-500 dark:text-neutral-400">没有记录</p>
|
|
</div>
|
|
<div v-else>
|
|
<div class="p-4">
|
|
<div
|
|
class="relative grid grid-cols-1 gap-4 md:grid-cols-2 xl:grid-cols-3 2xl:grid-cols-3 fhd:grid-cols-5"
|
|
>
|
|
<TransitionGroup
|
|
name="card"
|
|
@beforeLeave="beforeLeave"
|
|
@leave="leave"
|
|
>
|
|
<GBTaskCard
|
|
v-for="(v, i) in videoList?.data.items"
|
|
:key="v.task_id"
|
|
:video="v"
|
|
@delete="(v) => onCourseGreenDelete(v)"
|
|
/>
|
|
</TransitionGroup>
|
|
</div>
|
|
<div class="mt-4 flex justify-end">
|
|
<UPagination
|
|
v-model:page="page"
|
|
:max="9"
|
|
:page-count="pageCount"
|
|
:total="videoList?.data.total || 0"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</Transition>
|
|
</div>
|
|
</template>
|
|
|
|
<style scoped></style>
|