forked from 77media/video-flow
99 lines
3.5 KiB
TypeScript
99 lines
3.5 KiB
TypeScript
import React, { useState, useRef, useEffect, forwardRef } from "react";
|
|
import { motion } from "framer-motion";
|
|
import { Sparkles, X, Plus, RefreshCw } from 'lucide-react';
|
|
import MainEditor from "./main-editor/MainEditor";
|
|
import { cn } from "@/public/lib/utils";
|
|
import { TextToShotAdapter } from "@/app/service/adapter/textToShot";
|
|
import { TagValueObject } from "@/app/service/domain/valueObject";
|
|
|
|
interface CharacterEditorProps {
|
|
className?: string;
|
|
description: string;
|
|
highlight: TagValueObject[];
|
|
onSmartPolish: (text: string) => void;
|
|
}
|
|
|
|
const mockContent = [
|
|
{
|
|
type: 'paragraph',
|
|
content: [
|
|
{ type: 'highlightText', attrs: { text: 'Hello, world!', color: 'blue' } },
|
|
{ type: 'text', text: 'Hello, world!' },
|
|
{ type: 'highlightText', attrs: { text: 'Hello, world!', color: 'red' } },
|
|
{ type: 'text', text: 'Hello, world!' },
|
|
{ type: 'highlightText', attrs: { text: 'Hello, world!', color: 'green' } },
|
|
{ type: 'text', text: 'Hello, world!' },
|
|
{ type: 'highlightText', attrs: { text: 'Hello, world!', color: 'yellow' } },
|
|
{ type: 'text', text: 'Hello, world!' },
|
|
{ type: 'highlightText', attrs: { text: 'Hello, world!', color: 'purple' } },
|
|
{ type: 'text', text: 'Hello, world!' },
|
|
{ type: 'highlightText', attrs: { text: 'Hello, world!', color: 'orange' } },
|
|
{ type: 'text', text: 'Hello, world!' },
|
|
{ type: 'highlightText', attrs: { text: 'Hello, world!', color: 'pink' } },
|
|
{ type: 'text', text: 'Hello, world!' },
|
|
],
|
|
},
|
|
];
|
|
|
|
export const CharacterEditor = forwardRef<any, CharacterEditorProps>(({
|
|
className,
|
|
description,
|
|
highlight,
|
|
onSmartPolish
|
|
}, ref) => {
|
|
const [isOptimizing, setIsOptimizing] = useState(false);
|
|
const [content, setContent] = useState<any[]>([]);
|
|
const [isInit, setIsInit] = useState(true);
|
|
|
|
const handleSmartPolish = async () => {
|
|
setIsOptimizing(true);
|
|
console.log('-==========handleSmartPolish===========-', content);
|
|
const text = TextToShotAdapter.fromRoleToText(content);
|
|
console.log('-==========getText===========-', text);
|
|
onSmartPolish(text);
|
|
};
|
|
|
|
useEffect(() => {
|
|
setIsInit(true);
|
|
console.log('-==========description===========-', description);
|
|
console.log('-==========highlight===========-', highlight);
|
|
const paragraphs = TextToShotAdapter.fromTextToRole(description, highlight);
|
|
console.log('-==========paragraphs===========-', paragraphs);
|
|
setContent(paragraphs);
|
|
setTimeout(() => {
|
|
setIsInit(false);
|
|
setIsOptimizing(false);
|
|
}, 100);
|
|
}, [description, highlight]);
|
|
|
|
// 暴露方法给父组件
|
|
React.useImperativeHandle(ref, () => ({
|
|
getRoleText: () => {
|
|
return TextToShotAdapter.fromRoleToText(content);
|
|
}
|
|
}));
|
|
|
|
return (
|
|
<div className={cn("space-y-2 border border-white/10 relative p-2 rounded-[0.5rem] pb-12", className)}>
|
|
{/* 自由输入区域 */}
|
|
{
|
|
!isInit && <MainEditor content={content} onChangeContent={setContent} />
|
|
}
|
|
|
|
{/* 智能润色按钮 */}
|
|
<motion.button
|
|
onClick={handleSmartPolish}
|
|
disabled={isOptimizing}
|
|
className="absolute bottom-3 right-3 flex items-center gap-1.5 px-3 py-1.5
|
|
bg-purple-500/10 hover:bg-purple-500/20 text-purple-500 rounded-full
|
|
transition-colors text-xs disabled:opacity-50"
|
|
whileHover={{ scale: 1.05 }}
|
|
whileTap={{ scale: 0.95 }}
|
|
>
|
|
<Sparkles className="w-3.5 h-3.5" />
|
|
<span>{isOptimizing ? "优化中..." : "智能优化"}</span>
|
|
</motion.button>
|
|
</div>
|
|
);
|
|
});
|