| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| 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, |
| setIsModalOpen, |
| 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: isVideo ? '450px' : '400px', |
| overflow: 'auto', |
| padding: isVideo && videoError ? '0' : '24px', |
| }} |
| width={800} |
| > |
| {isVideo ? ( |
| renderVideoContent() |
| ) : ( |
| <p style={{ whiteSpace: 'pre-line' }}>{modalContent}</p> |
| )} |
| </Modal> |
| ); |
| }; |
|
|
| export default ContentModal; |
|
|