From c0e7b64b94f6e6826a2abba6ee973aae9f622c65 Mon Sep 17 00:00:00 2001 From: Deroino <117969239+Deroino@users.noreply.github.com> Date: Thu, 13 Nov 2025 07:53:23 +0800 Subject: [PATCH] feat(frontend): add loading state to publish button to prevent duplicate clicks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add publishing state property to each tab to track publishing status - Implement loading indicator on publish button with visual feedback - Prevent duplicate clicks during active publishing process - Update button text to show "发布中..." (Publishing...) when loading - Ensure publishing state is properly reset in all scenarios (success, failure, validation errors) - Add duplicate click prevention with user-friendly error message The publish button now shows a loading spinner and prevents multiple clicks during the publishing process, improving user experience and preventing duplicate uploads to social media platforms. --- sau_frontend/src/views/PublishCenter.vue | 30 ++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/sau_frontend/src/views/PublishCenter.vue b/sau_frontend/src/views/PublishCenter.vue index d54f431..61d5cd1 100644 --- a/sau_frontend/src/views/PublishCenter.vue +++ b/sau_frontend/src/views/PublishCenter.vue @@ -457,7 +457,14 @@
取消 - 发布 + + {{ tab.publishing ? '发布中...' : '发布' }} +
@@ -526,7 +533,8 @@ const defaultTabInit = { videosPerDay: 1, // 每天发布视频数量 dailyTimes: ['10:00'], // 每天发布时间点列表 startDays: 0, // 从今天开始计算的发布天数,0表示明天,1表示后天 - publishStatus: null // 发布状态,包含message和type + publishStatus: null, // 发布状态,包含message和type + publishing: false // 发布状态,用于控制按钮loading效果 } // helper to create a fresh deep-copied tab from defaultTabInit @@ -733,29 +741,40 @@ const cancelPublish = (tab) => { // 确认发布 const confirmPublish = async (tab) => { + // 防止重复点击 + if (tab.publishing) { + return Promise.reject(new Error('正在发布中,请稍候...')) + } + + tab.publishing = true // 设置发布状态为进行中 + return new Promise((resolve, reject) => { // 数据验证 if (tab.fileList.length === 0) { ElMessage.error('请先上传视频文件') + tab.publishing = false // 重置发布状态 reject(new Error('请先上传视频文件')) return } if (!tab.title.trim()) { ElMessage.error('请输入标题') + tab.publishing = false // 重置发布状态 reject(new Error('请输入标题')) return } if (!tab.selectedPlatform) { ElMessage.error('请选择发布平台') + tab.publishing = false // 重置发布状态 reject(new Error('请选择发布平台')) return } if (tab.selectedAccounts.length === 0) { ElMessage.error('请选择发布账号') + tab.publishing = false // 重置发布状态 reject(new Error('请选择发布账号')) return } - + // 构造发布数据,符合后端API格式 const publishData = { type: tab.selectedPlatform, @@ -774,7 +793,7 @@ const confirmPublish = async (tab) => { productLink: tab.productLink.trim() || '', // 商品链接 productTitle: tab.productTitle.trim() || '' // 商品名称 } - + // 调用后端发布API fetch(`${apiBaseUrl}/postVideo`, { method: 'POST', @@ -815,6 +834,9 @@ const confirmPublish = async (tab) => { } reject(error) }) + .finally(() => { + tab.publishing = false // 重置发布状态 + }) }) }