Преглед изворни кода

Merge pull request #1554 from feitianbubu/pr/fix-video-preview

feat: if video cannot play open in a new tab
Seefs пре 5 месеци
родитељ
комит
b294ff5e96
1 измењених фајлова са 110 додато и 4 уклоњено
  1. 110 4
      web/src/components/table/task-logs/modals/ContentModal.jsx

+ 110 - 4
web/src/components/table/task-logs/modals/ContentModal.jsx

@@ -17,8 +17,11 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
 For commercial licensing, please contact support@quantumnous.com
 */
 
-import React from 'react';
-import { Modal } from '@douyinfe/semi-ui';
+import React, { useState, useEffect } from 'react';
+import { Modal, Button, Typography, Spin } from '@douyinfe/semi-ui';
+import { IconExternalOpen, IconCopy } from '@douyinfe/semi-icons';
+
+const { Text } = Typography;
 
 const ContentModal = ({
   isModalOpen,
@@ -26,17 +29,120 @@ const ContentModal = ({
   modalContent,
   isVideo,
 }) => {
+  const [videoError, setVideoError] = useState(false);
+  const [isLoading, setIsLoading] = useState(false);
+
+  useEffect(() => {
+    if (isModalOpen && isVideo) {
+      setVideoError(false);
+      setIsLoading(true);
+    }
+  }, [isModalOpen, isVideo]);
+
+  const handleVideoError = () => {
+    setVideoError(true);
+    setIsLoading(false);
+  };
+
+  const handleVideoLoaded = () => {
+    setIsLoading(false);
+  };
+
+  const handleCopyUrl = () => {
+    navigator.clipboard.writeText(modalContent);
+  };
+
+  const handleOpenInNewTab = () => {
+    window.open(modalContent, '_blank');
+  };
+
+  const renderVideoContent = () => {
+    if (videoError) {
+      return (
+        <div style={{ textAlign: 'center', padding: '40px' }}>
+          <Text type="tertiary" style={{ display: 'block', marginBottom: '16px' }}>
+            视频无法在当前浏览器中播放,这可能是由于:
+          </Text>
+          <Text type="tertiary" style={{ display: 'block', marginBottom: '8px', fontSize: '12px' }}>
+            • 视频服务商的跨域限制
+          </Text>
+          <Text type="tertiary" style={{ display: 'block', marginBottom: '8px', fontSize: '12px' }}>
+            • 需要特定的请求头或认证
+          </Text>
+          <Text type="tertiary" style={{ display: 'block', marginBottom: '16px', fontSize: '12px' }}>
+            • 防盗链保护机制
+          </Text>
+          
+          <div style={{ marginTop: '20px' }}>
+            <Button 
+              icon={<IconExternalOpen />}
+              onClick={handleOpenInNewTab}
+              style={{ marginRight: '8px' }}
+            >
+              在新标签页中打开
+            </Button>
+            <Button 
+              icon={<IconCopy />}
+              onClick={handleCopyUrl}
+            >
+              复制链接
+            </Button>
+          </div>
+          
+          <div style={{ marginTop: '16px', padding: '8px', backgroundColor: '#f8f9fa', borderRadius: '4px' }}>
+            <Text 
+              type="tertiary" 
+              style={{ fontSize: '10px', wordBreak: 'break-all' }}
+            >
+              {modalContent}
+            </Text>
+          </div>
+        </div>
+      );
+    }
+
+    return (
+      <div style={{ position: 'relative' }}>
+        {isLoading && (
+          <div style={{
+            position: 'absolute',
+            top: '50%',
+            left: '50%',
+            transform: 'translate(-50%, -50%)',
+            zIndex: 10
+          }}>
+            <Spin size="large" />
+          </div>
+        )}
+        <video 
+          src={modalContent} 
+          controls 
+          style={{ width: '100%' }} 
+          autoPlay
+          crossOrigin="anonymous"
+          onError={handleVideoError}
+          onLoadedData={handleVideoLoaded}
+          onLoadStart={() => setIsLoading(true)}
+        />
+      </div>
+    );
+  };
+
   return (
     <Modal
       visible={isModalOpen}
       onOk={() => setIsModalOpen(false)}
       onCancel={() => setIsModalOpen(false)}
       closable={null}
-      bodyStyle={{ height: '400px', overflow: 'auto' }}
+      bodyStyle={{ 
+        height: isVideo ? '450px' : '400px', 
+        overflow: 'auto',
+        padding: isVideo && videoError ? '0' : '24px'
+      }}
       width={800}
     >
       {isVideo ? (
-        <video src={modalContent} controls style={{ width: '100%' }} autoPlay />
+        renderVideoContent()
       ) : (
         <p style={{ whiteSpace: 'pre-line' }}>{modalContent}</p>
       )}