contentBox.tsx 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. import React, { useState } from "react"
  2. import { Button, Popover, Space, Tag } from "antd"
  3. import { PlusOutlined, EditOutlined, DeleteOutlined, DownOutlined, UpOutlined, VerticalAlignTopOutlined, VerticalAlignBottomOutlined } from '@ant-design/icons';
  4. import { MediaContentProps, MediaTypeProps } from "../../API/weMaterial/weMaterial";
  5. import TextNews from "../newsMould/textNews";
  6. import style from './index.less'
  7. import useNewToken from "@/Hook/useNewToken";
  8. import ImgNews from "../newsMould/imgNews";
  9. import UploadButton, { MediaSize } from "./uploadButton";
  10. import FileNews from "../newsMould/fileNews";
  11. import VideoNews from "../newsMould/videoNews";
  12. import { RcFile } from "antd/es/upload";
  13. import AudioNews from "../newsMould/audioNews";
  14. import LinkNews from "../newsMould/linkNews";
  15. import MiniprogramNews from "../newsMould/miniprogramNews";
  16. interface Props {
  17. data: MediaContentProps[]
  18. onChange?: (item: MediaContentProps | string, index: number, type: 'add' | 'edit' | 'del' | 'up' | 'down' | 'upV' | 'downV', mediaType?: MediaTypeProps | 'sck', file?: RcFile, name?: string) => void,
  19. noShowType?: Array<'text' | 'video' | 'file' | 'link' | 'voice' | 'miniprogram' | 'sck' | 'image'>,
  20. textCount?: number, // 可选文案数量
  21. dataLength: number
  22. mediaSize?: MediaSize
  23. disabledAdd?: boolean
  24. }
  25. //
  26. /**
  27. * 素材库使用内容模板
  28. * @returns
  29. */
  30. const ContentBox: React.FC<Props> = ({ data, onChange, noShowType, dataLength, mediaSize, textCount, disabledAdd }) => {
  31. /****************************/
  32. const { token } = useNewToken()
  33. const [hover, setHover] = useState(-1)
  34. /****************************/
  35. // 鼠标移入
  36. const hoverIn = (index: number) => {
  37. setHover(index)
  38. }
  39. // 鼠标移出
  40. const hoverOut = () => {
  41. setHover(-1)
  42. }
  43. // 点击按钮
  44. const clickHandle = (item: MediaContentProps | string, index: number, type: 'add' | 'edit' | 'del' | 'up' | 'down' | 'upV' | 'downV', mediaType?: MediaTypeProps | 'sck', file?: RcFile, name?: string) => {
  45. onChange?.(item, index, type, mediaType, file, name)
  46. }
  47. return <>
  48. {data?.filter(item => textCount ? item.mediaType !== 'text' : true)?.map(((item, index) => {
  49. return <div
  50. key={index}
  51. onMouseEnter={() => { hoverIn(index) }}
  52. onMouseLeave={hoverOut}
  53. style={{
  54. background: hover === index ? token.colorPrimaryBgHover : token.colorBgContainerDisabled,
  55. borderRadius: token.borderRadius
  56. }}
  57. >
  58. <div className={style.left}>
  59. <Tag style={{ borderRadius: '50%' }} color={token.colorPrimaryHover}>{index + 1}</Tag>
  60. {item?.mediaType === 'text' ? <div key={index}><TextNews style={{ marginBottom: 0 }} strong msg={item?.textContent || ''} /></div>
  61. : item?.mediaType === 'image' ? <div key={index}><ImgNews src={item?.imageUrl} preview /></div>
  62. : item?.mediaType === 'video' ? <div key={index}><VideoNews src={item?.videoUrl} preview /></div>
  63. : item?.mediaType === 'voice' ? <div key={index}><AudioNews url={item?.voiceUrl} times={item.mediaPlayTime} /></div>
  64. : item?.mediaType === 'miniprogram' ? <div key={index}><MiniprogramNews {...item} /></div>
  65. : item?.mediaType === 'link' ? <div key={index}><LinkNews width={240} isBlank content={{ url: item.linkUrl as string, title: item.linkTitle as string, desc: item.linkDesc as string, cover: item.linkPicurl as string }} /></div>
  66. : item?.mediaType === 'file' ? <div key={index}><FileNews fileName={item?.fileName} fileSize={item.mediaSize} fileUrl={item.fileUrl} /></div>
  67. : null}
  68. </div>
  69. <div style={{ opacity: hover === index ? 1 : 0 }} className={style.right}>
  70. <Space wrap>
  71. {(data.length < dataLength && !disabledAdd) && <Popover
  72. placement="topRight"
  73. content={<Space wrap>
  74. {!(noShowType?.some(i => i === 'text')) && !textCount && <Button disabled={data.length === dataLength} onClick={() => {
  75. clickHandle(item, index, 'add', 'text')
  76. }}>文字</Button>}
  77. {!(noShowType?.some(i => i === 'image')) && <UploadButton mediaSize={mediaSize} text="图片" disabled={data.length === dataLength} type='image' onChange={(url, file, name) => {
  78. clickHandle(url, index, 'add', 'image', file, name)
  79. }} />}
  80. {!(noShowType?.some(i => i === 'video')) && <UploadButton mediaSize={mediaSize} text="视频" disabled={data.length === dataLength} type='video' tooltip="发送视频传送比较耗时,如果发送消息间隔设置又较短,可能会出现消息乱序,所以视频尽量压缩小一点" onChange={(url, file, name) => {
  81. clickHandle(url, index, 'add', 'video', file, name)
  82. }} />}
  83. {!(noShowType?.some(i => i === 'file')) && <UploadButton mediaSize={mediaSize} text="文件" disabled={data.length === dataLength} type='file' onChange={(url, file, name) => {
  84. clickHandle(url, index, 'add', 'file', file, name)
  85. }} />}
  86. {!(noShowType?.some(i => i === 'link')) && <Button disabled={data.length === dataLength} onClick={() => { clickHandle(item, index, 'add', 'link') }}>链接</Button>}
  87. {/* {!(noShowType?.some(i => i === 'voice')) && <UploadButton mediaSize={mediaSize} text="语音" disabled={data.length === dataLength} type='voice' onChange={async (url, file, name) => {
  88. clickHandle(url, index, 'add', 'voice', file, name)
  89. }} />} */}
  90. {!(noShowType?.some(i => i === 'miniprogram')) && <Button disabled={data.length === dataLength} onClick={() => { clickHandle(item, index, 'add', 'miniprogram') }}>小程序</Button>}
  91. {!(noShowType?.some(i => i === 'sck')) && <Button disabled={data.length === dataLength} onClick={() => { clickHandle(item, index, 'add', 'sck') }}>素材库</Button>}
  92. </Space>}
  93. color={token.colorBgBase}
  94. >
  95. <Button size="small"><PlusOutlined /></Button>
  96. </Popover>}
  97. {['image', 'video', 'file', 'voice'].includes(item?.mediaType as any) ? <UploadButton
  98. text={<EditOutlined />}
  99. mediaSize={mediaSize}
  100. type={item?.mediaType}
  101. size="small"
  102. onChange={(url, file) => {
  103. clickHandle(url, index, 'edit', item?.mediaType, file)
  104. }}
  105. /> : <Button size="small" onClick={() => clickHandle(item, index, 'edit', item?.mediaType)}><EditOutlined /></Button>}
  106. {!disabledAdd && <Button size="small" onClick={() => clickHandle(item, index, 'del', item?.mediaType)}><DeleteOutlined /></Button>}
  107. {data.length > 1 && <>
  108. {data.length !== index + 1 && <>
  109. <Button size="small" onClick={() => clickHandle(item, index, 'down', item?.mediaType)}><DownOutlined /></Button>
  110. <Button size="small" onClick={() => clickHandle(item, index, 'downV', item?.mediaType)}><VerticalAlignBottomOutlined /></Button>
  111. </>}
  112. {index !== 0 && <>
  113. <Button size="small" onClick={() => clickHandle(item, index, 'up', item?.mediaType)}><UpOutlined /></Button>
  114. <Button size="small" onClick={() => clickHandle(item, index, 'upV', item?.mediaType)}><VerticalAlignTopOutlined /></Button>
  115. </>}
  116. </>}
  117. </Space>
  118. </div>
  119. </div>
  120. }))}
  121. </>
  122. }
  123. export default React.memo(ContentBox)