352 lines
8.8 KiB
Markdown
352 lines
8.8 KiB
Markdown
|
|
# 单页面任务执行体验优化
|
|||
|
|
|
|||
|
|
## 🎯 **功能概述**
|
|||
|
|
|
|||
|
|
根据用户需求,我们优化了任务提交后的用户体验,实现了**单页面更新模式**:
|
|||
|
|
- 任务提交成功后,页面保持在当前页面
|
|||
|
|
- 只是中间的内容区域发生变化,显示任务进度和结果
|
|||
|
|
- 不需要跳转到其他页面
|
|||
|
|
|
|||
|
|
## 📱 **用户体验流程**
|
|||
|
|
|
|||
|
|
### 1. **提交前状态**
|
|||
|
|
- 左侧:输入框和设置面板
|
|||
|
|
- 右侧:显示"开始创作您的第一个作品吧!"的提示
|
|||
|
|
|
|||
|
|
### 2. **任务提交后**
|
|||
|
|
- 页面保持在当前页面,不跳转
|
|||
|
|
- 右侧内容区域动态更新,显示:
|
|||
|
|
- 任务状态标题(如"处理中"、"已完成")
|
|||
|
|
- 任务创建时间(如"文生视频 2025年10月17日 14:28")
|
|||
|
|
- 任务描述内容
|
|||
|
|
- 视频预览区域
|
|||
|
|
|
|||
|
|
### 3. **生成中状态**
|
|||
|
|
- 显示"生成中"文字
|
|||
|
|
- 显示进度条动画
|
|||
|
|
- 提供"取消任务"按钮
|
|||
|
|
|
|||
|
|
### 4. **完成状态**
|
|||
|
|
- 显示生成的视频播放器
|
|||
|
|
- 提供"做同款"和"下载视频"按钮
|
|||
|
|
- 视频可以正常播放和控制
|
|||
|
|
|
|||
|
|
### 5. **失败状态**
|
|||
|
|
- 显示失败图标和提示
|
|||
|
|
- 提供"重新生成"按钮
|
|||
|
|
|
|||
|
|
## 🔧 **技术实现**
|
|||
|
|
|
|||
|
|
### 前端页面更新
|
|||
|
|
|
|||
|
|
#### 文生视频页面 (`TextToVideoCreate.vue`)
|
|||
|
|
```vue
|
|||
|
|
<!-- 右侧预览区域 -->
|
|||
|
|
<div class="right-panel">
|
|||
|
|
<div class="preview-area">
|
|||
|
|
<!-- 任务状态显示 -->
|
|||
|
|
<div class="task-status" v-if="currentTask">
|
|||
|
|
<div class="status-header">
|
|||
|
|
<h3>{{ getStatusText(taskStatus) }}</h3>
|
|||
|
|
<div class="task-id">文生视频 {{ formatDate(currentTask.createdAt) }}</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!-- 任务描述 -->
|
|||
|
|
<div class="task-description">
|
|||
|
|
{{ inputText }}
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!-- 视频预览区域 -->
|
|||
|
|
<div class="video-preview-container">
|
|||
|
|
<!-- 生成中的状态 -->
|
|||
|
|
<div v-if="inProgress" class="generating-container">
|
|||
|
|
<div class="generating-placeholder">
|
|||
|
|
<div class="generating-text">生成中</div>
|
|||
|
|
<div class="progress-bar-large">
|
|||
|
|
<div class="progress-fill-large" :style="{ width: taskProgress + '%' }"></div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!-- 完成状态 -->
|
|||
|
|
<div v-else-if="taskStatus === 'COMPLETED'" class="completed-container">
|
|||
|
|
<div class="video-result">
|
|||
|
|
<video
|
|||
|
|
v-if="currentTask.resultUrl"
|
|||
|
|
:src="currentTask.resultUrl"
|
|||
|
|
controls
|
|||
|
|
class="result-video"
|
|||
|
|
></video>
|
|||
|
|
</div>
|
|||
|
|
<div class="result-actions">
|
|||
|
|
<button class="action-btn primary" @click="createSimilar">做同款</button>
|
|||
|
|
<button class="action-btn secondary" @click="downloadVideo">下载视频</button>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!-- 失败状态 -->
|
|||
|
|
<div v-else-if="taskStatus === 'FAILED'" class="failed-container">
|
|||
|
|
<div class="failed-placeholder">
|
|||
|
|
<div class="failed-icon">❌</div>
|
|||
|
|
<div class="failed-text">生成失败</div>
|
|||
|
|
<div class="failed-desc">请检查输入内容或重试</div>
|
|||
|
|
</div>
|
|||
|
|
<div class="result-actions">
|
|||
|
|
<button class="action-btn primary" @click="retryTask">重新生成</button>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!-- 初始状态 -->
|
|||
|
|
<div class="preview-content" v-else>
|
|||
|
|
<div class="preview-placeholder">
|
|||
|
|
<div class="placeholder-text">开始创作您的第一个作品吧!</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 图生视频页面 (`ImageToVideoCreate.vue`)
|
|||
|
|
- 实现了与文生视频页面相同的单页面更新体验
|
|||
|
|
- 保持了功能的一致性
|
|||
|
|
|
|||
|
|
### JavaScript 功能方法
|
|||
|
|
|
|||
|
|
```javascript
|
|||
|
|
// 格式化日期
|
|||
|
|
const formatDate = (dateString) => {
|
|||
|
|
if (!dateString) return ''
|
|||
|
|
const date = new Date(dateString)
|
|||
|
|
const year = date.getFullYear()
|
|||
|
|
const month = String(date.getMonth() + 1).padStart(2, '0')
|
|||
|
|
const day = String(date.getDate()).padStart(2, '0')
|
|||
|
|
const hours = String(date.getHours()).padStart(2, '0')
|
|||
|
|
const minutes = String(date.getMinutes()).padStart(2, '0')
|
|||
|
|
return `${year}年${month}月${day}日 ${hours}:${minutes}`
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 创建同款
|
|||
|
|
const createSimilar = () => {
|
|||
|
|
// 保持当前设置,重新生成
|
|||
|
|
startGenerate()
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 下载视频
|
|||
|
|
const downloadVideo = () => {
|
|||
|
|
if (currentTask.value && currentTask.value.resultUrl) {
|
|||
|
|
const link = document.createElement('a')
|
|||
|
|
link.href = currentTask.value.resultUrl
|
|||
|
|
link.download = `video_${currentTask.value.taskId}.mp4`
|
|||
|
|
document.body.appendChild(link)
|
|||
|
|
link.click()
|
|||
|
|
document.body.removeChild(link)
|
|||
|
|
ElMessage.success('开始下载视频')
|
|||
|
|
} else {
|
|||
|
|
ElMessage.error('视频链接不可用')
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 重新生成
|
|||
|
|
const retryTask = () => {
|
|||
|
|
// 重置状态
|
|||
|
|
currentTask.value = null
|
|||
|
|
inProgress.value = false
|
|||
|
|
taskProgress.value = 0
|
|||
|
|
taskStatus.value = ''
|
|||
|
|
|
|||
|
|
// 重新开始生成
|
|||
|
|
startGenerate()
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### CSS 样式设计
|
|||
|
|
|
|||
|
|
```css
|
|||
|
|
/* 任务描述样式 */
|
|||
|
|
.task-description {
|
|||
|
|
background: rgba(255, 255, 255, 0.05);
|
|||
|
|
border-radius: 8px;
|
|||
|
|
padding: 16px;
|
|||
|
|
margin: 15px 0;
|
|||
|
|
font-size: 14px;
|
|||
|
|
line-height: 1.6;
|
|||
|
|
color: #e5e7eb;
|
|||
|
|
border: 1px solid rgba(255, 255, 255, 0.1);
|
|||
|
|
max-height: 120px;
|
|||
|
|
overflow-y: auto;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 视频预览容器 */
|
|||
|
|
.video-preview-container {
|
|||
|
|
background: #1a1a1a;
|
|||
|
|
border: 2px solid #2a2a2a;
|
|||
|
|
border-radius: 12px;
|
|||
|
|
min-height: 300px;
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
justify-content: center;
|
|||
|
|
margin: 15px 0;
|
|||
|
|
overflow: hidden;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 生成中状态 */
|
|||
|
|
.generating-container {
|
|||
|
|
width: 100%;
|
|||
|
|
height: 100%;
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
justify-content: center;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.generating-text {
|
|||
|
|
font-size: 18px;
|
|||
|
|
color: #3b82f6;
|
|||
|
|
font-weight: 600;
|
|||
|
|
margin-bottom: 20px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.progress-bar-large {
|
|||
|
|
width: 200px;
|
|||
|
|
height: 8px;
|
|||
|
|
background: rgba(255, 255, 255, 0.1);
|
|||
|
|
border-radius: 4px;
|
|||
|
|
overflow: hidden;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.progress-fill-large {
|
|||
|
|
height: 100%;
|
|||
|
|
background: linear-gradient(90deg, #3b82f6, #1d4ed8);
|
|||
|
|
border-radius: 4px;
|
|||
|
|
transition: width 0.3s ease;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 完成状态 */
|
|||
|
|
.completed-container {
|
|||
|
|
width: 100%;
|
|||
|
|
height: 100%;
|
|||
|
|
display: flex;
|
|||
|
|
flex-direction: column;
|
|||
|
|
align-items: center;
|
|||
|
|
justify-content: center;
|
|||
|
|
padding: 20px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.result-video {
|
|||
|
|
max-width: 100%;
|
|||
|
|
max-height: 100%;
|
|||
|
|
border-radius: 8px;
|
|||
|
|
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.result-actions {
|
|||
|
|
margin-top: 20px;
|
|||
|
|
display: flex;
|
|||
|
|
gap: 12px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.action-btn {
|
|||
|
|
padding: 10px 20px;
|
|||
|
|
border-radius: 8px;
|
|||
|
|
font-size: 14px;
|
|||
|
|
font-weight: 600;
|
|||
|
|
cursor: pointer;
|
|||
|
|
transition: all 0.2s ease;
|
|||
|
|
border: none;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.action-btn.primary {
|
|||
|
|
background: linear-gradient(135deg, #3b82f6, #1d4ed8);
|
|||
|
|
color: white;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.action-btn.primary:hover {
|
|||
|
|
transform: translateY(-1px);
|
|||
|
|
box-shadow: 0 4px 12px rgba(59, 130, 246, 0.4);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.action-btn.secondary {
|
|||
|
|
background: rgba(255, 255, 255, 0.1);
|
|||
|
|
color: #e5e7eb;
|
|||
|
|
border: 1px solid rgba(255, 255, 255, 0.2);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.action-btn.secondary:hover {
|
|||
|
|
background: rgba(255, 255, 255, 0.2);
|
|||
|
|
transform: translateY(-1px);
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 🎨 **界面效果**
|
|||
|
|
|
|||
|
|
### 1. **提交前**
|
|||
|
|
- 右侧显示"开始创作您的第一个作品吧!"提示
|
|||
|
|
- 界面简洁,引导用户开始创作
|
|||
|
|
|
|||
|
|
### 2. **生成中**
|
|||
|
|
- 显示任务状态标题(如"处理中")
|
|||
|
|
- 显示任务创建时间
|
|||
|
|
- 显示任务描述内容
|
|||
|
|
- 显示"生成中"文字和进度条动画
|
|||
|
|
- 提供"取消任务"按钮
|
|||
|
|
|
|||
|
|
### 3. **生成完成**
|
|||
|
|
- 显示任务状态标题(如"已完成")
|
|||
|
|
- 显示任务创建时间
|
|||
|
|
- 显示任务描述内容
|
|||
|
|
- 显示生成的视频播放器
|
|||
|
|
- 提供"做同款"和"下载视频"按钮
|
|||
|
|
|
|||
|
|
### 4. **生成失败**
|
|||
|
|
- 显示失败图标和提示文字
|
|||
|
|
- 提供"重新生成"按钮
|
|||
|
|
|
|||
|
|
## 🔄 **状态流转**
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
初始状态 → 任务提交 → 生成中 → 完成/失败
|
|||
|
|
↓ ↓ ↓ ↓
|
|||
|
|
提示页面 状态显示 进度条 结果展示
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## ✅ **功能特性**
|
|||
|
|
|
|||
|
|
### 1. **单页面体验**
|
|||
|
|
- ✅ 任务提交后不跳转页面
|
|||
|
|
- ✅ 中间内容区域动态更新
|
|||
|
|
- ✅ 保持左侧设置面板不变
|
|||
|
|
|
|||
|
|
### 2. **实时状态更新**
|
|||
|
|
- ✅ 任务状态实时显示
|
|||
|
|
- ✅ 进度条动画效果
|
|||
|
|
- ✅ 任务描述内容展示
|
|||
|
|
|
|||
|
|
### 3. **交互功能**
|
|||
|
|
- ✅ 视频播放控制
|
|||
|
|
- ✅ 下载视频功能
|
|||
|
|
- ✅ 做同款功能
|
|||
|
|
- ✅ 重新生成功能
|
|||
|
|
- ✅ 取消任务功能
|
|||
|
|
|
|||
|
|
### 4. **视觉设计**
|
|||
|
|
- ✅ 深色主题风格
|
|||
|
|
- ✅ 渐变色彩搭配
|
|||
|
|
- ✅ 动画过渡效果
|
|||
|
|
- ✅ 响应式布局
|
|||
|
|
|
|||
|
|
## 🚀 **使用体验**
|
|||
|
|
|
|||
|
|
用户现在可以享受流畅的单页面体验:
|
|||
|
|
|
|||
|
|
1. **输入内容** → 在左侧面板输入文本描述
|
|||
|
|
2. **设置参数** → 选择比例、时长、画质等
|
|||
|
|
3. **提交任务** → 点击"开始生成"按钮
|
|||
|
|
4. **查看进度** → 右侧实时显示生成进度
|
|||
|
|
5. **获取结果** → 完成后直接播放和下载视频
|
|||
|
|
6. **继续创作** → 可以"做同款"或重新生成
|
|||
|
|
|
|||
|
|
整个流程在一个页面内完成,无需跳转,提供了更加流畅和直观的用户体验!
|
|||
|
|
|
|||
|
|
|