修改弹窗的关闭图标和整体样式,增加素材云的浮动下载
This commit is contained in:
+4
-4
File diff suppressed because one or more lines are too long
Vendored
+36
-36
@@ -1,37 +1,37 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="zh-CN">
|
<html lang="zh-CN">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;600;700&display=swap" rel="stylesheet" />
|
<link href="https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;600;700&display=swap" rel="stylesheet" />
|
||||||
<title>民众智创</title>
|
<title>民众智创</title>
|
||||||
<script>
|
<script>
|
||||||
(function() {
|
(function() {
|
||||||
var cached = localStorage.getItem('siteInfo');
|
var cached = localStorage.getItem('siteInfo');
|
||||||
if (cached) {
|
if (cached) {
|
||||||
try {
|
try {
|
||||||
var info = JSON.parse(cached);
|
var info = JSON.parse(cached);
|
||||||
if (info.siteName) {
|
if (info.siteName) {
|
||||||
document.title = info.siteName;
|
document.title = info.siteName;
|
||||||
}
|
}
|
||||||
if (info.siteLogo) {
|
if (info.siteLogo) {
|
||||||
var link = document.querySelector('link[rel="icon"]');
|
var link = document.querySelector('link[rel="icon"]');
|
||||||
if (link) {
|
if (link) {
|
||||||
link.href = info.siteLogo;
|
link.href = info.siteLogo;
|
||||||
link.type = 'image/png';
|
link.type = 'image/png';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
</script>
|
</script>
|
||||||
<script type="module" crossorigin src="/assets/index-Cs6AfEXe.js"></script>
|
<script type="module" crossorigin src="/assets/index-BxqbNh67.js"></script>
|
||||||
<link rel="stylesheet" crossorigin href="/assets/index-BhPFzWLH.css">
|
<link rel="stylesheet" crossorigin href="/assets/index-BhPFzWLH.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="root"></div>␍
|
<div id="root"></div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ import {
|
|||||||
SettingOutlined,
|
SettingOutlined,
|
||||||
LayoutOutlined,
|
LayoutOutlined,
|
||||||
ArrowUpOutlined,
|
ArrowUpOutlined,
|
||||||
|
DownloadOutlined,
|
||||||
|
|
||||||
} from '@ant-design/icons';
|
} from '@ant-design/icons';
|
||||||
|
|
||||||
@@ -2297,46 +2298,30 @@ const AIChatPage: React.FC = () => {
|
|||||||
{/* 图片/视频预览弹窗 */}
|
{/* 图片/视频预览弹窗 */}
|
||||||
<Modal
|
<Modal
|
||||||
open={previewVisible}
|
open={previewVisible}
|
||||||
onCancel={handleClosePreview}
|
title={
|
||||||
footer={[
|
<div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
|
||||||
<Button key="download" type="primary" onClick={handleDownload} style={{ background: 'linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%)', borderRadius: 10, border: 'none' }}>
|
<div style={{ width: 4, height: 20, background: 'linear-gradient(180deg, #6366f1 0%, #8b5cf6 100%)', borderRadius: 2 }} />
|
||||||
下载
|
<span style={{ fontSize: 16, fontWeight: 700, background: 'linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%)', WebkitBackgroundClip: 'text', WebkitTextFillColor: 'transparent', backgroundClip: 'text' }}>
|
||||||
</Button>,
|
预览
|
||||||
]}
|
</span>
|
||||||
width={800}
|
</div>
|
||||||
centered
|
|
||||||
closeIcon={
|
|
||||||
<button
|
|
||||||
onClick={handleClosePreview}
|
|
||||||
style={{
|
|
||||||
width: 32,
|
|
||||||
height: 32,
|
|
||||||
borderRadius: '50%',
|
|
||||||
border: 'none',
|
|
||||||
background: 'rgba(99, 102, 241, 0.1)',
|
|
||||||
cursor: 'pointer',
|
|
||||||
fontSize: 16,
|
|
||||||
color: '#6366f1',
|
|
||||||
fontWeight: 'bold',
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'center',
|
|
||||||
transition: 'all 0.2s',
|
|
||||||
}}
|
|
||||||
onMouseEnter={(e) => {
|
|
||||||
e.currentTarget.style.background = 'rgba(239, 68, 68, 0.1)';
|
|
||||||
e.currentTarget.style.color = '#ef4444';
|
|
||||||
e.currentTarget.style.transform = 'scale(1.1)';
|
|
||||||
}}
|
|
||||||
onMouseLeave={(e) => {
|
|
||||||
e.currentTarget.style.background = 'rgba(99, 102, 241, 0.1)';
|
|
||||||
e.currentTarget.style.color = '#6366f1';
|
|
||||||
e.currentTarget.style.transform = 'scale(1)';
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
×
|
|
||||||
</button>
|
|
||||||
}
|
}
|
||||||
|
onCancel={handleClosePreview}
|
||||||
|
width={800}
|
||||||
|
footer={
|
||||||
|
<div style={{ display: 'flex', justifyContent: 'flex-end', gap: 12, padding: '16px 24px', background: 'rgba(255,255,255,0.6)', borderTop: '1px solid rgba(99, 102, 241, 0.08)' }}>
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
icon={<DownloadOutlined />}
|
||||||
|
onClick={handleDownload}
|
||||||
|
style={{ borderRadius: 8, background: 'linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%)', border: 'none', boxShadow: '0 4px 12px rgba(99, 102, 241, 0.3)' }}
|
||||||
|
disabled={isMediaExpired(previewUrl)}
|
||||||
|
>
|
||||||
|
{isMediaExpired(previewUrl) ? '资源已过期' : '下载'}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
centered
|
||||||
style={{ borderRadius: 16 }}
|
style={{ borderRadius: 16 }}
|
||||||
styles={{
|
styles={{
|
||||||
body: {
|
body: {
|
||||||
@@ -2345,21 +2330,13 @@ const AIChatPage: React.FC = () => {
|
|||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
minHeight: '400px',
|
minHeight: '400px',
|
||||||
},
|
},
|
||||||
|
header: { background: 'rgba(255,255,255,0.6)', backdropFilter: 'blur(10px)', borderBottom: '1px solid rgba(99, 102, 241, 0.08)', padding: '16px 24px' },
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', width: '100%', height: '100%' }}>
|
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', width: '100%', height: '100%' }}>
|
||||||
{isMediaExpired(previewUrl) ? (
|
{isMediaExpired(previewUrl) ? (
|
||||||
<div style={{ textAlign: 'center', padding: '40px' }}>
|
<div style={{ textAlign: 'center', padding: '40px' }}>
|
||||||
{/* <div style={{ fontSize: 48, marginBottom: 16 }}>⚠️</div> */}
|
|
||||||
<p style={{ fontSize: 16, color: '#ff4d4f', marginBottom: 16 }}>图片/视频资源已过期,请刷新重新加载~</p>
|
<p style={{ fontSize: 16, color: '#ff4d4f', marginBottom: 16 }}>图片/视频资源已过期,请刷新重新加载~</p>
|
||||||
{/* <Button
|
|
||||||
type="primary"
|
|
||||||
onClick={() => {
|
|
||||||
window.location.reload();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
刷新页面重新加载
|
|
||||||
</Button> */}
|
|
||||||
</div>
|
</div>
|
||||||
) : previewType === 'image' ? (
|
) : previewType === 'image' ? (
|
||||||
<img
|
<img
|
||||||
@@ -2381,54 +2358,37 @@ const AIChatPage: React.FC = () => {
|
|||||||
{/* 附件预览弹窗(独立弹窗) */}
|
{/* 附件预览弹窗(独立弹窗) */}
|
||||||
<Modal
|
<Modal
|
||||||
open={attachmentPreviewVisible}
|
open={attachmentPreviewVisible}
|
||||||
onCancel={() => setAttachmentPreviewVisible(false)}
|
title={
|
||||||
footer={[
|
<div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
|
||||||
<Button key="download" type="primary" onClick={() => {
|
<div style={{ width: 4, height: 20, background: 'linear-gradient(180deg, #6366f1 0%, #8b5cf6 100%)', borderRadius: 2 }} />
|
||||||
if (!attachmentPreviewUrl) return;
|
<span style={{ fontSize: 16, fontWeight: 700, background: 'linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%)', WebkitBackgroundClip: 'text', WebkitTextFillColor: 'transparent', backgroundClip: 'text' }}>
|
||||||
const link = document.createElement('a');
|
附件预览
|
||||||
link.href = `${import.meta.env.VITE_API_BASE || "http://localhost:8000"}${attachmentPreviewUrl}&download=1`;
|
</span>
|
||||||
link.download = attachmentPreviewName || (attachmentPreviewType === 'image' ? 'image.png' : 'video.mp4');
|
</div>
|
||||||
document.body.appendChild(link);
|
|
||||||
link.click();
|
|
||||||
document.body.removeChild(link);
|
|
||||||
}} style={{ background: 'linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%)', borderRadius: 10, border: 'none' }}>
|
|
||||||
下载
|
|
||||||
</Button>,
|
|
||||||
]}
|
|
||||||
width={800}
|
|
||||||
centered
|
|
||||||
closeIcon={
|
|
||||||
<button
|
|
||||||
onClick={() => setAttachmentPreviewVisible(false)}
|
|
||||||
style={{
|
|
||||||
width: 32,
|
|
||||||
height: 32,
|
|
||||||
borderRadius: '50%',
|
|
||||||
border: 'none',
|
|
||||||
background: 'rgba(99, 102, 241, 0.1)',
|
|
||||||
cursor: 'pointer',
|
|
||||||
fontSize: 16,
|
|
||||||
color: '#6366f1',
|
|
||||||
fontWeight: 'bold',
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'center',
|
|
||||||
transition: 'all 0.2s',
|
|
||||||
}}
|
|
||||||
onMouseEnter={(e) => {
|
|
||||||
e.currentTarget.style.background = 'rgba(239, 68, 68, 0.1)';
|
|
||||||
e.currentTarget.style.color = '#ef4444';
|
|
||||||
e.currentTarget.style.transform = 'scale(1.1)';
|
|
||||||
}}
|
|
||||||
onMouseLeave={(e) => {
|
|
||||||
e.currentTarget.style.background = 'rgba(99, 102, 241, 0.1)';
|
|
||||||
e.currentTarget.style.color = '#6366f1';
|
|
||||||
e.currentTarget.style.transform = 'scale(1)';
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
×
|
|
||||||
</button>
|
|
||||||
}
|
}
|
||||||
|
onCancel={() => setAttachmentPreviewVisible(false)}
|
||||||
|
width={800}
|
||||||
|
footer={
|
||||||
|
<div style={{ display: 'flex', justifyContent: 'flex-end', gap: 12, padding: '16px 24px', background: 'rgba(255,255,255,0.6)', borderTop: '1px solid rgba(99, 102, 241, 0.08)' }}>
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
icon={<DownloadOutlined />}
|
||||||
|
onClick={() => {
|
||||||
|
if (!attachmentPreviewUrl) return;
|
||||||
|
const link = document.createElement('a');
|
||||||
|
link.href = `${import.meta.env.VITE_API_BASE || "http://localhost:8000"}${attachmentPreviewUrl}&download=1`;
|
||||||
|
link.download = attachmentPreviewName || (attachmentPreviewType === 'image' ? 'image.png' : 'video.mp4');
|
||||||
|
document.body.appendChild(link);
|
||||||
|
link.click();
|
||||||
|
document.body.removeChild(link);
|
||||||
|
}}
|
||||||
|
style={{ borderRadius: 8, background: 'linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%)', border: 'none', boxShadow: '0 4px 12px rgba(99, 102, 241, 0.3)' }}
|
||||||
|
>
|
||||||
|
下载
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
centered
|
||||||
style={{ borderRadius: 16 }}
|
style={{ borderRadius: 16 }}
|
||||||
styles={{
|
styles={{
|
||||||
body: {
|
body: {
|
||||||
@@ -2437,6 +2397,7 @@ const AIChatPage: React.FC = () => {
|
|||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
minHeight: '400px',
|
minHeight: '400px',
|
||||||
},
|
},
|
||||||
|
header: { background: 'rgba(255,255,255,0.6)', backdropFilter: 'blur(10px)', borderBottom: '1px solid rgba(99, 102, 241, 0.08)', padding: '16px 24px' },
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', width: '100%', height: '100%' }}>
|
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', width: '100%', height: '100%' }}>
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import {
|
|||||||
PlusOutlined,
|
PlusOutlined,
|
||||||
PictureOutlined,
|
PictureOutlined,
|
||||||
SwapOutlined,
|
SwapOutlined,
|
||||||
|
XOutlined,
|
||||||
} from "@ant-design/icons";
|
} from "@ant-design/icons";
|
||||||
import { useNavigate, useParams } from "react-router-dom";
|
import { useNavigate, useParams } from "react-router-dom";
|
||||||
import { useAppStore } from "../store/useAppStore";
|
import { useAppStore } from "../store/useAppStore";
|
||||||
@@ -4583,7 +4584,7 @@ const GeneratePage: React.FC = () => {
|
|||||||
e.currentTarget.style.background = "rgba(0,0,0,0.6)";
|
e.currentTarget.style.background = "rgba(0,0,0,0.6)";
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<CloseCircleOutlined style={{ color: "#fff", fontSize: 16 }} />
|
<XOutlined style={{ color: "#fff", fontSize: 16 }} />
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React, { useEffect, useState, useLayoutEffect, useRef, useCallback } from 'react';
|
import React, { useEffect, useState, useLayoutEffect, useRef, useCallback } from 'react';
|
||||||
import { Button, Empty, Input, Select, Space, Typography, Tag, message, Modal, Table, DatePicker, Tabs, Transfer } from 'antd';
|
import { Button, Empty, Input, Select, Space, Typography, Tag, message, Modal, Table, DatePicker, Tabs, Transfer, Tooltip } from 'antd';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import JSZip from 'jszip';
|
import JSZip from 'jszip';
|
||||||
import {
|
import {
|
||||||
@@ -216,6 +216,7 @@ const GeneratedRecord: React.FC = () => {
|
|||||||
const [isError, setIsError] = useState(false);
|
const [isError, setIsError] = useState(false);
|
||||||
const [isExpired, setIsExpired] = useState(false);
|
const [isExpired, setIsExpired] = useState(false);
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
const [isHovered, setIsHovered] = useState(false);
|
||||||
const placeholderRef = useRef<HTMLDivElement>(null);
|
const placeholderRef = useRef<HTMLDivElement>(null);
|
||||||
const mediaRef = useRef<HTMLImageElement | HTMLVideoElement>(null);
|
const mediaRef = useRef<HTMLImageElement | HTMLVideoElement>(null);
|
||||||
const errorTimer = useRef<ReturnType<typeof setTimeout> | null>(null);
|
const errorTimer = useRef<ReturnType<typeof setTimeout> | null>(null);
|
||||||
@@ -299,12 +300,14 @@ const GeneratedRecord: React.FC = () => {
|
|||||||
}}
|
}}
|
||||||
onClick={!isSelectionMode ? onClick : undefined}
|
onClick={!isSelectionMode ? onClick : undefined}
|
||||||
onMouseEnter={(e) => {
|
onMouseEnter={(e) => {
|
||||||
|
setIsHovered(true);
|
||||||
if (!isSelectionMode) {
|
if (!isSelectionMode) {
|
||||||
(e.currentTarget as HTMLElement).style.transform = 'scale(1.05)';
|
(e.currentTarget as HTMLElement).style.transform = 'scale(1.05)';
|
||||||
(e.currentTarget as HTMLElement).style.boxShadow = '0 4px 16px rgba(0,0,0,0.2)';
|
(e.currentTarget as HTMLElement).style.boxShadow = '0 4px 16px rgba(0,0,0,0.2)';
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
onMouseLeave={(e) => {
|
onMouseLeave={(e) => {
|
||||||
|
setIsHovered(false);
|
||||||
if (!isSelectionMode) {
|
if (!isSelectionMode) {
|
||||||
(e.currentTarget as HTMLElement).style.transform = 'scale(1)';
|
(e.currentTarget as HTMLElement).style.transform = 'scale(1)';
|
||||||
(e.currentTarget as HTMLElement).style.boxShadow = '0 2px 8px rgba(0,0,0,0.1)';
|
(e.currentTarget as HTMLElement).style.boxShadow = '0 2px 8px rgba(0,0,0,0.1)';
|
||||||
@@ -484,6 +487,56 @@ const GeneratedRecord: React.FC = () => {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{/* 下载按钮 - hover时显示 */}
|
||||||
|
{!isSelectionMode && !isExpired && !isError && isLoaded && (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
position: 'absolute',
|
||||||
|
top: 8,
|
||||||
|
right: 8,
|
||||||
|
zIndex: 10,
|
||||||
|
opacity: isHovered ? 1 : 0,
|
||||||
|
transition: 'opacity 0.2s',
|
||||||
|
pointerEvents: isHovered ? 'auto' : 'none',
|
||||||
|
}}
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
const url = `${import.meta.env.VITE_API_BASE || "http://localhost:8000"}${item.videoUrl || item.imageUrl}&download=1`;
|
||||||
|
const link = document.createElement('a');
|
||||||
|
link.href = url;
|
||||||
|
link.download = '';
|
||||||
|
document.body.appendChild(link);
|
||||||
|
link.click();
|
||||||
|
document.body.removeChild(link);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Tooltip title="下载">
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
width: 28,
|
||||||
|
height: 28,
|
||||||
|
borderRadius: '50%',
|
||||||
|
background: 'rgba(0,0,0,0.5)',
|
||||||
|
backdropFilter: 'blur(4px)',
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
cursor: 'pointer',
|
||||||
|
transition: 'background 0.15s',
|
||||||
|
}}
|
||||||
|
onMouseEnter={(e) => {
|
||||||
|
e.currentTarget.style.background = 'rgba(0,0,0,0.7)';
|
||||||
|
}}
|
||||||
|
onMouseLeave={(e) => {
|
||||||
|
e.currentTarget.style.background = 'rgba(0,0,0,0.5)';
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<DownloadOutlined style={{ color: '#fff', fontSize: 14 }} />
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* 选择模式下的选择框 */}
|
{/* 选择模式下的选择框 */}
|
||||||
{isSelectionMode && (
|
{isSelectionMode && (
|
||||||
<div
|
<div
|
||||||
@@ -2030,77 +2083,67 @@ const GeneratedRecord: React.FC = () => {
|
|||||||
|
|
||||||
{/* 预览弹窗 */}
|
{/* 预览弹窗 */}
|
||||||
{previewVisible && previewItem && (
|
{previewVisible && previewItem && (
|
||||||
<div
|
<Modal
|
||||||
style={{
|
title={
|
||||||
position: 'fixed',
|
<div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
|
||||||
top: 0,
|
<div style={{ width: 4, height: 20, background: 'linear-gradient(180deg, #6366f1 0%, #8b5cf6 100%)', borderRadius: 2 }} />
|
||||||
left: 0,
|
<span style={{ fontSize: 16, fontWeight: 700, background: 'linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%)', WebkitBackgroundClip: 'text', WebkitTextFillColor: 'transparent', backgroundClip: 'text' }}>
|
||||||
right: 0,
|
|
||||||
bottom: 0,
|
|
||||||
background: 'rgba(0,0,0,0.85)',
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'center',
|
|
||||||
zIndex: 1000,
|
|
||||||
padding: 16,
|
|
||||||
boxSizing: 'border-box',
|
|
||||||
overflow: 'auto',
|
|
||||||
}}
|
|
||||||
onClick={handleClosePreview}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
background: '#fff',
|
|
||||||
borderRadius: 16,
|
|
||||||
padding: 0,
|
|
||||||
width: '100%',
|
|
||||||
maxWidth: '1200px',
|
|
||||||
maxHeight: '95vh',
|
|
||||||
minHeight: '300px',
|
|
||||||
overflow: 'hidden',
|
|
||||||
position: 'relative',
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column',
|
|
||||||
boxShadow: '0 20px 60px rgba(0,0,0,0.3)',
|
|
||||||
}}
|
|
||||||
onClick={(e) => e.stopPropagation()}
|
|
||||||
>
|
|
||||||
{/* 头部 */}
|
|
||||||
<div style={{
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'space-between',
|
|
||||||
padding: '12px 16px',
|
|
||||||
borderBottom: '1px solid #f0f0f0',
|
|
||||||
flexShrink: 0,
|
|
||||||
}}>
|
|
||||||
<Typography.Title level={5} style={{ margin: 0, color: '#1a1a2e', fontSize: 16 }}>
|
|
||||||
{previewItem.title || '预览'}
|
{previewItem.title || '预览'}
|
||||||
</Typography.Title>
|
</span>
|
||||||
<Button
|
|
||||||
icon={<XOutlined />}
|
|
||||||
onClick={handleClosePreview}
|
|
||||||
style={{
|
|
||||||
background: 'transparent',
|
|
||||||
border: 'none',
|
|
||||||
color: '#94a3b8',
|
|
||||||
fontSize: 16,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
{/* 内容区域 */}
|
open={previewVisible}
|
||||||
<div style={{
|
onCancel={handleClosePreview}
|
||||||
flex: 1,
|
width={1200}
|
||||||
display: 'flex',
|
footer={
|
||||||
flexWrap: 'wrap',
|
<div style={{ display: 'flex', justifyContent: 'flex-end', gap: 12, padding: '16px 24px', background: 'rgba(255,255,255,0.6)', borderTop: '1px solid rgba(99, 102, 241, 0.08)' }}>
|
||||||
height: '500px',
|
<Button
|
||||||
gap: 20,
|
type="primary"
|
||||||
padding: 20,
|
icon={<DownloadOutlined />}
|
||||||
overflow: 'auto',
|
onClick={() => {
|
||||||
justifyContent: 'center',
|
if (videoRef.current) {
|
||||||
alignItems: 'center',
|
videoRef.current.pause();
|
||||||
}}>
|
}
|
||||||
|
const url = `${import.meta.env.VITE_API_BASE || "http://localhost:8000"}${previewItem.videoUrl || previewItem.imageUrl}&download=1`;
|
||||||
|
const link = document.createElement('a');
|
||||||
|
link.href = url;
|
||||||
|
link.download = '';
|
||||||
|
document.body.appendChild(link);
|
||||||
|
link.click();
|
||||||
|
document.body.removeChild(link);
|
||||||
|
}}
|
||||||
|
style={{ borderRadius: 8, background: 'linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%)', border: 'none', boxShadow: '0 4px 12px rgba(99, 102, 241, 0.3)' }}
|
||||||
|
disabled={isMediaExpired(previewItem.videoUrl || previewItem.imageUrl)}
|
||||||
|
>
|
||||||
|
{isMediaExpired(previewItem.videoUrl || previewItem.imageUrl) ? '资源已过期' : '下载'}
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
onClick={handleSinglePushToMedia}
|
||||||
|
style={{ borderRadius: 8 }}
|
||||||
|
disabled={isMediaExpired(previewItem.videoUrl || previewItem.imageUrl)}
|
||||||
|
>
|
||||||
|
推送媒体后台
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
style={{ borderRadius: 20 }}
|
||||||
|
styles={{
|
||||||
|
body: { height: 460, display: 'flex', flexDirection: 'column', padding: 0 },
|
||||||
|
header: { background: 'rgba(255,255,255,0.6)', backdropFilter: 'blur(10px)', borderBottom: '1px solid rgba(99, 102, 241, 0.08)', padding: '16px 24px' },
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{/* 内容区域 */}
|
||||||
|
<div style={{
|
||||||
|
flex: 1,
|
||||||
|
display: 'flex',
|
||||||
|
flexWrap: 'wrap',
|
||||||
|
height: '460px',
|
||||||
|
gap: 20,
|
||||||
|
padding: 20,
|
||||||
|
overflow: 'auto',
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
}}>
|
||||||
{/* 媒体预览 */}
|
{/* 媒体预览 */}
|
||||||
<div style={{
|
<div style={{
|
||||||
flex: 1,
|
flex: 1,
|
||||||
@@ -2314,47 +2357,9 @@ const GeneratedRecord: React.FC = () => {
|
|||||||
))}
|
))}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{/* 操作按钮 */}
|
|
||||||
<div >
|
|
||||||
<div style={{ display: 'flex', gap: 12, marginTop: 20 }}>
|
|
||||||
<Button
|
|
||||||
type="primary"
|
|
||||||
icon={<DownloadOutlined />}
|
|
||||||
onClick={() => {
|
|
||||||
// 暂停视频
|
|
||||||
if (videoRef.current) {
|
|
||||||
videoRef.current.pause();
|
|
||||||
}
|
|
||||||
const url = `${import.meta.env.VITE_API_BASE || "http://localhost:8000"}${previewItem.videoUrl || previewItem.imageUrl}&download=1`;
|
|
||||||
window.open(url, '_blank');
|
|
||||||
}}
|
|
||||||
style={{ flex: 1, borderRadius: 8 }}
|
|
||||||
disabled={isMediaExpired(previewItem.videoUrl || previewItem.imageUrl)}
|
|
||||||
>
|
|
||||||
{isMediaExpired(previewItem.videoUrl || previewItem.imageUrl) ? '资源已过期' : '下载'}
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
onClick={handleClosePreview}
|
|
||||||
style={{ flex: 1, borderRadius: 8 }}
|
|
||||||
>
|
|
||||||
关闭
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<Button
|
|
||||||
type="primary"
|
|
||||||
onClick={handleSinglePushToMedia}
|
|
||||||
style={{ width: '100%', borderRadius: 8, marginTop: 20 }}
|
|
||||||
disabled={isMediaExpired(previewItem.videoUrl || previewItem.imageUrl)}
|
|
||||||
>
|
|
||||||
推送媒体后台
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</Modal>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user