This commit is contained in:
hrx 2026-04-10 16:11:08 +08:00
parent 76f4407dec
commit 70ee0e1bba
6 changed files with 71 additions and 17 deletions

View File

@ -147,7 +147,7 @@
content: ''; content: '';
position: absolute; position: absolute;
inset: 0; inset: 0;
background-image: var(--bg-image-url); background-image: var(--bg-image-url, none);
background-size: cover; background-size: cover;
background-position: center; background-position: center;
opacity: 0.48; opacity: 0.48;

View File

@ -64,10 +64,10 @@
<div class="task-prompt-wrapper"> <div class="task-prompt-wrapper">
<div class="prompt-content"> <div class="prompt-content">
<div class="video-preview"> <div class="video-preview">
<div class="preview-bg" :style="{ '--bg-image-url': `url(${task.cover_url})` }"> <div class="preview-bg" :style="getPreviewBgStyle(task.cover_url)">
<video <video
:src="task.video_url" :src="task.video_url"
:poster="task.cover_url" :poster="task.cover_url || ''"
class="preview-video" class="preview-video"
autoplay loop muted playsinline autoplay loop muted playsinline
></video> ></video>
@ -223,6 +223,16 @@ const handleLogin = () => {
*/ */
const handleFilterChange = () => {}; const handleFilterChange = () => {};
const getPreviewBgStyle = (coverUrl?: string) => {
if (!coverUrl) {
return {};
}
return {
'--bg-image-url': `url("${coverUrl}")`
};
};
/** /**
* 获取状态显示文本 * 获取状态显示文本
* @param status 状态值 * @param status 状态值

View File

@ -21,11 +21,12 @@
</div> </div>
</template> </template>
<script setup lang='ts'> <script setup lang='ts'>
import { ref, onMounted, watch } from 'vue'; import { ref, onMounted, onUnmounted, watch } from 'vue';
import { useRoute, useRouter } from 'vue-router'; import { useRoute, useRouter } from 'vue-router';
import ImgTap from './ImgTap.vue'; import ImgTap from './ImgTap.vue';
import ReferenceImg from './ReferenceImg.vue'; import ReferenceImg from './ReferenceImg.vue';
import TextImg from './TextImg.vue'; import TextImg from './TextImg.vue';
import { debounce } from '@/utlis/debounce';
const route = useRoute(); const route = useRoute();
const router = useRouter(); const router = useRouter();
@ -34,11 +35,11 @@ const router = useRouter();
const activeTab = ref('reference'); const activeTab = ref('reference');
// 处理tab切换 // 处理tab切换
const handleTabChange = (tab: string) => { const handleTabChange = debounce((tab: string) => {
activeTab.value = tab; activeTab.value = tab;
// 更新路由 // 更新路由
router.push(`/ImgGenerate/${tab}`); router.push(`/ImgGenerate/${tab}`);
}; }, 300);
// 根据路由设置activeTab // 根据路由设置activeTab
const updateActiveTabFromRoute = () => { const updateActiveTabFromRoute = () => {
@ -62,6 +63,10 @@ watch(() => route.path, () => {
onMounted(() => { onMounted(() => {
updateActiveTabFromRoute(); updateActiveTabFromRoute();
}); });
onUnmounted(() => {
handleTabChange.cancel();
});
</script> </script>
<style scoped lang='less'> <style scoped lang='less'>
.left{ .left{

View File

@ -634,23 +634,42 @@ onBeforeUnmount(() => {
@import url('../../assets/less/Video/text/text.less'); @import url('../../assets/less/Video/text/text.less');
.reference-to-video { .reference-to-video {
height: 100%; height: auto;
min-height: 100%;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
overflow-y: auto; overflow: visible;
box-sizing: border-box; box-sizing: border-box;
background-color: #0f1114; background-color: #0f1114;
.card { .card {
margin-bottom: 16px; margin-bottom: 16px;
flex-shrink: 0; flex: 0 0 auto;
min-height: fit-content;
} }
.btmcard { .btmcard {
flex: 0 0 auto;
min-height: fit-content;
margin-bottom: 0; margin-bottom: 0;
overflow: visible;
} }
} }
.card :deep(.el-card__body) {
height: auto;
overflow: visible;
}
.reference-container {
flex: none;
overflow: visible;
}
.select {
min-height: max-content;
}
.image-preview-container { .image-preview-container {
position: relative; position: relative;
width: 148px; width: 148px;

View File

@ -45,13 +45,14 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, computed, onMounted, watch } from 'vue'; import { ref, computed, onMounted, onUnmounted, watch } from 'vue';
import { useRoute, useRouter } from 'vue-router'; import { useRoute, useRouter } from 'vue-router';
import { ElMessage } from 'element-plus'; import { ElMessage } from 'element-plus';
import VideoTab from './VideoTab.vue'; import VideoTab from './VideoTab.vue';
import Referencevideo from './ReferenceVideo.vue'; import Referencevideo from './ReferenceVideo.vue';
import TextVideo from './TextVideo.vue'; import TextVideo from './TextVideo.vue';
import ImgVideo from './ImgVideo.vue'; import ImgVideo from './ImgVideo.vue';
import { debounce } from '@/utlis/debounce';
// ==================== 子组件暴露的方法类型定义 ==================== // ==================== 子组件暴露的方法类型定义 ====================
/** 文生视频组件暴露的方法 */ /** 文生视频组件暴露的方法 */
@ -119,13 +120,13 @@ const isCreateButtonDisabled = computed(() => {
}); });
// 切换标签页(类型已明确) // 切换标签页(类型已明确)
const handleTabChange = (tab: 'reference' | 'image' | 'text') => { const handleTabChange = debounce((tab: 'reference' | 'image' | 'text') => {
activeTab.value = tab; activeTab.value = tab;
router.push(`/videoGenerate/${tab}`); router.push(`/videoGenerate/${tab}`);
}; }, 300);
// 创作按钮点击 // 创作按钮点击
const handleCreate = async () => { const handleCreate = debounce(async () => {
if (isCreateButtonDisabled.value) { if (isCreateButtonDisabled.value) {
ElMessage.warning('请先填写必要信息'); ElMessage.warning('请先填写必要信息');
return; return;
@ -155,7 +156,7 @@ const handleCreate = async () => {
break; break;
} }
return result; return result;
}; }, 500);
const emit = defineEmits<{ (e: 'task-created', taskid: string): void }>(); const emit = defineEmits<{ (e: 'task-created', taskid: string): void }>();
@ -196,6 +197,11 @@ const updateActiveTabFromRoute = () => {
watch(() => route.path, () => updateActiveTabFromRoute()); watch(() => route.path, () => updateActiveTabFromRoute());
onMounted(() => updateActiveTabFromRoute()); onMounted(() => updateActiveTabFromRoute());
onUnmounted(() => {
handleTabChange.cancel();
handleCreate.cancel();
});
</script> </script>

View File

@ -26,6 +26,7 @@
:rules="rules" :rules="rules"
label-width="0px" label-width="0px"
class="login-form" class="login-form"
@submit.prevent="submitForm"
> >
<!-- 手机号 --> <!-- 手机号 -->
<el-form-item prop="cellphone"> <el-form-item prop="cellphone">
@ -34,6 +35,7 @@
placeholder="请输入手机号" placeholder="请输入手机号"
:prefix-icon="Iphone" :prefix-icon="Iphone"
size="large" size="large"
@keyup.enter="submitForm"
/> />
</el-form-item> </el-form-item>
@ -46,6 +48,7 @@
:prefix-icon="Key" :prefix-icon="Key"
size="large" size="large"
class="captcha-input" class="captcha-input"
@keyup.enter="submitForm"
/> />
<el-button <el-button
:disabled="countingDown || !validPhone" :disabled="countingDown || !validPhone"
@ -110,6 +113,7 @@ import { ElMessage } from 'element-plus';
import { Code } from '@/apis/login'; import { Code } from '@/apis/login';
import type { CodeResult, LoginParams, CaptchaParams } from '@/types/login'; import type { CodeResult, LoginParams, CaptchaParams } from '@/types/login';
import { useLoginStore } from '@/store/LoginStore'; import { useLoginStore } from '@/store/LoginStore';
import { debounce } from '@/utlis/debounce';
// 登录Store // 登录Store
const loginStore = useLoginStore(); const loginStore = useLoginStore();
@ -160,7 +164,7 @@ const validPhone = computed(() => {
}); });
// 获取验证码 // 获取验证码
const handleGetCaptcha = async () => { const requestCaptcha = async () => {
if (countingDown.value) return; if (countingDown.value) return;
try { try {
@ -190,9 +194,12 @@ const handleGetCaptcha = async () => {
}, 1000); }, 1000);
}; };
const handleGetCaptcha = debounce(requestCaptcha, 500);
// 提交表单(登录) // 提交表单(登录)
const submitForm = async () => { const doSubmitForm = async () => {
if (!formRef.value) return; if (!formRef.value) return;
if (loading.value) return;
await formRef.value.validate(async (valid, fields) => { await formRef.value.validate(async (valid, fields) => {
if (valid) { if (valid) {
@ -217,8 +224,10 @@ const submitForm = async () => {
}); });
}; };
const submitForm = debounce(doSubmitForm, 500);
// 选择账号 // 选择账号
const selectAccount = async (selectedId: string) => { const handleSelectAccount = async (selectedId: string) => {
// 避免重复点击时多次请求 // 避免重复点击时多次请求
if (loading.value) return; if (loading.value) return;
loading.value = true; loading.value = true;
@ -233,6 +242,8 @@ const selectAccount = async (selectedId: string) => {
} }
}; };
const selectAccount = debounce(handleSelectAccount, 500);
// 弹窗关闭时的回调(如果用户直接关闭,清空账号列表,避免下次残留) // 弹窗关闭时的回调(如果用户直接关闭,清空账号列表,避免下次残留)
const handleDialogClose = () => { const handleDialogClose = () => {
loginStore.accountList = []; loginStore.accountList = [];
@ -241,6 +252,9 @@ const handleDialogClose = () => {
// 组件卸载时清除定时器 // 组件卸载时清除定时器
onUnmounted(() => { onUnmounted(() => {
if (timer) clearInterval(timer); if (timer) clearInterval(timer);
handleGetCaptcha.cancel();
submitForm.cancel();
selectAccount.cancel();
}); });
</script> </script>