forked from 77media/video-flow
推进,样式更新完成
This commit is contained in:
parent
5fe8c76efa
commit
0133cc0798
@ -83,6 +83,8 @@ const RenderTemplateStoryMode = ({
|
||||
const { uploadFile, isUploading } = useUploadFile();
|
||||
// 本地加载状态,用于 UI 反馈
|
||||
const [localLoading, setLocalLoading] = useState(0);
|
||||
// 控制输入框显示状态
|
||||
const [inputVisible, setInputVisible] = useState<{ [key: string]: boolean }>({});
|
||||
const router = useRouter();
|
||||
// 组件挂载时获取模板列表
|
||||
useEffect(() => {
|
||||
@ -91,6 +93,23 @@ const RenderTemplateStoryMode = ({
|
||||
}
|
||||
}, [isOpen, getTemplateStoryList]);
|
||||
|
||||
// 监听点击外部区域关闭输入框
|
||||
useEffect(() => {
|
||||
const handleClickOutside = (event: MouseEvent) => {
|
||||
const target = event.target as Element;
|
||||
// 检查是否点击了输入框相关的元素
|
||||
if (!target.closest('.ant-tooltip') && !target.closest('[data-alt*="field-ai-button"]')) {
|
||||
// 关闭所有打开的输入框
|
||||
setInputVisible({});
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener('mousedown', handleClickOutside);
|
||||
return () => {
|
||||
document.removeEventListener('mousedown', handleClickOutside);
|
||||
};
|
||||
}, []);
|
||||
|
||||
// 处理模板选择
|
||||
const handleTemplateSelect = (template: StoryTemplateEntity) => {
|
||||
setSelectedTemplate(template);
|
||||
@ -251,13 +270,13 @@ const RenderTemplateStoryMode = ({
|
||||
{/* AI生成按钮 */}
|
||||
<ActionButton
|
||||
isCreating={false}
|
||||
handleCreateVideo={() =>
|
||||
handleCreateVideo={() => {
|
||||
handleFieldBlur(
|
||||
field.field_name,
|
||||
field.value || ""
|
||||
)
|
||||
}
|
||||
|
||||
);
|
||||
setInputVisible(prev => ({ ...prev, [field.field_name]: false }));
|
||||
}}
|
||||
icon={<Sparkles className="w-4 h-4" />}
|
||||
width="w-8"
|
||||
height="h-8"
|
||||
@ -269,7 +288,9 @@ const RenderTemplateStoryMode = ({
|
||||
classNames={{
|
||||
root: "max-w-none",
|
||||
}}
|
||||
trigger="focus"
|
||||
open={inputVisible[field.field_name]}
|
||||
onOpenChange={(visible) => setInputVisible(prev => ({ ...prev, [field.field_name]: visible }))}
|
||||
trigger="contextMenu"
|
||||
styles={{ root: { zIndex: 1000 } }}
|
||||
>
|
||||
{/* 图片 */}
|
||||
@ -301,52 +322,66 @@ const RenderTemplateStoryMode = ({
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* 上传按钮 - 右上角 */}
|
||||
<Upload
|
||||
name="fieldImage"
|
||||
showUploadList={false}
|
||||
beforeUpload={(file) => {
|
||||
const isImage = file.type.startsWith("image/");
|
||||
if (!isImage) {
|
||||
console.error("只能上传图片文件");
|
||||
return false;
|
||||
}
|
||||
const isLt5M = file.size / 1024 / 1024 < 5;
|
||||
if (!isLt5M) {
|
||||
console.error("图片大小不能超过5MB");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}}
|
||||
customRequest={async ({ file, onSuccess, onError }) => {
|
||||
try {
|
||||
const fileObj = file as File;
|
||||
const uploadedUrl = await uploadFile(
|
||||
fileObj,
|
||||
(progress) => {
|
||||
console.log(`上传进度: ${progress}%`);
|
||||
}
|
||||
);
|
||||
await AvatarAndAnalyzeFeatures(
|
||||
uploadedUrl,
|
||||
field.field_name
|
||||
);
|
||||
onSuccess?.(uploadedUrl);
|
||||
} catch (error) {
|
||||
console.error("字段图片上传失败:", error);
|
||||
onError?.(error as Error);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Tooltip title="upload your image" placement="top">
|
||||
{/* 按钮组 - 右上角 */}
|
||||
<div className="absolute -top-8 left-[1.2rem] flex gap-3 opacity-0 group-hover:opacity-100 transition-all duration-200">
|
||||
{/* AI生成按钮 */}
|
||||
<Tooltip title="AI generate image" placement="top">
|
||||
<button
|
||||
data-alt={`field-upload-button-${index}`}
|
||||
className="absolute -top-1 -right-1 w-6 h-6 bg-blue-500 hover:bg-blue-600 text-white rounded-full flex items-center justify-center transition-all duration-200 opacity-0 group-hover:opacity-100 hover:scale-110 shadow-lg"
|
||||
data-alt={`field-ai-button-${index}`}
|
||||
onClick={() => setInputVisible(prev => ({ ...prev, [field.field_name]: !prev[field.field_name] }))}
|
||||
className="w-6 h-6 bg-purple-500 hover:bg-purple-600 text-white rounded-full flex items-center justify-center transition-all duration-200 hover:scale-110 shadow-lg"
|
||||
>
|
||||
<UploadOutlined className="w-3.5 h-3.5" />
|
||||
<Sparkles className="w-3.5 h-3.5" />
|
||||
</button>
|
||||
</Tooltip>
|
||||
</Upload>
|
||||
|
||||
{/* 上传按钮 */}
|
||||
<Upload
|
||||
name="fieldImage"
|
||||
showUploadList={false}
|
||||
beforeUpload={(file) => {
|
||||
const isImage = file.type.startsWith("image/");
|
||||
if (!isImage) {
|
||||
console.error("只能上传图片文件");
|
||||
return false;
|
||||
}
|
||||
const isLt5M = file.size / 1024 / 1024 < 5;
|
||||
if (!isLt5M) {
|
||||
console.error("图片大小不能超过5MB");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}}
|
||||
customRequest={async ({ file, onSuccess, onError }) => {
|
||||
try {
|
||||
const fileObj = file as File;
|
||||
const uploadedUrl = await uploadFile(
|
||||
fileObj,
|
||||
(progress) => {
|
||||
console.log(`上传进度: ${progress}%`);
|
||||
}
|
||||
);
|
||||
await AvatarAndAnalyzeFeatures(
|
||||
uploadedUrl,
|
||||
field.field_name
|
||||
);
|
||||
onSuccess?.(uploadedUrl);
|
||||
} catch (error) {
|
||||
console.error("字段图片上传失败:", error);
|
||||
onError?.(error as Error);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Tooltip title="upload your image" placement="top">
|
||||
<button
|
||||
data-alt={`field-upload-button-${index}`}
|
||||
className="w-6 h-6 bg-blue-500 hover:bg-blue-600 text-white rounded-full flex items-center justify-center transition-all duration-200 hover:scale-110 shadow-lg"
|
||||
>
|
||||
<UploadOutlined className="w-3.5 h-3.5" />
|
||||
</button>
|
||||
</Tooltip>
|
||||
</Upload>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user