feat: 系统优化和功能完善
主要更新: - 调整并发配置为50人(数据库连接池30,Tomcat线程150,异步线程池5/20) - 实现无界阻塞队列(LinkedBlockingQueue)任务处理 - 实现分镜视频保存功能(保存到uploads目录) - 统一管理页面导航栏和右上角样式 - 添加日活用户统计功能 - 优化视频拼接和保存逻辑 - 添加部署文档和快速部署指南 - 更新.gitignore排除敏感配置文件
This commit is contained in:
@@ -57,11 +57,24 @@
|
||||
</div>
|
||||
|
||||
<div class="works-grid">
|
||||
<div class="work-item" v-for="(work, index) in publishedWorks" :key="work.id" @click="openDetail(work)">
|
||||
<div class="work-item" v-for="(work, index) in publishedWorks" :key="work.taskId || work.id" @click="openDetail(work)">
|
||||
<div class="work-thumbnail">
|
||||
<img :src="work.cover" :alt="work.title" />
|
||||
<!-- 使用video元素显示视频,浏览器会自动使用首帧作为封面 -->
|
||||
<video
|
||||
v-if="work.resultUrl"
|
||||
:src="work.resultUrl"
|
||||
class="work-video-thumbnail"
|
||||
preload="metadata"
|
||||
muted
|
||||
@mouseenter="playPreview($event)"
|
||||
@mouseleave="pausePreview($event)"
|
||||
></video>
|
||||
<!-- 如果没有视频URL,显示占位符 -->
|
||||
<div v-else class="work-placeholder">
|
||||
<div class="play-icon">▶</div>
|
||||
</div>
|
||||
<div class="work-overlay">
|
||||
<div class="overlay-text">{{ work.text }}</div>
|
||||
<div class="overlay-text">{{ work.prompt || work.text || '文生视频' }}</div>
|
||||
</div>
|
||||
<!-- 鼠标悬停时显示的做同款按钮 -->
|
||||
<div class="hover-create-btn" @click.stop="goToCreate(work)">
|
||||
@@ -72,8 +85,8 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="work-info">
|
||||
<div class="work-title">{{ work.title }}</div>
|
||||
<div class="work-meta">{{ work.id }} · {{ work.size }}</div>
|
||||
<div class="work-title">{{ work.prompt || work.title || '文生视频' }}</div>
|
||||
<div class="work-meta">{{ work.taskId || work.id }} · {{ formatSize(work) }}</div>
|
||||
</div>
|
||||
<div class="work-actions" v-if="index === 0">
|
||||
<el-button type="primary" class="create-similar-btn" @click.stop="goToCreate(work)">做同款</el-button>
|
||||
@@ -149,6 +162,7 @@ import { ref, onMounted } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { ElIcon, ElButton, ElTag, ElMessage, ElDialog } from 'element-plus'
|
||||
import { User, Document, VideoPlay, Picture, Film, Compass } from '@element-plus/icons-vue'
|
||||
import { textToVideoApi } from '@/api/textToVideo'
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
@@ -157,35 +171,7 @@ const detailDialogVisible = ref(false)
|
||||
const selectedItem = ref(null)
|
||||
|
||||
// 已发布作品数据
|
||||
const publishedWorks = ref([
|
||||
{
|
||||
id: '2995000000001',
|
||||
title: '文生视频作品 #1',
|
||||
cover: '/images/backgrounds/welcome.jpg',
|
||||
text: 'What Does it Mean To You',
|
||||
size: '9 MB',
|
||||
category: '文生视频',
|
||||
createTime: '2025/01/15 14:30'
|
||||
},
|
||||
{
|
||||
id: '2995000000002',
|
||||
title: '文生视频作品 #2',
|
||||
cover: '/images/backgrounds/welcome.jpg',
|
||||
text: 'What Does it Mean To You',
|
||||
size: '9 MB',
|
||||
category: '文生视频',
|
||||
createTime: '2025/01/14 16:45'
|
||||
},
|
||||
{
|
||||
id: '2995000000003',
|
||||
title: '文生视频作品 #3',
|
||||
cover: '/images/backgrounds/welcome.jpg',
|
||||
text: 'What Does it Mean To You',
|
||||
size: '9 MB',
|
||||
category: '文生视频',
|
||||
createTime: '2025/01/13 09:20'
|
||||
}
|
||||
])
|
||||
const publishedWorks = ref([])
|
||||
|
||||
// 导航函数
|
||||
const goToProfile = () => {
|
||||
@@ -235,8 +221,62 @@ const createSimilar = () => {
|
||||
router.push('/text-to-video/create')
|
||||
}
|
||||
|
||||
// 格式化文件大小
|
||||
const formatSize = (work) => {
|
||||
if (work.size) return work.size
|
||||
return '未知大小'
|
||||
}
|
||||
|
||||
// 播放预览(鼠标悬停时)
|
||||
const playPreview = (event) => {
|
||||
const video = event.target
|
||||
if (video && video.tagName === 'VIDEO') {
|
||||
video.currentTime = 0
|
||||
video.play().catch(() => {
|
||||
// 忽略自动播放失败
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 暂停预览(鼠标离开时)
|
||||
const pausePreview = (event) => {
|
||||
const video = event.target
|
||||
if (video && video.tagName === 'VIDEO') {
|
||||
video.pause()
|
||||
video.currentTime = 0
|
||||
}
|
||||
}
|
||||
|
||||
// 加载任务列表
|
||||
const loadTasks = async () => {
|
||||
try {
|
||||
const response = await textToVideoApi.getTasks(0, 20)
|
||||
if (response.data && response.data.success && response.data.data) {
|
||||
// 只显示已完成的任务
|
||||
publishedWorks.value = response.data.data
|
||||
.filter(task => task.status === 'COMPLETED' && task.resultUrl)
|
||||
.map(task => ({
|
||||
taskId: task.taskId,
|
||||
prompt: task.prompt,
|
||||
resultUrl: task.resultUrl,
|
||||
status: task.status,
|
||||
createdAt: task.createdAt,
|
||||
id: task.taskId,
|
||||
title: task.prompt || '文生视频',
|
||||
text: task.prompt || '文生视频',
|
||||
category: '文生视频',
|
||||
createTime: task.createdAt ? new Date(task.createdAt).toLocaleString('zh-CN') : ''
|
||||
}))
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载任务列表失败:', error)
|
||||
ElMessage.error('加载任务列表失败')
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
// 页面初始化
|
||||
// 页面初始化时加载任务列表
|
||||
loadTasks()
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -462,12 +502,40 @@ onMounted(() => {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.work-thumbnail img {
|
||||
.work-thumbnail img,
|
||||
.work-thumbnail video {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.work-video-thumbnail {
|
||||
display: block;
|
||||
background: #000;
|
||||
}
|
||||
|
||||
.work-placeholder {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: #000;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.play-icon {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
border-radius: 50%;
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #fff;
|
||||
font-size: 24px;
|
||||
backdrop-filter: blur(8px);
|
||||
}
|
||||
|
||||
/* 鼠标悬停时显示的做同款按钮 */
|
||||
.hover-create-btn {
|
||||
position: absolute;
|
||||
|
||||
Reference in New Issue
Block a user