ci: Prettier纳入两层防御体系 (#520)
CI Build & Deploy Pipeline / Staging E2E Tests (push) Failing after 2m50s
CI Build & Deploy Pipeline / Production Browser E2E (push) Failing after 1437h19m24s
CI Build & Deploy Pipeline / Build Production Web Image (push) Failing after 1437h19m26s
CI Build & Deploy Pipeline / Deploy Production (push) Failing after 1437h19m25s
CI Build & Deploy Pipeline / Build Production API Image (push) Failing after 1437h19m26s
CI/CD Pipeline / Check if frontend-only change (push) Failing after 1437h21m16s
CI Build & Deploy Pipeline / Build Staging API Image (push) Has been skipped
CI Build & Deploy Pipeline / Build Staging Web Image (push) Has been skipped
CI Build & Deploy Pipeline / Build Staging Worker Image (push) Has been skipped
CI Build & Deploy Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Has been skipped
CI Build & Deploy Pipeline / Staging API Integration Tests (push) Has been skipped
CI Build & Deploy Pipeline / Build Production Worker Image (push) Failing after 1437h51m29s
CI/CD Pipeline / Validate Code Quality And Tests (push) Has been skipped
CI/CD Pipeline / Unit Tests (push) Has been skipped
CI/CD Pipeline / Integration Tests (push) Has been skipped
CI/CD Pipeline / Frontend Lint (push) Has been skipped

Co-authored-by: xiaoxia <dev@xiaoxiajianji.com>
Co-committed-by: xiaoxia <dev@xiaoxiajianji.com>
This commit was merged in pull request #520.
This commit is contained in:
2026-07-18 18:08:19 +08:00
committed by auto-approve-bot
parent 1ee779a566
commit 0fcb77b991
145 changed files with 10310 additions and 12869 deletions
+32 -32
View File
@@ -4,76 +4,76 @@
* 当存在 processing 状态的克隆条目时,每 3 秒自动拉取最新列表;
* 全部完成(ready / failed)后停止轮询。
*/
import { useState, useEffect, useCallback, useRef } from "react";
import { getVoiceClones } from "@/api/voiceClone";
import type { VoiceClone } from "@/api/voiceClone";
import { useState, useEffect, useCallback, useRef } from "react"
import { getVoiceClones } from "@/api/voiceClone"
import type { VoiceClone } from "@/api/voiceClone"
const POLL_INTERVAL = 3000; // 3 秒
const POLL_INTERVAL = 3000 // 3 秒
export const useCloneProgress = () => {
const [clones, setClones] = useState<VoiceClone[]>([]);
const [loading, setLoading] = useState(false);
const timerRef = useRef<ReturnType<typeof setInterval>>(undefined);
const [clones, setClones] = useState<VoiceClone[]>([])
const [loading, setLoading] = useState(false)
const timerRef = useRef<ReturnType<typeof setInterval>>(undefined)
const fetchClones = useCallback(async (silent = false) => {
if (!silent) setLoading(true);
if (!silent) setLoading(true)
try {
const data = await getVoiceClones();
setClones(data);
const data = await getVoiceClones()
setClones(data)
} catch {
// 静默失败,下次轮询重试
} finally {
if (!silent) setLoading(false);
if (!silent) setLoading(false)
}
}, []);
}, [])
/* 初始加载 */
useEffect(() => {
fetchClones();
}, [fetchClones]);
fetchClones()
}, [fetchClones])
/* 轮询:有 processing 条目时启动,全部结束时停止 */
useEffect(() => {
const hasProcessing = clones.some((c) => c.status === "processing");
const hasProcessing = clones.some((c) => c.status === "processing")
if (hasProcessing) {
if (!timerRef.current) {
timerRef.current = setInterval(() => {
fetchClones(true);
}, POLL_INTERVAL);
fetchClones(true)
}, POLL_INTERVAL)
}
} else {
if (timerRef.current) {
clearInterval(timerRef.current);
timerRef.current = undefined;
clearInterval(timerRef.current)
timerRef.current = undefined
}
}
return () => {
if (timerRef.current) {
clearInterval(timerRef.current);
timerRef.current = undefined;
clearInterval(timerRef.current)
timerRef.current = undefined
}
};
}, [clones, fetchClones]);
}
}, [clones, fetchClones])
/** 手动刷新 */
const refresh = useCallback(() => fetchClones(), [fetchClones]);
const refresh = useCallback(() => fetchClones(), [fetchClones])
/** 克隆成功后追加到列表 */
const addClone = useCallback((voice: VoiceClone) => {
setClones((prev) => [voice, ...prev]);
}, []);
setClones((prev) => [voice, ...prev])
}, [])
/** 删除后从列表移除 */
const removeClone = useCallback((id: string) => {
setClones((prev) => prev.filter((c) => c.id !== id));
}, []);
setClones((prev) => prev.filter((c) => c.id !== id))
}, [])
/** 更新某条克隆(如改名) */
const updateClone = useCallback((updated: VoiceClone) => {
setClones((prev) => prev.map((c) => (c.id === updated.id ? updated : c)));
}, []);
setClones((prev) => prev.map((c) => (c.id === updated.id ? updated : c)))
}, [])
return {
clones,
@@ -84,5 +84,5 @@ export const useCloneProgress = () => {
updateClone,
/** 是否有正在处理中的克隆 */
hasProcessing: clones.some((c) => c.status === "processing"),
};
};
}
}