123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492 |
- import { useAjax } from "@/Hook/useAjax"
- import SelectCloud from "@/pages/launchSystemNew/components/selectCloud"
- import { get_tools_video_capture } from "@/services/launchAdq/global"
- import { MinusCircleOutlined, PlusOutlined } from "@ant-design/icons"
- import { Button, Form, message, Modal, Radio, Space, Switch, Image, Popconfirm } from "antd"
- import React, { useEffect, useState } from "react"
- import { useModel } from "umi"
- import styles from './index.less'
- import { getVideoImgUrl } from "@/utils/utils"
- interface Props {
- value?: any[]
- material?: { label: string, name: string, restriction: any, arrayProperty?: any }[],
- sysAdcreative: any
- onChange?: (data: any) => void
- }
- /**
- * 选择素材组
- * @returns
- */
- const Material: React.FC<Props> = (props) => {
- /**************************/
- const { onChange, material = [], sysAdcreative, value } = props
- const { adcreativeTemplateId } = sysAdcreative
- const [visible, setVisible] = useState<boolean>(false)
- const [selectVideoVisible, set_selectVideoVisible] = useState(false)
- const [videoImgsVisbile, set_videoImgsVisbile] = useState(false)
- const [videoUploads, setVideoUploads] = useState<any>()
- const [imgUploads, setImgUploads] = useState<any>()
- const { init } = useModel('useLaunchAdq.useBdMediaPup')
- const [materialConfig, setMaterialConfig] = useState<{
- adcreativeTemplateId?: number,
- type: string,
- cloudSize: { relation: string, width: number, height: number }[],
- list: any[],
- index: number,
- max: number,
- sliderImgContent: any
- }>({
- type: '',//类型
- cloudSize: [],//素材搜索条件
- list: [],//素材
- index: 0, // 素材组下标
- max: 1,//素材数量
- sliderImgContent: undefined
- })//图片素材配置
- const [videoImgs, set_videoImgs] = useState<{//视频封面图设置
- activeUrl: string,//选中的视频封面图地址
- preview: boolean,//是否开启图片点击预览
- urlList: any[],//生成的视频封面列表
- }>({
- activeUrl: '',
- preview: false,
- urlList: [
- 'https://test-adq-media.oss-cn-hangzhou.aliyuncs.com/image/21D8D51AD98C4FF8BF41F1C2D28EA39F.jpg',
- 'https://test-adq-media.oss-cn-hangzhou.aliyuncs.com/image/80DBE1AB3EDE4E85ABAE5F1670D9FED0.jpg',
- 'https://test-adq-media.oss-cn-hangzhou.aliyuncs.com/image/BCB2DAB86BDB4549BCB8E493C4F29E82.jpg',
- 'https://test-adq-media.oss-cn-hangzhou.aliyuncs.com/image/545A4C2A5B874C82A9D1C0C063624AE5.jpg'
- ]
- })
- const [form] = Form.useForm();
- let materials = Form.useWatch('materials', form)
- const getVideoCapture = useAjax((params) => get_tools_video_capture(params))
- /**************************/
-
- // 回填
- useEffect(() => {
- if (visible) {
- if (value && value?.length > 0) {
- let data = value?.map((item: any) => {
- let data: any = {}
- for (const key in item) {
- switch (key) {
- case 'imageUrl'://图素材
- data.image = item[key]
- break;
- case 'videoUrl'://视频素材
- data.video = item[key]
- break;
- case 'imageUrlList'://图素材
- data.image_list = item[key]
- break;
- case 'shortVideo1Url'://视频素材
- data.short_video1 = item[key]
- break;
- case 'elementStory':
- data.element_story = item[key].map((item: { imageUrl: string }) => item.imageUrl)
- break;
- }
- }
- return data
- })
- form.setFieldsValue({ materials: data })
- } else {
- form.setFieldsValue({ materials: [undefined] })
- }
- }
- }, [value, visible])
- // 处理判断有哪些素材 展示按钮
- useEffect(() => {
- if (material?.length > 0) {
- setVideoUploads(material?.find((item: { name: string }) => item.name === 'short_video1' || item.name === 'video'))
- setImgUploads(material?.find((item: { name: string }) => item.name === 'image' || item.name === 'image_list' || item.name === 'element_story'))
- } else {
- setVideoUploads({})
- setImgUploads({})
- }
- }, [material])
- // 确定
- const handleOk = () => {
- form.validateFields().then(values => {
- let data = values?.materials?.map((item: any) => {
- let data: any = {}
- for (const key in item) {
- switch (key) {
- case 'image'://图素材
- data.imageUrl = item[key]
- break;
- case 'video'://视频素材
- data.videoUrl = item[key]
- break;
- case 'image_list'://图素材
- data.imageUrlList = item[key]
- break;
- case 'short_video1'://视频素材
- data.shortVideo1Url = item[key]
- break;
- case 'element_story':
- data.elementStory = item[key].map((url: string) => ({ imageUrl: url }))
- break;
- }
- }
- return data
- })
- onChange && onChange(data)
- setVisible(false)
- })
- }
- return <>
- <span onClick={() => { setVisible(true) }}>{value && value?.length > 0 ? '编辑' : '添加'}</span>
- {visible && <Modal
- visible={visible}
- onCancel={() => setVisible(false)}
- title={<>
- <span>创意素材</span>
- {videoUploads && Object.keys(videoUploads)?.length > 0 && <Button type="link" onClick={() => {
- init({ mediaType: 'VIDEO', num: 100, cloudSize: adcreativeTemplateId === 1708 ? [[{ relation: '=', width: 1280, height: 720 }]] : [[{ relation: '=', width: videoUploads.restriction.videoRestriction.minWidth, height: videoUploads.restriction.videoRestriction.minHeight }]], maxSize: videoUploads.restriction.videoRestriction.fileSize * 1024 })
- setMaterialConfig({
- ...materialConfig,
- type: videoUploads.name,
- max: 1,
- index: 99999,
- adcreativeTemplateId
- })
- setTimeout(() => {
- set_selectVideoVisible(true)
- }, 100)
- }}>批量添加视频素材</Button>}
- {imgUploads && Object.keys(imgUploads)?.length > 0 && <Button type="link" onClick={() => {
- init({ mediaType: 'IMG', num: 100, cloudSize: [[{ relation: '=', width: imgUploads.restriction.imageRestriction.width, height: imgUploads.restriction.imageRestriction.height }]], maxSize: imgUploads.restriction.imageRestriction.fileSize * 1024 })
- setMaterialConfig({
- ...materialConfig,
- type: imgUploads.name,
- max: (imgUploads.name === 'image_list' || imgUploads.name === 'element_story') ? imgUploads.arrayProperty.maxNumber : 1,
- index: 99999,
- adcreativeTemplateId
- })
- setTimeout(() => {
- set_selectVideoVisible(true)
- }, 100)
- }}>批量添加图片素材</Button>}
- {(materials && materials?.length > 1) && <Popconfirm
- title="是否清空?"
- onConfirm={() => form.setFieldsValue({ materials: [undefined] })}
- okText="是"
- cancelText="否"
- >
- <Button type="link" danger>一键清空</Button>
- </Popconfirm>}
- </>}
- width={930}
- bodyStyle={{
- maxHeight: 650,
- overflowY: 'scroll'
- }}
- onOk={handleOk}
- >
- <Form name="dynamic_form_item" form={form} labelAlign='left' >
- <Form.List name="materials">
- {(fields, { add, remove }) => (<>
- {fields.map((field, num) => (<div key={field.key}>
- <Space size={30} style={{ width: '100%' }} className={styles.space}>
- {material?.map((item, index) => {
- if (item.name === 'short_video1' || item.name === 'video') {
- return <Form.Item
- {...field}
- label={<strong>{item.label}</strong>}
- rules={[{ required: true, message: '请选择素材!' }]}
- name={[field.name, item.name]}
- key={index}
- >
- <div className={`${styles.box} ${styles.video}`} style={{ width: 300, height: 160 }} onClick={() => {
- init({ mediaType: 'VIDEO', cloudSize: adcreativeTemplateId === 1708 ? [[{ relation: '=', width: 1280, height: 720 }]] : [[{ relation: '=', width: item.restriction.videoRestriction.minWidth, height: item.restriction.videoRestriction.minHeight }]], maxSize: item.restriction.videoRestriction.fileSize * 1024 })
- setMaterialConfig({
- ...materialConfig,
- type: item.name,
- max: 1,
- index: num,
- adcreativeTemplateId
- })
- setTimeout(() => {
- set_selectVideoVisible(true)
- }, 100)
- }}>
- <p>
- {materials?.length > 0 && materials[num] && Object.keys(materials[num])?.includes(item.name) ? <video src={materials[num][item.name]} controls /> : <>
- <span>{`推荐尺寸(${adcreativeTemplateId === 1708 ? 1280 : item.restriction.videoRestriction.minWidth} x ${adcreativeTemplateId === 1708 ? 720 : item.restriction.videoRestriction.minHeight})`}</span>
- <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>
- </>}
- </p>
- </div>
- </Form.Item>
- }
- if (item.name === 'image') {
- return <Form.Item
- {...field}
- label={<strong>{item.label}</strong>}
- rules={[{ required: true, message: '请选择素材!' }]}
- name={[field.name, item.name]}
- key={index}
- >
- <div className={`${styles.box} ${styles.image}`} style={{ width: 300, height: 160 }} onClick={() => {
- init({ mediaType: 'IMG', cloudSize: [[{ relation: '=', width: item.restriction.imageRestriction.width, height: item.restriction.imageRestriction.height }]], maxSize: item.restriction.imageRestriction.fileSize * 1024 })
- setMaterialConfig({
- ...materialConfig,
- type: item.name,
- max: 1,
- index: num,
- adcreativeTemplateId
- })
- setTimeout(() => {
- set_selectVideoVisible(true)
- }, 100)
- }}>
- <p>
- {materials?.length > 0 && materials[num] && Object.keys(materials[num])?.includes(item.name) ? <img src={materials[num][item.name]} /> : <>
- <span>{`推荐尺寸(${item.restriction.imageRestriction.width} x ${item.restriction.imageRestriction.height})`}</span>
- <span>{`${item.restriction.imageRestriction.fileFormat?.map((str: any) => str?.replace('IMAGE_TYPE_', ''))};小于 ${item.restriction.imageRestriction.fileSize}KB`}</span>
- </>}
- </p>
- </div>
- </Form.Item>
- }
- if (item.name === 'image_list') {
- return <Form.Item
- {...field}
- label={<strong>{item.label}</strong>}
- rules={[{ required: true, message: '请选择素材!' }]}
- name={[field.name, item.name]}
- key={index}
- >
- <div className={`${styles.box} ${item.arrayProperty.maxNumber >= 3 ? styles.image_list : styles.imageMater}`} style={item.arrayProperty.maxNumber >= 3 ? { flexFlow: 'row', width: '100%' } : {}} onClick={() => {
- init({ mediaType: 'IMG', num: item.arrayProperty.maxNumber, cloudSize: [[{ relation: '=', width: item.restriction.imageRestriction.width, height: item.restriction.imageRestriction.height }]], maxSize: item.restriction.imageRestriction.fileSize * 1024 })
- setMaterialConfig({
- ...materialConfig,
- type: item.name,
- max: item.arrayProperty.maxNumber,
- index: num,
- adcreativeTemplateId
- })
- setTimeout(() => {
- set_selectVideoVisible(true)
- }, 100)
- }}>
- {Array(item.arrayProperty.maxNumber).fill('').map((arr, index1) => {
- return <p key={index1} style={item.arrayProperty.maxNumber >= 3 ? { width: 130, height: 130 } : { width: 130, height: 130, justifyContent: 'center' }}>
- {materials?.length > 0 && materials[num] && Object.keys(materials[num])?.includes(item.name) && materials[num][item.name][index1] ? <img src={materials[num][item.name][index1]} /> : <>
- <span>{`推荐尺寸(${item.restriction.imageRestriction.width} x ${item.restriction.imageRestriction.height})`}</span>
- <span>{`${item.restriction.imageRestriction.fileFormat?.map((str: any) => str?.replace('IMAGE_TYPE_', ''))};小于 ${item.restriction.imageRestriction.fileSize}KB`}</span>
- </>}
- </p>
- })}
- </div>
- </Form.Item>
- }
- if (item.name === 'element_story') {
- return <Form.Item
- {...field}
- label={<strong>{item.label}</strong>}
- rules={[{ required: true, message: '请选择素材!' }]}
- name={[field.name, item.name]}
- key={index}
- >
- <div className={`${styles.box} ${item.arrayProperty.maxNumber >= 3 ? styles.image_list : styles.imageMater}`} style={item.arrayProperty.maxNumber >= 3 ? { flexFlow: 'row', width: '100%' } : {}} onClick={() => {
- init({ mediaType: 'IMG', num: item.arrayProperty.maxNumber, cloudSize: [[{ relation: '=', width: item.restriction.imageRestriction.width, height: item.restriction.imageRestriction.height }]], maxSize: item.restriction.imageRestriction.fileSize * 1024 })
- setMaterialConfig({
- ...materialConfig,
- type: item.name,
- max: item.arrayProperty.maxNumber,
- index: num,
- adcreativeTemplateId
- })
- setTimeout(() => {
- set_selectVideoVisible(true)
- }, 100)
- }}>
- {Array(item.arrayProperty.maxNumber).fill('').map((arr, index1) => {
- return <p key={index1} style={item.arrayProperty.maxNumber >= 3 ? { width: 130, height: 130 } : { width: 130, height: 130, justifyContent: 'center' }}>
- {materials?.length > 0 && materials[num] && Object.keys(materials[num])?.includes(item.name) && materials[num][item.name][index1] ? <img style={item?.restriction.imageRestriction?.width > item?.restriction.imageRestriction?.height ? { width: '100%', height: 'auto' } : {}} src={materials[num][item.name][index1]} /> : <>
- <span>{`推荐尺寸(${item.restriction.imageRestriction.width} x ${item.restriction.imageRestriction.height})`}</span>
- <span>{`${item.restriction.imageRestriction.fileFormat?.map((str: any) => str?.replace('IMAGE_TYPE_', ''))};小于 ${item.restriction.imageRestriction.fileSize}KB`}</span>
- </>}
- </p>
- })}
- </div>
- </Form.Item>
- }
- return null
- })}
- {fields?.length > 1 && <MinusCircleOutlined className={styles.clear} onClick={() => remove(field.name)} style={{ marginBottom: 24, color: 'red' }} />}
- </Space>
- </div>))}
- <Form.Item>
- <Button type="link" onClick={() => add()} icon={<PlusOutlined />} style={{ padding: 0 }}>
- 新增素材组
- </Button>
- </Form.Item>
- </>)}
- </Form.List>
- </Form>
- </Modal>}
- {/* 选择视频素材 */}
- {selectVideoVisible && <SelectCloud
- visible={selectVideoVisible}
- onClose={() => set_selectVideoVisible(false)}
- sliderImgContent={materialConfig.index === 99999 ? undefined :
- materialConfig.type === 'element_story' ? (materials[materialConfig.index] && Object.keys(materials[materialConfig.index])?.includes('element_story')) ? materials[materialConfig.index]['element_story']?.map((item: string) => ({ url: item })) : undefined :
- materialConfig.type === 'image_list' ? (materials[materialConfig.index] && Object.keys(materials[materialConfig.index])?.includes('image_list')) ? materials[materialConfig.index]['image_list']?.map((item: string) => ({ url: item })) : undefined :
- (materials[materialConfig.index] && Object.keys(materials[materialConfig.index])?.includes(materialConfig.type)) ? [{ url: materials[materialConfig.index][materialConfig.type] }] : undefined
- }
- onChange={(content: any) => {
- if (content.length > 0) {
- if (materialConfig.index === 99999) {
- if (materialConfig.type === 'image_list' || materialConfig.type === 'element_story') {
- let urls = content?.map((item: any) => item?.url)
- let max = materialConfig.max
- let materialsNew = materials.map((item: any) => {
- let newItem = item || {}
- // 判断是否有字段,是否设置了值
- if (Object.keys(newItem).includes(materialConfig.type) && newItem[materialConfig.type]) {
- if (max > newItem[materialConfig.type].length && urls.length > 0) {
- let difference = max - newItem[materialConfig.type].length
- let material: any[] = []
- if (urls.length >= difference) {
- material = urls.splice(0, difference)
- } else {
- material = urls.splice(0, urls.length)
- }
- newItem[materialConfig.type] = [...newItem[materialConfig.type], ...material]
- return newItem
- } else {
- return newItem
- }
- } else {
- if (urls.length >= max) {
- let material = urls.splice(0, max)
- return { ...newItem, [materialConfig.type]: material }
- } else if (urls.length > 0) {
- let material = urls.splice(0, urls.length)
- return { ...newItem, [materialConfig.type]: material }
- } else {
- return newItem
- }
- }
- })
- if (urls.length > 0) {
- let data = Array(Math.ceil(urls.length / max)).fill(undefined).map(item => {
- if (urls.length >= max) {
- let material = urls.splice(0, max)
- return { [materialConfig.type]: material }
- } else {
- let material = urls.splice(0, urls.length)
- return { [materialConfig.type]: material }
- }
- })
- materialsNew = [...materialsNew, ...data]
- }
- form.setFieldsValue({ materials: materialsNew })
- } else {
- let newMaterials = content?.map((item: any) => {
- if (materialConfig.type === 'video' && material.length === 2) {
- return { [materialConfig.type]: item?.url, image: getVideoImgUrl(item?.url) }
- }
- return { [materialConfig.type]: item?.url }
- })
- if (newMaterials.length > 0) {
- if (materials?.every((item: any) => !item)) { // 没设置过
- form.setFieldsValue({ materials: newMaterials })
- } else { // 设置过
- let materialsNew = materials.map((item: any) => {
- let newItem = item || {}
- if (Object.keys(newItem).includes(materialConfig.type) && newItem[materialConfig.type]) {
- return item
- } else {
- if (newMaterials.length > 0) {
- let material = newMaterials.splice(0, 1)
- return { ...newItem, ...material[0] }
- } else {
- return item
- }
- }
- })
- if (newMaterials.length > 0) {
- materialsNew = [...materialsNew, ...newMaterials]
- }
- form.setFieldsValue({ materials: materialsNew })
- }
- }
- }
- } else {
- materials = materials?.map((item: any, index: number) => {
- if (materialConfig.index === index) {
- if (materialConfig.type === 'image_list' || materialConfig.type === 'element_story') {
- if (item) {
- item[materialConfig.type] = content?.map((item: any) => item?.url)
- return { ...item }
- } else {
- return { [materialConfig.type]: content?.map((item: any) => item?.url) }
- }
- } else {
- if (item) {
- item[materialConfig.type] = content[0]?.url
- return { ...item }
- } else {
- if (materialConfig.type === 'video' && material.length === 2) {
- return { [materialConfig.type]: content[0]?.url, image: getVideoImgUrl(content[0]?.url) }
- }
- return { [materialConfig.type]: content[0]?.url }
- }
- }
- }
- return item
- })
- form.setFieldsValue({ materials })
- }
- }
- set_selectVideoVisible(false)
- }}
- />}
- {/* 视频封面图弹窗 */}
- {videoImgsVisbile && <Modal
- visible={videoImgsVisbile}
- title={<div>生成封面图 <Switch checkedChildren="开启预览" unCheckedChildren="关闭预览" checked={videoImgs.preview} onChange={(checked) => { set_videoImgs({ ...videoImgs, preview: checked }) }} /></div>}
- onOk={() => {
- if (videoImgs.activeUrl) {
- // setImgMaterialConfig({ ...imgMaterialConfig, list: [{ url: videoImgs.activeUrl }] })
- set_videoImgsVisbile(false)
- } else {
- message.error('请选择图片,获取使用取消按钮关闭弹窗!')
- }
- }}
- onCancel={() => { set_videoImgsVisbile(false) }}
- confirmLoading={getVideoCapture.loading}
- width={600}
- >
- <Radio.Group className={styles.videoImgs} onChange={(e) => {
- let url = e.target.value
- set_videoImgs({ ...videoImgs, activeUrl: url })
- }}>
- {
- videoImgs?.urlList?.map((item: any, index: number) => {
- return <Radio.Button value={item} key={index}>
- <Image src={item} preview={videoImgs.preview} />
- </Radio.Button>
- })
- }
- </Radio.Group>
- </Modal>}
- </>
- }
- export default React.memo(Material)
|