feat: finish Douyin production readiness flow
This commit is contained in:
@@ -317,6 +317,17 @@ describe("creator pages", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("subscribes to realtime updates on non-DM operational tabs", async () => {
|
||||
const creatorSubscribe = vi.fn(() => new Promise(() => {}));
|
||||
const dataProvider = provider({ creatorSubscribe });
|
||||
renderPage(<CreatorWorkbenchPage />, dataProvider);
|
||||
await waitFor(() => expect(creatorSubscribe).toHaveBeenCalledTimes(1));
|
||||
fireEvent.click(await screen.findByRole("tab", { name: "事件监听" }));
|
||||
await waitFor(() => expect(creatorSubscribe).toHaveBeenCalledTimes(2));
|
||||
fireEvent.click(screen.getByRole("tab", { name: "操作记录" }));
|
||||
await waitFor(() => expect(creatorSubscribe).toHaveBeenCalledTimes(3));
|
||||
});
|
||||
|
||||
it("isolates private messages by account and confirms one durable send", async () => {
|
||||
const conversation = {
|
||||
id: "conversation-a",
|
||||
|
||||
@@ -123,6 +123,7 @@ export function CreatorWorkbenchPage() {
|
||||
const [messagePending, setMessagePending] = useState(false);
|
||||
const [messageError, setMessageError] = useState(null);
|
||||
const [messageRetry, setMessageRetry] = useState(0);
|
||||
const [messageSyncing, setMessageSyncing] = useState(false);
|
||||
const [updateStatus, setUpdateStatus] = useState("disconnected");
|
||||
const [conversationID, setConversationID] = useState("");
|
||||
const [dmAccountID, setDmAccountID] = useState("");
|
||||
@@ -300,13 +301,42 @@ export function CreatorWorkbenchPage() {
|
||||
if (sequence === messageSequence.current) setMessagePending(false);
|
||||
};
|
||||
}, [conversationID, tab, dataProvider, messageRetry, messagePage]);
|
||||
const syncMessages = async () => {
|
||||
if (!conversationID || messageSyncing) return;
|
||||
setMessageSyncing(true);
|
||||
setMessageError(null);
|
||||
try {
|
||||
const result = await dataProvider.creatorSyncConversation(conversationID);
|
||||
setNotice({
|
||||
variant: result?.history_has_more ? "warning" : "success",
|
||||
text: result?.history_has_more
|
||||
? `已同步 ${result?.messages ?? 0} 条平台私信历史,仍有更多内容待同步。`
|
||||
: `已同步 ${result?.messages ?? 0} 条平台私信历史。`,
|
||||
});
|
||||
setMessageRetry((value) => value + 1);
|
||||
} catch (syncError) {
|
||||
setMessageError(syncError);
|
||||
} finally {
|
||||
setMessageSyncing(false);
|
||||
}
|
||||
};
|
||||
useEffect(() => {
|
||||
if (reply.target_comment_id) {
|
||||
writeDraft(replyDraftKey(reply.target_comment_id), reply);
|
||||
}
|
||||
}, [reply]);
|
||||
useEffect(() => {
|
||||
if (tab !== "dms" || typeof dataProvider.creatorSubscribe !== "function") {
|
||||
const realtimeTabs = new Set([
|
||||
"comments",
|
||||
"leads",
|
||||
"events",
|
||||
"dms",
|
||||
"operations",
|
||||
]);
|
||||
if (
|
||||
!realtimeTabs.has(tab) ||
|
||||
typeof dataProvider.creatorSubscribe !== "function"
|
||||
) {
|
||||
setUpdateStatus("disconnected");
|
||||
return undefined;
|
||||
}
|
||||
@@ -321,7 +351,9 @@ export function CreatorWorkbenchPage() {
|
||||
"/creator/updates",
|
||||
() => {
|
||||
load();
|
||||
setMessageRetry((value) => value + 1);
|
||||
if (tab === "dms") {
|
||||
setMessageRetry((value) => value + 1);
|
||||
}
|
||||
},
|
||||
controller.signal,
|
||||
(status) => setUpdateStatus(status),
|
||||
@@ -343,7 +375,7 @@ export function CreatorWorkbenchPage() {
|
||||
window.clearTimeout(retryTimer);
|
||||
setUpdateStatus("disconnected");
|
||||
};
|
||||
}, [tab, dmAccountID, dataProvider]);
|
||||
}, [tab, dataProvider]);
|
||||
useEffect(() => {
|
||||
if (!dmAccountID || !conversationID) return;
|
||||
const draft = readDraft(dmDraftKey(dmAccountID, conversationID));
|
||||
@@ -1135,14 +1167,25 @@ export function CreatorWorkbenchPage() {
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<Button
|
||||
size="sm"
|
||||
variant="outline"
|
||||
onClick={() => setMessageRetry((value) => value + 1)}
|
||||
busy={messagePending}
|
||||
>
|
||||
刷新
|
||||
</Button>
|
||||
<div className="flex gap-2">
|
||||
<Button
|
||||
size="sm"
|
||||
variant="outline"
|
||||
onClick={() => setMessageRetry((value) => value + 1)}
|
||||
busy={messagePending}
|
||||
>
|
||||
刷新
|
||||
</Button>
|
||||
<Button
|
||||
size="sm"
|
||||
variant="outline"
|
||||
onClick={syncMessages}
|
||||
busy={messageSyncing}
|
||||
disabled={!conversationID}
|
||||
>
|
||||
同步平台历史
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<PageState
|
||||
pending={messagePending}
|
||||
|
||||
@@ -251,6 +251,12 @@ export const dataProvider = {
|
||||
creatorGet(path) {
|
||||
return request(path);
|
||||
},
|
||||
creatorSyncConversation(id, limit = 200) {
|
||||
return request(
|
||||
`/creator/conversations/${encodeURIComponent(id)}/sync?limit=${encodeURIComponent(limit)}`,
|
||||
{ method: "POST" },
|
||||
);
|
||||
},
|
||||
async creatorSubscribe(path, onMessage, signal, onStatus) {
|
||||
const auth = localStorage.getItem("creatorhub.auth");
|
||||
const headers = {};
|
||||
|
||||
Reference in New Issue
Block a user