AI创作模块优化样式

This commit is contained in:
2026-07-02 13:27:59 +08:00
parent 854a251d22
commit 6b7604dd38
+156 -126
View File
@@ -1569,7 +1569,7 @@ const AIChatPage: React.FC = () => {
lineHeight: 1.6, lineHeight: 1.6,
cursor: 'pointer', cursor: 'pointer',
transition: 'all 0.2s ease', transition: 'all 0.2s ease',
boxShadow: '0 1px 3px rgba(99, 102, 241, 0.04)', boxShadow: '0 1px 2px rgba(15, 23, 42, 0.03)',
}} }}
onMouseEnter={() => { onMouseEnter={() => {
setExpandedPrompts(prev => { setExpandedPrompts(prev => {
@@ -1726,7 +1726,7 @@ const AIChatPage: React.FC = () => {
borderRadius: 12, borderRadius: 12,
boxShadow: '0 4px 20px rgba(0,0,0,0.15)', boxShadow: '0 4px 20px rgba(0,0,0,0.15)',
padding: 16, padding: 16,
minWidth: 200, minWidth: 174,
zIndex: 9999, zIndex: 9999,
}} }}
onClick={(e) => e.stopPropagation()} onClick={(e) => e.stopPropagation()}
@@ -1805,19 +1805,18 @@ const AIChatPage: React.FC = () => {
{/* 输入区域 - 始终显示 */} {/* 输入区域 - 始终显示 */}
<div <div
style={{ style={{
background: 'rgba(255,255,255,0.15)', background: '#ffffff',
backdropFilter: 'blur(24px)', borderRadius: 22,
borderRadius: 24, padding: '16px 18px',
padding: 16, boxShadow: '0 10px 28px rgba(15, 23, 42, 0.06)',
boxShadow: '0 12px 40px rgba(99, 102, 241, 0.12), 0 4px 16px rgba(0,0,0,0.06), inset 0 1px 0 rgba(255,255,255,0.6)', transition: 'all 0.25s ease',
transition: 'all 0.3s ease', border: '1px solid #eef1f5',
border: '1px solid rgba(99, 102, 241, 0.12)',
}} }}
> >
{/* 左右布局容器 */} {/* 上方输入布局 */}
<div style={{ display: 'flex', gap: 16, marginBottom: 14 }}> <div style={{ display: 'flex', gap: 16, alignItems: 'flex-start', marginBottom: 14 }}>
{/* 左侧附件区域 - 20% */} {/* 左侧附件区域 */}
<div style={{ width: '20%', minWidth: 100, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'flex-start' }}> <div style={{ width: 68, minWidth: 68, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'flex-start', paddingTop: 2 }}>
{/* 首尾帧模式 */} {/* 首尾帧模式 */}
{mediaType === 'video' && referenceMode === 'first_last_frame' ? ( {mediaType === 'video' && referenceMode === 'first_last_frame' ? (
<div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 6, width: '100%' }}> <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 6, width: '100%' }}>
@@ -2010,11 +2009,11 @@ const AIChatPage: React.FC = () => {
<> <>
{currentMedia.length > 0 ? ( {currentMedia.length > 0 ? (
<div <div
style={{ position: 'relative', width: '100%', minHeight: 80, display: 'flex', justifyContent: 'center' }} style={{ position: 'relative', width: '100%', minHeight: 62, display: 'flex', justifyContent: 'center' }}
onMouseEnter={() => setMediaStackHovered(true)} onMouseEnter={() => setMediaStackHovered(true)}
onMouseLeave={() => setMediaStackHovered(false)} onMouseLeave={() => setMediaStackHovered(false)}
> >
<div style={{ position: 'relative', width: 70, height: 70 }}> <div style={{ position: 'relative', width: 54, height: 62 }}>
{currentMedia.slice(0, 4).map((media, idx) => { {currentMedia.slice(0, 4).map((media, idx) => {
const reversedIdx = currentMedia.slice(0, 4).length - 1 - idx; const reversedIdx = currentMedia.slice(0, 4).length - 1 - idx;
const offsetX = mediaStackHovered ? idx * 6 : idx * 3; const offsetX = mediaStackHovered ? idx * 6 : idx * 3;
@@ -2032,7 +2031,7 @@ const AIChatPage: React.FC = () => {
opacity: mediaStackHovered ? 1 : (1 - reversedIdx * 0.18), opacity: mediaStackHovered ? 1 : (1 - reversedIdx * 0.18),
}} }}
> >
<div style={{ position: 'relative', width: 60, height: 60 }}> <div style={{ position: 'relative', width: 50, height: 58 }}>
{media.type === 'image' ? ( {media.type === 'image' ? (
<img <img
src={`${import.meta.env.VITE_API_BASE || "http://localhost:8000"}${media.url}`} src={`${import.meta.env.VITE_API_BASE || "http://localhost:8000"}${media.url}`}
@@ -2043,7 +2042,7 @@ const AIChatPage: React.FC = () => {
setAttachmentPreviewName(media.name); setAttachmentPreviewName(media.name);
setAttachmentPreviewVisible(true); setAttachmentPreviewVisible(true);
}} }}
style={{ width: 60, height: 60, objectFit: 'cover', borderRadius: 8, cursor: 'pointer', border: '2px solid rgba(255,255,255,0.9)', boxShadow: '0 2px 8px rgba(99, 102, 241, 0.2)' }} style={{ width: 50, height: 58, objectFit: 'cover', borderRadius: 8, cursor: 'pointer', border: '2px solid rgba(255,255,255,0.95)', boxShadow: '0 2px 8px rgba(15, 23, 42, 0.12)' }}
/> />
) : ( ) : (
<video <video
@@ -2055,7 +2054,7 @@ const AIChatPage: React.FC = () => {
setAttachmentPreviewName(media.name); setAttachmentPreviewName(media.name);
setAttachmentPreviewVisible(true); setAttachmentPreviewVisible(true);
}} }}
style={{ width: 60, height: 60, objectFit: 'cover', borderRadius: 8, cursor: 'pointer', border: '2px solid rgba(255,255,255,0.9)', boxShadow: '0 2px 8px rgba(99, 102, 241, 0.2)' }} style={{ width: 50, height: 58, objectFit: 'cover', borderRadius: 8, cursor: 'pointer', border: '2px solid rgba(255,255,255,0.95)', boxShadow: '0 2px 8px rgba(15, 23, 42, 0.12)' }}
/> />
)} )}
<button <button
@@ -2096,7 +2095,7 @@ const AIChatPage: React.FC = () => {
{/* 上传按钮 - 非首尾帧模式且还有上传空间时显示 */} {/* 上传按钮 - 非首尾帧模式且还有上传空间时显示 */}
{!(mediaType === 'video' && referenceMode === 'first_last_frame') && ( {!(mediaType === 'video' && referenceMode === 'first_last_frame') && (
<div style={{ marginTop: currentMedia.length > 0 ? 8 : 0, width: '100%', maxWidth: 70, display: 'flex', justifyContent: 'center' }}> <div style={{ marginTop: currentMedia.length > 0 ? 6 : 0, width: '100%', maxWidth: 58, display: 'flex', justifyContent: 'center' }}>
<Upload <Upload
accept={mediaType === 'image' ? 'image/*' : 'image/*,video/*'} accept={mediaType === 'image' ? 'image/*' : 'image/*,video/*'}
showUploadList={false} showUploadList={false}
@@ -2108,30 +2107,39 @@ const AIChatPage: React.FC = () => {
}> }>
<div <div
style={{ style={{
width: 70, width: 48,
aspectRatio: '1', height: 68,
borderRadius: 10, borderRadius: 6,
border: '2px dashed rgba(99, 102, 241, 0.3)', border: '1px solid #eef1f5',
display: 'flex', display: 'flex',
alignItems: 'center', alignItems: 'center',
justifyContent: 'center', justifyContent: 'center',
cursor: 'pointer', cursor: 'pointer',
transition: 'all 0.25s ease', transition: 'all 0.25s ease',
backgroundColor: 'rgba(99, 102, 241, 0.04)', backgroundColor: '#f3f6f8',
flexDirection: 'column',
gap: 6,
transform: currentMedia.length > 0 ? 'none' : 'rotate(-7deg)',
boxShadow: '0 8px 18px rgba(15, 23, 42, 0.06)',
}} }}
onMouseEnter={(e) => { onMouseEnter={(e) => {
e.currentTarget.style.borderColor = '#6366f1'; e.currentTarget.style.borderColor = '#d7e7f2';
e.currentTarget.style.backgroundColor = 'rgba(99, 102, 241, 0.08)'; e.currentTarget.style.backgroundColor = '#eef7fb';
e.currentTarget.style.transform = 'rotate(0deg) translateY(-1px)';
}} }}
onMouseLeave={(e) => { onMouseLeave={(e) => {
e.currentTarget.style.borderColor = 'rgba(99, 102, 241, 0.3)'; e.currentTarget.style.borderColor = '#eef1f5';
e.currentTarget.style.backgroundColor = 'rgba(99, 102, 241, 0.04)'; e.currentTarget.style.backgroundColor = '#f3f6f8';
e.currentTarget.style.transform = currentMedia.length > 0 ? 'none' : 'rotate(-7deg)';
}} }}
> >
{uploading ? ( {uploading ? (
<LoadingOutlined style={{ fontSize: 18, color: '#6366f1' }} /> <LoadingOutlined style={{ fontSize: 17, color: '#94a3b8' }} />
) : ( ) : (
<PlusOutlined style={{ fontSize: 18, color: '#6366f1' }} /> <>
<PlusOutlined style={{ fontSize: 17, color: '#94a3b8' }} />
<span style={{ fontSize: 10, color: '#94a3b8', fontWeight: 600, lineHeight: 1.1, writingMode: 'vertical-rl', letterSpacing: 1 }}></span>
</>
)} )}
</div> </div>
</Tooltip> </Tooltip>
@@ -2142,21 +2150,21 @@ const AIChatPage: React.FC = () => {
)} )}
</div> </div>
{/* 右侧输入区域 - 80% */} {/* 右侧输入区域 */}
<div style={{ width: '80%', flex: 1 }}> <div style={{ flex: 1, minWidth: 0 }}>
{/* 输入框区域 */} {/* 输入框区域 */}
<div style={{ <div style={{
display: 'flex', display: 'flex',
flexDirection: 'column', flexDirection: 'column',
gap: 10, gap: 10,
padding: '16px 18px', padding: '2px 0 0',
backgroundColor: 'rgba(248,250,252,0.7)', backgroundColor: 'transparent',
borderRadius: 18, borderRadius: 0,
border: '1px solid rgba(99, 102, 241, 0.1)', border: 'none',
boxShadow: '0 2px 12px rgba(99, 102, 241, 0.06)', boxShadow: 'none',
transition: 'all 0.2s ease', transition: 'all 0.2s ease',
position: 'relative', position: 'relative',
minHeight: 120, minHeight: 82,
}}> }}>
{/* 文本输入框 */} {/* 文本输入框 */}
<TextArea <TextArea
@@ -2166,25 +2174,26 @@ const AIChatPage: React.FC = () => {
onKeyDown={handleInputKeyDown} onKeyDown={handleInputKeyDown}
onKeyPress={handleKeyPress} onKeyPress={handleKeyPress}
placeholder={mediaType === 'image' placeholder={mediaType === 'image'
? `上传参考图,输入提示词描述您想生成的画面...` ? '上传最多12个参考素材,输入文字或 @ 参考内容,自由组合图、文、音、视频多元素,定义精彩互动。例如:@图片1 参考风格生成海报。'
: referenceMode === 'first_last_frame' : referenceMode === 'first_last_frame'
? '上传首帧和尾帧,输入提示词描述您想生成的视频...' ? '上传首帧和尾帧,输入文字描述镜头运动、主体动作和画面氛围。'
: `上传参考图和视频,输入提示词描述您想生成的画面...` : '上传最多12个参考素材,输入文字或 @ 参考内容,自由组合图、文、音、视频多元素,定义精彩互动。例如:@图片1 模仿 @视频1 的动作,音色参考 @音频1。'
} }
autoSize={{ minRows: 3, maxRows: 6 }} autoSize={{ minRows: 3, maxRows: 6 }}
style={{ style={{
flex: 1, flex: 1,
width: '100%', width: '100%',
borderRadius: 10, borderRadius: 0,
border: 'none', border: 'none',
outline: 'none', outline: 'none',
boxShadow: 'none', boxShadow: 'none',
fontSize: 15, fontSize: 14,
lineHeight: 1.6, lineHeight: 1.55,
color: '#1e293b', color: '#1e293b',
fontWeight: 400, fontWeight: 400,
resize: 'none', resize: 'none',
backgroundColor: 'transparent', backgroundColor: 'transparent',
padding: 0,
}} }}
disabled={loading} disabled={loading}
/> />
@@ -2242,72 +2251,34 @@ const AIChatPage: React.FC = () => {
))} ))}
</div> </div>
)} )}
{/* 发送按钮 - 右下角 */}
<div style={{ display: 'flex', justifyContent: 'flex-end' }}>
<Button
type="primary"
shape="circle"
icon={<ArrowUpOutlined />}
onClick={handleSend}
disabled={
mediaType === 'video' && referenceMode === 'first_last_frame'
? !inputValue.trim() && !firstFrame
: !inputValue.trim() && currentMedia.length === 0
}
loading={loading}
style={{
flexShrink: 0,
width: 40,
height: 40,
borderRadius: 12,
background: (
mediaType === 'video' && referenceMode === 'first_last_frame'
? (inputValue.trim() || firstFrame)
: (inputValue.trim() || currentMedia.length > 0)
)
? 'linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%)'
: '#c7cfdaff',
boxShadow: (
mediaType === 'video' && referenceMode === 'first_last_frame'
? (inputValue.trim() || firstFrame)
: (inputValue.trim() || currentMedia.length > 0)
)
? '0 4px 16px rgba(99, 102, 241, 0.4)'
: 'none',
transition: 'all 0.2s ease',
border: 'none',
}}
/>
</div>
</div> </div>
</div> </div>
</div> </div>
{/* 底部选择器 - 媒体类型和数量 */} {/* 底部工具栏 */}
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginTop: 14, paddingTop: 14, borderTop: '1px solid rgba(99, 102, 241, 0.1)' }}> <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: 12, marginTop: 8, paddingTop: 10, borderTop: '1px solid #f1f5f9' }}>
<Space size={10}> <Space size={8} wrap style={{ flex: 1, minWidth: 0 }}>
{/* 文件类型选择器 */} {/* 文件类型选择器 */}
<Select <Select
value={mediaType} value={mediaType}
onChange={(val) => setMediaType(val)} onChange={(val) => setMediaType(val)}
style={{ style={{
width: 100, width: 118,
height: 36, height: 32,
outline: 'none', outline: 'none',
border: 'none', border: '1px solid #e9eef5',
backgroundColor: '#f1f5f9', backgroundColor: '#ffffff',
borderRadius: 10, borderRadius: 10,
}} }}
size="middle" size="middle"
> >
<Option value="video"> <Option value="video">
<VideoCameraOutlined style={{ marginRight: 6, fontSize: 14, color: '#6366f1' }} /> <VideoCameraOutlined style={{ marginRight: 6, fontSize: 14, color: '#6366f1' }} />
<span style={{ fontSize: 13, fontWeight: 500, color: '#6366f1' }}></span> <span style={{ fontSize: 13, fontWeight: 600, color: '#0ea5e9' }}></span>
</Option> </Option>
<Option value="image"> <Option value="image">
<PictureOutlined style={{ marginRight: 6, fontSize: 14, color: '#6366f1' }} /> <PictureOutlined style={{ marginRight: 6, fontSize: 14, color: '#6366f1' }} />
<span style={{ fontSize: 13, fontWeight: 500, color: '#6366f1' }}></span> <span style={{ fontSize: 13, fontWeight: 600, color: '#0ea5e9' }}></span>
</Option> </Option>
</Select> </Select>
@@ -2317,35 +2288,35 @@ const AIChatPage: React.FC = () => {
onClick={() => setShowEngineModal(true)} onClick={() => setShowEngineModal(true)}
className="image-settings-trigger" className="image-settings-trigger"
style={{ style={{
minWidth: 200, minWidth: 174,
padding: '6px 14px', padding: '5px 12px',
height: 36, height: 32,
borderRadius: 10, borderRadius: 10,
border: '1px solid rgba(99, 102, 241, 0.15)', border: '1px solid #e9eef5',
backgroundColor: 'rgba(241, 245, 249, 0.8)', backgroundColor: '#ffffff',
cursor: 'pointer', cursor: 'pointer',
display: 'inline-flex', display: 'inline-flex',
alignItems: 'center', alignItems: 'center',
gap: 6, gap: 6,
transition: 'all 0.2s ease', transition: 'all 0.2s ease',
boxShadow: '0 1px 3px rgba(99, 102, 241, 0.04)', boxShadow: '0 1px 2px rgba(15, 23, 42, 0.03)',
}} }}
onMouseEnter={(e) => { onMouseEnter={(e) => {
e.currentTarget.style.backgroundColor = 'rgba(99, 102, 241, 0.08)'; e.currentTarget.style.backgroundColor = '#f8fafc';
e.currentTarget.style.borderColor = 'rgba(99, 102, 241, 0.3)'; e.currentTarget.style.borderColor = '#d7e7f2';
e.currentTarget.style.boxShadow = '0 2px 8px rgba(99, 102, 241, 0.1)'; e.currentTarget.style.boxShadow = '0 2px 8px rgba(15, 23, 42, 0.06)';
}} }}
onMouseLeave={(e) => { onMouseLeave={(e) => {
e.currentTarget.style.backgroundColor = 'rgba(241, 245, 249, 0.8)'; e.currentTarget.style.backgroundColor = '#ffffff';
e.currentTarget.style.borderColor = 'rgba(99, 102, 241, 0.15)'; e.currentTarget.style.borderColor = '#e9eef5';
e.currentTarget.style.boxShadow = '0 1px 3px rgba(99, 102, 241, 0.04)'; e.currentTarget.style.boxShadow = '0 1px 2px rgba(15, 23, 42, 0.03)';
}} }}
> >
<SettingOutlined style={{ fontSize: 14, color: '#6366f1' }} /> <SettingOutlined style={{ fontSize: 14, color: '#6366f1' }} />
<Text style={{ <Text style={{
fontSize: 13, fontSize: 13,
fontWeight: 500, fontWeight: 500,
color: '#6366f1', color: '#334155',
}}> }}>
{mediaType === 'image' ? enginesele.image?.find((e: any) => e.id === countType)?.name : enginesele.video?.find((e: any) => e.id === countType)?.name || '选择引擎'} {mediaType === 'image' ? enginesele.image?.find((e: any) => e.id === countType)?.name : enginesele.video?.find((e: any) => e.id === countType)?.name || '选择引擎'}
</Text> </Text>
@@ -2459,7 +2430,7 @@ const AIChatPage: React.FC = () => {
onClick={() => setReferenceModeDropdownVisible(!referenceModeDropdownVisible)} onClick={() => setReferenceModeDropdownVisible(!referenceModeDropdownVisible)}
className="image-settings-trigger" className="image-settings-trigger"
style={{ style={{
minWidth: 120, minWidth: 118,
padding: '6px 14px', padding: '6px 14px',
height: 36, height: 36,
borderRadius: 10, borderRadius: 10,
@@ -2470,7 +2441,7 @@ const AIChatPage: React.FC = () => {
alignItems: 'center', alignItems: 'center',
gap: 6, gap: 6,
transition: 'all 0.2s ease', transition: 'all 0.2s ease',
boxShadow: '0 1px 3px rgba(99, 102, 241, 0.04)', boxShadow: '0 1px 2px rgba(15, 23, 42, 0.03)',
}} }}
onMouseEnter={(e) => { onMouseEnter={(e) => {
e.currentTarget.style.backgroundColor = 'rgba(99, 102, 241, 0.08)'; e.currentTarget.style.backgroundColor = 'rgba(99, 102, 241, 0.08)';
@@ -2487,7 +2458,7 @@ const AIChatPage: React.FC = () => {
<Text style={{ <Text style={{
fontSize: 13, fontSize: 13,
fontWeight: 500, fontWeight: 500,
color: '#6366f1', color: '#334155',
}}> }}>
{referenceMode === 'universal' ? '全能参考' : '首尾帧'} {referenceMode === 'universal' ? '全能参考' : '首尾帧'}
</Text> </Text>
@@ -2627,7 +2598,7 @@ const AIChatPage: React.FC = () => {
onClick={() => setShowImageSettingsModal(!showImageSettingsModal)} onClick={() => setShowImageSettingsModal(!showImageSettingsModal)}
className="image-settings-trigger" className="image-settings-trigger"
style={{ style={{
minWidth: 220, minWidth: 156,
padding: '6px 14px', padding: '6px 14px',
height: 36, height: 36,
borderRadius: 10, borderRadius: 10,
@@ -2638,7 +2609,7 @@ const AIChatPage: React.FC = () => {
alignItems: 'center', alignItems: 'center',
gap: 6, gap: 6,
transition: 'all 0.2s ease', transition: 'all 0.2s ease',
boxShadow: '0 1px 3px rgba(99, 102, 241, 0.04)', boxShadow: '0 1px 2px rgba(15, 23, 42, 0.03)',
}} }}
onMouseEnter={(e) => { onMouseEnter={(e) => {
e.currentTarget.style.backgroundColor = 'rgba(99, 102, 241, 0.08)'; e.currentTarget.style.backgroundColor = 'rgba(99, 102, 241, 0.08)';
@@ -2655,7 +2626,7 @@ const AIChatPage: React.FC = () => {
<Text style={{ <Text style={{
fontSize: 13, fontSize: 13,
fontWeight: 500, fontWeight: 500,
color: '#6366f1', color: '#334155',
}}> }}>
{selectedRatio === 'auto' ? '智能' : selectedRatio} · {selectedResolution == '2K' ? '2K高清' : '4K超清'} · {width}×{height} {selectedRatio === 'auto' ? '智能' : selectedRatio} · {selectedResolution == '2K' ? '2K高清' : '4K超清'} · {width}×{height}
</Text> </Text>
@@ -2931,7 +2902,7 @@ const AIChatPage: React.FC = () => {
onClick={() => setShowVideoSettingsModal(!showVideoSettingsModal)} onClick={() => setShowVideoSettingsModal(!showVideoSettingsModal)}
className="image-settings-trigger" className="image-settings-trigger"
style={{ style={{
minWidth: 220, minWidth: 156,
padding: '6px 14px', padding: '6px 14px',
height: 36, height: 36,
borderRadius: 10, borderRadius: 10,
@@ -2942,7 +2913,7 @@ const AIChatPage: React.FC = () => {
alignItems: 'center', alignItems: 'center',
gap: 6, gap: 6,
transition: 'all 0.2s ease', transition: 'all 0.2s ease',
boxShadow: '0 1px 3px rgba(99, 102, 241, 0.04)', boxShadow: '0 1px 2px rgba(15, 23, 42, 0.03)',
}} }}
onMouseEnter={(e) => { onMouseEnter={(e) => {
e.currentTarget.style.backgroundColor = 'rgba(99, 102, 241, 0.08)'; e.currentTarget.style.backgroundColor = 'rgba(99, 102, 241, 0.08)';
@@ -2955,15 +2926,13 @@ const AIChatPage: React.FC = () => {
e.currentTarget.style.boxShadow = '0 1px 3px rgba(99, 102, 241, 0.04)'; e.currentTarget.style.boxShadow = '0 1px 3px rgba(99, 102, 241, 0.04)';
}} }}
> >
<LayoutOutlined style={{ fontSize: 14, color: '#6366f1' }} /> <LayoutOutlined style={{ fontSize: 14, color: '#334155' }} />
<Text style={{ <span style={{ fontSize: 13, fontWeight: 600, color: '#334155' }}>{videoAspectRatio}</span>
fontSize: 13, <span style={{ width: 1, height: 14, background: '#e5e7eb' }} />
fontWeight: 500, <span style={{ fontSize: 13, fontWeight: 600, color: '#334155' }}>{videoResolution?.toUpperCase?.() || videoResolution}</span>
color: '#6366f1', <span style={{ width: 1, height: 14, background: '#e5e7eb' }} />
}}> <span style={{ fontSize: 13, fontWeight: 600, color: '#334155' }}>{videoDuration}s</span>
{videoAspectRatio} · {videoDuration}s · {videoResolution} <CaretDownOutlined style={{ fontSize: 10, color: '#64748b', marginLeft: 'auto' }} />
</Text>
<CaretDownOutlined style={{ fontSize: 10, color: '#6366f1', marginLeft: 'auto' }} />
</button> </button>
{showVideoSettingsModal && ( {showVideoSettingsModal && (
@@ -3176,13 +3145,68 @@ const AIChatPage: React.FC = () => {
)} )}
</div> </div>
)} )}
{/* 预估积分 */} <button
<div style={{ display: 'flex', alignItems: 'center', gap: 6, padding: '6px 14px', backgroundColor: 'rgba(99, 102, 241, 0.06)', borderRadius: 10, border: '1px solid rgba(99, 102, 241, 0.1)' }}> type="button"
<Text style={{ fontSize: 13, color: '#6366f1', fontWeight: 500 }}></Text> onClick={() => {
<Text style={{ fontSize: 14, color: '#6366f1', fontWeight: 600 }}>{getEstimatedCredits()}</Text> setInputValue(`${inputValue}@`);
</div> setMentionVisible(currentMedia.length > 0 && referenceMode === 'universal');
setTimeout(() => mentionInputRef.current?.focus?.(), 0);
}}
style={{
width: 32,
height: 32,
borderRadius: 10,
border: '1px solid #e9eef5',
background: '#ffffff',
color: '#334155',
fontSize: 16,
fontWeight: 700,
cursor: 'pointer',
display: 'inline-flex',
alignItems: 'center',
justifyContent: 'center',
boxShadow: '0 1px 2px rgba(15, 23, 42, 0.03)',
}}
>
@
</button>
</Space> </Space>
<div style={{ display: 'flex', alignItems: 'center', gap: 12, flexShrink: 0 }}>
<div style={{ display: 'flex', alignItems: 'center', gap: 6, color: '#64748b' }}>
<span style={{ fontSize: 15, lineHeight: 1, color: '#475569' }}></span>
<Text style={{ fontSize: 13, color: '#64748b', fontWeight: 600 }}>{getEstimatedCredits()}</Text>
</div>
<Button
type="primary"
shape="circle"
icon={<ArrowUpOutlined />}
onClick={handleSend}
disabled={
mediaType === 'video' && referenceMode === 'first_last_frame'
? !inputValue.trim() && !firstFrame
: !inputValue.trim() && currentMedia.length === 0
}
loading={loading}
style={{
flexShrink: 0,
width: 36,
height: 36,
borderRadius: '50%',
background: (
mediaType === 'video' && referenceMode === 'first_last_frame'
? (inputValue.trim() || firstFrame)
: (inputValue.trim() || currentMedia.length > 0)
)
? '#cbd5e1'
: '#d9dee6',
color: '#ffffff',
boxShadow: 'none',
transition: 'all 0.2s ease',
border: 'none',
}}
/>
</div>
</div> </div>
</div> </div>
</Content> </Content>
@@ -3194,6 +3218,12 @@ const AIChatPage: React.FC = () => {
0%, 50% { opacity: 1; } 0%, 50% { opacity: 1; }
51%, 100% { opacity: 0.3; } 51%, 100% { opacity: 0.3; }
} }
textarea::placeholder {
color: #9aa7b2 !important;
}
.ant-select-selector {
border-radius: 10px !important;
}
`}</style> `}</style>
{/* 图片/视频预览弹窗 */} {/* 图片/视频预览弹窗 */}