报错提示修复,样式优化

This commit is contained in:
海龙 2025-08-21 22:27:16 +08:00
parent 2c88b8201b
commit e405f4bd7d
6 changed files with 148 additions and 71 deletions

View File

@ -60,7 +60,11 @@ export interface CreateMovieProjectV2Request {
/** 类型 */
genre: string;
/** 角色简介数组 */
character_briefs: string[];
character_briefs: {
name:string;
image_url:string;
character_analysis:Record<string,any>;
}[];
/** 语言 */
language: string;
/** 图片URL */

View File

@ -30,7 +30,7 @@ request.interceptors.request.use(
request.interceptors.response.use(
(response: AxiosResponse) => {
// 直接返回响应数据
if (!response.data?.successful) {
if (response.data?.code !=0) {
// TODO 暂时固定报错信息,后续根据后端返回的错误码进行处理
errorHandle(0);
}

View File

@ -426,9 +426,11 @@ export const useImageStoryServiceHook = (): UseImageStoryService => {
// 从charactersAnalysis中提取whisk_caption字段组成数组
const character_briefs = charactersAnalysis.map(char => {
const obj = JSON.parse(char.whisk_caption);
obj.character_analysis.role_name = char.role_name;
return JSON.stringify(obj);
return {
name:char.role_name,
image_url:char.crop_url,
character_analysis:JSON.parse(char.whisk_caption).character_analysis
}
});
const params: CreateMovieProjectV2Request = {

View File

@ -142,7 +142,7 @@ export const useTemplateStoryServiceHook = (): UseTemplateStoryService => {
]
}
]);
}, 10000);
}, 3000);
});
setTemplateStoryList(templates);

View File

@ -10,13 +10,13 @@ describe("flow 提示词优化", () => {
-
-
2. ****
-
-
-
-
-
- 线
2. ****:20
-
-
-
-
-
-
3. **** 30
- 使

View File

@ -18,7 +18,15 @@ import {
Sparkles,
Settings,
} from "lucide-react";
import { Dropdown, Modal, Tooltip, Upload, Spin, Popconfirm } from "antd";
import {
Dropdown,
Modal,
Tooltip,
Upload,
Spin,
Popconfirm,
Image,
} from "antd";
import { UploadOutlined } from "@ant-design/icons";
import { StoryTemplateEntity } from "@/app/service/domain/Entities";
import { useImageStoryServiceHook } from "@/app/service/Interaction/ImageStoryService";
@ -53,9 +61,12 @@ const RenderTemplateStoryMode = ({
setActiveRoleIndex,
setActiveRoleImage,
setActiveRoleAudio,
clearData
clearData,
} = useTemplateStoryServiceHook();
// 使用上传文件hook
const { uploadFile, isUploading } = useUploadFile();
// 本地加载状态,用于 UI 反馈
const [localLoading, setLocalLoading] = useState(0);
@ -103,14 +114,23 @@ const RenderTemplateStoryMode = ({
}
};
// 处理角色图片上传
const handleRoleImageUpload = (roleIndex: number, file: any) => {
if (file && selectedTemplate) {
// 模拟上传成功设置图片URL
const imageUrl = URL.createObjectURL(file);
setActiveRoleImage(imageUrl);
}
};
// 处理角色图片上传 - 已移至customRequest中处理
// const handleRoleImageUpload = async (roleIndex: number, file: File) => {
// if (!file || !selectedTemplate) return;
//
// try {
// // 使用真正的文件上传功能
// const imageUrl = await uploadFile(file, (progress) => {
// console.log(`上传进度: ${progress}%`);
// });
//
// // 上传成功后,更新角色图片
// setActiveRoleImage(imageUrl);
// } catch (error) {
// console.error("图片上传失败:", error);
// // 这里可以添加错误提示
// }
// };
// 删除角色图片
const handleDeleteRoleImage = (roleIndex: number) => {
@ -122,7 +142,6 @@ const RenderTemplateStoryMode = ({
const templateListRender = () => {
return (
<div className="w-1/3 p-4 border-r border-white/[0.1]">
<h3 className="text-xl font-bold text-white mb-6">Story Templates</h3>
<div className="space-y-4 max-h-[700px] overflow-y-auto pr-3 template-list-scroll">
{templateStoryList.map((template, index) => (
<div
@ -148,7 +167,7 @@ const RenderTemplateStoryMode = ({
};
// 故事编辑器渲染
const storyEditorRender = () => {
return selectedTemplate ? (
return selectedTemplate ? (
<div className="relative h-full">
{/* 模板信息头部 - 增加顶部空间 */}
<div className="flex gap-3 py-4 border-b border-white/[0.1] h-[300px]">
@ -211,25 +230,67 @@ const RenderTemplateStoryMode = ({
listType="picture-card"
className="avatar-uploader [&_.ant-upload-select]:!w-32 [&_.ant-upload-select]:!h-32"
showUploadList={false}
action="https://660d2bd96ddfa2943b33731c.mockapi.io/api/upload"
beforeUpload={() => false}
onChange={(info) => {
if (info.file.status === "done") {
handleRoleImageUpload(
activeRoleIndex,
info.file.originFileObj
beforeUpload={(file) => {
// 验证文件类型
const isImage = file.type.startsWith("image/");
if (!isImage) {
console.error("只能上传图片文件");
return false;
}
// 验证文件大小 (5MB)
const isLt5M = file.size / 1024 / 1024 < 10;
if (!isLt5M) {
console.error("图片大小不能超过10MB");
return false;
}
return true; // 允许文件通过验证
}}
customRequest={async ({ file, onSuccess, onError }) => {
try {
const fileObj = file as File;
console.log(
"开始上传图片文件:",
fileObj.name,
fileObj.type,
fileObj.size
);
// 使用 hook 上传文件到七牛云
const uploadedUrl = await uploadFile(
fileObj,
(progress) => {
console.log(`上传进度: ${progress}%`);
}
);
console.log("图片上传成功URL:", uploadedUrl);
// 上传成功后,更新角色图片
setActiveRoleImage(uploadedUrl);
// 调用成功回调
onSuccess?.(uploadedUrl);
} catch (error) {
console.error("图片上传失败:", error);
onError?.(error as Error);
}
}}
>
{activeRole?.photo_url ? (
<div className="relative w-32 h-32 rounded-lg overflow-hidden">
<img
<Image
src={activeRole.photo_url}
alt="Character Portrait"
className="w-full h-full object-cover"
preview={{
mask: null,
maskClassName: "hidden",
}}
fallback="/assets/empty_video.png"
/>
<button
{/* <button
onClick={(e) => {
e.stopPropagation();
handleDeleteRoleImage(activeRoleIndex);
@ -238,7 +299,7 @@ const RenderTemplateStoryMode = ({
title="Delete Photo"
>
<Trash2 className="w-2.5 h-2.5" />
</button>
</button> */}
<div className="absolute inset-0 bg-black/50 opacity-0 hover:opacity-100 transition-opacity duration-200 flex items-center justify-center">
<div className="text-white text-center">
<UploadOutlined className="w-4 h-4 mb-1" />
@ -248,8 +309,17 @@ const RenderTemplateStoryMode = ({
</div>
) : (
<div className="w-32 h-32 flex flex-col items-center justify-center text-white/50 bg-white/[0.05] border border-white/[0.1] rounded-lg hover:bg-white/[0.08] transition-colors">
<UploadOutlined className="w-6 h-6 mb-1" />
<span className="text-xs">Upload Photo</span>
{isUploading ? (
<>
<Loader2 className="w-6 h-6 mb-1 animate-spin" />
<span className="text-xs">...</span>
</>
) : (
<>
<UploadOutlined className="w-6 h-6 mb-1" />
<span className="text-xs">Upload Photo</span>
</>
)}
</div>
)}
</Upload>
@ -280,11 +350,7 @@ const RenderTemplateStoryMode = ({
Characters
</h4>
{selectedTemplate.storyRole.map((role, index: number) => (
<Tooltip
key={index}
title={role.role_name}
placement="left"
>
<Tooltip key={index} title={role.role_name} placement="left">
<button
data-alt={`character-thumbnail-${index}`}
className={`w-full aspect-square rounded-lg overflow-hidden border-2 transition-all duration-200 hover:scale-105 ${
@ -294,10 +360,15 @@ const RenderTemplateStoryMode = ({
}`}
onClick={() => setActiveRoleIndex(index)}
>
<img
<Image
src={role.photo_url}
alt={role.role_name}
className="w-full h-full object-cover"
preview={{
mask: null,
maskClassName: "hidden",
}}
fallback="/assets/empty_video.png"
/>
</button>
</Tooltip>
@ -305,7 +376,7 @@ const RenderTemplateStoryMode = ({
</div>
</div>
</div>
<div className=" absolute bottom-0 right-0">
<div className=" absolute -bottom-4 right-0">
<ActionButton
isCreating={localLoading > 0}
handleCreateVideo={handleConfirm}
@ -321,7 +392,7 @@ const RenderTemplateStoryMode = ({
<p className="text-sm">Please try again later</p>
</div>
</div>
)
);
};
return (
<>
@ -329,7 +400,7 @@ const RenderTemplateStoryMode = ({
open={isOpen}
onCancel={() => {
// 清空所有选中的内容数据
clearData()
clearData();
onClose();
}}
footer={null}
@ -344,7 +415,7 @@ const RenderTemplateStoryMode = ({
</div>
}
>
<div className="rounded-2xl">
<div className="rounded-2xl min-h-min transition-all duration-700 ease-out">
{/* 弹窗头部 */}
<div className="flex gap-4 p-4 border-b border-white/[0.1]">
<h2 className="text-2xl font-bold text-white">
@ -352,7 +423,7 @@ const RenderTemplateStoryMode = ({
</h2>
</div>
<GlobalLoad show={isLoading} progress={0}>
<div className="flex gap-4">
<div className="flex gap-4 pb-4 ">
{templateListRender()}
<div className="flex-1">{storyEditorRender()}</div>
</div>
@ -871,22 +942,22 @@ const PhotoStoryModal = ({
<div className="flex items-start gap-4">
{/* 左侧:图片上传 */}
<div className="flex-shrink-0">
<div
data-alt="image-upload-area"
className={`w-24 h-24 rounded-lg flex flex-col items-center justify-center transition-all duration-300 cursor-pointer ${
activeImageUrl
? "border-2 border-white/20 bg-white/[0.05]"
: "border-2 border-dashed border-white/20 bg-white/[0.02] hover:border-white/40 hover:bg-white/[0.05] hover:scale-105"
}`}
<div
data-alt="image-upload-area"
className={`w-32 h-32 rounded-lg flex flex-col items-center justify-center transition-all duration-300 cursor-pointer ${
activeImageUrl
? "border-2 border-white/20 bg-white/[0.05]"
: "border-2 border-dashed border-white/20 bg-white/[0.02] hover:border-white/40 hover:bg-white/[0.05] hover:scale-105"
}`}
onClick={handleImageUpload}
>
{activeImageUrl ? (
<div className="relative w-full h-full">
<img
src={activeImageUrl}
alt="Story inspiration"
className="w-full h-full object-cover rounded-lg"
/>
<img
src={activeImageUrl}
alt="Story inspiration"
className="w-full h-full object-cover rounded-lg bg-white/[0.05]"
/>
<Popconfirm
title="Clear all content"
description="Are you sure you want to clear all content? This action cannot be undone."
@ -932,17 +1003,17 @@ const PhotoStoryModal = ({
key={`${avatar.name}-${index}`}
className="flex flex-col items-center"
>
<div className="relative w-14 h-14 rounded-sm overflow-hidden bg-white/[0.05] border border-white/[0.1] mb-2 group cursor-pointer">
<img
src={avatar.url}
alt={avatar.name}
className="w-full h-full object-cover"
onError={(e) => {
// 如果裁剪的头像加载失败,回退到原图
const target = e.target as HTMLImageElement;
target.src = activeImageUrl;
}}
/>
<div className="relative w-20 h-20 rounded-sm overflow-hidden bg-white/[0.05] border border-white/[0.1] mb-2 group cursor-pointer">
<img
src={avatar.url}
alt={avatar.name}
className="w-full h-full object-cover bg-white/[0.05]"
onError={(e) => {
// 如果裁剪的头像加载失败,回退到原图
const target = e.target as HTMLImageElement;
target.src = activeImageUrl;
}}
/>
{/* 删除角色按钮 - 使用Tooltip并调整z-index避免被遮挡 */}
<Tooltip
title="Remove this character from the movie"