addMaterial.tsx 45 KB

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