diff --git a/lesingle-creation-frontend/src/views/public/create/views/CreatingView.vue b/lesingle-creation-frontend/src/views/public/create/views/CreatingView.vue index 72bdd51..12e7b32 100644 --- a/lesingle-creation-frontend/src/views/public/create/views/CreatingView.vue +++ b/lesingle-creation-frontend/src/views/public/create/views/CreatingView.vue @@ -207,7 +207,9 @@ const startWebSocket = (workId: string) => { closeWebSocket() saveWorkId('') const route = getRouteByStatus(STATUS.COMPLETED, workId) - if (route) setTimeout(() => router.replace(route), 800) + if (route) { + setTimeout(() => router.replace(route), 800) + } } else if (data.progress < 0) { closeWebSocket() saveWorkId('') @@ -246,52 +248,59 @@ const closeWebSocket = () => { stompClient = null } } +async function getWorkDetailApi(workId: string) { + try { + const work = await getWorkDetail(workId) + if (!work) return + if (consecutiveErrors > 0 || networkWarn.value) { + consecutiveErrors = 0 + networkWarn.value = false + } + + if (work.progress != null && work.progress > progress.value) progress.value = work.progress + if (work.progressMessage) stage.value = friendlyStage(progress.value, work.progressMessage) + + if (work.status >= STATUS.COMPLETED) { + progress.value = 100 + stage.value = '绘本创作完成' + clearInterval(pollTimer!) + pollTimer = null + saveWorkId('') + const route = getRouteByStatus(work.status, workId) + if (route) replaceWhenCreationAdvances(route) + } else if (work.status === STATUS.FAILED) { + clearInterval(pollTimer!) + pollTimer = null + saveWorkId('') + error.value = sanitizeError(work.failReason) + } + } catch { + consecutiveErrors++ + if (consecutiveErrors > MAX_POLL_ERRORS) { + clearInterval(pollTimer!) + pollTimer = null + networkWarn.value = false + error.value = '网络连接异常,创作仍在后台进行中' + } else if (consecutiveErrors > MAX_SILENT_ERRORS) { + networkWarn.value = true + } + } +} // ─── B2 轮询 ─── -const startPolling = (workId: string) => { +const startPolling = async (workId: string) => { if (pollTimer) clearInterval(pollTimer) consecutiveErrors = 0 networkWarn.value = false pollTimer = setInterval(async () => { - try { - const work = await getWorkDetail(workId) - if (!work) return - - if (consecutiveErrors > 0 || networkWarn.value) { - consecutiveErrors = 0 - networkWarn.value = false - } - - if (work.progress != null && work.progress > progress.value) progress.value = work.progress - if (work.progressMessage) stage.value = friendlyStage(progress.value, work.progressMessage) - - if (work.status >= STATUS.COMPLETED) { - progress.value = 100 - stage.value = '绘本创作完成' - clearInterval(pollTimer!) - pollTimer = null - saveWorkId('') - const route = getRouteByStatus(work.status, workId) - if (route) replaceWhenCreationAdvances(route) - } else if (work.status === STATUS.FAILED) { - clearInterval(pollTimer!) - pollTimer = null - saveWorkId('') - error.value = sanitizeError(work.failReason) - } - } catch { - consecutiveErrors++ - if (consecutiveErrors > MAX_POLL_ERRORS) { - clearInterval(pollTimer!) - pollTimer = null - networkWarn.value = false - error.value = '网络连接异常,创作仍在后台进行中' - } else if (consecutiveErrors > MAX_SILENT_ERRORS) { - networkWarn.value = true - } - } - }, 8000) + await getWorkDetailApi(workId); + }, 8000); + try { + await getWorkDetailApi(workId); + } catch (error) { + console.log('error', error); + } } const startCreation = async () => { @@ -323,9 +332,10 @@ const startCreation = async () => { saveWorkId(workId) progress.value = 10 stage.value = '故事构思中…' - startWebSocket(workId) - + // startWebSocket(workId) + startPolling(store.workId) } catch (e: any) { + console.error('e', e); if (store.workId) { progress.value = 10 stage.value = '创作已提交到后台…' @@ -366,15 +376,19 @@ onMounted(() => { tipTimer = setInterval(() => { currentTipIdx.value = (currentTipIdx.value + 1) % creatingTips.length }, 3500) - // 恢复 workId const urlWorkId = new URLSearchParams(window.location.search).get('workId') + console.log('store.workId', urlWorkId, window.location.search) if (urlWorkId) { saveWorkId(urlWorkId) } else { restoreWorkId() } - + try { + getWorkDetailApi(store.workId) + } catch (error) { + console.log('error', error); + } if (store.workId) { submitted = true progress.value = 10 diff --git a/lesingle-creation-frontend/src/views/public/create/views/PreviewView.vue b/lesingle-creation-frontend/src/views/public/create/views/PreviewView.vue index b479685..f5a498d 100644 --- a/lesingle-creation-frontend/src/views/public/create/views/PreviewView.vue +++ b/lesingle-creation-frontend/src/views/public/create/views/PreviewView.vue @@ -53,13 +53,7 @@ export default { name: 'PreviewView' }
-
+
@@ -156,6 +150,9 @@ async function loadWork() { imageUrl: p.imageUrl, audioUrl: p.audioUrl, })) + + // 进入成功页后清空创作流程内存与本地残留键,再按路由 workId 拉取本页展示所需详情 + store.reset() } catch (e: any) { error.value = e.message || '加载失败' } finally { @@ -185,11 +182,13 @@ onMounted(loadWork) text-align: center; box-shadow: 0 6px 20px rgba(99, 102, 241, 0.18); } + .top-title { font-size: 20px; font-weight: 800; letter-spacing: 1px; } + .top-sub { font-size: 13px; opacity: 0.92; @@ -207,26 +206,31 @@ onMounted(loadWork) justify-content: center; padding: 60px 24px; } + .loading-icon { font-size: 44px; color: var(--ai-primary); margin-bottom: 14px; } + .loading-text { color: var(--ai-text-sub); font-size: 14px; } + .error-icon { font-size: 48px; color: var(--ai-text-sub); margin-bottom: 14px; } + .error-title { font-size: 16px; font-weight: 700; color: var(--ai-text); margin-bottom: 6px; } + .error-msg { color: var(--ai-text-sub); font-size: 13px; @@ -234,6 +238,7 @@ onMounted(loadWork) text-align: center; max-width: 280px; } + .error-btn { width: auto !important; padding: 10px 32px !important; @@ -252,9 +257,11 @@ onMounted(loadWork) position: relative; border-radius: 18px; overflow: hidden; - background: #1e1b4b; /* 深紫黑底,电影画幅感 */ + background: #1e1b4b; + /* 深紫黑底,电影画幅感 */ box-shadow: 0 8px 28px rgba(99, 102, 241, 0.2); } + .page-image { width: 100%; display: block; @@ -262,6 +269,7 @@ onMounted(loadWork) aspect-ratio: 16 / 9; background: #1e1b4b; } + .placeholder-img { aspect-ratio: 16 / 9; display: flex; @@ -271,6 +279,7 @@ onMounted(loadWork) color: rgba(255, 255, 255, 0.3); background: #1e1b4b; } + .page-badge { position: absolute; top: 12px; @@ -298,6 +307,7 @@ onMounted(loadWork) box-shadow: 0 4px 16px rgba(99, 102, 241, 0.06); min-height: 64px; } + .story-text { font-size: 15px; line-height: 1.8; @@ -313,6 +323,7 @@ onMounted(loadWork) gap: 22px; margin-top: 18px; } + .nav-btn { width: 38px; height: 38px; @@ -332,9 +343,17 @@ onMounted(loadWork) border-color: var(--ai-primary); background: rgba(99, 102, 241, 0.04); } - &:active { transform: scale(0.92); } - &.invisible { opacity: 0; pointer-events: none; } + + &:active { + transform: scale(0.92); + } + + &.invisible { + opacity: 0; + pointer-events: none; + } } + .page-counter { font-size: 12px; color: var(--ai-text-sub); @@ -355,7 +374,10 @@ onMounted(loadWork) /* 隐藏滚动条 */ scrollbar-width: none; -ms-overflow-style: none; - &::-webkit-scrollbar { display: none; } + + &::-webkit-scrollbar { + display: none; + } } .thumb-item { @@ -427,6 +449,8 @@ onMounted(loadWork) padding: 14px 0 !important; border-radius: 28px !important; - :deep(.anticon) { font-size: 16px; } + :deep(.anticon) { + font-size: 16px; + } }