import { Button, Card, Checkbox, Divider, Empty, Form, message, Modal, Pagination, Popover, Radio, Select, Space, Spin, Tooltip, Typography } from "antd" import React, { useEffect, useRef, useState } from "react" import { useAjax } from "@/Hook/useAjax" import { getMaterialDataListApi } from "@/services/adqV3/cloudNew" import style from './index.less' import SelectSearch from "./selectSearch" import './global.less' import '../../tencentAdPutIn/index.less' import { useLocalStorageState, useSize } from "ahooks" import useFileDrop from "@/Hook/useFileDrop" import { formatBytes, formatSecondsToTime, getVideoImgUrl } from "@/utils/utils" import UploadFile from "./uploadFile" import { useModel } from "umi" import UploadsTable from "./uploadsTable" import { DeleteOutlined, PlayCircleOutlined, SortAscendingOutlined } from "@ant-design/icons" import PlayVideo from "./playVideo" import { showFieldList } from "./const" import SelectFolder from "./selectFolder" import SelectGroupCloudNew from "./selectGroupCloudNew" import SelectGroupUnitNew from "./selectGroupUnitNew" const { Text, Paragraph } = Typography; /** * 选择素材 * @param param0 * @returns */ const SelectCloudNew: React.FC = ({ visible, defaultParams, num, sliderImgContent, isGroup, onChange, onClose, accountCreateLogs, putInType }) => { /************************************/ const { initialState } = useModel('@@initialState'); const ref = useRef(null); const size = useSize(ref); const [checkedFolderList, setCheckedFolderList] = useState([]) const [checkFolderAll, setCheckFolderAll] = useState(false); const [indeterminateFolder, setIndeterminateFolder] = useState(false); const [rowNum, setRowNum] = useState(0) const [SCKType, setSCKType] = useState<'1' | '2'>('1') const [queryParams, setQueryParams] = useState({ pageNum: 1, pageSize: 20 }) const [searchParams, setSearchParams] = useState>({}) const [uploadVisible, setUploadVisible] = useState(false) const [showField, setShowField] = useLocalStorageState('show-field', ['material.create_time', 'material_data_day.cost', 'material_data_day.ctr', 'material_data_day.conversions_rate', 'material_data_day.dynamic_creative_count']); const [sortData, setSortData] = useLocalStorageState<{ sortField: string | undefined, sortType: boolean }>('sort-data', { sortField: undefined, sortType: false }); const [active, setActive] = useState() const [isShowAll, setIsShowAll] = useState(false) const getMaterialDataList = useAjax((params) => getMaterialDataListApi(params)) /************************************/ useEffect(() => { if (sliderImgContent && sliderImgContent?.length > 0) { setCheckedFolderList(sliderImgContent as any || []) } }, []) useEffect(() => { let params = { ...searchParams, ...defaultParams, ...queryParams } if (sortData?.sortField) { params = { ...params, ...sortData } } if (params?.sizeList?.length) { params.sizeQueries = params.sizeList.map(item => { const [width, height, relation] = item.split('*') return { width: Number(width), height: Number(height), relation: relation || '=' } }) } delete params?.sizeList if (isShowAll) { delete params?.sizeQueries } getMaterialDataList.run(params) }, [queryParams, defaultParams, searchParams, sortData, showField, isShowAll]) // 根据内容宽度计算列数 useEffect(() => { if (size?.width) { let rowNum = Math.floor((size?.width - 26) / 200) setRowNum(rowNum || 1) } }, [size?.width]) // 处理全选按钮状态 useEffect(() => { let data: any[] = getMaterialDataList?.data?.records || [] let dataIds = data.map(item => item.id) let selectIds = checkedFolderList.map(item => item.id) if (selectIds.length === 0 || dataIds.length === 0) { setCheckFolderAll(false) setIndeterminateFolder(false); } else if (dataIds.every((element) => selectIds.includes(element))) { setCheckFolderAll(true) setIndeterminateFolder(false); } else if (dataIds.some((element) => selectIds.includes(element))) { setCheckFolderAll(false) setIndeterminateFolder(true); } else { setCheckFolderAll(false) setIndeterminateFolder(false); } }, [checkedFolderList, getMaterialDataList?.data?.records]) const handleOk = () => { if (isGroup && num && checkedFolderList && num > checkedFolderList?.length) { message.error(`当前选择了组图${num}图,当前选择了${checkedFolderList.length}个图片`) return } onChange?.(checkedFolderList) } // 选择 const onCheckboxChange = (checked: boolean, item: any) => { let newCheckedFolderList: any[] = JSON.parse(JSON.stringify(checkedFolderList)) if (active || active === 0) { if (checked) { // 选中 newCheckedFolderList[active] = { ...item, materialType: 0 } } else { // 取消 message.warning('请选择其他图片替换') return } } else { if (checked) { // 选中 newCheckedFolderList.push({ ...item, materialType: 0 }) } else { // 取消 newCheckedFolderList = newCheckedFolderList.filter(i => i.id !== item.id) } } setCheckedFolderList(newCheckedFolderList) }; // 获取拖拽的文件 const [fileList, setFileList] = useState() const [uploadsVisible, setUploadsVisible] = useState(false) const { isDragOver, dropAreaProps } = useFileDrop((fileList) => { setFileList(fileList) setUploadsVisible(true) }); return {[{ label: '素材库', value: '1' }, { label: '账户组媒体素材', value: '2' }, { label: '业务单元素材', value: '3' }].map(item =>
{ setSCKType(item.value as any) // setCheckedFolderList([]) }}> {item.label}
)} {SCKType === '1' && } } open={visible} onCancel={onClose} width={1400} maskClosable={false} footer={
{checkedFolderList.length > 0 ? <>
{checkedFolderList.map((item, index) =>
isGroup && setActive(index)}>
{item.material_type === 'video' && {(onPlay) => }} setCheckedFolderList(data => data.filter(i => i.id !== item.id))}>
)}
{!!active && setActive(undefined)}>清除单独修改} setCheckedFolderList([])}>清除所有 :
}
} className={`modalResetCss selectModal SCK`} bodyStyle={{ backgroundColor: '#f1f4fc', height: 700, overflow: 'hidden', padding: '10px' }} > {SCKType === '1' ?
{/* 搜索 */} { ref.current?.scrollTo(0, 0) setSearchParams(value) }} />
{/* 选择文件夹 */} { setQueryParams({ ...queryParams, folderId: value, pageNum: 1 }) }} />
{ let newCheckedFolderList: any[] = JSON.parse(JSON.stringify(checkedFolderList)) const data: any[] = getMaterialDataList?.data?.records if (e.target.checked) { // 全选 const selectIds = newCheckedFolderList.map(item => item.id) const remainData = data.filter(item => !selectIds.includes(item.id)) const remainDataLength = remainData.length const remainNum = num - newCheckedFolderList.length if (remainNum > remainDataLength) { newCheckedFolderList.push(...remainData.map(item => ({ ...item, materialType: 0 }))) } else { newCheckedFolderList.push(...remainData.splice(0, remainNum).map(item => ({ ...item, materialType: 0 }))) } newCheckedFolderList = Array.from(new Set(newCheckedFolderList.map(item => JSON.stringify(item)))).map(item => JSON.parse(item)); } else { // 取消全选 const dataIds = data.map(item => item.id) newCheckedFolderList = newCheckedFolderList.filter(i => !dataIds.includes(i.id)) } setCheckedFolderList(newCheckedFolderList) }} disabled={checkedFolderList?.length >= num || !!active || active === 0 || isShowAll} indeterminate={indeterminateFolder} checked={checkFolderAll} >全选 已选 {checkedFolderList?.length || 0}/{num} 个素材 {checkedFolderList.length > 0 && setCheckedFolderList([])}>清除所有} {sortData?.sortField && 「排序-{showFieldList.find(item => item.value === sortData.sortField)?.label}-{sortData.sortType ? '正序' : '倒序'}」}
setIsShowAll(e.target.checked)} checked={isShowAll}> 显示所有{defaultParams?.materialType === 'video' ? '视频' : '图片'}素材
展示指标}> (option?.label as any)?.toLowerCase().indexOf(input.toLowerCase()) >= 0 } options={showFieldList.filter(item => showField.includes(item.value) && item.value !== 'description')} value={sortData.sortField} allowClear onChange={(value) => { setSortData({ ...sortData, sortField: value as any }) }} /> setSortData({ ...sortData, sortType: e.target.value })} buttonStyle="solid"> 正序 倒序
} trigger={['click']} title={自定义展示指标与排序} placement="bottomRight" >
{isDragOver &&
拖动文件到这里
} {getMaterialDataList?.data?.records?.length > 0 ? (active || active === 0) ? index === active : true)?.map(item => item.id)} style={{ width: '100%' }}>
{getMaterialDataList?.data?.records.map((item: any) => { const isSelect = checkedFolderList?.filter((_, index) => (active || active === 0) ? index === active : true)?.map(item => item.id).includes(item.id) const disabled = ((active || active === 0) ? false : (checkedFolderList.length >= num && !isSelect)) || isShowAll return
onCheckboxChange(e.target.checked, item)} />
{item.material_type === 'video' &&
{(onPlay) => { e.stopPropagation(); e.preventDefault() onPlay() }} src={require('../../../../../public/image/play.png')} alt="" />}
}
{item.width}*{item.height}
{item.material_type === 'video' &&
{formatSecondsToTime(Math.floor(item.video_duration))}
}
} onClick={() => !disabled && onCheckboxChange(!isSelect, item)} >
{item?.material_name} {formatBytes(item?.file_size)}
{showField.map(field => { switch (field) { case 'material.create_time': return 创建时间:{item?.create_time} case 'material_data_day.cost': return 消耗:{(item?.cost === null || item?.cost === undefined) ? '--' : item?.cost} case 'material_data_day.order_pv': return 下单次数:{(item?.order_pv === null || item?.order_pv === undefined) ? '--' : item?.order_pv} case 'material_data_day.order_cost': return 下单成本:{(item?.order_cost === null || item?.order_cost === undefined) ? '--' : item?.order_cost} case 'material_data_day.ctr': return 点击率:{(item?.ctr === null || item?.ctr === undefined) ? '--' : (item?.ctr * 100).toFixed(2) + '%'} case 'material_data_day.conversions_rate': return 目标转化率:{(item?.conversions_rate === null || item?.conversions_rate === undefined) ? '--' : (item?.conversions_rate * 100).toFixed(2) + '%'} case 'material_data_day.adgroup_count': return 广告关联数:{(item?.adgroup_count === null || item?.adgroup_count === undefined) ? '--' : item?.adgroup_count} case 'material_data_day.dynamic_creative_count': return 创意关联数:{(item?.dynamic_creative_count === null || item?.dynamic_creative_count === undefined) ? '--' : item?.dynamic_creative_count} default: return null } })} {showField.includes('description') && 备注:{item.description || '--'}}
})}
:
}
{ ref.current?.scrollTo(0, 0) setQueryParams({ ...queryParams, pageNum: page, pageSize }) }} pageSizeOptions={[10, 15, 20, 50, 100]} />
: SCKType === '2' ? : } {/* 上传素材 */} {uploadVisible && { setUploadVisible(false) getMaterialDataList.refresh() }} onClose={() => { setUploadVisible(false) }} />} {/* 拖动上传 */} {uploadsVisible && { setUploadsVisible(false) setFileList(undefined) }} onChange={() => { setUploadsVisible(false) setFileList(undefined) getMaterialDataList.refresh() }} />}
} export default React.memo(SelectCloudNew)