123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379 |
- import React, { useEffect, useState, useRef } from "react"
- import style from './index.less'
- import { Card, Checkbox, Divider, Empty, message, Pagination, Result, Space, Spin, Typography, Image } from "antd"
- import { useAjax } from "@/Hook/useAjax"
- import './global.less'
- import '../../tencentAdPutIn/index.less'
- import { EyeOutlined } from "@ant-design/icons"
- import PlayVideo from "./playVideo"
- import Lazyimg from "react-lazyimg-component"
- import SyncCloudSc from "./syncCloudSc"
- import { checkAccountUnitApi } from "@/services/launchAdq/adAuthorize"
- import { getCreativeComponentListApi, GetCreativeComponentProps } from "@/services/adqV3/global"
- import { COMPONENT_GENERATION_TYPE_ENUM, COMPONENT_SUB_TYPE, getComponentType } from "../../tencenTasset/manageComponent/const"
- import moment from "moment"
- import SelectComponentsUnitSearch from "./selectComponentsUnitSearch"
- const { Text, Paragraph } = Typography;
- interface Props extends CLOUDNEW.SelectGroupCloudNewProps {
- isGroup?: boolean
- componentCount?: number
- }
- /**
- * 选择业务单元组件
- * @param param0
- * @returns
- */
- const SelectComponentsUnit: React.FC<Props> = ({ num: count, defaultParams, checkedFolderList, setCheckedFolderList, accountCreateLogs, active, isGroup, componentCount }) => {
- /*****************************************/
- const num = (isGroup ? componentCount : count) || 1
- const [rowNum, setRowNum] = useState<number>(0)
- const refScllor = useRef<HTMLDivElement>(null)
- const [checkFolderAll, setCheckFolderAll] = useState<boolean>(false);
- const [indeterminateFolder, setIndeterminateFolder] = useState<boolean>(false);
- const [queryParams, setQueryParams] = useState<GetCreativeComponentProps>({ pageNum: 1, pageSize: 20 })
- const [searchParams, setSearchParams] = useState<Partial<GetCreativeComponentProps>>({})
- const [unitAccountId, setUnitAccountId] = useState<number>()
- const [previewData, setPreviewData] = useState<{ visible: boolean, url?: string[] }>({ visible: false })
- const [componentSubType, setComponentSubType] = useState<string[]>([])
- const getCreativeComponentList = useAjax((params) => getCreativeComponentListApi(params))
- const checkAccountUnit = useAjax((params) => checkAccountUnitApi(params))
- /*****************************************/
- // 根据内容宽度计算列数
- useEffect(() => {
- let rowNum = Math.floor(1350 / 220)
- setRowNum(rowNum || 1)
- }, [])
- // 处理全选按钮状态
- useEffect(() => {
- let data: any[] = getCreativeComponentList?.data?.records || []
- let dataIds = data.map(item => item.componentId)
- 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, getCreativeComponentList?.data?.records])
- useEffect(() => {
- if (accountCreateLogs?.length) {
- checkAccountUnit.run(accountCreateLogs.map(item => item.accountId)).then(res => {
- setUnitAccountId(res?.adUnitAccountId)
- })
- }
- }, [accountCreateLogs])
- useEffect(() => {
- console.log('defaultParams--->', defaultParams)
- if (unitAccountId) {
- const materialType = defaultParams.materialType
- let componentSubType: string[] = []
- if (isGroup) {
- switch (count) {
- case 1:
- componentSubType = ['IMAGE_LIST_1X1_1']
- break
- case 3:
- componentSubType = ['IMAGE_LIST_1X1_3']
- break
- case 4:
- componentSubType = ['IMAGE_LIST_1X1_4']
- break
- case 6:
- componentSubType = ['IMAGE_LIST_1X1_6']
- break
- case 9:
- componentSubType = ['IMAGE_LIST_1X1_9']
- break
- }
- } else {
- // 组件化创意
- if (defaultParams?.sizeQueries && defaultParams?.sizeQueries?.length > 1) {
- if (defaultParams?.materialType === "image") {
- componentSubType = ['IMAGE_1X1', 'IMAGE_16X9', 'IMAGE_20X7', 'IMAGE_3X2', 'IMAGE_9X16']
- } else if (defaultParams?.materialType === "video") {
- componentSubType = ['VIDEO_16X9', 'VIDEO_9X16', 'VIDEO_4X3']
- }
- } else {
- const { width, height } = defaultParams?.sizeQueries?.[0] || { width: 0, height: 0 }
- if (width === 1280 && height === 720) {
- if (materialType === "video") {
- componentSubType = ['VIDEO_16X9']
- } else {
- componentSubType = ['IMAGE_16X9']
- }
- }
- }
- }
- setComponentSubType(componentSubType)
- // defaultParams
- const params = { ...searchParams, ...queryParams, adAccountId: unitAccountId, componentSubType, isDeleted: false }
- getCreativeComponentList.run(params)
- }
- }, [queryParams, defaultParams, searchParams, unitAccountId, isGroup, count])
- // 选择
- const onCheckboxChange = (checked: boolean, item: any, type: "IMAGE" | "VIDEO" | "IMAGE_LIST" | "OTHER") => {
- let newCheckedFolderList: any[] = JSON.parse(JSON.stringify(checkedFolderList))
- let data: { oss_url: string, key_frame_image_url?: string } = { oss_url: '' }
- switch (type) {
- case "IMAGE":
- data = { oss_url: item?.componentValue?.image?.value?.imageUrl }
- break
- case "VIDEO":
- data = {
- oss_url: item?.componentValue?.video?.value?.videoUrl || item?.componentValue?.shortVideo?.value?.shortVideo1Url,
- key_frame_image_url: item?.componentValue?.video?.value?.coverUrl || item?.componentValue?.shortVideo?.value?.shortVideo2Url
- }
- break
- case "IMAGE_LIST":
- data = { oss_url: item?.componentValue?.imageList?.value?.list }
- break
- }
- if (active || active === 0) {
- if (checked) { // 选中
- newCheckedFolderList[active] = { ...item, ...data, id: item.componentId, material_type: defaultParams.materialType, materialType: 4, isUnitComponent: true }
- } else { // 取消
- message.warning('请选择其他图片替换')
- return
- }
- } else {
- if (checked) { // 选中
- newCheckedFolderList.push({ ...item, ...data, id: item.componentId, material_type: defaultParams.materialType, materialType: 4, isUnitComponent: true })
- } else { // 取消
- const id = item.componentId
- newCheckedFolderList = newCheckedFolderList.filter(i => i.id !== id)
- }
- }
- setCheckedFolderList(newCheckedFolderList)
- };
- return <Spin spinning={checkAccountUnit.loading} wrapperClassName={'select_group_spin'}>
- <div className={style.select_cloudNew_layout}>
- {unitAccountId ? <>
- {/* 搜索 */}
- <SelectComponentsUnitSearch
- type={defaultParams.materialType}
- componentSubType={componentSubType}
- onSearch={(value) => {
- refScllor.current?.scrollTo(0, 0)
- setSearchParams(value)
- }}
- />
- <Card
- style={{ height: '100%', flex: '1 0', overflow: 'hidden' }}
- bodyStyle={{ padding: 0, overflow: 'auto hidden', height: '100%' }}
- className="cardResetCss buttonResetCss"
- bordered
- >
- <div className={style.cloudNew}>
- <div className={style.material} style={{ height: '100%' }}>
- <div className={style.operates}>
- <div className={style.left_bts}>
- <Checkbox
- onChange={(e) => {
- let newCheckedFolderList: any[] = JSON.parse(JSON.stringify(checkedFolderList))
- const data: any[] = getCreativeComponentList?.data?.records?.filter((item: { status: string }) => item?.status === '正常')
- if (e.target.checked) { // 全选
- const selectIds = newCheckedFolderList.map(item => item.id)
- const remainData = data.filter(item => {
- const id = item.componentId
- return !selectIds.includes(id)
- })
- const remainDataLength = remainData.length
- const remainNum = num - newCheckedFolderList.length
- if (remainNum > remainDataLength) {
- newCheckedFolderList.push(...remainData.map(i => {
- let data: { oss_url: string, key_frame_image_url?: string } = { oss_url: '' }
- const type = getComponentType(i.componentSubType)
- switch (type) {
- case "IMAGE":
- data = { oss_url: i?.componentValue?.image?.value?.imageUrl }
- break
- case "VIDEO":
- data = {
- oss_url: i?.componentValue?.video?.value?.videoUrl || i?.componentValue?.shortVideo?.value?.shortVideo1Url,
- key_frame_image_url: i?.componentValue?.video?.value?.coverUrl || i?.componentValue?.shortVideo?.value?.shortVideo2Url
- }
- break
- case "IMAGE_LIST":
- data = { oss_url: i?.componentValue?.imageList?.value?.list }
- break
- }
- return { ...i, ...data, material_type: defaultParams.materialType, id: i.componentId, materialType: 4, isUnitComponent: true }
- }))
- } else {
- newCheckedFolderList.push(...remainData.splice(0, remainNum).map(i => {
- let data: { oss_url: string, key_frame_image_url?: string } = { oss_url: '' }
- const type = getComponentType(i.componentSubType)
- switch (type) {
- case "IMAGE":
- data = { oss_url: i?.componentValue?.image?.value?.imageUrl }
- break
- case "VIDEO":
- data = {
- oss_url: i?.componentValue?.video?.value?.videoUrl || i?.componentValue?.shortVideo?.value?.shortVideo1Url,
- key_frame_image_url: i?.componentValue?.video?.value?.coverUrl || i?.componentValue?.shortVideo?.value?.shortVideo2Url
- }
- break
- case "IMAGE_LIST":
- data = { oss_url: i?.componentValue?.imageList?.value?.list }
- break
- }
- return { ...i, ...data, material_type: defaultParams.materialType, id: i.componentId, materialType: 4, isUnitComponent: true }
- }))
- }
- newCheckedFolderList = Array.from(new Set(newCheckedFolderList.map(item => JSON.stringify(item)))).map(item => JSON.parse(item));
- } else { // 取消全选
- const dataIds = data.map(item => item.componentId)
- newCheckedFolderList = newCheckedFolderList.filter(i => !dataIds.includes(i.id))
- }
- setCheckedFolderList(newCheckedFolderList)
- }}
- disabled={checkedFolderList?.length >= num || !!active || active === 0}
- indeterminate={indeterminateFolder}
- checked={checkFolderAll}
- >全选</Checkbox>
- <span>已选 <span style={{ color: '#1890FF' }}>{checkedFolderList?.length || 0}</span>/{num} 个素材</span>
- {checkedFolderList.length > 0 && <a style={{ color: 'red' }} onClick={() => setCheckedFolderList([])}>清除所有</a>}
- {/* 同步素材 */}
- <SyncCloudSc
- accountId={unitAccountId}
- />
- </div>
- <div className={style.left_bts}>
- </div>
- </div>
- <div className={`${style.content} content_global`}>
- <Spin spinning={getCreativeComponentList.loading}>
- <div className={`${style.content_scroll} scroll`} ref={refScllor}>
- {getCreativeComponentList?.data?.records?.length > 0 ? <Checkbox.Group value={checkedFolderList?.filter((_, index) => (active || active === 0) ? index === active : true)?.map(item => item.id)} style={{ width: '100%' }}>
- <div className={style.content_scroll_div}>
- {getCreativeComponentList?.data?.records.map((item: any) => {
- let id = item.componentId
- const componentSubType = item.componentSubType
- const type = getComponentType(componentSubType)
- const isSelect = checkedFolderList?.filter((_, index) => (active || active === 0) ? index === active : true)?.map(item => item.id).includes(id)
- const disabled = ((active || active === 0) ? false : (checkedFolderList.length >= num && !isSelect)) || item?.status !== '正常'
- const imageListLength = item?.componentValue?.imageList?.value?.list?.length || 0
- return <div key={id} className={style.content_row} style={{ width: rowNum ? (1 / rowNum * 100) + '%' : 220 }}>
- <Card
- hoverable
- bodyStyle={{ padding: 0 }}
- style={{ cursor: disabled ? 'not-allowed' : 'pointer' }}
- className={`${style.content_col}`}
- cover={<div style={{ height: 120, padding: 0 }} className={style.content_cover}>
- <div className={style.checkbox}><Checkbox disabled={disabled} value={id} onChange={(e) => onCheckboxChange(e.target.checked, item, type)} /></div>
- {defaultParams.materialType === 'video' ? <div className={style.playr}>
- <PlayVideo videoUrl={item?.componentValue?.video?.value?.videoUrl || item?.componentValue?.shortVideo?.value?.shortVideo1Url}>{(onPlay) => <img onClick={(e) => {
- e.stopPropagation(); e.preventDefault()
- onPlay()
- }} src={require('../../../../../public/image/play.png')} alt="" />}</PlayVideo>
- </div> : <div className={style.imgPreview} onClick={(e) => {
- e.stopPropagation()
- setPreviewData({
- visible: true,
- url: item?.componentValue?.image?.value?.imageUrl ? [item?.componentValue?.image?.value?.imageUrl] : item?.componentValue?.imageList?.value?.list?.map((i: { imageUrl: any }) => i.imageUrl)
- })
- }}>
- <Space><EyeOutlined /><span>预览</span></Space>
- </div>}
- <div className={style.file_info}>
- <span></span>
- <div>{COMPONENT_SUB_TYPE?.find(item => item.value === componentSubType)?.label || '--'}</div>
- </div>
- {type === 'IMAGE' ? <Lazyimg
- animateType="transition"
- src={item?.componentValue?.image?.value?.imageUrl}
- className={`${style.coverImg} lazy`}
- animateClassName={['transition-enter', 'transition-enter-active']}
- /> : type === 'IMAGE_LIST' ? <div className={style.mediaPic_select}>
- <div className={`${style.mediaPicImgList} ${style['mediaPicImgList' + imageListLength]}`}>
- {item?.componentValue?.imageList?.value?.list?.map((item: { componentValue: { imageList: { value: { list: string | any[] } } }; imageId: string; imageUrl: string }, _: any, records: any[]) => <Lazyimg
- key={item.imageId}
- animateType="transition"
- src={item.imageUrl}
- className={`lazy`}
- animateClassName={['transition-enter', 'transition-enter-active']}
- />)}
- </div>
- </div> : type === 'VIDEO' ? <Lazyimg
- animateType="transition"
- src={item?.componentValue?.video?.value?.coverUrl || item?.componentValue?.shortVideo?.value?.shortVideo2Url}
- className={`${style.coverImg} lazy`}
- animateClassName={['transition-enter', 'transition-enter-active']}
- /> : '联系技术添加'}
- </div>}
- onClick={() => !disabled && onCheckboxChange(!isSelect, item, type)}
- >
- <div className={style.body}>
- <Text ellipsis strong style={{ flex: '1 0', color: item?.status !== '正常' ? 'red' : 'rgba(0, 0, 0, 0.85)' }}>{item?.status !== '正常' ? item?.status : item?.componentCustomName}</Text>
- </div>
- <Divider style={{ margin: '0 0 4px 0' }} />
- <div style={{ padding: '0 10px 6px' }}>
- <Paragraph style={{ fontSize: 12, marginBottom: 1 }}>创建时间:{moment.unix(item?.createdTime).format('YYYY-MM-DD')}</Paragraph>
- <Paragraph style={{ fontSize: 12, marginBottom: 1 }}>组件ID:{item?.componentId}</Paragraph>
- <Paragraph style={{ fontSize: 12, marginBottom: 1 }}>来源:{COMPONENT_GENERATION_TYPE_ENUM['COMPONENT_GENERATION_TYPE_' + item.generationType as keyof typeof COMPONENT_GENERATION_TYPE_ENUM] || '--'}</Paragraph>
- </div>
- </Card>
- </div>
- })}
- </div>
- </Checkbox.Group> : <div style={{ height: '100%', width: '100%', alignContent: 'center' }}><Empty image={Empty.PRESENTED_IMAGE_SIMPLE} /></div>}
- </div>
- </Spin>
- </div>
- <div className={style.fotter}>
- <Pagination
- size="small"
- total={getCreativeComponentList?.data?.total || 0}
- showSizeChanger
- showQuickJumper
- pageSize={getCreativeComponentList?.data?.size || 20}
- current={getCreativeComponentList?.data?.current || 1}
- onChange={(page: number, pageSize: number) => {
- refScllor.current?.scrollTo(0, 0)
- setQueryParams({ ...queryParams, pageNum: page, pageSize })
- }}
- pageSizeOptions={[10, 15, 20, 50, 100]}
- />
- </div>
- </div>
- </div>
- </Card>
- </> : checkAccountUnit?.data ? <div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100%' }}>
- <Result
- title="警告"
- status="500"
- subTitle="选择的账户不在一个业务单元中或者没有加入业务单元"
- />
- </div> : undefined}
- </div>
- {/* 预览 */}
- {previewData.visible && <Image.PreviewGroup preview={{ visible: previewData.visible, onVisibleChange: vis => setPreviewData({ visible: vis, url: [] }) }}>
- {previewData?.url?.map((url: string, index: number) => <Image src={url} key={index} />)}
- </Image.PreviewGroup>}
- </Spin>
- }
- export default React.memo(SelectComponentsUnit)
|