Video.tsx 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. import { Button, Card, Collapse, Modal, Popover, Space } from "antd";
  2. import { Typography } from "antd";
  3. import { useState } from "react";
  4. import { CloseOutlined } from "@ant-design/icons";
  5. import type { TDisplayStyle } from "./Article";
  6. import Video from "../general/Video";
  7. import { VideoIcon } from "../../assets/icon";
  8. import type { IAttachmentResponse } from "../../api/Attachments";
  9. import { get } from "../../request";
  10. const { Text } = Typography;
  11. const getUrl = async (fileId: string) => {
  12. const url = `/v2/attachment/${fileId}`;
  13. console.info("url", url);
  14. const res = await get<IAttachmentResponse>(url);
  15. if (res.ok) {
  16. return res.data.url;
  17. } else {
  18. return "";
  19. }
  20. };
  21. const getLink = async ({ url, id, _____type, _____title }: IVideoCtl) => {
  22. let link = url;
  23. if (!link && id) {
  24. const res = await getUrl(id);
  25. link = res;
  26. }
  27. return link;
  28. };
  29. interface IVideoCtl {
  30. url?: string;
  31. id?: string;
  32. type?: string;
  33. title?: React.ReactNode;
  34. style?: TDisplayStyle;
  35. _style?: TDisplayStyle;
  36. }
  37. const VideoPopover = ({ url, id, type, title }: IVideoCtl) => {
  38. const [popOpen, setPopOpen] = useState(false);
  39. console.debug("popOpen", popOpen);
  40. return (
  41. <Popover
  42. title={
  43. <div>
  44. {title}
  45. <Button
  46. type="link"
  47. icon={<CloseOutlined />}
  48. onClick={() => {
  49. setPopOpen(false);
  50. }}
  51. />
  52. </div>
  53. }
  54. content={
  55. <div style={{ width: 600, height: 480 }}>
  56. <Video fileId={id} src={url} type={type} />
  57. </div>
  58. }
  59. trigger={"click"}
  60. placement="bottom"
  61. open={popOpen}
  62. >
  63. <span onClick={() => setPopOpen(true)}>
  64. <VideoIcon />
  65. {title}
  66. </span>
  67. </Popover>
  68. );
  69. };
  70. const VideoModal = ({ url, id, type, title }: IVideoCtl) => {
  71. const [isModalOpen, setIsModalOpen] = useState(false);
  72. const showModal = () => {
  73. setIsModalOpen(true);
  74. };
  75. const handleOk = () => {
  76. setIsModalOpen(false);
  77. };
  78. const handleCancel = () => {
  79. setIsModalOpen(false);
  80. };
  81. return (
  82. <>
  83. <Typography.Link
  84. onClick={async (event: React.MouseEvent<HTMLElement, MouseEvent>) => {
  85. if (event.ctrlKey || event.metaKey) {
  86. const link = await getLink({ url: url, id: id });
  87. window.open(link, "_blank");
  88. } else {
  89. showModal();
  90. }
  91. }}
  92. >
  93. <Space>
  94. <VideoIcon />
  95. {title}
  96. </Space>
  97. </Typography.Link>
  98. <Modal
  99. width={800}
  100. destroyOnClose
  101. style={{ maxWidth: "90%", top: 20, height: 700 }}
  102. title={
  103. <div
  104. style={{
  105. display: "flex",
  106. justifyContent: "space-between",
  107. marginRight: 30,
  108. }}
  109. >
  110. <Text>{title}</Text>
  111. </div>
  112. }
  113. open={isModalOpen}
  114. onOk={handleOk}
  115. onCancel={handleCancel}
  116. footer={[]}
  117. >
  118. <div style={{ height: 550 }}>
  119. <Video fileId={id} src={url} type={type} />
  120. </div>
  121. </Modal>
  122. </>
  123. );
  124. };
  125. export const VideoCtl = ({
  126. url,
  127. id,
  128. type,
  129. title,
  130. style = "modal",
  131. _style,
  132. }: IVideoCtl) => {
  133. const curStyle = _style ? _style : style;
  134. const VideoCard = () => {
  135. return (
  136. <Card title={title} bodyStyle={{ width: 550, height: 420 }}>
  137. <Video fileId={id} src={url} type={type} />
  138. </Card>
  139. );
  140. };
  141. const VideoWindow = () => {
  142. return (
  143. <div style={{ width: 550, height: 420 }}>
  144. <Video fileId={id} src={url} type={type} />
  145. </div>
  146. );
  147. };
  148. const VideoToggle = () => {
  149. return (
  150. <Collapse bordered={false}>
  151. <Collapse.Panel header={title} key="parent2">
  152. <Video fileId={id} src={url} type={type} />
  153. </Collapse.Panel>
  154. </Collapse>
  155. );
  156. };
  157. const VideoLink = () => {
  158. return (
  159. <Typography.Link
  160. onClick={async () => {
  161. const link = await getLink({ url: url, id: id });
  162. window.open(link, "_blank");
  163. }}
  164. >
  165. <Space>
  166. <VideoIcon />
  167. {title}
  168. </Space>
  169. </Typography.Link>
  170. );
  171. };
  172. return curStyle === "modal" ? (
  173. <VideoModal url={url} id={id} type={type} title={title} />
  174. ) : curStyle === "card" ? (
  175. <VideoCard />
  176. ) : curStyle === "window" ? (
  177. <VideoWindow />
  178. ) : curStyle === "toggle" ? (
  179. <VideoToggle />
  180. ) : curStyle === "link" ? (
  181. <VideoLink />
  182. ) : curStyle === "popover" ? (
  183. <VideoPopover url={url} id={id} type={type} title={title} />
  184. ) : (
  185. <></>
  186. );
  187. };
  188. interface IWidget {
  189. props: string;
  190. children?: React.ReactNode;
  191. }
  192. const VideoWidget = ({ props, _____children }: IWidget) => {
  193. const prop = JSON.parse(atob(props)) as IVideoCtl;
  194. return <VideoCtl {...prop} />;
  195. };
  196. export default VideoWidget;