fix:AI创作优化
This commit is contained in:
parent
0d7063077f
commit
93c1f0d497
@ -207,7 +207,9 @@ const startWebSocket = (workId: string) => {
|
|||||||
closeWebSocket()
|
closeWebSocket()
|
||||||
saveWorkId('')
|
saveWorkId('')
|
||||||
const route = getRouteByStatus(STATUS.COMPLETED, workId)
|
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) {
|
} else if (data.progress < 0) {
|
||||||
closeWebSocket()
|
closeWebSocket()
|
||||||
saveWorkId('')
|
saveWorkId('')
|
||||||
@ -246,52 +248,59 @@ const closeWebSocket = () => {
|
|||||||
stompClient = null
|
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 轮询 ───
|
// ─── B2 轮询 ───
|
||||||
const startPolling = (workId: string) => {
|
const startPolling = async (workId: string) => {
|
||||||
if (pollTimer) clearInterval(pollTimer)
|
if (pollTimer) clearInterval(pollTimer)
|
||||||
consecutiveErrors = 0
|
consecutiveErrors = 0
|
||||||
networkWarn.value = false
|
networkWarn.value = false
|
||||||
|
|
||||||
pollTimer = setInterval(async () => {
|
pollTimer = setInterval(async () => {
|
||||||
try {
|
await getWorkDetailApi(workId);
|
||||||
const work = await getWorkDetail(workId)
|
}, 8000);
|
||||||
if (!work) return
|
try {
|
||||||
|
await getWorkDetailApi(workId);
|
||||||
if (consecutiveErrors > 0 || networkWarn.value) {
|
} catch (error) {
|
||||||
consecutiveErrors = 0
|
console.log('error', error);
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const startCreation = async () => {
|
const startCreation = async () => {
|
||||||
@ -323,9 +332,10 @@ const startCreation = async () => {
|
|||||||
saveWorkId(workId)
|
saveWorkId(workId)
|
||||||
progress.value = 10
|
progress.value = 10
|
||||||
stage.value = '故事构思中…'
|
stage.value = '故事构思中…'
|
||||||
startWebSocket(workId)
|
// startWebSocket(workId)
|
||||||
|
startPolling(store.workId)
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
|
console.error('e', e);
|
||||||
if (store.workId) {
|
if (store.workId) {
|
||||||
progress.value = 10
|
progress.value = 10
|
||||||
stage.value = '创作已提交到后台…'
|
stage.value = '创作已提交到后台…'
|
||||||
@ -366,15 +376,19 @@ onMounted(() => {
|
|||||||
tipTimer = setInterval(() => {
|
tipTimer = setInterval(() => {
|
||||||
currentTipIdx.value = (currentTipIdx.value + 1) % creatingTips.length
|
currentTipIdx.value = (currentTipIdx.value + 1) % creatingTips.length
|
||||||
}, 3500)
|
}, 3500)
|
||||||
|
|
||||||
// 恢复 workId
|
// 恢复 workId
|
||||||
const urlWorkId = new URLSearchParams(window.location.search).get('workId')
|
const urlWorkId = new URLSearchParams(window.location.search).get('workId')
|
||||||
|
console.log('store.workId', urlWorkId, window.location.search)
|
||||||
if (urlWorkId) {
|
if (urlWorkId) {
|
||||||
saveWorkId(urlWorkId)
|
saveWorkId(urlWorkId)
|
||||||
} else {
|
} else {
|
||||||
restoreWorkId()
|
restoreWorkId()
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
|
getWorkDetailApi(store.workId)
|
||||||
|
} catch (error) {
|
||||||
|
console.log('error', error);
|
||||||
|
}
|
||||||
if (store.workId) {
|
if (store.workId) {
|
||||||
submitted = true
|
submitted = true
|
||||||
progress.value = 10
|
progress.value = 10
|
||||||
|
|||||||
@ -53,13 +53,7 @@ export default { name: 'PreviewView' }
|
|||||||
|
|
||||||
<!-- 4. 缩略图横向胶卷 -->
|
<!-- 4. 缩略图横向胶卷 -->
|
||||||
<div class="thumb-strip" ref="thumbStrip">
|
<div class="thumb-strip" ref="thumbStrip">
|
||||||
<div
|
<div v-for="(p, i) in pages" :key="i" class="thumb-item" :class="{ active: i === idx }" @click="idx = i">
|
||||||
v-for="(p, i) in pages"
|
|
||||||
:key="i"
|
|
||||||
class="thumb-item"
|
|
||||||
:class="{ active: i === idx }"
|
|
||||||
@click="idx = i"
|
|
||||||
>
|
|
||||||
<img v-if="p.imageUrl" :src="p.imageUrl" class="thumb-img" />
|
<img v-if="p.imageUrl" :src="p.imageUrl" class="thumb-img" />
|
||||||
<div v-else class="thumb-placeholder">
|
<div v-else class="thumb-placeholder">
|
||||||
<picture-outlined />
|
<picture-outlined />
|
||||||
@ -156,6 +150,9 @@ async function loadWork() {
|
|||||||
imageUrl: p.imageUrl,
|
imageUrl: p.imageUrl,
|
||||||
audioUrl: p.audioUrl,
|
audioUrl: p.audioUrl,
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
// 进入成功页后清空创作流程内存与本地残留键,再按路由 workId 拉取本页展示所需详情
|
||||||
|
store.reset()
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
error.value = e.message || '加载失败'
|
error.value = e.message || '加载失败'
|
||||||
} finally {
|
} finally {
|
||||||
@ -185,11 +182,13 @@ onMounted(loadWork)
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
box-shadow: 0 6px 20px rgba(99, 102, 241, 0.18);
|
box-shadow: 0 6px 20px rgba(99, 102, 241, 0.18);
|
||||||
}
|
}
|
||||||
|
|
||||||
.top-title {
|
.top-title {
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
letter-spacing: 1px;
|
letter-spacing: 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.top-sub {
|
.top-sub {
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
opacity: 0.92;
|
opacity: 0.92;
|
||||||
@ -207,26 +206,31 @@ onMounted(loadWork)
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
padding: 60px 24px;
|
padding: 60px 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.loading-icon {
|
.loading-icon {
|
||||||
font-size: 44px;
|
font-size: 44px;
|
||||||
color: var(--ai-primary);
|
color: var(--ai-primary);
|
||||||
margin-bottom: 14px;
|
margin-bottom: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.loading-text {
|
.loading-text {
|
||||||
color: var(--ai-text-sub);
|
color: var(--ai-text-sub);
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.error-icon {
|
.error-icon {
|
||||||
font-size: 48px;
|
font-size: 48px;
|
||||||
color: var(--ai-text-sub);
|
color: var(--ai-text-sub);
|
||||||
margin-bottom: 14px;
|
margin-bottom: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.error-title {
|
.error-title {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
color: var(--ai-text);
|
color: var(--ai-text);
|
||||||
margin-bottom: 6px;
|
margin-bottom: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.error-msg {
|
.error-msg {
|
||||||
color: var(--ai-text-sub);
|
color: var(--ai-text-sub);
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
@ -234,6 +238,7 @@ onMounted(loadWork)
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
max-width: 280px;
|
max-width: 280px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.error-btn {
|
.error-btn {
|
||||||
width: auto !important;
|
width: auto !important;
|
||||||
padding: 10px 32px !important;
|
padding: 10px 32px !important;
|
||||||
@ -252,9 +257,11 @@ onMounted(loadWork)
|
|||||||
position: relative;
|
position: relative;
|
||||||
border-radius: 18px;
|
border-radius: 18px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background: #1e1b4b; /* 深紫黑底,电影画幅感 */
|
background: #1e1b4b;
|
||||||
|
/* 深紫黑底,电影画幅感 */
|
||||||
box-shadow: 0 8px 28px rgba(99, 102, 241, 0.2);
|
box-shadow: 0 8px 28px rgba(99, 102, 241, 0.2);
|
||||||
}
|
}
|
||||||
|
|
||||||
.page-image {
|
.page-image {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
display: block;
|
display: block;
|
||||||
@ -262,6 +269,7 @@ onMounted(loadWork)
|
|||||||
aspect-ratio: 16 / 9;
|
aspect-ratio: 16 / 9;
|
||||||
background: #1e1b4b;
|
background: #1e1b4b;
|
||||||
}
|
}
|
||||||
|
|
||||||
.placeholder-img {
|
.placeholder-img {
|
||||||
aspect-ratio: 16 / 9;
|
aspect-ratio: 16 / 9;
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -271,6 +279,7 @@ onMounted(loadWork)
|
|||||||
color: rgba(255, 255, 255, 0.3);
|
color: rgba(255, 255, 255, 0.3);
|
||||||
background: #1e1b4b;
|
background: #1e1b4b;
|
||||||
}
|
}
|
||||||
|
|
||||||
.page-badge {
|
.page-badge {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 12px;
|
top: 12px;
|
||||||
@ -298,6 +307,7 @@ onMounted(loadWork)
|
|||||||
box-shadow: 0 4px 16px rgba(99, 102, 241, 0.06);
|
box-shadow: 0 4px 16px rgba(99, 102, 241, 0.06);
|
||||||
min-height: 64px;
|
min-height: 64px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.story-text {
|
.story-text {
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
line-height: 1.8;
|
line-height: 1.8;
|
||||||
@ -313,6 +323,7 @@ onMounted(loadWork)
|
|||||||
gap: 22px;
|
gap: 22px;
|
||||||
margin-top: 18px;
|
margin-top: 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-btn {
|
.nav-btn {
|
||||||
width: 38px;
|
width: 38px;
|
||||||
height: 38px;
|
height: 38px;
|
||||||
@ -332,9 +343,17 @@ onMounted(loadWork)
|
|||||||
border-color: var(--ai-primary);
|
border-color: var(--ai-primary);
|
||||||
background: rgba(99, 102, 241, 0.04);
|
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 {
|
.page-counter {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: var(--ai-text-sub);
|
color: var(--ai-text-sub);
|
||||||
@ -355,7 +374,10 @@ onMounted(loadWork)
|
|||||||
/* 隐藏滚动条 */
|
/* 隐藏滚动条 */
|
||||||
scrollbar-width: none;
|
scrollbar-width: none;
|
||||||
-ms-overflow-style: none;
|
-ms-overflow-style: none;
|
||||||
&::-webkit-scrollbar { display: none; }
|
|
||||||
|
&::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.thumb-item {
|
.thumb-item {
|
||||||
@ -427,6 +449,8 @@ onMounted(loadWork)
|
|||||||
padding: 14px 0 !important;
|
padding: 14px 0 !important;
|
||||||
border-radius: 28px !important;
|
border-radius: 28px !important;
|
||||||
|
|
||||||
:deep(.anticon) { font-size: 16px; }
|
:deep(.anticon) {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user