Codex/generation task reliability #20

Merged
stringadmin merged 20 commits from codex/generation-task-reliability into master 2026-06-08 05:56:38 +00:00
5 changed files with 56 additions and 6 deletions
Showing only changes of commit e3bdd10156 - Show all commits
+19 -1
View File
@@ -19,10 +19,10 @@ import { ossAssets } from "../data/ossAssets";
import { canManageCommunityCases, canReviewCommunity } from "../features/community-review/communityPermissions"; import { canManageCommunityCases, canReviewCommunity } from "../features/community-review/communityPermissions";
import type { WebNavItem, WebNotification, WebUsageSummary, WebUserSession, WebViewKey } from "../types"; import type { WebNavItem, WebNotification, WebUsageSummary, WebUserSession, WebViewKey } from "../types";
import NotificationCenter from "./NotificationCenter"; import NotificationCenter from "./NotificationCenter";
import { RechargeModal } from "./RechargeModal/RechargeModal";
import { AnimatedPanel } from "./AnimatedPanel"; import { AnimatedPanel } from "./AnimatedPanel";
import AdminMonitor from "./AdminMonitor"; import AdminMonitor from "./AdminMonitor";
import CookieConsentBanner from "./CookieConsentBanner"; import CookieConsentBanner from "./CookieConsentBanner";
import { loadRechargeModal, type RechargeModalComponent } from "./RechargeModal/loadRechargeModal";
interface AppShellProps { interface AppShellProps {
activeView: WebViewKey; activeView: WebViewKey;
@@ -93,6 +93,7 @@ function AppShell({
const submenuHideTimerRef = useRef<number | null>(null); const submenuHideTimerRef = useRef<number | null>(null);
const [profileOpen, setProfileOpen] = useState(false); const [profileOpen, setProfileOpen] = useState(false);
const [rechargeOpen, setRechargeOpen] = useState(false); const [rechargeOpen, setRechargeOpen] = useState(false);
const [RechargeModal, setRechargeModal] = useState<RechargeModalComponent | null>(null);
const [infoOpen, setInfoOpen] = useState(false); const [infoOpen, setInfoOpen] = useState(false);
const infoRef = useRef<HTMLDivElement>(null); const infoRef = useRef<HTMLDivElement>(null);
const [openSubmenuKey, setOpenSubmenuKey] = useState<WebViewKey | null>(null); const [openSubmenuKey, setOpenSubmenuKey] = useState<WebViewKey | null>(null);
@@ -192,6 +193,21 @@ function AppShell({
}; };
}, []); }, []);
useEffect(() => {
if (!rechargeOpen || RechargeModal) return;
let cancelled = false;
void loadRechargeModal().then((component) => {
if (!cancelled) {
setRechargeModal(() => component);
}
});
return () => {
cancelled = true;
};
}, [RechargeModal, rechargeOpen]);
const showSubmenu = (key: WebViewKey) => { const showSubmenu = (key: WebViewKey) => {
if (submenuHideTimerRef.current) { if (submenuHideTimerRef.current) {
window.clearTimeout(submenuHideTimerRef.current); window.clearTimeout(submenuHideTimerRef.current);
@@ -491,7 +507,9 @@ function AppShell({
</main> </main>
</div> </div>
{session?.user.role === "admin" ? <AdminMonitor /> : null} {session?.user.role === "admin" ? <AdminMonitor /> : null}
{rechargeOpen && RechargeModal ? (
<RechargeModal open={rechargeOpen} onClose={() => setRechargeOpen(false)} currentBalance={displayedBalanceCents} /> <RechargeModal open={rechargeOpen} onClose={() => setRechargeOpen(false)} currentBalance={displayedBalanceCents} />
) : null}
<CookieConsentBanner /> <CookieConsentBanner />
</div> </div>
); );
@@ -1,5 +1,6 @@
import { CheckCircleOutlined, CloseOutlined, CrownOutlined, RocketOutlined } from "@ant-design/icons"; import { CheckCircleOutlined, CloseOutlined, CrownOutlined, RocketOutlined } from "@ant-design/icons";
import { useMemo, useState, type ReactNode } from "react"; import { useMemo, useState, type ReactNode } from "react";
import "../../styles/components/recharge-modal.css";
import { keyServerClient, type RechargeOrderResult } from "../../api/keyServerClient"; import { keyServerClient, type RechargeOrderResult } from "../../api/keyServerClient";
import { toast } from "../toast/toastStore"; import { toast } from "../toast/toastStore";
@@ -116,7 +117,7 @@ const paymentMethods: Array<{ id: PaymentMethod; label: string; hint: string }>
{ id: "bank", label: "对公转账", hint: "企业客户可联系客服确认" }, { id: "bank", label: "对公转账", hint: "企业客户可联系客服确认" },
]; ];
interface RechargeModalProps { export interface RechargeModalProps {
open: boolean; open: boolean;
onClose: () => void; onClose: () => void;
currentBalance?: number; currentBalance?: number;
@@ -0,0 +1,14 @@
import type { ComponentType } from "react";
import type { RechargeModalProps } from "./RechargeModal";
export type RechargeModalComponent = ComponentType<RechargeModalProps>;
let rechargeModalPromise: Promise<RechargeModalComponent> | null = null;
export function loadRechargeModal(): Promise<RechargeModalComponent> {
if (!rechargeModalPromise) {
rechargeModalPromise = import("./RechargeModal").then((module) => module.RechargeModal);
}
return rechargeModalPromise;
}
+19 -1
View File
@@ -41,7 +41,7 @@ import { claimGenerationSlot, getActiveGenerationTaskCount, getGenerationUserKey
import { preUploadReference, resolvePreUploadedUrl } from "../../api/referenceUploadService"; import { preUploadReference, resolvePreUploadedUrl } from "../../api/referenceUploadService";
import { assetClient } from "../../api/assetClient"; import { assetClient } from "../../api/assetClient";
import { communityClient } from "../../api/communityClient"; import { communityClient } from "../../api/communityClient";
import { RechargeModal } from "../../components/RechargeModal/RechargeModal"; import { loadRechargeModal, type RechargeModalComponent } from "../../components/RechargeModal/loadRechargeModal";
import { useGenerationTasks } from "../../hooks/useGenerationTasks"; import { useGenerationTasks } from "../../hooks/useGenerationTasks";
import { conversationClient, type ConversationSummary } from "../../api/conversationClient"; import { conversationClient, type ConversationSummary } from "../../api/conversationClient";
@@ -268,6 +268,7 @@ function WorkbenchPage({
const [isGenerating, setIsGenerating] = useState(false); const [isGenerating, setIsGenerating] = useState(false);
const [generationStatus, setGenerationStatus] = useState("准备就绪"); const [generationStatus, setGenerationStatus] = useState("准备就绪");
const [showRechargeModal, setShowRechargeModal] = useState(false); const [showRechargeModal, setShowRechargeModal] = useState(false);
const [RechargeModal, setRechargeModal] = useState<RechargeModalComponent | null>(null);
const [savedAssetMentionItems, setSavedAssetMentionItems] = useState< const [savedAssetMentionItems, setSavedAssetMentionItems] = useState<
Pick<ReferenceItem, "id" | "kind" | "name" | "previewUrl" | "remoteUrl" | "token">[] Pick<ReferenceItem, "id" | "kind" | "name" | "previewUrl" | "remoteUrl" | "token">[]
>([]); >([]);
@@ -291,6 +292,21 @@ function WorkbenchPage({
activeConversationIdRef.current = activeConversationId; activeConversationIdRef.current = activeConversationId;
}, []); }, []);
useEffect(() => {
if (!showRechargeModal || RechargeModal) return;
let cancelled = false;
void loadRechargeModal().then((component) => {
if (!cancelled) {
setRechargeModal(() => component);
}
});
return () => {
cancelled = true;
};
}, [RechargeModal, showRechargeModal]);
useEffect(() => { useEffect(() => {
if (!isAuthenticated) return; if (!isAuthenticated) return;
let cancelled = false; let cancelled = false;
@@ -3191,7 +3207,9 @@ function WorkbenchPage({
{renderMessagePreviewOverlay()} {renderMessagePreviewOverlay()}
{renderDeleteDialog()} {renderDeleteDialog()}
{showRechargeModal && RechargeModal ? (
<RechargeModal open={showRechargeModal} onClose={() => setShowRechargeModal(false)} currentBalance={session?.user?.balanceCents} /> <RechargeModal open={showRechargeModal} onClose={() => setShowRechargeModal(false)} currentBalance={session?.user?.balanceCents} />
) : null}
</section> </section>
); );
} }
-1
View File
@@ -3,7 +3,6 @@
@import "./shell/app-shell.css"; @import "./shell/app-shell.css";
@import "./components/primitives.css"; @import "./components/primitives.css";
@import "./components/legacy-components.css"; @import "./components/legacy-components.css";
@import "./components/recharge-modal.css";
@import "./components/toast.css"; @import "./components/toast.css";
@import "./components/page-transition.css"; @import "./components/page-transition.css";
@import "./components/motion.css"; @import "./components/motion.css";