index.tsx 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. import React, { useEffect, useState } from 'react';
  2. import { Modal, Button, Descriptions, Image, Space, Tooltip, message, Typography } from 'antd';
  3. import { CopyOutlined, PlayCircleOutlined, DownloadOutlined } from '@ant-design/icons';
  4. import { WeComPlan, WeComPlanType } from '@src/views/publishContent/weCom/type';
  5. import copy from 'copy-to-clipboard';
  6. import VideoPlayModal from '../videoPlayModal';
  7. import { getShareQrPic } from '@src/http/api';
  8. import http from '@src/http';
  9. const { Text } = Typography;
  10. interface PlanDetailModalProps {
  11. visible: boolean;
  12. onClose: () => void;
  13. planData: WeComPlan | null | undefined;
  14. }
  15. const PlanDetailModal: React.FC<PlanDetailModalProps> = ({ visible, onClose, planData }) => {
  16. const [isVideoPlayModalVisible, setIsVideoPlayModalVisible] = useState<boolean>(false);
  17. const [qrCode, setQrCode] = useState<string>('');
  18. useEffect(() => {
  19. if (planData?.pageUrl) {
  20. getShareQr(planData?.pageUrl || '');
  21. }
  22. }, [planData]);
  23. if (!planData) {
  24. return null; // Don't render if no data
  25. }
  26. const getShareQr = (pageUrl: string) => {
  27. http.get<string>(getShareQrPic, {
  28. params: {
  29. pageUrl,
  30. }
  31. }).then(res => {
  32. setQrCode(res.data);
  33. }).catch(err => {
  34. message.error(err.msg || '获取二维码失败');
  35. });
  36. };
  37. const handleCopy = (text: string | undefined, successMessage: string) => {
  38. if (text && copy(text)) {
  39. message.success(successMessage);
  40. } else if (!text) {
  41. message.warning('没有内容可复制');
  42. } else {
  43. message.error('复制失败');
  44. }
  45. };
  46. const downloadFile = (url: string | undefined, filename: string) => {
  47. if (!url) {
  48. message.warning('无可用文件下载');
  49. return;
  50. }
  51. const link = document.createElement('a');
  52. link.href = url;
  53. link.download = filename || url.substring(url.lastIndexOf('/') + 1);
  54. link.target = '_blank';
  55. link.rel = 'noopener noreferrer';
  56. document.body.appendChild(link);
  57. link.click();
  58. document.body.removeChild(link);
  59. message.success('开始下载...');
  60. };
  61. const playVideo = () => {
  62. setIsVideoPlayModalVisible(true);
  63. }
  64. // Determine scene text based on plan type (adjust logic if needed)
  65. const getSceneText = (plan: WeComPlan) => {
  66. if (plan.type === +WeComPlanType.社群) {
  67. return plan.scene === 0 ? '群发' : '单发';
  68. }
  69. // Add logic for other plan types if necessary
  70. return '自动回复'; // Example placeholder for other types
  71. }
  72. // Determine publish type text (adjust based on your data model)
  73. const getPublishTypeText = (plan: WeComPlan) => {
  74. // This field isn't directly in WeComPlan, you might need to fetch/derive it
  75. // Returning a placeholder for now.
  76. return plan.type === +WeComPlanType.社群 ? '社群' : '自动回复'; // Example
  77. }
  78. // Determine account type text (adjust based on your data model)
  79. const getAccountTypeText = () => {
  80. // This field isn't in WeComPlan, returning placeholder.
  81. return '小慧爱厨房'; // Placeholder based on image
  82. }
  83. // Determine account name text (adjust based on your data model)
  84. const getAccountNameText = () => {
  85. // This field isn't in WeComPlan, returning placeholder.
  86. return '企微号'; // Placeholder based on image
  87. }
  88. return (
  89. <Modal
  90. title="内容详情"
  91. open={visible}
  92. onCancel={onClose}
  93. footer={[
  94. <Button key="close" type="primary" onClick={onClose}>
  95. 关闭
  96. </Button>,
  97. ]}
  98. width={650} // Adjust width as needed
  99. destroyOnClose
  100. >
  101. <Descriptions bordered column={1} size="small" labelStyle={{ width: '120px' }}>
  102. <Descriptions.Item label="链接ID">{planData.id}</Descriptions.Item>
  103. {/* Placeholder fields based on image - replace with actual data source if available */}
  104. <Descriptions.Item label="发布账号类型">{getAccountTypeText()}</Descriptions.Item>
  105. <Descriptions.Item label="公众号名称">{getAccountNameText()}</Descriptions.Item>
  106. <Descriptions.Item label="发布场景">{getPublishTypeText(planData)}</Descriptions.Item>
  107. <Descriptions.Item label="场景">{getSceneText(planData)}</Descriptions.Item>
  108. <Descriptions.Item label="推送链接">
  109. <Space>
  110. <Text style={{ maxWidth: 350 }} ellipsis={{ tooltip: planData.pageUrl }}>
  111. {planData.pageUrl}
  112. </Text>
  113. <Tooltip title="复制链接">
  114. <Button
  115. type="text"
  116. icon={<CopyOutlined />}
  117. onClick={() => handleCopy(planData.pageUrl, '推送链接已复制')}
  118. size="small"
  119. />
  120. </Tooltip>
  121. </Space>
  122. </Descriptions.Item>
  123. <Descriptions.Item label="视频标题">
  124. <Space>
  125. <Text style={{ maxWidth: 400 }} ellipsis={{ tooltip: planData.title }}>
  126. {planData.title}
  127. </Text>
  128. <Tooltip title="复制标题">
  129. <Button
  130. type="text"
  131. icon={<CopyOutlined />}
  132. onClick={() => handleCopy(planData.title, '标题已复制')}
  133. size="small"
  134. />
  135. </Tooltip>
  136. </Space>
  137. </Descriptions.Item>
  138. <Descriptions.Item label="视频封面">
  139. <Space direction="vertical" align="start">
  140. <Image
  141. width={150}
  142. src={planData.cover}
  143. alt="视频封面"
  144. referrerPolicy="no-referrer"
  145. placeholder={ <div style={{ width: 150, height: 100, background: '#f0f0f0', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>加载中...</div> }
  146. />
  147. <Button
  148. type="link"
  149. icon={<DownloadOutlined />}
  150. onClick={() => downloadFile(planData.cover, planData.title + '_cover.jpg')}
  151. size="small"
  152. >
  153. 下载封面
  154. </Button>
  155. </Space>
  156. </Descriptions.Item>
  157. <Descriptions.Item label="二维码">
  158. {qrCode ? (
  159. <Space direction="vertical" align="start">
  160. <img style={{ width: 150, height: 150 }} src={qrCode} alt="二维码" />
  161. {/* You might want to add a logo overlay if needed */}
  162. </Space>
  163. ) : (
  164. <Text type="secondary">无可用链接生成二维码</Text>
  165. )}
  166. </Descriptions.Item>
  167. <Descriptions.Item label="视频内容">
  168. <Button type="link" icon={<PlayCircleOutlined />} onClick={playVideo} size="small">播放</Button>
  169. </Descriptions.Item>
  170. </Descriptions>
  171. <VideoPlayModal
  172. visible={isVideoPlayModalVisible}
  173. onClose={() => setIsVideoPlayModalVisible(false)}
  174. videoUrl={planData.video || ''}
  175. title={planData.title || ''}
  176. />
  177. </Modal>
  178. );
  179. };
  180. export default PlanDetailModal;