addMaterial.tsx 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639
  1. import { CloseCircleOutlined, DeleteOutlined, PlusOutlined } from "@ant-design/icons"
  2. import { Button, Card, Dropdown, Empty, Form, Menu, Modal, Popconfirm, Space, message } from "antd"
  3. import React, { useEffect, useState } from "react"
  4. import styles from './index.less'
  5. import VideoNews from "@/pages/launchSystemNew/components/newsModal/videoNews"
  6. import { useModel } from "umi"
  7. import SelectCloud from "@/pages/launchSystemNew/components/selectCloud"
  8. import { getVideoImgUrl } from "@/utils/utils"
  9. import VideoFrameSelect from "@/pages/launchSystemV3/components/VideoFrameSelect"
  10. import New1Radio from "@/pages/launchSystemV3/components/New1Radio"
  11. interface Props {
  12. adLength: number,
  13. creativeTemplateId: number
  14. materialData: any
  15. deliveryMode: string,
  16. value?: any,
  17. visible?: boolean
  18. onClose?: () => void
  19. onChange?: (value: any) => void
  20. }
  21. const AddMaterial: React.FC<Props> = ({ creativeTemplateId, materialData, deliveryMode, visible, value, onChange, onClose, adLength }) => {
  22. /*********************************/
  23. const { init } = useModel('useLaunchAdq.useBdMediaPup')
  24. const [form] = Form.useForm();
  25. const dynamicGroup = Form.useWatch('dynamicGroup', form)
  26. const mediaType = Form.useWatch('mediaType', form)
  27. const [materialConfig, setMaterialConfig] = useState<{
  28. adcreativeTemplateId?: number,
  29. type: string,
  30. cloudSize: { relation: string, width: number, height: number }[],
  31. list: any[],
  32. index: number,
  33. max: number,
  34. sliderImgContent: any,
  35. isGroup?: boolean
  36. }>({
  37. type: '',//类型
  38. cloudSize: [],//素材搜索条件
  39. list: [],//素材
  40. index: 0, // 素材组下标
  41. max: 1,//素材数量
  42. sliderImgContent: undefined
  43. })//图片素材配置
  44. const [selectVideoVisible, setSelectVideoVisible] = useState(false)
  45. const [mLength, setMLength] = useState<number>(1)
  46. const [videoUploads, setVideoUploads] = useState<any>()
  47. const [imgUploads, setImgUploads] = useState<any>()
  48. const [minNumber, setMinNumber] = useState<number>(3)
  49. /*********************************/
  50. useEffect(() => {
  51. if (materialData && Object.keys(materialData).length > 0) {
  52. let fKey = Object.keys(materialData)[0];
  53. let children = materialData[fKey]?.children
  54. let childrenKey = Object.keys(children)
  55. setMLength(childrenKey?.length)
  56. let videoData = childrenKey?.find(item => item === 'short_video1' || item === 'video_id')
  57. if (videoData) {
  58. setVideoUploads(children[videoData])
  59. }
  60. let imageData = childrenKey?.find(item => item === 'cover_id' || item === 'image_id')
  61. if (imageData) {
  62. setImgUploads(children[imageData])
  63. }
  64. let imageListData = childrenKey?.find(item => item === 'list')
  65. if (imageListData) {
  66. let data = children[imageListData]
  67. if (fKey === 'image_list') {
  68. setMinNumber(data.arrayProperty.mixNumber)
  69. setImgUploads({ ...data['children']['image_id'], arrayProperty: data.arrayProperty, name: 'image_list' })
  70. } else if (fKey === 'element_story') {
  71. setMinNumber(data.arrayProperty.mixNumber)
  72. setImgUploads({ ...data['children']['image'], arrayProperty: data.arrayProperty, name: 'element_story' })
  73. }
  74. }
  75. } else {
  76. setVideoUploads({})
  77. setImgUploads({})
  78. }
  79. }, [materialData])
  80. const setFrame = (url: string, num: number, field: string) => {
  81. let newDynamicGroup = dynamicGroup?.map((item: any, index: number) => {
  82. if (num === index) {
  83. if (item) {
  84. item[field] = { ...item[field], url, id: null }
  85. return { ...item }
  86. } else {
  87. return { [field]: { url, id: null, materialType: 0 } }
  88. }
  89. }
  90. return item
  91. })
  92. form.setFieldsValue({ dynamicGroup: newDynamicGroup })
  93. }
  94. const handleOk = (values: any) => {
  95. const { mediaType, dynamicGroup } = values
  96. if (mediaType === 1 && dynamicGroup.length < adLength) {
  97. message.error({
  98. content: `创意组分配规则选择“平均分配到广告”时,创意组总数必须大于等于广告总数。当前广告总数:${adLength},创意组总数:${dynamicGroup.length}`,
  99. duration: 8
  100. })
  101. return
  102. }
  103. if (mediaType === 2 && dynamicGroup.length > adLength) {
  104. message.error({
  105. content: `创意组分配规则选择“顺序分配到广告”时,创意组总数必须小于等于广告总数。当前广告总数:${adLength},创意组总数:${dynamicGroup.length}`,
  106. duration: 8
  107. })
  108. return
  109. }
  110. onChange?.({ mediaType, dynamicMaterialDTos: { dynamicGroup } })
  111. }
  112. useEffect(() => {
  113. console.log('value--->', value)
  114. if (value) {
  115. const { dynamicMaterialDTos, mediaType } = value
  116. form.setFieldsValue({ ...dynamicMaterialDTos, mediaType })
  117. }
  118. }, [value])
  119. const clearTem = (index: number, count: number) => {
  120. let newDynamicGroup = dynamicGroup?.map((item: any, i: number) => {
  121. if (i === index) {
  122. let oldList = item?.list?.filter((_: any, li: number) => count !== li)
  123. return { list: oldList }
  124. }
  125. return item
  126. })
  127. form.setFieldsValue({ dynamicGroup: newDynamicGroup })
  128. }
  129. const selectGroupImg = (index: number, num: number) => {
  130. init({ mediaType: 'IMG', num, cloudSize: [[{ relation: '=', width: 800, height: 800 }]], maxSize: 400 * 1024 })
  131. setMaterialConfig({
  132. ...materialConfig,
  133. type: 'image',
  134. max: num,
  135. index,
  136. adcreativeTemplateId: creativeTemplateId,
  137. isGroup: true
  138. })
  139. setTimeout(() => {
  140. setSelectVideoVisible(true)
  141. }, 100)
  142. }
  143. return <Modal
  144. title={<Space>
  145. <strong style={{ fontSize: 20 }}>创意素材</strong>
  146. {deliveryMode === 'DELIVERY_MODE_CUSTOMIZE' && <>
  147. {videoUploads && Object.keys(videoUploads)?.length > 0 && <Button type="link" onClick={() => {
  148. init({ mediaType: 'VIDEO', num: 100, cloudSize: creativeTemplateId === 1708 ? [[{ relation: '=', width: 1280, height: 720 }]] : [[{ relation: '=', width: videoUploads.restriction.videoRestriction.minWidth, height: videoUploads.restriction.videoRestriction.minHeight }]], maxSize: videoUploads.restriction.videoRestriction.fileSize * 1024 })
  149. setMaterialConfig({
  150. ...materialConfig,
  151. type: videoUploads.name,
  152. max: 1,
  153. index: 99999,
  154. adcreativeTemplateId: creativeTemplateId
  155. })
  156. setTimeout(() => {
  157. setSelectVideoVisible(true)
  158. }, 100)
  159. }}>批量添加视频素材</Button>}
  160. {imgUploads && Object.keys(imgUploads)?.length > 0 && <Button type="link" onClick={() => {
  161. init({ mediaType: 'IMG', num: 100, cloudSize: [[{ relation: '=', width: imgUploads.restriction.imageRestriction.width, height: imgUploads.restriction.imageRestriction.height }]], maxSize: imgUploads.restriction.imageRestriction.fileSize * 1024 })
  162. setMaterialConfig({
  163. ...materialConfig,
  164. type: imgUploads.name,
  165. max: (imgUploads.name === 'image_list' || imgUploads.name === 'element_story') ? imgUploads.arrayProperty.maxNumber : 1,
  166. index: 99999,
  167. adcreativeTemplateId: creativeTemplateId
  168. })
  169. setTimeout(() => {
  170. setSelectVideoVisible(true)
  171. }, 100)
  172. }}>批量添加图片素材</Button>}
  173. </>}
  174. {(dynamicGroup && dynamicGroup?.length > 1) && <Popconfirm
  175. title="是否清空?"
  176. onConfirm={() => form.setFieldsValue({ dynamicGroup: [undefined] })}
  177. okText="是"
  178. cancelText="否"
  179. >
  180. <Button type="link" danger>一键清空</Button>
  181. </Popconfirm>}
  182. </Space>}
  183. visible={visible}
  184. onCancel={onClose}
  185. footer={null}
  186. width={900}
  187. className={`modalResetCss`}
  188. bodyStyle={{ padding: '0 0 40px', position: 'relative', borderRadius: '0 0 8px 8px' }}
  189. maskClosable={false}
  190. >
  191. <Form
  192. form={form}
  193. name="newMaterial"
  194. labelAlign='left'
  195. layout="vertical"
  196. colon={false}
  197. style={{ backgroundColor: '#f1f4fc', maxHeight: 650, overflow: 'hidden', overflowY: 'auto', padding: 10, borderRadius: '0 0 8px 8px' }}
  198. scrollToFirstError={{
  199. behavior: 'smooth',
  200. block: 'center'
  201. }}
  202. onFinishFailed={({ errorFields }) => {
  203. message.error(errorFields?.[0]?.errors?.[0])
  204. }}
  205. onFinish={handleOk}
  206. initialValues={{
  207. dynamicGroup: [undefined]
  208. }}
  209. >
  210. <Card className="cardResetCss" style={{ marginBottom: 10 }}>
  211. <Form.Item name="mediaType" label={<strong>创意组分配规则</strong>} style={{ marginBottom: 0 }} rules={[{ required: true, message: '请选择创意组分配规则!' }]}>
  212. <New1Radio
  213. data={[{ label: '全账号复用', value: 0 }, { label: '平均分配到广告', value: 1 }, { label: '顺序分配到广告', value: 2 }]}
  214. onChange={(e) => {
  215. if (e === 2 && dynamicGroup?.length > adLength) {
  216. form.setFieldsValue({ dynamicGroup: dynamicGroup.slice(0, adLength) })
  217. }
  218. }}
  219. />
  220. </Form.Item>
  221. </Card>
  222. <Form.List name="dynamicGroup">
  223. {(fields, { add, remove }) => (<>
  224. <div style={{ display: 'flex', flexWrap: 'wrap', gap: 10 }}>
  225. {fields.map((field, num) => (<Card
  226. title={<Space>
  227. <strong style={{ fontSize: 18 }}>创意组{num + 1}</strong>
  228. {deliveryMode === 'DELIVERY_MODE_COMPONENT' && <>
  229. <Dropdown
  230. overlay={<Menu>
  231. <Menu.Item onClick={() => {
  232. init({
  233. mediaType: 'VIDEO', num: 15, cloudSize: [[
  234. { relation: '=', width: 1280, height: 720 },
  235. { relation: '=', width: 720, height: 1280 }
  236. ]], maxSize: 512000 * 1024
  237. })
  238. setMaterialConfig({
  239. ...materialConfig,
  240. type: 'video',
  241. max: 15 - (dynamicGroup?.[num]?.['list']?.length || 0),
  242. index: num,
  243. adcreativeTemplateId: creativeTemplateId,
  244. isGroup: false
  245. })
  246. setTimeout(() => {
  247. setSelectVideoVisible(true)
  248. }, 100)
  249. }}>添加视频</Menu.Item>
  250. <Menu.Item onClick={() => {
  251. init({
  252. mediaType: 'IMG', num: 15, cloudSize: [[
  253. { relation: '=', width: 800, height: 800 },
  254. { relation: '=', width: 1280, height: 720 },
  255. { relation: '=', width: 720, height: 1280 },
  256. { relation: '=', width: 960, height: 334 },
  257. { relation: '=', width: 480, height: 320 },
  258. ]], maxSize: 400 * 1024
  259. })
  260. setMaterialConfig({
  261. ...materialConfig,
  262. type: 'image',
  263. max: 15 - (dynamicGroup?.[num]?.['list']?.length || 0),
  264. index: num,
  265. adcreativeTemplateId: creativeTemplateId,
  266. isGroup: false
  267. })
  268. setTimeout(() => {
  269. setSelectVideoVisible(true)
  270. }, 100)
  271. }}>新增图片</Menu.Item>
  272. </Menu>}
  273. placement="bottomLeft"
  274. arrow
  275. >
  276. <Button type="primary">添加图片/视频</Button>
  277. </Dropdown>
  278. <Dropdown
  279. overlay={<Menu>
  280. <Menu.Item disabled={dynamicGroup?.[num]?.['list']?.length >= 15} onClick={() => { selectGroupImg(num, 6) }}>1:1 六图</Menu.Item>
  281. <Menu.Item disabled={dynamicGroup?.[num]?.['list']?.length >= 15} onClick={() => { selectGroupImg(num, 3) }}>1:1 三图</Menu.Item>
  282. <Menu.Item disabled={dynamicGroup?.[num]?.['list']?.length >= 15} onClick={() => { selectGroupImg(num, 4) }}>1:1 四图</Menu.Item>
  283. </Menu>}
  284. placement="bottomLeft"
  285. arrow
  286. >
  287. <Button type="primary">上传组图</Button>
  288. </Dropdown>
  289. </>}
  290. </Space>}
  291. className="cardResetCss"
  292. key={field.key}
  293. style={{ width: deliveryMode === 'DELIVERY_MODE_CUSTOMIZE' ? ([641, 642, 643, 720, 721, 722, 1529, 618].includes(creativeTemplateId) || dynamicGroup?.length === 1) ? '100%' : 'calc(50% - 5px)' : '100%' }}
  294. extra={fields?.length > 1 && <DeleteOutlined className={styles.clear} onClick={() => remove(field.name)} style={{ color: 'red' }} />}
  295. >
  296. {deliveryMode === 'DELIVERY_MODE_CUSTOMIZE' ? <Space size={30} style={{ width: '100%' }} className={styles.space}>
  297. {Object.keys(materialData)?.map(key => {
  298. let m = materialData[key]
  299. let children = m.children
  300. return Object.keys(children).map(k => {
  301. let item = children[k]
  302. if (k === 'short_video1' || k === 'video_id') {
  303. return <Form.Item
  304. {...field}
  305. label={<strong>{item.description}</strong>}
  306. rules={[{ required: true, message: '请选择素材!' }]}
  307. name={[field.name, item.name]}
  308. key={k}
  309. >
  310. <div className={`${styles.box} ${styles.video}`} style={{ width: 300, height: 160 }} onClick={() => {
  311. init({ mediaType: 'VIDEO', cloudSize: creativeTemplateId === 1708 ? [[{ relation: '=', width: 1280, height: 720 }]] : [[{ relation: '=', width: item.restriction.videoRestriction.minWidth, height: item.restriction.videoRestriction.minHeight }]], maxSize: item.restriction.videoRestriction.fileSize * 1024 })
  312. setMaterialConfig({
  313. ...materialConfig,
  314. type: item.name,
  315. max: 1,
  316. index: num,
  317. adcreativeTemplateId: creativeTemplateId
  318. })
  319. setTimeout(() => {
  320. setSelectVideoVisible(true)
  321. }, 100)
  322. }}>
  323. <div className={styles.p}>
  324. {dynamicGroup?.length > 0 && dynamicGroup[num] && Object.keys(dynamicGroup[num])?.includes(item.name) ? <VideoNews src={dynamicGroup[num][item.name]['url']} style={{ display: 'block', width: 'auto', margin: 0, height: '100%' }} maskImgStyle={{ position: 'absolute', top: '50%', left: '50%', width: 40, height: 40, transform: 'translate(-50%, -50%)', zIndex: 10 }} /> : <>
  325. <span>{`推荐尺寸(${creativeTemplateId === 1708 ? 1280 : item.restriction.videoRestriction.minWidth} x ${creativeTemplateId === 1708 ? 720 : item.restriction.videoRestriction.minHeight})`}</span>
  326. <span>{`${item.restriction.videoRestriction.fileFormat?.map((str: any) => str?.replace('MEDIA_TYPE_', ''))};< ${item.restriction.videoRestriction.fileSize / 1024}M;时长 ≥ ${item.restriction.videoRestriction.minDuration}s,≤ ${item.restriction.videoRestriction.maxDuration}s,必须带有声音`}</span>
  327. </>}
  328. </div>
  329. </div>
  330. </Form.Item>
  331. }
  332. if (item.name === 'image_id' || item.name === 'cover_id') {
  333. return <Form.Item
  334. {...field}
  335. label={<strong>{item.description}</strong>}
  336. rules={[{ required: true, message: '请选择素材!' }]}
  337. name={[field.name, item.name]}
  338. key={key}
  339. >
  340. <Space align="end">
  341. <div className={`${styles.box} ${styles.image}`} style={{ width: 300, height: 160 }} onClick={() => {
  342. init({ mediaType: 'IMG', cloudSize: [[{ relation: '=', width: item.restriction.imageRestriction.width, height: item.restriction.imageRestriction.height }]], maxSize: item.restriction.imageRestriction.fileSize * 1024 })
  343. setMaterialConfig({
  344. ...materialConfig,
  345. type: item.name,
  346. max: 1,
  347. index: num,
  348. adcreativeTemplateId: creativeTemplateId
  349. })
  350. setTimeout(() => {
  351. setSelectVideoVisible(true)
  352. }, 100)
  353. }}>
  354. <p>
  355. {dynamicGroup?.length > 0 && dynamicGroup[num] && Object.keys(dynamicGroup[num])?.includes(item.name) ? <img src={dynamicGroup[num][item.name]['url']} /> : <>
  356. <span>{`推荐尺寸(${item.restriction.imageRestriction.width} x ${item.restriction.imageRestriction.height})`}</span>
  357. <span>{`${item.restriction.imageRestriction.fileFormat?.map((str: any) => str?.replace('IMAGE_TYPE_', ''))};小于 ${item.restriction.imageRestriction.fileSize}KB`}</span>
  358. </>}
  359. </p>
  360. </div>
  361. {videoUploads && Object.keys(videoUploads)?.length > 0 && <div style={{ width: 32 }}>
  362. {dynamicGroup?.length > 0 && dynamicGroup[num] && (Object.keys(dynamicGroup[num])?.includes('video_id') || Object.keys(dynamicGroup[num])?.includes('short_video1')) && <VideoFrameSelect onChange={(e) => setFrame(e, num, item.name)} url={dynamicGroup[num]?.['video_id']?.['url'] || dynamicGroup[num]?.['short_video1']?.['url']} />}
  363. </div>}
  364. </Space>
  365. </Form.Item>
  366. }
  367. if (item.name === 'list') {
  368. let name = ''
  369. let imageData: any = {}
  370. if (key === 'image_list') {
  371. imageData = item.children.image_id
  372. name = 'image_list';
  373. } else if (key === 'element_story') {
  374. imageData = item.children.image
  375. name = 'element_story'
  376. }
  377. return <Form.Item
  378. {...field}
  379. label={<strong>{imageData.description}</strong>}
  380. rules={[
  381. { required: true, type: 'array', len: minNumber || item.arrayProperty.maxNumber, message: '素材数量不对!' },
  382. { required: true, message: '请选择素材!' },
  383. ]}
  384. name={[field.name, name]}
  385. key={key}
  386. >
  387. <div className={`${styles.box} ${item.arrayProperty.maxNumber >= 3 ? styles.image_list : styles.imageMater}`} style={item.arrayProperty.maxNumber >= 3 ? { flexFlow: 'row', width: '100%', gap: 2 } : {}} onClick={() => {
  388. init({ mediaType: 'IMG', num: item.arrayProperty.maxNumber, cloudSize: [[{ relation: '=', width: imageData.restriction.imageRestriction.width, height: imageData.restriction.imageRestriction.height }]], maxSize: imageData.restriction.imageRestriction.fileSize * 1024 })
  389. setMaterialConfig({
  390. ...materialConfig,
  391. type: name,
  392. max: item.arrayProperty.maxNumber,
  393. index: num,
  394. adcreativeTemplateId: creativeTemplateId
  395. })
  396. setTimeout(() => {
  397. setSelectVideoVisible(true)
  398. }, 100)
  399. }}>
  400. {Array(item.arrayProperty.maxNumber).fill('').map((arr, index1) => {
  401. return <p key={index1} style={item.arrayProperty.maxNumber >= 3 ? { width: 130, height: 130 } : { justifyContent: 'center' }}>
  402. {dynamicGroup?.length > 0 && dynamicGroup[num] && Object.keys(dynamicGroup[num])?.includes(name) && dynamicGroup[num][name][index1] ? <img src={dynamicGroup[num][name][index1]['url']} /> : <>
  403. <span>{`推荐尺寸(${imageData.restriction.imageRestriction.width} x ${imageData.restriction.imageRestriction.height})`}</span>
  404. <span>{`${imageData.restriction.imageRestriction.fileFormat?.map((str: any) => str?.replace('IMAGE_TYPE_', ''))};小于 ${imageData.restriction.imageRestriction.fileSize}KB`}</span>
  405. </>}
  406. </p>
  407. })}
  408. </div>
  409. </Form.Item>
  410. }
  411. return null
  412. })
  413. })}
  414. </Space> : <Form.Item
  415. {...field}
  416. label={<strong>创意素材</strong>}
  417. rules={[{ required: true, message: '请选择素材!' }]}
  418. name={[field.name, 'list']}
  419. >
  420. <div className={`${styles.box} ${styles.video}`} style={{ width: '100%', height: 'auto', backgroundColor: 'rgb(247, 249, 252)' }}>
  421. {dynamicGroup?.length && dynamicGroup?.[num]?.['list']?.length > 0 ? <div className={styles.boxList}>
  422. <div className={styles.boxList_title}>
  423. <span>上传素材</span>
  424. <a onClick={() => {
  425. let newDynamicGroup = dynamicGroup?.map((item: any, i: number) => {
  426. if (i === num) {
  427. return { list: [] }
  428. }
  429. return item
  430. })
  431. form.setFieldsValue({ dynamicGroup: newDynamicGroup })
  432. }}>清空</a>
  433. </div>
  434. <div className={styles.boxList_body}>
  435. {dynamicGroup?.[num]?.['list']?.map((item: any, index: number) => {
  436. if (Array.isArray(item)) {
  437. let length = item.length
  438. return <div className={styles.boxList_body_item} key={index}>
  439. <div className={styles.tag}>{length}图</div>
  440. <div className={styles.content}>
  441. {item.map((l, i) => <img src={l?.url} key={i} style={{width: length === 6 ? 33.3 : 49.9}}/>)}
  442. </div>
  443. <div className={styles.clear} onClick={() => { clearTem(num, index) }}><CloseCircleOutlined /></div>
  444. </div>
  445. } else if (item?.url?.includes('mp4')) {
  446. return <div className={styles.boxList_body_item} key={index}>
  447. <div className={styles.content}>
  448. <VideoNews src={item?.url} style={{ width: 100, height: 100 }} maskBodyStyle={{ backgroundColor: "rgba(242, 246, 254, 0.1)" }} />
  449. </div>
  450. <div className={styles.clear} onClick={() => { clearTem(num, index) }}><CloseCircleOutlined /></div>
  451. </div>
  452. } else {
  453. return <div className={styles.boxList_body_item} key={index}>
  454. <div className={styles.content}><img src={item?.url} /></div>
  455. <div className={styles.clear} onClick={() => { clearTem(num, index) }}><CloseCircleOutlined /></div>
  456. </div>
  457. }
  458. })}
  459. </div>
  460. </div> : <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} description="暂无素材内容,可通过上方添加" />}
  461. </div>
  462. </Form.Item>}
  463. </Card>))}
  464. </div>
  465. {!(mediaType === 2 && dynamicGroup?.length >= adLength) && <Form.Item style={{ marginBottom: 0, marginTop: 10 }}>
  466. <Button type="dashed" style={{ color: '#1890ff' }} onClick={() => add()} block icon={<PlusOutlined />}>添加创意组</Button>
  467. </Form.Item>}
  468. </>)}
  469. </Form.List>
  470. <Form.Item className="submit_pull">
  471. <Space>
  472. <Button onClick={onClose}>取消</Button>
  473. <Button type="primary" htmlType="submit" className="modalResetCss">
  474. 确定
  475. </Button>
  476. </Space>
  477. </Form.Item>
  478. </Form>
  479. {/* 选择视频素材 */}
  480. {selectVideoVisible && <SelectCloud
  481. isGroup={materialConfig?.isGroup}
  482. visible={selectVideoVisible}
  483. onClose={() => setSelectVideoVisible(false)}
  484. sliderImgContent={materialConfig.index === 99999 ? undefined :
  485. materialConfig.type === 'element_story' ? (dynamicGroup[materialConfig.index] && Object.keys(dynamicGroup[materialConfig.index])?.includes('element_story')) ? dynamicGroup[materialConfig.index]['element_story']?.map((item: any) => item) : undefined :
  486. materialConfig.type === 'image_list' ? (dynamicGroup[materialConfig.index] && Object.keys(dynamicGroup[materialConfig.index])?.includes('image_list')) ? dynamicGroup[materialConfig.index]['image_list']?.map((item: any) => item) : undefined :
  487. (dynamicGroup[materialConfig.index] && Object.keys(dynamicGroup[materialConfig.index])?.includes(materialConfig.type)) ? [{ url: dynamicGroup[materialConfig.index][materialConfig.type] }] : undefined
  488. }
  489. onChange={(content: any) => {
  490. if (content.length > 0) {
  491. if (deliveryMode === 'DELIVERY_MODE_COMPONENT') { // 组件化创意
  492. let newDynamicGroup = dynamicGroup?.map((item: any, index: number) => {
  493. if (materialConfig.index === index) {
  494. let oldList = item?.list || []
  495. if (materialConfig.isGroup) {
  496. oldList = oldList.concat([content.map((m: any) => ({ id: m?.id, url: m?.url, materialType: 0 }))])
  497. return { list: oldList }
  498. } else {
  499. oldList = oldList.concat(content.map((m: any) => ({ id: m?.id, url: m?.url, materialType: 0 })))
  500. return { list: oldList }
  501. }
  502. }
  503. return item
  504. })
  505. form.setFieldsValue({ dynamicGroup: newDynamicGroup })
  506. } else { // 自定义创意
  507. if (materialConfig.index === 99999) {
  508. if (materialConfig.type === 'image_list' || materialConfig.type === 'element_story') {
  509. let urls = content?.map((item: any) => ({ id: item?.id, url: item?.url, materialType: 0 }))
  510. let max = materialConfig.max
  511. let materialsNew = dynamicGroup.map((item: any) => {
  512. let newItem = item || {}
  513. // 判断是否有字段,是否设置了值
  514. if (Object.keys(newItem).includes(materialConfig.type) && newItem[materialConfig.type]) {
  515. if (max > newItem[materialConfig.type].length && urls.length > 0) {
  516. let difference = max - newItem[materialConfig.type].length
  517. let material: any[] = []
  518. if (urls.length >= difference) {
  519. material = urls.splice(0, difference)
  520. } else {
  521. material = urls.splice(0, urls.length)
  522. }
  523. newItem[materialConfig.type] = [...newItem[materialConfig.type], ...material]
  524. return newItem
  525. } else {
  526. return newItem
  527. }
  528. } else {
  529. if (urls.length >= max) {
  530. let material = urls.splice(0, max)
  531. return { ...newItem, [materialConfig.type]: material }
  532. } else if (urls.length > 0) {
  533. let material = urls.splice(0, urls.length)
  534. return { ...newItem, [materialConfig.type]: material }
  535. } else {
  536. return newItem
  537. }
  538. }
  539. })
  540. if (urls.length > 0) {
  541. let data = Array(Math.ceil(urls.length / max)).fill(undefined).map(item => {
  542. if (urls.length >= max) {
  543. let material = urls.splice(0, max)
  544. return { [materialConfig.type]: material }
  545. } else {
  546. let material = urls.splice(0, urls.length)
  547. return { [materialConfig.type]: material }
  548. }
  549. })
  550. materialsNew = [...materialsNew, ...data]
  551. }
  552. console.log('materialsNew-->', materialsNew)
  553. form.setFieldsValue({ dynamicGroup: materialsNew })
  554. } else {
  555. let newMaterials = content?.map((item: any) => {
  556. if (["short_video1", 'video_id'].includes(materialConfig.type) && mLength === 2) {
  557. return { [materialConfig.type]: { url: item?.url, id: item?.id, materialType: 0 }, cover_id: { url: getVideoImgUrl(item?.url), id: null, materialType: 0 } }
  558. }
  559. return { [materialConfig.type]: { url: item?.url, id: item?.id, materialType: 0 } }
  560. })
  561. if (newMaterials.length > 0) {
  562. if (dynamicGroup?.every((item: any) => !item)) { // 没设置过
  563. form.setFieldsValue({ dynamicGroup: newMaterials })
  564. } else { // 设置过
  565. let materialsNew = dynamicGroup.map((item: any) => {
  566. let newItem = item || {}
  567. if (Object.keys(newItem).includes(materialConfig.type) && newItem[materialConfig.type]) {
  568. return item
  569. } else {
  570. if (newMaterials.length > 0) {
  571. let material = newMaterials.splice(0, 1)
  572. return { ...newItem, ...material[0] }
  573. } else {
  574. return item
  575. }
  576. }
  577. })
  578. if (newMaterials.length > 0) {
  579. materialsNew = [...materialsNew, ...newMaterials]
  580. }
  581. form.setFieldsValue({ dynamicGroup: materialsNew })
  582. }
  583. }
  584. }
  585. } else {
  586. let newDynamicGroup = dynamicGroup?.map((item: any, index: number) => {
  587. if (materialConfig.index === index) {
  588. if (materialConfig.type === 'image_list' || materialConfig.type === 'element_story') {
  589. if (item) {
  590. item[materialConfig.type] = content?.map((item: any) => ({ id: item?.id, url: item?.url, materialType: 0 }))
  591. return { ...item }
  592. } else {
  593. return { [materialConfig.type]: content?.map((item: any) => ({ id: item?.id, url: item?.url, materialType: 0 })) }
  594. }
  595. } else {
  596. if (item) {
  597. item[materialConfig.type] = { id: content[0]?.id, url: content[0]?.url, materialType: 0 }
  598. return { ...item }
  599. } else {
  600. if (["short_video1", 'video_id'].includes(materialConfig.type) && mLength === 2) {
  601. return { [materialConfig.type]: { id: content[0]?.id, url: content[0]?.url, materialType: 0 }, cover_id: { id: null, url: getVideoImgUrl(content[0]?.url), materialType: 0 } }
  602. }
  603. return { [materialConfig.type]: { id: content[0]?.id, url: content[0]?.url, materialType: 0 } }
  604. }
  605. }
  606. }
  607. return item
  608. })
  609. form.setFieldsValue({ dynamicGroup: newDynamicGroup })
  610. }
  611. }
  612. }
  613. setSelectVideoVisible(false)
  614. }}
  615. />}
  616. </Modal>
  617. }
  618. export default React.memo(AddMaterial)