feat(ppt-templates): 添加PPT模板库页面
This commit is contained in:
@@ -18,10 +18,15 @@ export default defineAppConfig({
|
|||||||
container: 'gap-2',
|
container: 'gap-2',
|
||||||
base: 'px-3 py-4',
|
base: 'px-3 py-4',
|
||||||
after: 'after:hidden',
|
after: 'after:hidden',
|
||||||
active: 'before:bg-neutral-600 hover:before:bg-neutral-600 dark:before:bg-neutral-800 dark:hover:before:bg-neutral-800 text-neutral-50 dark:text-neutral-300',
|
active:
|
||||||
|
'before:bg-neutral-600 hover:before:bg-neutral-600 dark:before:bg-neutral-800 dark:hover:before:bg-neutral-800 text-neutral-50 dark:text-neutral-300',
|
||||||
icon: {
|
icon: {
|
||||||
active: 'text-neutral-50 dark:text-neutral-300',
|
active: 'text-neutral-50 dark:text-neutral-300',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
formGroup: {
|
||||||
|
hint: 'text-xs',
|
||||||
|
help: 'text-xs',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ const colorMode = useColorMode()
|
|||||||
const dayjs = useDayjs()
|
const dayjs = useDayjs()
|
||||||
const modal = useModal()
|
const modal = useModal()
|
||||||
const toast = useToast()
|
const toast = useToast()
|
||||||
|
const router = useRouter()
|
||||||
const loginState = useLoginState()
|
const loginState = useLoginState()
|
||||||
|
|
||||||
const isDark = computed({
|
const isDark = computed({
|
||||||
@@ -42,6 +43,7 @@ const items = [
|
|||||||
}], [{
|
}], [{
|
||||||
label: '账号资料',
|
label: '账号资料',
|
||||||
icon: 'i-tabler-user-circle',
|
icon: 'i-tabler-user-circle',
|
||||||
|
to: '/profile'
|
||||||
}], [{
|
}], [{
|
||||||
label: '注销登录',
|
label: '注销登录',
|
||||||
icon: 'i-tabler-logout',
|
icon: 'i-tabler-logout',
|
||||||
@@ -63,8 +65,8 @@ const open_login_modal = () => {
|
|||||||
<div class="relative grid w-full min-h-screen">
|
<div class="relative grid w-full min-h-screen">
|
||||||
<header>
|
<header>
|
||||||
<h1 class="inline-flex flex-col">
|
<h1 class="inline-flex flex-col">
|
||||||
<span class="text-lg text-neutral-600 dark:text-neutral-300 font-bold">眩生花 AI 助手</span>
|
<span class="text-lg text-neutral-600 dark:text-neutral-300 font-bold">AIGC 微课视频研创平台</span>
|
||||||
<span class="text-xs text-neutral-600 dark:text-neutral-300">XSH AI Assistant</span>
|
<!-- <span class="text-xs text-neutral-600 dark:text-neutral-300">眩生花科技</span> -->
|
||||||
</h1>
|
</h1>
|
||||||
<div class="hidden md:block">
|
<div class="hidden md:block">
|
||||||
<UHorizontalNavigation :links="links" class="select-none"/>
|
<UHorizontalNavigation :links="links" class="select-none"/>
|
||||||
|
|||||||
@@ -33,6 +33,11 @@ const navList = ref<
|
|||||||
icon: 'tabler:keyframes',
|
icon: 'tabler:keyframes',
|
||||||
to: '/generation/materials',
|
to: '/generation/materials',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: 'PPT 模板库',
|
||||||
|
icon: 'tabler:file-type-ppt',
|
||||||
|
to: '/generation/ppt-templates',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: '用户管理',
|
label: '用户管理',
|
||||||
icon: 'tabler:users',
|
icon: 'tabler:users',
|
||||||
|
|||||||
125
pages/generation/ppt-templates.vue
Normal file
125
pages/generation/ppt-templates.vue
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
const loginState = useLoginState()
|
||||||
|
|
||||||
|
const { data: pptCategories } = useAsyncData('pptCategories', () =>
|
||||||
|
useFetchWrapped<
|
||||||
|
PagedDataRequest & AuthedRequest,
|
||||||
|
BaseResponse<PagedData<PPTCategory>>
|
||||||
|
>('App.Digital_PowerPointCat.GetList', {
|
||||||
|
token: loginState.token!,
|
||||||
|
user_id: loginState.user.id,
|
||||||
|
page: 1,
|
||||||
|
perpage: 20,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
const selectedCat = ref<number>(0)
|
||||||
|
const pagination = reactive({
|
||||||
|
page: 1,
|
||||||
|
perpage: 18,
|
||||||
|
})
|
||||||
|
|
||||||
|
const { data: pptTemplates } = useAsyncData(
|
||||||
|
'pptTemplates',
|
||||||
|
() =>
|
||||||
|
useFetchWrapped<
|
||||||
|
PagedDataRequest & { type: string | number } & AuthedRequest,
|
||||||
|
BaseResponse<PagedData<PPTTemplate>>
|
||||||
|
>('App.Digital_PowerPoint.GetList', {
|
||||||
|
token: loginState.token!,
|
||||||
|
user_id: loginState.user.id,
|
||||||
|
page: pagination.page,
|
||||||
|
perpage: pagination.perpage,
|
||||||
|
type: selectedCat.value === 0 ? '' : selectedCat.value,
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
watch: [selectedCat, pagination],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
const onDownloadClick = (ppt: PPTTemplate) => {
|
||||||
|
const { download } = useDownload(ppt.file_url, `${ppt.title}.pptx`)
|
||||||
|
download()
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div class="p-4 pb-0">
|
||||||
|
<BubbleTitle
|
||||||
|
title="PPT 模板库"
|
||||||
|
subtitle="Slide Templates"
|
||||||
|
/>
|
||||||
|
<GradientDivider />
|
||||||
|
</div>
|
||||||
|
<div class="p-4 pt-0">
|
||||||
|
<!-- cat selector -->
|
||||||
|
<div class="flex flex-wrap gap-2">
|
||||||
|
<div
|
||||||
|
v-for="cat in [
|
||||||
|
{ id: 0, type: '全部' },
|
||||||
|
...(pptCategories?.data.items || []),
|
||||||
|
]"
|
||||||
|
@click="selectedCat = cat.id"
|
||||||
|
:key="cat.id"
|
||||||
|
:class="{
|
||||||
|
'bg-primary text-white': selectedCat === cat.id,
|
||||||
|
'bg-gray-100 text-gray-500': selectedCat !== cat.id,
|
||||||
|
}"
|
||||||
|
class="rounded-lg px-4 py-2 text-sm cursor-pointer"
|
||||||
|
>
|
||||||
|
{{ cat.type }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="space-y-4">
|
||||||
|
<div
|
||||||
|
class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 2xl:grid-cols-4 gap-4 mt-4"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
v-for="ppt in pptTemplates?.data.items"
|
||||||
|
:key="ppt.id"
|
||||||
|
class="relative bg-white rounded-lg shadow-md overflow-hidden"
|
||||||
|
>
|
||||||
|
<NuxtImg
|
||||||
|
:src="ppt.preview_url"
|
||||||
|
:alt="ppt.title"
|
||||||
|
class="w-full aspect-video object-cover"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
class="absolute inset-x-0 bottom-0 p-3 pt-6 flex justify-between items-end bg-gradient-to-t from-black/50 to-transparent"
|
||||||
|
>
|
||||||
|
<div class="space-y-0.5">
|
||||||
|
<h3 class="text-base font-bold text-white">{{ ppt.title }}</h3>
|
||||||
|
<p class="text-xs font-medium text-neutral-400">
|
||||||
|
{{ ppt.description }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<UButton
|
||||||
|
label="下载"
|
||||||
|
size="sm"
|
||||||
|
color="primary"
|
||||||
|
icon="tabler:download"
|
||||||
|
@click="onDownloadClick(ppt)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="w-full flex justify-end">
|
||||||
|
<UPagination
|
||||||
|
v-if="pptTemplates?.data.total > pagination.perpage"
|
||||||
|
:total="pptTemplates?.data.total"
|
||||||
|
:page-count="pagination.perpage"
|
||||||
|
:max="9"
|
||||||
|
v-model="pagination.page"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped></style>
|
||||||
33
typings/types.d.ts
vendored
33
typings/types.d.ts
vendored
@@ -32,6 +32,7 @@ interface UserSchema {
|
|||||||
email: string
|
email: string
|
||||||
mobile: string
|
mobile: string
|
||||||
auth_code: 0 | 1 | 2 // 0: Banned, 1: User, 2: Operator
|
auth_code: 0 | 1 | 2 // 0: Banned, 1: User, 2: Operator
|
||||||
|
company?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
interface DigitalHumanItem {
|
interface DigitalHumanItem {
|
||||||
@@ -76,6 +77,22 @@ interface TitlesTemplate {
|
|||||||
description: string
|
description: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface PPTCategory {
|
||||||
|
id: number
|
||||||
|
type: string
|
||||||
|
create_time: number
|
||||||
|
}
|
||||||
|
|
||||||
|
interface PPTTemplate {
|
||||||
|
id: number
|
||||||
|
create_time: number
|
||||||
|
file_url: string
|
||||||
|
preview_url: string
|
||||||
|
title: string
|
||||||
|
description: string
|
||||||
|
type: string
|
||||||
|
}
|
||||||
|
|
||||||
// Common request and response schemas
|
// Common request and response schemas
|
||||||
namespace req {
|
namespace req {
|
||||||
namespace user {
|
namespace user {
|
||||||
@@ -103,6 +120,22 @@ namespace req {
|
|||||||
perpage?: number
|
perpage?: number
|
||||||
is_verify: boolean
|
is_verify: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface ChangePassword {
|
||||||
|
username: string
|
||||||
|
old_password: string
|
||||||
|
new_password: string
|
||||||
|
}
|
||||||
|
|
||||||
|
interface SmsChangePasswordVerify {
|
||||||
|
mobile: string
|
||||||
|
}
|
||||||
|
|
||||||
|
interface SmsChangePassword {
|
||||||
|
mobile: string
|
||||||
|
sms_code: string
|
||||||
|
new_password: string
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace file {
|
namespace file {
|
||||||
|
|||||||
Reference in New Issue
Block a user