feat: 邮箱注册验证 + 9项功能修复与优化
【认证系统】 - 新增邮箱验证码注册/登录流程 (sendEmailCode / verifyEmail / forgotPassword / resetPassword) - register-email 现在需要验证码 - 服务端新增 email_verification_codes 表 + patch-email-verification.js - App.tsx 登录后 emailVerified 检查提醒 - keyServerClient token 显式传递修复 401 错误 【电商模块】 - 自动推进: 策划完成后自动生成分镜图/视频 - 模特图选项 (性别/年龄/种族/体型/场景) 注入 AI 提示词 - 任务持久化指纹修复 (图片数量替代 blob URL) - 新增「视频换装」入口 (happyhorse-1.0-video-edit) 【剧本评分】 - 新增 .docx/.doc Word 文档支持 (ZIP解压+XML提取) - 历史记录支持点击查看/恢复评测结果 【画布】 - ReactFlow 节点禁止内置拖拽避免冲突 - 连接线拖拽弹窗优化 (预览线不消失, 弹窗跟踪鼠标) 【页面修复】 - 首页轮播图改为 aspect-ratio: 16/9 解决尺寸问题 - 资产库新增悬停删除按钮 - scriptEvalClient 改用服务端 /api/ai/chat 端点 - TokenUsagePage 未登录跳过 API 调用
This commit is contained in:
+25
-7
@@ -20,6 +20,7 @@ import { reportError } from "./utils/errorReporting";
|
||||
import { initNotificationPermission } from "./utils/generationNotifier";
|
||||
import PageTransition from "./components/PageTransition";
|
||||
import ToastContainer from "./components/toast/ToastContainer";
|
||||
import { toast } from "./components/toast/toastStore";
|
||||
import { aiGenerationClient } from "./api/aiGenerationClient";
|
||||
import { keyServerClient } from "./api/keyServerClient";
|
||||
import { notificationClient } from "./api/notificationClient";
|
||||
@@ -32,8 +33,10 @@ import {
|
||||
} from "./api/serverConnection";
|
||||
import { webGenerationGateway, type CreatePreviewTaskInput } from "./api/webGenerationGateway";
|
||||
import { translateTaskError } from "./utils/translateTaskError";
|
||||
import { recoverAndResumeTasks } from "./services/backgroundTaskRunner";
|
||||
import AppShell from "./components/AppShell";
|
||||
const NotFoundPage = lazy(() => import("./components/NotFoundPage"));
|
||||
const CompliancePage = lazy(() => import("./features/compliance/CompliancePage"));
|
||||
import { cloneWorkflow, createBlankWorkflow } from "./data/workflows";
|
||||
const AgentPage = lazy(() => import("./features/agent/AgentPage"));
|
||||
const AssetsPage = lazy(() => import("./features/assets/AssetsPage"));
|
||||
@@ -56,7 +59,6 @@ const WatermarkRemovalPage = lazy(() => import("./features/watermark-removal/Wat
|
||||
const SubtitleRemovalPage = lazy(() => import("./features/subtitle-removal/SubtitleRemovalPage"));
|
||||
const ScriptTokensPage = lazy(() => import("./features/script-tokens/ScriptTokensPage"));
|
||||
const TokenUsagePage = lazy(() => import("./features/script-tokens/TokenUsagePage"));
|
||||
const SettingsPage = lazy(() => import("./features/settings/SettingsPage"));
|
||||
const WorkbenchPage = lazy(() => import("./features/workbench/WorkbenchPage"));
|
||||
import type { WorkbenchResultActionPayload } from "./features/workbench/WorkbenchPage";
|
||||
import {
|
||||
@@ -103,7 +105,6 @@ const VIEW_KEYS = new Set<WebViewKey>([
|
||||
"ecommerce",
|
||||
"scriptTokens",
|
||||
"tokenUsage",
|
||||
"settings",
|
||||
"imageWorkbench",
|
||||
"resolutionUpscale",
|
||||
"watermarkRemoval",
|
||||
@@ -116,17 +117,23 @@ const VIEW_KEYS = new Set<WebViewKey>([
|
||||
"communityCaseAdd",
|
||||
"report",
|
||||
"providerHealth",
|
||||
"userAgreement",
|
||||
"privacyPolicy",
|
||||
"not-found",
|
||||
]);
|
||||
|
||||
const PUBLIC_VIEW_SET = new Set<WebViewKey>(["home", "login", "community", "more", "not-found"]);
|
||||
const PUBLIC_VIEW_SET = new Set<WebViewKey>(["home", "login", "community", "more", "userAgreement", "privacyPolicy", "not-found"]);
|
||||
|
||||
function normalizeViewKey(rawView: string): WebViewKey {
|
||||
const normalized =
|
||||
rawView === "profile" || rawView === "auth"
|
||||
? "login"
|
||||
: rawView === "ecommerceHub"
|
||||
? "ecommerce"
|
||||
: rawView === "ecommerceHub"
|
||||
? "ecommerce"
|
||||
: rawView === "terms" || rawView === "agreement" || rawView === "user-agreement"
|
||||
? "userAgreement"
|
||||
: rawView === "privacy" || rawView === "privacy-policy"
|
||||
? "privacyPolicy"
|
||||
: rawView === "community-review"
|
||||
? "communityReview"
|
||||
: rawView === "community-case-add"
|
||||
@@ -321,6 +328,11 @@ function App() {
|
||||
}
|
||||
}, []); // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
// ── Recover background tasks on app start ──────────
|
||||
useEffect(() => {
|
||||
recoverAndResumeTasks();
|
||||
}, []);
|
||||
|
||||
const navItems = useMemo<WebNavItem[]>(
|
||||
() => [
|
||||
{ key: "home", label: "首页", hint: "项目入口", icon: <HomeOutlined /> },
|
||||
@@ -838,6 +850,10 @@ function App() {
|
||||
setSession(nextSession);
|
||||
await hydrateAccountData(nextSession);
|
||||
|
||||
if (nextSession.user.email && !nextSession.user.emailVerified) {
|
||||
toast.info("邮箱尚未验证,部分功能可能受限,请在登录页通过邮箱验证码完成验证");
|
||||
}
|
||||
|
||||
const action = pendingAction;
|
||||
closeLoginPrompt();
|
||||
if (action) {
|
||||
@@ -1112,8 +1128,6 @@ function App() {
|
||||
onSelectView={handleSetView}
|
||||
/>
|
||||
);
|
||||
case "settings":
|
||||
return <SettingsPage />;
|
||||
case "imageWorkbench":
|
||||
return (
|
||||
<ImageWorkbenchPage
|
||||
@@ -1153,6 +1167,10 @@ function App() {
|
||||
return <ReportPage />;
|
||||
case "providerHealth":
|
||||
return <ProviderHealthPage session={session} onOpenLogin={handleOpenLogin} />;
|
||||
case "userAgreement":
|
||||
return <CompliancePage kind="agreement" />;
|
||||
case "privacyPolicy":
|
||||
return <CompliancePage kind="privacy" />;
|
||||
case "communityReview":
|
||||
return (
|
||||
<CommunityReviewPage
|
||||
|
||||
Reference in New Issue
Block a user