123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338 |
- import React, { useState } from 'react';
- import '../../tencentAdPutIn/index.less'
- import { Button, Card, Dropdown, Empty, Form, message, Modal, Space, Table } from 'antd';
- import { CloseCircleOutlined, DeleteOutlined, PlusOutlined } from '@ant-design/icons';
- import { DEFAULT_COMPONENT_SUB_IMAGE_TYPE, DEFAULT_COMPONENT_SUB_VIDEO_TYPE, IComponent } from './const';
- import style from './index.less'
- import SelectCloudComponent from '../../material/cloudNew/selectCloudComponent';
- import VideoNews from '@/pages/launchSystemNew/components/newsModal/videoNews';
- import { useAjax } from '@/Hook/useAjax';
- import { addBatchCreativeComponentApi, CreativeComponentDetailDTOS } from '@/services/adqV3/global';
- interface Props {
- type: 'IMAGE' | 'VIDEO'
- putInType: 'NOVEL' | 'GAME',
- accountId: number;
- visible?: boolean;
- onClose?: () => void;
- onChange?: () => void;
- }
- /**
- * 新建组件
- * @param param0
- * @returns
- */
- const AddComponents: React.FC<Props> = ({ type, putInType, accountId, visible, onChange, onClose }) => {
- /****************************************/
- const [form] = Form.useForm();
- const componentsGroup = Form.useWatch('componentsGroup', form)
- const [selectCloudData, setSelectCloudData] = useState<{
- defaultParams: {
- sizeQueries?: {
- width: number,
- height: number,
- relation: string
- }[],
- materialType: 'image' | 'video'
- fileSize: number
- }
- num: number
- }>()
- const [materialConfig, setMaterialConfig] = useState<{
- adcreativeTemplateId?: number,
- type: string,
- cloudSize: { relation: string, width: number, height: number }[],
- list: any[],
- index: number,
- max: number,
- sliderImgContent: any,
- isGroup?: boolean
- }>({
- type: '',//类型
- cloudSize: [],//素材搜索条件
- list: [],//素材
- index: 0, // 素材组下标
- max: 1,//素材数量
- sliderImgContent: undefined
- })//图片素材配置
- const [selectVideoVisible, setSelectVideoVisible] = useState(false)
- const addBatchCreativeComponent = useAjax((params) => addBatchCreativeComponentApi(params))
- /****************************************/
- const handleOk = (values: any) => {
- if (values?.componentsGroup?.length) {
- const params = values.componentsGroup.reduce((pre: CreativeComponentDetailDTOS[], cur: { componentSubType: string; list: any[] }) => {
- pre.push(...cur?.list?.map((item) => {
- if (cur?.componentSubType?.includes('IMAGE_LIST')) {
- return {
- componentSubType: cur.componentSubType,
- materialIdList: item.map((i: { id: any; }) => i.id),
- componentType: 'imageList'
- }
- } else if (cur?.componentSubType?.includes('VIDEO')) {
- return {
- componentSubType: cur.componentSubType,
- materialId: item.id,
- componentType: 'video',
- coverUrl: item.key_frame_image_url
- }
- }
- return {
- componentSubType: cur.componentSubType,
- materialId: item.id,
- componentType: 'image'
- }
- }))
- return pre
- }, [])
- console.log(params);
- addBatchCreativeComponent.run({
- adAccountId: accountId,
- creativeComponentDetailDTOS: params
- }).then((res) => {
- if (res?.length === 0) {
- message.success('创建成功')
- onChange?.()
- } else {
- console.log(res);
- Modal.confirm({
- okText: '关闭',
- cancelText: '继续',
- className: 'modalResetCss',
- icon: false,
- width: 750,
- content: <Table
- dataSource={res?.map((text: string, index: number) => ({ des: text, id: index + 1 }))}
- columns={[
- {
- title: '新增详情',
- dataIndex: 'des',
- key: 'des',
- ellipsis: true
- }
- ]}
- size="small"
- bordered
- rowKey={'id'}
- />,
- onOk() {
- onChange?.()
- },
- onCancel() {}
- });
- }
- })
- }
- }
- /** 删除单个 */
- const clearTem = (index: number, count: number) => {
- const newComponentsGroup = componentsGroup?.map((item: any, i: number) => {
- if (i === index) {
- const oldList = item?.list?.filter((_: any, li: number) => count !== li)
- return { ...item, list: oldList }
- }
- return item
- })
- form.setFieldsValue({ componentsGroup: newComponentsGroup })
- }
- const componentsGroupSubTypeList = componentsGroup?.map((item: { componentSubType: any; }) => item.componentSubType) || []
- return <Modal
- title={<strong style={{ fontSize: 20 }}>新建组件</strong>}
- open={visible}
- onCancel={onClose}
- footer={null}
- width={900}
- className={`modalResetCss`}
- bodyStyle={{ padding: '0 0 40px', position: 'relative', borderRadius: '0 0 8px 8px' }}
- maskClosable={false}
- >
- <Form
- form={form}
- name="newComponents"
- labelAlign='left'
- layout="vertical"
- colon={false}
- style={{ backgroundColor: '#f1f4fc', maxHeight: 650, overflow: 'hidden', overflowY: 'auto', padding: 10, borderRadius: '0 0 8px 8px' }}
- scrollToFirstError={{
- behavior: 'smooth',
- block: 'center'
- }}
- onFinishFailed={({ errorFields }) => {
- message.error(errorFields?.[0]?.errors?.[0])
- }}
- onFinish={handleOk}
- initialValues={{
- // componentsGroup: [{ componentSubType: 'IMAGE_16X9' }, { componentSubType: 'IMAGE_LIST_1X1_3' }]
- }}
- >
- <Form.List name="componentsGroup">
- {(fields, { add, remove }) => (<>
- <div style={{ display: 'flex', flexWrap: 'wrap', gap: 10 }}>
- {fields.map((field, num) => {
- const componentData = (type === 'IMAGE' ? DEFAULT_COMPONENT_SUB_IMAGE_TYPE : DEFAULT_COMPONENT_SUB_VIDEO_TYPE).find(item => item.value === componentsGroup?.[num]?.componentSubType) as IComponent
- const title = componentData?.label
- return <Card
- title={<Space>
- <strong>{title || '组件'} 组件</strong>
- <Button
- type="link"
- disabled={componentsGroup?.[num]?.['list']?.length >= 200}
- onClick={() => {
- let count = 200 - (componentsGroup?.[num]?.['list']?.length || 0)
- let isGroup = false
- if (componentData?.value?.includes('IMAGE_LIST')) {
- count = componentData?.restriction.minNumber || count
- isGroup = true
- }
- setSelectCloudData({
- num: count,
- defaultParams: {
- materialType: type === 'IMAGE' ? 'image' : 'video',
- sizeQueries: [
- { relation: '=', width: componentData?.restriction.width || 0, height: componentData?.restriction.height || 0 }
- ],
- fileSize: (componentData?.restriction.fileSize || 0) * 1024
- }
- })
- setMaterialConfig({
- ...materialConfig,
- type: type === 'IMAGE' ? 'image' : 'video',
- max: count,
- index: num,
- isGroup
- })
- setTimeout(() => {
- setSelectVideoVisible(true)
- }, 100)
- }}
- >添加</Button>
- </Space>}
- className="cardResetCss"
- key={field.key}
- style={{ width: '100%' }}
- extra={fields?.length > 1 && <DeleteOutlined className={style.clear} onClick={() => remove(field.name)} style={{ color: 'red' }} />}
- >
- <Form.Item
- {...field}
- label={<strong>素材</strong>}
- rules={[{ required: true, message: '请选择素材!' }]}
- name={[field.name, 'list']}
- >
- <div className={`${style.box} ${style.video}`} style={{ width: '100%', height: 'auto', backgroundColor: 'rgb(247, 249, 252)' }}>
- {componentsGroup?.length && componentsGroup?.[num]?.['list']?.length > 0 ? <div className={style.boxList}>
- <div className={style.boxList_title}>
- <span>上传素材 <span style={{ marginLeft: 5, color: '#999', fontWeight: 'normal' }}>已选:{componentsGroup?.[num]?.['list']?.length || 0} 个素材</span></span>
- <a onClick={() => {
- const newComponentsGroup = componentsGroup?.map((item: any, i: number) => {
- if (i === num) {
- return { ...item, list: [] }
- }
- return item
- })
- form.setFieldsValue({ componentsGroup: newComponentsGroup })
- }}>清空</a>
- </div>
- <div className={style.boxList_body}>
- {componentsGroup?.[num]?.['list']?.map((item: any, index: number) => {
- if (componentsGroup?.[num]?.componentSubType?.includes('IMAGE_LIST')) {
- let length = item.length
- return <div className={style.boxList_body_item} key={index}>
- <div className={style.tag}>{length}图</div>
- <div className={style.content}>
- {item?.map((l: { oss_url: string | undefined; }, i: number) => <img src={l?.oss_url} key={i} style={{ width: length >= 6 ? 33.3 : 49.9 }} />)}
- </div>
- <div className={style.clear} onClick={() => { clearTem(num, index) }}><CloseCircleOutlined /></div>
- </div>
- } else if (componentsGroup?.[num]?.componentSubType?.includes('VIDEO')) {
- return <div className={style.boxList_body_item} key={index}>
- <div className={style.content}>
- <VideoNews src={item?.oss_url} keyFrameImageUrl={item?.key_frame_image_url} style={{ width: 100, height: 100 }} maskBodyStyle={{ backgroundColor: "rgba(242, 246, 254, 0.1)" }} />
- </div>
- <div className={style.clear} onClick={() => { clearTem(num, index) }}><CloseCircleOutlined /></div>
- </div>
- }
- return <div className={style.boxList_body_item} key={index}>
- <div className={style.content}><img src={item?.oss_url} /></div>
- <div className={style.clear} onClick={() => { clearTem(num, index) }}><CloseCircleOutlined /></div>
- </div>
- })}
- </div>
- </div> : <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} description="暂无素材内容,可通过上方添加" />}
- </div>
- </Form.Item>
- </Card>
- })}
- </div>
- <Form.Item style={{ marginBottom: 0, marginTop: 10 }}>
- <Dropdown
- menu={{
- items: (type === 'IMAGE' ? DEFAULT_COMPONENT_SUB_IMAGE_TYPE : DEFAULT_COMPONENT_SUB_VIDEO_TYPE).map(item => ({ label: item.label, key: item.value, disabled: componentsGroupSubTypeList.includes(item.value) })),
- onClick: (e) => {
- setTimeout(() => add({ componentSubType: e.key }), 100)
- },
- style: { maxHeight: 260, overflowY: 'auto' }
- }}
- overlayStyle={{ minWidth: 350 }}
- trigger={['click']}
- placement='top'
- >
- <Button type="dashed" style={{ color: '#1890ff' }} block icon={<PlusOutlined />}>添加组件组</Button>
- </Dropdown>
- </Form.Item>
- </>)}
- </Form.List>
- {(componentsGroup?.length === 0 || !componentsGroup) && <Card className="cardResetCss" style={{ marginTop: 10 }}><Empty image={Empty.PRESENTED_IMAGE_SIMPLE} description="暂无组内容,可通过上方添加" /></Card>}
- <Form.Item className="submit_pull">
- <Space>
- <Button onClick={onClose}>取消</Button>
- <Button type="primary" htmlType="submit" className="modalResetCss" loading={addBatchCreativeComponent.loading}>
- 确定
- </Button>
- </Space>
- </Form.Item>
- </Form>
- {/* 选择素材 */}
- {(selectVideoVisible && selectCloudData) && <SelectCloudComponent
- {...selectCloudData}
- accountCreateLogs={[{ accountId: accountId }]}
- visible={selectVideoVisible}
- isGroup={materialConfig?.isGroup}
- onClose={() => {
- setSelectVideoVisible(false)
- setSelectCloudData(undefined)
- }}
- putInType={putInType}
- onChange={(content: any) => {
- console.log(content)
- if (content.length > 0) {
- const newComponentsGroup = componentsGroup?.map((item: any, index: number) => {
- if (materialConfig.index === index) {
- let oldList = item?.list || []
- if (materialConfig.isGroup) {
- oldList = oldList.concat([content])
- return { ...item, list: oldList }
- } else {
- oldList = oldList.concat(content)
- return { ...item, list: oldList }
- }
- }
- return item
- })
- form.setFieldsValue({ componentsGroup: newComponentsGroup })
- }
- setSelectVideoVisible(false)
- setSelectCloudData(undefined)
- }}
- />}
- </Modal>
- };
- export default AddComponents;
|