index.tsx 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. import React, { useState } from 'react';
  2. import { Modal, Descriptions, Space, Button, Tooltip, message, Table } from 'antd';
  3. import { GzhPlanDataType, GzhPlanType } from '../../hooks/useGzhPlanList';
  4. import { CopyOutlined, PlayCircleOutlined, DownloadOutlined, LinkOutlined, QrcodeOutlined } from '@ant-design/icons';
  5. import { VideoItem } from '../types';
  6. import VideoPlayModal from '@src/views/publishContent/weCom/components/videoPlayModal';
  7. import modal from 'antd/es/modal';
  8. import http from '@src/http';
  9. import { getShareQrPic } from '@src/http/api';
  10. import copy from 'copy-to-clipboard';
  11. import { Typography } from 'antd';
  12. const { Text } = Typography;
  13. interface PunlishPlanDetailModalProps {
  14. visible: boolean;
  15. onCancel: () => void;
  16. planData: GzhPlanDataType;
  17. }
  18. const PunlishPlanDetailModal: React.FC<PunlishPlanDetailModalProps> = ({
  19. visible,
  20. onCancel,
  21. planData,
  22. }) => {
  23. const [isVideoPlayModalVisible, setIsVideoPlayModalVisible] = useState(false);
  24. const [activeVideo, setActiveVideo] = useState<VideoItem | null>(null);
  25. const columns = [
  26. {
  27. title: '视频标题',
  28. dataIndex: 'title',
  29. key: 'title',
  30. render: (title: string) => (
  31. <Space>
  32. <Text style={{ maxWidth: 200 }} ellipsis={{ tooltip: title }}>{title}</Text>
  33. <Tooltip title="复制标题">
  34. <Button
  35. type="text"
  36. icon={<CopyOutlined />}
  37. onClick={() => {
  38. if (copy(title)) {
  39. message.success('标题已复制');
  40. } else {
  41. message.error('复制失败');
  42. }
  43. }}
  44. size="small"
  45. />
  46. </Tooltip>
  47. </Space>
  48. ),
  49. },
  50. {
  51. title: '操作',
  52. key: 'action',
  53. render: (_: any, record: VideoItem) => (
  54. <Space wrap size="small">
  55. <Button type="link" icon={<PlayCircleOutlined />} onClick={() => playVideo(record)} size="small">播放</Button>
  56. <Button type="link" icon={<DownloadOutlined />} onClick={() => downloadCover(record)} size="small">下载封面</Button>
  57. <Button type="link" icon={<LinkOutlined />} onClick={() => copyPushLink(record)} size="small">复制推送链接</Button>
  58. <Button type="link" icon={<QrcodeOutlined />} onClick={() => showQRCode(record)} size="small">二维码</Button>
  59. </Space>
  60. ),
  61. },
  62. ];
  63. const playVideo = (video: VideoItem) => {
  64. setActiveVideo(video);
  65. setIsVideoPlayModalVisible(true);
  66. };
  67. const downloadCover = (video: VideoItem) => {
  68. if (video.cover) {
  69. const link = document.createElement('a');
  70. link.href = video.cover;
  71. // Attempt to infer filename, might need refinement
  72. const filename = video.cover.substring(video.cover.lastIndexOf('/') + 1) || `cover_${video.videoId}.jpg`;
  73. link.download = filename;
  74. link.target = '_blank'; // Open in new tab might be safer for some browsers
  75. link.rel = 'noopener noreferrer';
  76. document.body.appendChild(link);
  77. link.click();
  78. document.body.removeChild(link);
  79. } else {
  80. message.warning('No cover image URL available.');
  81. }
  82. };
  83. const copyPushLink = (video: VideoItem) => {
  84. // Assuming video object might have a 'pushLink' property added by the parent component
  85. const linkToCopy = video.pageUrl || 'Push link not available'; // Updated placeholder
  86. if (video.pageUrl && copy(linkToCopy)) {
  87. message.success('推送链接已复制');
  88. } else if (!video.pageUrl) {
  89. message.warning('没有可复制的推送链接');
  90. } else {
  91. message.error('复制失败');
  92. }
  93. };
  94. const showQRCode = (video: VideoItem) => {
  95. http.get<string>(getShareQrPic, {
  96. params: {
  97. pageUrl: video.pageUrl,
  98. }
  99. }).then(res => {
  100. modal.info({
  101. title: '二维码',
  102. content: <img src={res.data} alt="二维码" />,
  103. });
  104. }).catch(err => {
  105. message.error(err.msg || '获取二维码失败');
  106. });
  107. };
  108. return (
  109. planData && visible && <Modal
  110. title="发布计划详情"
  111. open={true}
  112. destroyOnClose
  113. onCancel={onCancel}
  114. footer={null}
  115. width={800}
  116. >
  117. <Descriptions column={1} className='mb-4'>
  118. <Descriptions.Item label="发布计划类型">{planData.type.toString() === GzhPlanType.自动回复 ? '自动回复' : '服务号推送'}</Descriptions.Item>
  119. { planData.type.toString() === GzhPlanType.自动回复 && <Descriptions.Item label="场景">关注回复</Descriptions.Item> }
  120. <Descriptions.Item label="发布方式">{planData?.publishStage === 0 ? '平台发布' : '用户获取路径'}</Descriptions.Item>
  121. <Descriptions.Item label="视频选取方式">{planData?.selectVideoType === 0 ? '手动选取' : '自动选取'}</Descriptions.Item>
  122. <Descriptions.Item label="公众号名称">{planData.accountName}</Descriptions.Item>
  123. {
  124. planData.videoList?.length > 0 ?
  125. <Descriptions.Item label="发布内容" >
  126. <Table
  127. columns={columns}
  128. dataSource={planData.videoList?.map(v => ({ ...v, key: v.videoId }))} // Ensure each item has a unique key
  129. pagination={false} // Disable pagination if the list is expected to be short
  130. size="small"
  131. />
  132. <VideoPlayModal
  133. visible={isVideoPlayModalVisible}
  134. onClose={() => setIsVideoPlayModalVisible(false)}
  135. videoUrl={activeVideo?.video || ''}
  136. title={activeVideo?.title || ''}
  137. />
  138. </Descriptions.Item>
  139. : <Descriptions.Item label="发布内容">
  140. <Text className='text-gray-500'>视频由系统自动选取</Text>
  141. </Descriptions.Item>
  142. }
  143. </Descriptions>
  144. </Modal>
  145. );
  146. };
  147. export default PunlishPlanDetailModal;