|
@@ -15,6 +15,7 @@ import UploadsTable from "./uploadsTable"
|
|
|
import { DeleteOutlined, PlayCircleOutlined, SortAscendingOutlined } from "@ant-design/icons"
|
|
|
import PlayVideo from "./playVideo"
|
|
|
import { showFieldList } from "./const"
|
|
|
+import SelectFolder from "./selectFolder"
|
|
|
|
|
|
|
|
|
const { Text, Paragraph } = Typography;
|
|
@@ -117,7 +118,7 @@ const SelectCloudNew: React.FC<CLOUDNEW.SelectCloudNewProps> = ({ visible, defau
|
|
|
</Space>}
|
|
|
open={visible}
|
|
|
onCancel={onClose}
|
|
|
- width={1200}
|
|
|
+ width={1400}
|
|
|
footer={<div className={style.divFooter}>
|
|
|
{checkedFolderList.length > 0 ? <>
|
|
|
<div className={style.selectedCloud}>
|
|
@@ -153,177 +154,181 @@ const SelectCloudNew: React.FC<CLOUDNEW.SelectCloudNewProps> = ({ visible, defau
|
|
|
className="cardResetCss buttonResetCss"
|
|
|
bordered
|
|
|
>
|
|
|
- <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[] = getMaterialDataList?.data?.records
|
|
|
+ <div className={style.cloudNew}>
|
|
|
+ {/* 选择文件夹 */}
|
|
|
+ <SelectFolder selectedKeys={queryParams?.folderId} onChange={(value) => { setQueryParams({ ...queryParams, folderId: value }) }} />
|
|
|
+ <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[] = 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(...data)
|
|
|
- } else {
|
|
|
- newCheckedFolderList.push(...remainData.splice(0, remainNum))
|
|
|
+ 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(...data)
|
|
|
+ } else {
|
|
|
+ newCheckedFolderList.push(...remainData.splice(0, remainNum))
|
|
|
+ }
|
|
|
+ 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))
|
|
|
}
|
|
|
- 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}
|
|
|
- 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>}
|
|
|
- <Text>「排序-{showFieldList.find(item => item.value === sortData.sortField)?.label}-{sortData.sortType ? '正序' : '倒序'}」</Text>
|
|
|
- </div>
|
|
|
- <div className={style.left_bts}>
|
|
|
- <Popover
|
|
|
- content={<div style={{ width: 320 }}>
|
|
|
- <Form
|
|
|
- labelCol={{ span: 5 }}
|
|
|
- labelAlign="left"
|
|
|
- colon={false}
|
|
|
- >
|
|
|
- <Form.Item label={<strong>展示指标</strong>}>
|
|
|
- <Select
|
|
|
- placeholder="选择展示指标"
|
|
|
- showSearch
|
|
|
- filterOption={(input, option) =>
|
|
|
- (option?.label as any)?.toLowerCase().indexOf(input.toLowerCase()) >= 0
|
|
|
- }
|
|
|
- mode="multiple"
|
|
|
- options={showFieldList}
|
|
|
- value={showField}
|
|
|
- onChange={(value) => {
|
|
|
- if (value.length > 6) {
|
|
|
- message.warn('最多只能选择6个指标')
|
|
|
- return
|
|
|
- }
|
|
|
- if (value.length < 1) {
|
|
|
- message.warn('最少选择1个指标')
|
|
|
- return
|
|
|
- }
|
|
|
- setShowField(value as any)
|
|
|
- }}
|
|
|
- />
|
|
|
- </Form.Item>
|
|
|
- <Form.Item label={<strong>排序</strong>}>
|
|
|
- <Space>
|
|
|
+ setCheckedFolderList(newCheckedFolderList)
|
|
|
+ }}
|
|
|
+ disabled={checkedFolderList?.length >= num}
|
|
|
+ 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>}
|
|
|
+ <Text>「排序-{showFieldList.find(item => item.value === sortData.sortField)?.label}-{sortData.sortType ? '正序' : '倒序'}」</Text>
|
|
|
+ </div>
|
|
|
+ <div className={style.left_bts}>
|
|
|
+ <Popover
|
|
|
+ content={<div style={{ width: 320 }}>
|
|
|
+ <Form
|
|
|
+ labelCol={{ span: 5 }}
|
|
|
+ labelAlign="left"
|
|
|
+ colon={false}
|
|
|
+ >
|
|
|
+ <Form.Item label={<strong>展示指标</strong>}>
|
|
|
<Select
|
|
|
- style={{ width: 125 }}
|
|
|
- placeholder="选择排序指标"
|
|
|
+ placeholder="选择展示指标"
|
|
|
showSearch
|
|
|
filterOption={(input, option) =>
|
|
|
(option?.label as any)?.toLowerCase().indexOf(input.toLowerCase()) >= 0
|
|
|
}
|
|
|
+ mode="multiple"
|
|
|
options={showFieldList}
|
|
|
- value={sortData.sortField}
|
|
|
+ value={showField}
|
|
|
onChange={(value) => {
|
|
|
- setSortData({ ...sortData, sortField: value as any })
|
|
|
+ if (value.length > 6) {
|
|
|
+ message.warn('最多只能选择6个指标')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if (value.length < 1) {
|
|
|
+ message.warn('最少选择1个指标')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ setShowField(value as any)
|
|
|
}}
|
|
|
/>
|
|
|
- <Radio.Group value={sortData.sortType} onChange={(e) => setSortData({ ...sortData, sortType: e.target.value })} buttonStyle="solid">
|
|
|
- <Radio.Button value={true}>正序</Radio.Button>
|
|
|
- <Radio.Button value={false}>倒序</Radio.Button>
|
|
|
- </Radio.Group>
|
|
|
- </Space>
|
|
|
- </Form.Item>
|
|
|
- </Form>
|
|
|
- </div>}
|
|
|
- trigger={['click']}
|
|
|
- title={<strong>自定义展示指标与排序</strong>}
|
|
|
- placement="bottomRight"
|
|
|
- >
|
|
|
- <Button icon={<SortAscendingOutlined />}>自定义展示指标与排序</Button>
|
|
|
- </Popover>
|
|
|
+ </Form.Item>
|
|
|
+ <Form.Item label={<strong>排序</strong>}>
|
|
|
+ <Space>
|
|
|
+ <Select
|
|
|
+ style={{ width: 125 }}
|
|
|
+ placeholder="选择排序指标"
|
|
|
+ showSearch
|
|
|
+ filterOption={(input, option) =>
|
|
|
+ (option?.label as any)?.toLowerCase().indexOf(input.toLowerCase()) >= 0
|
|
|
+ }
|
|
|
+ options={showFieldList}
|
|
|
+ value={sortData.sortField}
|
|
|
+ onChange={(value) => {
|
|
|
+ setSortData({ ...sortData, sortField: value as any })
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ <Radio.Group value={sortData.sortType} onChange={(e) => setSortData({ ...sortData, sortType: e.target.value })} buttonStyle="solid">
|
|
|
+ <Radio.Button value={true}>正序</Radio.Button>
|
|
|
+ <Radio.Button value={false}>倒序</Radio.Button>
|
|
|
+ </Radio.Group>
|
|
|
+ </Space>
|
|
|
+ </Form.Item>
|
|
|
+ </Form>
|
|
|
+ </div>}
|
|
|
+ trigger={['click']}
|
|
|
+ title={<strong>自定义展示指标与排序</strong>}
|
|
|
+ placement="bottomRight"
|
|
|
+ >
|
|
|
+ <Button icon={<SortAscendingOutlined />}>自定义展示指标与排序</Button>
|
|
|
+ </Popover>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
- </div>
|
|
|
- <div className={`${style.content} content_global`}>
|
|
|
- <Spin spinning={getMaterialDataList.loading}>
|
|
|
- <div className={style.content_scroll} ref={ref} {...dropAreaProps}>
|
|
|
- {isDragOver && <div className={`${style.placeholder} ${isDragOver ? style.dragOver : ''}`}><span>拖动文件到这里</span></div>}
|
|
|
- {getMaterialDataList?.data?.records?.length > 0 ? <Checkbox.Group value={checkedFolderList?.map(item => item.id)} style={{ width: '100%' }}>
|
|
|
- <div className={style.content_scroll_div}>
|
|
|
- {getMaterialDataList?.data?.records.map((item: any) => {
|
|
|
- const isSelect = checkedFolderList?.map(item => item.id).includes(item.id)
|
|
|
- const disabled = checkedFolderList.length >= num && !isSelect
|
|
|
- return <div key={item.id} className={style.content_row} style={{ width: rowNum ? (1 / rowNum * 100) + '%' : 200 }}>
|
|
|
- <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={item.id} onChange={(e) => onCheckboxChange(e.target.checked, item)} /></div>
|
|
|
- {item.material_type === 'video' && <div className={style.playr}>
|
|
|
- <PlayVideo videoUrl={item.oss_url}>{(onPlay) => <img onClick={(e) => {
|
|
|
- e.stopPropagation(); e.preventDefault()
|
|
|
- onPlay()
|
|
|
- }} src={require('../../../../../public/image/play.png')} alt="" />}</PlayVideo>
|
|
|
+ <div className={`${style.content} content_global`}>
|
|
|
+ <Spin spinning={getMaterialDataList.loading}>
|
|
|
+ <div className={style.content_scroll} ref={ref} {...dropAreaProps}>
|
|
|
+ {isDragOver && <div className={`${style.placeholder} ${isDragOver ? style.dragOver : ''}`}><span>拖动文件到这里</span></div>}
|
|
|
+ {getMaterialDataList?.data?.records?.length > 0 ? <Checkbox.Group value={checkedFolderList?.map(item => item.id)} style={{ width: '100%' }}>
|
|
|
+ <div className={style.content_scroll_div}>
|
|
|
+ {getMaterialDataList?.data?.records.map((item: any) => {
|
|
|
+ const isSelect = checkedFolderList?.map(item => item.id).includes(item.id)
|
|
|
+ const disabled = checkedFolderList.length >= num && !isSelect
|
|
|
+ return <div key={item.id} className={style.content_row} style={{ width: rowNum ? (1 / rowNum * 100) + '%' : 200 }}>
|
|
|
+ <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={item.id} onChange={(e) => onCheckboxChange(e.target.checked, item)} /></div>
|
|
|
+ {item.material_type === 'video' && <div className={style.playr}>
|
|
|
+ <PlayVideo videoUrl={item.oss_url}>{(onPlay) => <img onClick={(e) => {
|
|
|
+ e.stopPropagation(); e.preventDefault()
|
|
|
+ onPlay()
|
|
|
+ }} src={require('../../../../../public/image/play.png')} alt="" />}</PlayVideo>
|
|
|
+ </div>}
|
|
|
+ <div className={style.file_info}>
|
|
|
+ <div>{item.width}*{item.height}</div>
|
|
|
+ {item.material_type === 'video' && <div>{formatSecondsToTime(Math.floor(item.video_duration))}</div>}
|
|
|
+ </div>
|
|
|
+ <img src={item.material_type === 'image' ? item.oss_url : getVideoImgUrl(item.oss_url)} className={style.coverImg} alt="" />
|
|
|
</div>}
|
|
|
- <div className={style.file_info}>
|
|
|
- <div>{item.width}*{item.height}</div>
|
|
|
- {item.material_type === 'video' && <div>{formatSecondsToTime(Math.floor(item.video_duration))}</div>}
|
|
|
+ onClick={() => !disabled && onCheckboxChange(!isSelect, item)}
|
|
|
+ >
|
|
|
+ <div className={style.body}>
|
|
|
+ <Text ellipsis strong style={{ flex: '1 0' }}>{item?.material_name}</Text>
|
|
|
+ <Text style={{ fontSize: 12 }}>{formatBytes(item?.file_size)}</Text>
|
|
|
</div>
|
|
|
- <img src={item.material_type === 'image' ? item.oss_url : getVideoImgUrl(item.oss_url)} className={style.coverImg} alt="" />
|
|
|
- </div>}
|
|
|
- onClick={() => !disabled && onCheckboxChange(!isSelect, item)}
|
|
|
- >
|
|
|
- <div className={style.body}>
|
|
|
- <Text ellipsis strong style={{ flex: '1 0' }}>{item?.material_name}</Text>
|
|
|
- <Text style={{ fontSize: 12 }}>{formatBytes(item?.file_size)}</Text>
|
|
|
- </div>
|
|
|
- <Divider style={{ margin: '0 0 4px 0' }} />
|
|
|
- <div style={{ padding: '0 10px 6px' }}>
|
|
|
- {showField.map(field => {
|
|
|
- switch (field) {
|
|
|
- case 'material.create_time':
|
|
|
- return <Paragraph key={field} style={{ fontSize: 12, marginBottom: 1 }}>创建时间:{item?.create_time}</Paragraph>
|
|
|
- case 'material_data_day.cost':
|
|
|
- return <Paragraph key={field} style={{ fontSize: 12, marginBottom: 1 }}>消耗:{(item?.cost === null || item?.cost === undefined) ? '--' : item?.cost}</Paragraph>
|
|
|
- case 'material_data_day.ctr':
|
|
|
- return <Paragraph key={field} style={{ fontSize: 12, marginBottom: 1 }}>点击率:{(item?.ctr === null || item?.ctr === undefined) ? '--' : item?.ctr * 100 + '%'}</Paragraph>
|
|
|
- case 'material_data_day.conversions_rate':
|
|
|
- return <Paragraph key={field} style={{ fontSize: 12, marginBottom: 1 }}>目标转化率:{(item?.conversions_rate === null || item?.conversions_rate === undefined) ? '--' : item?.conversions_rate * 100 + '%'}</Paragraph>
|
|
|
- case 'material_data_day.adgroup_count':
|
|
|
- return <Paragraph key={field} style={{ fontSize: 12, marginBottom: 1 }}>广告关联数:{(item?.adgroup_count === null || item?.adgroup_count === undefined) ? '--' : item?.adgroup_count}</Paragraph>
|
|
|
- case 'material_data_day.dynamic_creative_count':
|
|
|
- return <Paragraph key={field} style={{ fontSize: 12, marginBottom: 1 }}>创意关联数:{(item?.dynamic_creative_count === null || item?.dynamic_creative_count === undefined) ? '--' : item?.dynamic_creative_count}</Paragraph>
|
|
|
- default:
|
|
|
- return null
|
|
|
- }
|
|
|
- })}
|
|
|
- </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={getMaterialDataList?.data?.total || 0}
|
|
|
- showSizeChanger
|
|
|
- showQuickJumper
|
|
|
- pageSize={getMaterialDataList?.data?.size || 20}
|
|
|
- current={getMaterialDataList?.data?.current || 1}
|
|
|
- onChange={(page: number, pageSize: number) => {
|
|
|
- setQueryParams({ ...queryParams, pageNum: page, pageSize })
|
|
|
- }}
|
|
|
- />
|
|
|
+ <Divider style={{ margin: '0 0 4px 0' }} />
|
|
|
+ <div style={{ padding: '0 10px 6px' }}>
|
|
|
+ {showField.map(field => {
|
|
|
+ switch (field) {
|
|
|
+ case 'material.create_time':
|
|
|
+ return <Paragraph key={field} style={{ fontSize: 12, marginBottom: 1 }}>创建时间:{item?.create_time}</Paragraph>
|
|
|
+ case 'material_data_day.cost':
|
|
|
+ return <Paragraph key={field} style={{ fontSize: 12, marginBottom: 1 }}>消耗:{(item?.cost === null || item?.cost === undefined) ? '--' : item?.cost}</Paragraph>
|
|
|
+ case 'material_data_day.ctr':
|
|
|
+ return <Paragraph key={field} style={{ fontSize: 12, marginBottom: 1 }}>点击率:{(item?.ctr === null || item?.ctr === undefined) ? '--' : (item?.ctr * 100).toFixed(2) + '%'}</Paragraph>
|
|
|
+ case 'material_data_day.conversions_rate':
|
|
|
+ return <Paragraph key={field} style={{ fontSize: 12, marginBottom: 1 }}>目标转化率:{(item?.conversions_rate === null || item?.conversions_rate === undefined) ? '--' : (item?.conversions_rate * 100).toFixed(2) + '%'}</Paragraph>
|
|
|
+ case 'material_data_day.adgroup_count':
|
|
|
+ return <Paragraph key={field} style={{ fontSize: 12, marginBottom: 1 }}>广告关联数:{(item?.adgroup_count === null || item?.adgroup_count === undefined) ? '--' : item?.adgroup_count}</Paragraph>
|
|
|
+ case 'material_data_day.dynamic_creative_count':
|
|
|
+ return <Paragraph key={field} style={{ fontSize: 12, marginBottom: 1 }}>创意关联数:{(item?.dynamic_creative_count === null || item?.dynamic_creative_count === undefined) ? '--' : item?.dynamic_creative_count}</Paragraph>
|
|
|
+ default:
|
|
|
+ return null
|
|
|
+ }
|
|
|
+ })}
|
|
|
+ </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={getMaterialDataList?.data?.total || 0}
|
|
|
+ showSizeChanger
|
|
|
+ showQuickJumper
|
|
|
+ pageSize={getMaterialDataList?.data?.size || 20}
|
|
|
+ current={getMaterialDataList?.data?.current || 1}
|
|
|
+ onChange={(page: number, pageSize: number) => {
|
|
|
+ setQueryParams({ ...queryParams, pageNum: page, pageSize })
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</Card>
|