Files
ViGent2/Docs/DevLogs/Day12.md
Kevin Wong b2c1042c5c 更新
2026-02-04 18:04:17 +08:00

9.6 KiB
Raw Blame History

Day 12 - iOS 兼容与移动端 UI 优化

日期2026-01-28


🔐 Axios 全局拦截器优化

背景

统一处理 API 请求的认证失败场景,避免各页面重复处理 401/403 错误。

实现 (frontend/src/shared/api/axios.ts)

import axios from 'axios';

// 动态获取 API 地址:服务端使用 localhost客户端使用当前域名
const API_BASE = typeof window === 'undefined'
    ? 'http://localhost:8006'
    : '';

// 防止重复跳转
let isRedirecting = false;

const api = axios.create({
    baseURL: API_BASE,
    withCredentials: true, // 自动携带 HttpOnly cookie
    headers: { 'Content-Type': 'application/json' },
});

// 响应拦截器 - 全局处理 401/403
api.interceptors.response.use(
    (response) => response,
    async (error) => {
        const status = error.response?.status;

        if ((status === 401 || status === 403) && !isRedirecting) {
            isRedirecting = true;

            // 调用 logout API 清除 HttpOnly cookie
            try {
                await fetch('/api/auth/logout', { method: 'POST' });
            } catch (e) { /* 忽略 */ }

            // 跳转登录页
            if (typeof window !== 'undefined') {
                window.location.replace('/login');
            }
        }
        return Promise.reject(error);
    }
);

export default api;

关键特性

  • 自动携带 Cookie: withCredentials: true 确保 HttpOnly JWT cookie 被发送
  • 401/403 自动跳转: 认证失败时自动清理并跳转登录页
  • 防重复跳转: isRedirecting 标志避免多个请求同时触发跳转
  • SSR 兼容: 服务端渲染时使用 localhost,客户端使用相对路径

🔧 iOS Safari 安全区域白边修复

问题描述

iPhone Safari 浏览器底部和顶部显示白色区域,安卓正常。原因是 iOS Safari 有安全区域 (Safe Area),页面背景没有延伸到该区域。

根本原因

  1. 缺少 viewport-fit=cover 配置
  2. min-h-screen (100vh) 在 iOS Safari 中不包含安全区域
  3. 背景渐变在页面 div 上,而非 body 上,导致安全区域显示纯色

解决方案

1. 添加 viewport 配置 (layout.tsx)

export const viewport: Viewport = {
  width: 'device-width',
  initialScale: 1,
  viewportFit: 'cover',    // 允许内容延伸到安全区域
  themeColor: '#0f172a',   // 顶部状态栏颜色
};

2. 统一渐变背景到 body (layout.tsx)

<html lang="en" style={{ backgroundColor: '#0f172a' }}>
  <body
    style={{
      margin: 0,
      minHeight: '100dvh',
      background: 'linear-gradient(to bottom, #0f172a 0%, #0f172a 5%, #581c87 50%, #0f172a 95%, #0f172a 100%)',
    }}
  >
    {children}
  </body>
</html>

3. CSS 安全区域支持 (globals.css)

html {
  background-color: #0f172a !important;
  min-height: 100%;
}

body {
  margin: 0 !important;
  min-height: 100dvh;
  padding-top: env(safe-area-inset-top);
  padding-bottom: env(safe-area-inset-bottom);
}

4. 移除页面独立渐变背景

各页面的根 div 移除 bg-gradient-to-br 类,统一使用 body 渐变:

  • page.tsx
  • login/page.tsx
  • publish/page.tsx
  • admin/page.tsx
  • register/page.tsx

结果

  • 顶部状态栏颜色与页面一致 (themeColor)
  • 底部安全区域颜色与渐变边缘一致
  • 消除分层感,背景统一

📱 移动端 Header 响应式优化

问题描述

移动端顶部导航按钮(视频生成、发布管理、退出)过于拥挤,文字换行显示。

解决方案

首页 Header (page.tsx)

<header className="border-b border-white/10 bg-black/20 backdrop-blur-sm">
  <div className="max-w-6xl mx-auto px-4 sm:px-6 py-3 sm:py-4 flex items-center justify-between">
    <Link href="/" className="text-xl sm:text-2xl font-bold ...">
      <span className="text-3xl sm:text-4xl">🎬</span>
      ViGent
    </Link>
    <div className="flex items-center gap-1 sm:gap-4">
      <span className="px-2 sm:px-4 py-1 sm:py-2 text-sm sm:text-base ...">
        视频生成
      </span>
      <!-- 其他按钮同样处理 -->
    </div>
  </div>
</header>

发布管理页 Header (publish/page.tsx)

同步应用相同的响应式类名。

关键改动

属性 移动端 桌面端
容器内边距 px-4 py-3 px-6 py-4
按钮间距 gap-1 gap-4
按钮内边距 px-2 py-1 px-4 py-2
字体大小 text-sm text-base
Logo 大小 text-xl + text-3xl text-2xl + text-4xl

结果

  • 移动端按钮紧凑排列,不再换行
  • 桌面端保持原有宽松布局

🚀 发布页面 UI 重构

问题描述

原有设计将"发布时间"选项放在表单中,用户可能误选"定时发布"但忘记设置时间。

解决方案

将"一键发布"按钮改为两个独立按钮:

  • 立即发布 (绿色,占 3/4 宽度) - 主要操作
  • 定时 (占 1/4 宽度) - 点击展开时间选择器

新布局 (publish/page.tsx)

{/* 发布按钮区域 */}
<div className="space-y-3">
  <div className="flex gap-3">
    {/* 立即发布 - 占 3/4 */}
    <button
      onClick={() => { setScheduleMode("now"); handlePublish(); }}
      className="flex-[3] py-4 rounded-xl font-bold text-lg bg-gradient-to-r from-green-600 to-teal-600 ..."
    >
      🚀 立即发布
    </button>

    {/* 定时发布 - 占 1/4 */}
    <button
      onClick={() => setScheduleMode(scheduleMode === "scheduled" ? "now" : "scheduled")}
      className="flex-1 py-4 rounded-xl font-bold text-base ..."
    >
       定时
    </button>
  </div>

  {/* 定时发布时间选择器 (展开时显示) */}
  {scheduleMode === "scheduled" && (
    <div className="flex gap-3 items-center">
      <input type="datetime-local" ... />
      <button>确认定时</button>
    </div>
  )}
</div>

结果

  • 主操作(立即发布)更醒目
  • 定时发布需要二次确认,防止误触
  • 从表单区域移除发布时间选项,界面更简洁

🛤️ 后续优化项

后端定时发布 (待实现)

当前状态:定时发布使用平台端定时(在各平台设置发布时间)

优化方向:改为后端定时任务

  • 使用 APScheduler 实现任务调度
  • 存储定时任务到数据库
  • 到时间后端自动触发发布 API
  • 支持查看/取消定时任务

优势

  • 统一逻辑,不依赖平台定时 UI
  • 更灵活,可管理定时任务
  • 平台页面更新不影响功能

🤖 Qwen3-TTS 0.6B 声音克隆部署

背景

为实现用户自定义声音克隆功能,部署 Qwen3-TTS 0.6B-Base 模型,支持 3 秒参考音频快速克隆。

GPU 分配

GPU 服务 模型
GPU0 Qwen3-TTS 0.6B-Base (声音克隆)
GPU1 LatentSync 1.6 (唇形同步)

部署步骤

1. 克隆仓库

cd /home/rongye/ProgramFiles/ViGent2/models
git clone https://github.com/QwenLM/Qwen3-TTS.git

2. 创建 conda 环境

conda create -n qwen-tts python=3.10 -y
conda activate qwen-tts

3. 安装依赖

cd Qwen3-TTS
pip install -e .
conda install -y -c conda-forge sox  # 音频处理依赖

4. 下载模型权重 (使用 ModelScope国内更快)

pip install modelscope
# Tokenizer (651MB)
modelscope download --model Qwen/Qwen3-TTS-Tokenizer-12Hz --local_dir ./checkpoints/Tokenizer
# 0.6B-Base 模型 (2.4GB)
modelscope download --model Qwen/Qwen3-TTS-12Hz-0.6B-Base --local_dir ./checkpoints/0.6B-Base

5. 测试推理

# test_inference.py
import torch
import soundfile as sf
from qwen_tts import Qwen3TTSModel

model = Qwen3TTSModel.from_pretrained(
    "./checkpoints/0.6B-Base",
    device_map="cuda:0",
    dtype=torch.bfloat16,
)

wavs, sr = model.generate_voice_clone(
    text="测试文本",
    language="Chinese",
    ref_audio="./examples/myvoice.wav",
    ref_text="参考音频的文字内容",
)
sf.write("output.wav", wavs[0], sr)

测试结果

  • 模型加载成功 (GPU0)
  • 声音克隆推理成功
  • 输出音频 24000Hz质量良好

目录结构

models/Qwen3-TTS/
├── checkpoints/
│   ├── Tokenizer/     # 651MB
│   └── 0.6B-Base/     # 2.4GB
├── qwen_tts/          # 源码
├── examples/
│   └── myvoice.wav    # 参考音频
└── test_inference.py  # 测试脚本

📁 今日修改文件清单

文件 变更类型 说明
frontend/src/shared/api/axios.ts 修改 Axios 全局拦截器 (401/403 自动跳转)
frontend/src/app/layout.tsx 修改 viewport 配置 + body 渐变背景
frontend/src/app/globals.css 修改 安全区域 CSS 支持
frontend/src/app/page.tsx 修改 移除独立渐变 + Header 响应式
frontend/src/app/login/page.tsx 修改 移除独立渐变
frontend/src/app/publish/page.tsx 修改 Header 响应式 + 发布按钮重构
frontend/src/app/admin/page.tsx 修改 移除独立渐变
frontend/src/app/register/page.tsx 修改 移除独立渐变
README.md 修改 添加 "iOS/Android 移动端适配" 功能说明
Docs/FRONTEND_DEV.md 修改 iOS Safari 安全区域兼容规范 + 移动端响应式规则
models/Qwen3-TTS/ 新增 Qwen3-TTS 声音克隆模型部署
Docs/QWEN3_TTS_DEPLOY.md 新增 Qwen3-TTS 部署指南

🔗 相关文档