新增内容,新增拉起软件层

This commit is contained in:
super
2026-06-08 09:19:15 +08:00
parent 8ab647c419
commit c85e5b278f
67 changed files with 1552 additions and 189 deletions
@@ -0,0 +1,198 @@
<template>
<div class="image-video-page">
<header class="page-header">
<span class="header-title">数富AI</span>
<a class="back-link" href="/home">返回首页</a>
</header>
<main class="entrances" aria-label="图生视频入口">
<button
type="button"
class="entrance-btn"
:disabled="launching"
@click="launchDesktop"
>
数字人
</button>
<button type="button" class="entrance-btn" @click="showSoon('带货视频')">
带货视频
</button>
<button type="button" class="entrance-btn" @click="showSoon('混剪')">
混剪
</button>
</main>
<div class="toast" :class="{ show: Boolean(statusText), error: statusType === 'error' }">
{{ statusText }}
</div>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { getPywebviewApi } from '@/shared/bridges/pywebview'
const launching = ref(false)
const statusText = ref('')
const statusType = ref<'normal' | 'error'>('normal')
let statusTimer: number | undefined
function showStatus(message: string, type: 'normal' | 'error' = 'normal') {
statusText.value = message
statusType.value = type
if (statusTimer) {
window.clearTimeout(statusTimer)
}
statusTimer = window.setTimeout(() => {
statusText.value = ''
}, 2200)
}
function showSoon(name: string) {
showStatus(`${name}暂未开通,敬请期待`)
}
async function launchDesktop() {
const api = getPywebviewApi()
if (!api?.launch_yaoayanui) {
showStatus('当前环境不支持拉起桌面端', 'error')
return
}
launching.value = true
try {
const result = await api.launch_yaoayanui()
if (result?.success) {
showStatus('已发送启动请求')
return
}
showStatus(result?.error || '启动失败', 'error')
} catch (error) {
showStatus(error instanceof Error ? error.message : String(error), 'error')
} finally {
launching.value = false
}
}
</script>
<style scoped>
.image-video-page {
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 40px;
color: #333;
font-family: "Microsoft YaHei", "PingFang SC", "Hiragino Sans GB", sans-serif;
background:
linear-gradient(rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0.5)),
url('/static/bg.jpg') center/cover no-repeat,
#eef3f7;
}
.page-header {
position: absolute;
top: 0;
left: 0;
right: 0;
height: 56px;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 24px;
background: rgba(255, 255, 255, 0.5);
}
.header-title {
color: #333;
font-size: 18px;
font-weight: 600;
}
.back-link {
color: #555;
font-size: 14px;
text-decoration: none;
}
.back-link:hover {
color: #667eea;
}
.entrances {
display: flex;
gap: 32px;
flex-wrap: wrap;
justify-content: center;
}
.entrance-btn {
width: 160px;
height: 100px;
display: flex;
align-items: center;
justify-content: center;
color: #333;
background: #c5c1c1;
border: 4px solid #b8d4e3;
border-radius: 12px;
cursor: pointer;
font: inherit;
font-size: 18px;
font-weight: 600;
text-decoration: none;
transition: all 0.2s;
}
.entrance-btn:hover:not(:disabled) {
background: #f8fbfd;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
}
.entrance-btn:disabled {
cursor: wait;
opacity: 0.72;
}
.toast {
position: fixed;
bottom: 40px;
left: 50%;
padding: 12px 24px;
max-width: min(420px, calc(100vw - 48px));
color: #fff;
background: rgba(0, 0, 0, 0.75);
border-radius: 8px;
font-size: 14px;
text-align: center;
opacity: 0;
pointer-events: none;
transform: translateX(-50%);
transition: opacity 0.3s;
}
.toast.show {
opacity: 1;
}
.toast.error {
background: rgba(176, 42, 55, 0.92);
}
@media (max-width: 640px) {
.image-video-page {
padding: 88px 24px 40px;
}
.entrances {
width: 100%;
gap: 18px;
}
.entrance-btn {
width: 100%;
max-width: 220px;
}
}
</style>