|
|
@ -162,7 +162,6 @@ export default function CharactersCreate() { |
|
|
// 左侧角色风格库数据与选中项。
|
|
|
// 左侧角色风格库数据与选中项。
|
|
|
const [characterList, setCharacterList] = useState<any[]>([]); |
|
|
const [characterList, setCharacterList] = useState<any[]>([]); |
|
|
const [diyCategoryList, setDiyCategoryList] = useState<Record<string, unknown>[]>([]); |
|
|
const [diyCategoryList, setDiyCategoryList] = useState<Record<string, unknown>[]>([]); |
|
|
const [selectedCharacterList, setSelectedCharacterList] = useState<any[]>([]); |
|
|
|
|
|
|
|
|
|
|
|
// 生成能力相关:分类 -> 模型 -> 参数。
|
|
|
// 生成能力相关:分类 -> 模型 -> 参数。
|
|
|
const [aiCategories, setAiCategories] = useState<any[]>([]); |
|
|
const [aiCategories, setAiCategories] = useState<any[]>([]); |
|
|
@ -211,11 +210,21 @@ export default function CharactersCreate() { |
|
|
const taskPageRef = useRef(1); |
|
|
const taskPageRef = useRef(1); |
|
|
const loadMoreRequestIdRef = useRef(0); |
|
|
const loadMoreRequestIdRef = useRef(0); |
|
|
|
|
|
|
|
|
|
|
|
const selectedCharacterIdSet = useMemo(() => { |
|
|
|
|
|
const idSet = new Set<string>(); |
|
|
|
|
|
images.forEach((imageItem) => { |
|
|
|
|
|
if (typeof imageItem === "object" && imageItem.type === "character" && imageItem.id != null) { |
|
|
|
|
|
idSet.add(String(imageItem.id)); |
|
|
|
|
|
} |
|
|
|
|
|
}); |
|
|
|
|
|
return idSet; |
|
|
|
|
|
}, [images]); |
|
|
|
|
|
|
|
|
const handleSelectCharacter = useCallback( |
|
|
const handleSelectCharacter = useCallback( |
|
|
(item: any) => { |
|
|
(item: any) => { |
|
|
const id = item?.id; |
|
|
const id = item?.id; |
|
|
if (id === undefined || id === null) return; |
|
|
if (id === undefined || id === null) return; |
|
|
const inList = selectedCharacterList.some((c) => String(c?.id) === String(id)); |
|
|
const normalizedId = String(id); |
|
|
const nextCharacterItem: CharacterImageItem = { |
|
|
const nextCharacterItem: CharacterImageItem = { |
|
|
type: "character", |
|
|
type: "character", |
|
|
id: item?.id, |
|
|
id: item?.id, |
|
|
@ -223,36 +232,23 @@ export default function CharactersCreate() { |
|
|
avatar: item?.avatar, |
|
|
avatar: item?.avatar, |
|
|
}; |
|
|
}; |
|
|
setImages((prev) => { |
|
|
setImages((prev) => { |
|
|
const inImages = prev.some( |
|
|
const existingIndex = prev.findIndex( |
|
|
(imageItem) => |
|
|
|
|
|
typeof imageItem === "object" && |
|
|
|
|
|
imageItem.type === "character" && |
|
|
|
|
|
String(imageItem.id) === String(id), |
|
|
|
|
|
); |
|
|
|
|
|
if (inImages) { |
|
|
|
|
|
setSelectedCharacterList((p) => p.filter((c) => String(c?.id) !== String(id))); |
|
|
|
|
|
return prev.filter( |
|
|
|
|
|
(imageItem) => |
|
|
(imageItem) => |
|
|
!( |
|
|
|
|
|
typeof imageItem === "object" && |
|
|
typeof imageItem === "object" && |
|
|
imageItem.type === "character" && |
|
|
imageItem.type === "character" && |
|
|
String(imageItem.id) === String(id) |
|
|
String(imageItem.id) === normalizedId, |
|
|
), |
|
|
|
|
|
); |
|
|
); |
|
|
} |
|
|
if (existingIndex >= 0) { |
|
|
if (!inImages && inList) { |
|
|
return prev.filter((_, idx) => idx !== existingIndex); |
|
|
setSelectedCharacterList((p) => p.filter((c) => String(c?.id) !== String(id))); |
|
|
|
|
|
return prev; |
|
|
|
|
|
} |
|
|
} |
|
|
if (prev.length >= MAX_UPLOAD_IMAGES) { |
|
|
if (prev.length >= MAX_UPLOAD_IMAGES) { |
|
|
Message.warning(t("composer.maxUploadReached", { max: MAX_UPLOAD_IMAGES })); |
|
|
Message.warning(t("composer.maxUploadReached", { max: MAX_UPLOAD_IMAGES })); |
|
|
return prev; |
|
|
return prev; |
|
|
} |
|
|
} |
|
|
setSelectedCharacterList((p) => (p.some((c) => String(c?.id) === String(id)) ? p : [...p, item])); |
|
|
|
|
|
return [...prev, nextCharacterItem]; |
|
|
return [...prev, nextCharacterItem]; |
|
|
}); |
|
|
}); |
|
|
}, |
|
|
}, |
|
|
[selectedCharacterList, t], |
|
|
[t], |
|
|
); |
|
|
); |
|
|
|
|
|
|
|
|
const handleSelectMaterial = useCallback((item: any) => { |
|
|
const handleSelectMaterial = useCallback((item: any) => { |
|
|
@ -626,14 +622,8 @@ export default function CharactersCreate() { |
|
|
|
|
|
|
|
|
// 删除某一张已上传图片。
|
|
|
// 删除某一张已上传图片。
|
|
|
const handleRemoveImage = useCallback((targetIdx: number) => { |
|
|
const handleRemoveImage = useCallback((targetIdx: number) => { |
|
|
setImages((prev) => { |
|
|
setImages((prev) => prev.filter((_, idx) => idx !== targetIdx)); |
|
|
const removedItem = prev[targetIdx]; |
|
|
}, []); |
|
|
if (typeof removedItem === "object" && removedItem.type === "character") { |
|
|
|
|
|
setSelectedCharacterList((list) => list.filter((c) => String(c?.id) !== String(removedItem.id))); |
|
|
|
|
|
} |
|
|
|
|
|
return prev.filter((_, idx) => idx !== targetIdx); |
|
|
|
|
|
}); |
|
|
|
|
|
}, [t]); |
|
|
|
|
|
|
|
|
|
|
|
const handleDownloadAsset = useCallback((asset: any, task: any, assetIdx: number) => { |
|
|
const handleDownloadAsset = useCallback((asset: any, task: any, assetIdx: number) => { |
|
|
const imageUrl = asset?.images?.[0]; |
|
|
const imageUrl = asset?.images?.[0]; |
|
|
@ -888,7 +878,7 @@ export default function CharactersCreate() { |
|
|
type="button" |
|
|
type="button" |
|
|
className={classNames( |
|
|
className={classNames( |
|
|
"charactersCreate__styleCell", |
|
|
"charactersCreate__styleCell", |
|
|
selectedCharacterList.some((c) => String(c?.id) === String(item.id)) && "charactersCreate__styleCell_selected", |
|
|
selectedCharacterIdSet.has(String(item.id)) && "charactersCreate__styleCell_selected", |
|
|
)} |
|
|
)} |
|
|
draggable |
|
|
draggable |
|
|
onMouseEnter={() => { |
|
|
onMouseEnter={() => { |
|
|
|