feat(web): 桌面端前端 Web 独立部署适配——浏览器降级桥+登录态引导+页面动态修正

- 新增 web-fallback.ts:无 pywebview 时以浏览器能力降级(文件选择/上传/模板下载/配置),
  其余桌面能力(enqueue_json/vc_*/folder 选择等)保持 undefined 交由页面既有请在本地客户端中打开提示
- 新增 ensure-auth.ts:无 uid 时经 /newApi/check_login 恢复登录态,无 token/失效跳登录页;
  21 个入口 main.ts 挂载前先引导(桌面端已注入 uid 时零开销)
- pywebview.ts:getPywebviewApi() 在纯浏览器环境返回降级桥;新增 isDesktopRuntime 标志
  (首页更新面板/退出链接据此区分桌面与 Web);hasPywebview 语义修正为真实桥判定
- 登录页跳转、首页登出链接、品牌检测页 hasBridge 判定(select_brand_folder 存在性)适配 Web
This commit is contained in:
2026-09-07 16:35:19 +08:00
parent c5982dd900
commit 30b8c910e8
28 changed files with 424 additions and 32 deletions
@@ -2,7 +2,7 @@
<div v-if="currentView === 'menu'" class="image-video-page">
<header class="page-header">
<span class="header-title">数富AI</span>
<a class="back-link" href="/home">返回首页</a>
<a class="back-link" :href="goHome()">返回首页</a>
</header>
<main class="entrances" :class="{ 'is-loading': permissionsLoading }" aria-label="视频与图片入口">
@@ -21,9 +21,12 @@
<button v-if="hasMenuPermission('mix-video')" type="button" class="entrance-btn" @click="showSoon('混剪')">
混剪
</button>
<a v-if="hasMenuPermission('image')" class="entrance-btn" href="/image">
<a v-if="hasMenuPermission('image') && isDesktop" class="entrance-btn" href="/new_web_source/image.html">
图片
</a>
<button v-else-if="hasMenuPermission('image')" type="button" class="entrance-btn" @click="showDesktopOnly('图片工作台')">
图片
</button>
</main>
<div class="toast" :class="{ show: Boolean(statusText), error: statusType === 'error' }">
@@ -75,10 +78,22 @@ import BrandTopBar from '@/pages/brand/components/BrandTopBar.vue'
import DeliveryVideoWorkspace from '@/pages/image-video/components/DeliveryVideoWorkspace.vue'
import { getCurrentUserAppColumnKeys } from '@/shared/api/permission'
import { getPywebviewApi } from '@/shared/bridges/pywebview'
import { isDesktopClientPage } from '@/shared/page-prefix'
import DownloadProgressPanel from '@/shared/components/DownloadProgressPanel.vue'
type ViewMode = 'menu' | 'delivery'
const isDesktop = isDesktopClientPage()
function goHome() {
// 桌面端首页是 Flask /home(重定向到 Vue home);dev 下是 MPA 的 /home.html
return isDesktop ? '/home' : '/home.html'
}
function showDesktopOnly(name: string) {
showStatus(`${name}为桌面客户端功能,请在本地客户端中打开`, 'error')
}
const currentView = ref<ViewMode>('menu')
const allowedColumnKeys = ref(new Set<string>())
const permissionsLoading = ref(true)
@@ -184,7 +199,7 @@ onBeforeUnmount(() => {
async function launchDesktop() {
const api = getPywebviewApi()
if (!api?.launch_yaoayanui) {
showStatus('当前环境不支持拉起桌面端', 'error')
showStatus('数字人为桌面客户端程序:请在本机客户端中打开后再点击', 'error')
return
}
@@ -246,7 +261,7 @@ async function launchDesktop() {
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,
url('/bg.jpg') center/cover no-repeat,
#eef3f7;
}