perf: reduce repeated collection traversal
This commit is contained in:
@@ -3529,9 +3529,14 @@ function CanvasPage({
|
||||
return;
|
||||
}
|
||||
const toDelete = selectedNode ? [selectedNode] : selectedNodes;
|
||||
const textIds = new Set(toDelete.filter((n) => n.kind === "text").map((n) => n.id));
|
||||
const imageIds = new Set(toDelete.filter((n) => n.kind === "image").map((n) => n.id));
|
||||
const videoIds = new Set(toDelete.filter((n) => n.kind === "video").map((n) => n.id));
|
||||
const textIds = new Set<string>();
|
||||
const imageIds = new Set<string>();
|
||||
const videoIds = new Set<string>();
|
||||
for (const node of toDelete) {
|
||||
if (node.kind === "text") textIds.add(node.id);
|
||||
else if (node.kind === "image") imageIds.add(node.id);
|
||||
else if (node.kind === "video") videoIds.add(node.id);
|
||||
}
|
||||
if (textIds.size) setTextNodes((nodes) => nodes.filter((n) => !textIds.has(n.id)));
|
||||
if (imageIds.size) setImageNodes((nodes) => nodes.filter((n) => !imageIds.has(n.id)));
|
||||
if (videoIds.size) setVideoNodes((nodes) => nodes.filter((n) => !videoIds.has(n.id)));
|
||||
|
||||
@@ -91,7 +91,11 @@ export function getCommunityCaseSurface(item: Pick<ServerCommunityCase, "metadat
|
||||
);
|
||||
if (explicitSurface !== "unknown") return explicitSurface;
|
||||
|
||||
const tags = item.tags.map((tag) => tag.trim()).filter(Boolean);
|
||||
const tags: string[] = [];
|
||||
for (const rawTag of item.tags) {
|
||||
const tag = rawTag.trim();
|
||||
if (tag) tags.push(tag);
|
||||
}
|
||||
if (tags.some((tag) => tag.includes("生成页面社区") || tag === "Web生成")) return "generation";
|
||||
if (tags.some((tag) => tag.includes("画布页面社区") || tag.includes("工作流"))) return "canvas";
|
||||
if (getWorkflowFromCase(item)) return "canvas";
|
||||
|
||||
@@ -576,6 +576,7 @@ const cloneSetCountOptions: Array<{
|
||||
{ key: "white", title: "白底图", desc: "白底主图,多角度呈现商品细节" },
|
||||
{ key: "scene", title: "场景图", desc: "展示商品的生活使用场景和人物搭配" },
|
||||
];
|
||||
const cloneSetCountKeys = cloneSetCountOptions.map((option) => option.key);
|
||||
const defaultCloneSetCounts: Record<CloneSetCountKey, number> = {
|
||||
selling: 3,
|
||||
white: 1,
|
||||
@@ -1634,7 +1635,7 @@ function ProductClonePage(_props: ProductClonePageProps = {}) {
|
||||
const generatedUrls: string[] = [];
|
||||
const stamp = Date.now();
|
||||
|
||||
for (const countKey of cloneSetCountOptions.map((o) => o.key)) {
|
||||
for (const countKey of cloneSetCountKeys) {
|
||||
const count = counts[countKey];
|
||||
for (let i = 0; i < count; i++) {
|
||||
if (imageAbortRef.current.current) break;
|
||||
@@ -1910,7 +1911,13 @@ function ProductClonePage(_props: ProductClonePageProps = {}) {
|
||||
platform, ratio, language, market,
|
||||
{ gender: modelGender, age: modelAge, ethnicity: modelEthnicity, body: modelBody, appearance, scenes: selectedScenes, smartScene },
|
||||
(s) => setTryOnStatus(s as TryOnStatus),
|
||||
(res) => setTryOnResultImages(res.map((r) => r.src).filter(Boolean)),
|
||||
(res) => {
|
||||
const urls: string[] = [];
|
||||
for (const item of res) {
|
||||
if (item.src) urls.push(item.src);
|
||||
}
|
||||
setTryOnResultImages(urls);
|
||||
},
|
||||
);
|
||||
lastFailedActionRef.current = () => handleTryOnGenerate();
|
||||
};
|
||||
@@ -2030,7 +2037,7 @@ function ProductClonePage(_props: ProductClonePageProps = {}) {
|
||||
productImages.length === 0 ? "请先上传商品原图" : status === "generating" ? "生成中..." : `生成${selectedCloneOutput.label}`;
|
||||
const setPreviewCards: CloneResult[] = [];
|
||||
let setIndex = 0;
|
||||
for (const countKey of cloneSetCountOptions.map((o) => o.key)) {
|
||||
for (const countKey of cloneSetCountKeys) {
|
||||
const count = cloneSetCounts[countKey];
|
||||
const info = setCountLabels[countKey];
|
||||
for (let i = 0; i < count; i++) {
|
||||
@@ -2045,7 +2052,7 @@ function ProductClonePage(_props: ProductClonePageProps = {}) {
|
||||
|
||||
const clonePreviewCards: CloneResult[] = [];
|
||||
let cloneIndex = 0;
|
||||
for (const countKey of cloneSetCountOptions.map((o) => o.key)) {
|
||||
for (const countKey of cloneSetCountKeys) {
|
||||
const count = cloneSetCounts[countKey];
|
||||
const info = setCountLabels[countKey];
|
||||
for (let i = 0; i < count; i++) {
|
||||
@@ -2057,6 +2064,12 @@ function ProductClonePage(_props: ProductClonePageProps = {}) {
|
||||
cloneIndex++;
|
||||
}
|
||||
}
|
||||
const detailSourcePreviewImages = detailProductImages.length
|
||||
? detailProductImages.reduce<string[]>((urls, item) => {
|
||||
urls.push(item.src);
|
||||
return urls;
|
||||
}, [])
|
||||
: detailProductSamples;
|
||||
const cloneBasicSelects: Array<{
|
||||
key: CloneBasicSelectKey;
|
||||
label: string;
|
||||
@@ -2555,7 +2568,7 @@ function ProductClonePage(_props: ProductClonePageProps = {}) {
|
||||
|
||||
<section className="product-detail-demo-board">
|
||||
<div className="product-detail-source-stack">
|
||||
{(detailProductImages.length ? detailProductImages.map((item) => item.src) : detailProductSamples).map((src, index) => (
|
||||
{detailSourcePreviewImages.map((src, index) => (
|
||||
<figure key={`${src}-${index}`}>
|
||||
<img src={src} alt={`商品原图 ${index + 1}`} />
|
||||
</figure>
|
||||
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
VideoCameraOutlined,
|
||||
} from "@ant-design/icons";
|
||||
import type { ReactNode } from "react";
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import { useCallback, useEffect, useMemo, useState } from "react";
|
||||
import "../../styles/pages/more.css";
|
||||
import type { WebImageWorkbenchTool, WebViewKey } from "../../types";
|
||||
|
||||
@@ -144,9 +144,12 @@ function MorePage({ onSelectView, onOpenImageTool }: MorePageProps) {
|
||||
return t.category === filter;
|
||||
});
|
||||
|
||||
const recentTools = recentIds
|
||||
.map((id) => tools.find((t) => t.id === id))
|
||||
.filter((t): t is MoreTool => Boolean(t) && (t?.ready ?? false));
|
||||
const toolById = useMemo(() => new Map(tools.map((tool) => [tool.id, tool])), []);
|
||||
const recentTools = recentIds.reduce<MoreTool[]>((acc, id) => {
|
||||
const tool = toolById.get(id);
|
||||
if (tool?.ready) acc.push(tool);
|
||||
return acc;
|
||||
}, []);
|
||||
|
||||
const groupedTools = filteredTools.reduce<Record<ToolCategory, MoreTool[]>>((acc, t) => {
|
||||
if (!acc[t.category]) acc[t.category] = [];
|
||||
|
||||
Reference in New Issue
Block a user