123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403 |
- import { useAjax } from '@/Hook/useAjax'
- import { Col, Row, message, Space, Button, Table, Statistic } from 'antd'
- import React, { useEffect, useCallback, useState, useRef } from 'react'
- import { getPutUserApi, delUserTagApi } from '@/services/launchAdq/adq'
- import { LineChartOutlined, PauseCircleOutlined, PlayCircleOutlined, TransactionOutlined } from '@ant-design/icons'
- import { planAdConfig } from './config'
- import '../../launchSystemNew/adq/ad/index.less'
- import tablePlanConfig from './tablePlanListConfig'
- import { AdListProps, getAdV3ListApi } from '@/services/adMonitor/adMonitor'
- import FilterQuery from './FilterQuery'
- import AdExpandedRowRender from './adExpandedRowRender'
- import { useSize, useUpdateEffect } from 'ahooks'
- import PlanTag from '../../launchSystemNew/adq/ad/planTag'
- import moment from 'moment'
- import ColumnTrend from '@/pages/adMonitor/adMonitorList/columnTrend'
- import TableData from '../../launchSystemNew/components/TableData'
- import RuleAccountLog from '@/components/EarlyWarning/ruleAccountLog'
- import Details from './Details'
- import { modifyStatusBatchApi, syncBatchApi } from '@/services/launchAdq/adqv3'
- import UpdateAd from '../adqv3/ad/updateAd'
- const AdPlanList: React.FC<{ userId: string }> = (props) => {
- /***********************/
- const { userId } = props
- const [selectedRows, setSelectedRows] = useState<any[]>([])
- const [detailShow, setDetailShow] = useState<boolean>(false)
- const [detailData, setDetailData] = useState<any>({})
- const [update, setUpdate] = useState<{ visible: boolean }>({ visible: false })
- const [queryForm, setQueryForm] = useState<AdListProps>({ pageNum: 1, pageSize: 20, columns: [], isDeleted: false, dataTimeMin: moment().subtract(7, 'days').format('YYYY-MM-DD'), dataTimeMax: moment().format('YYYY-MM-DD') })
- const [filterForm, setFilterForm] = useState<AdListProps>()
- const getAdList = useAjax((params) => getAdV3ListApi(params), { formatResult: true })
- const getPutUser = useAjax((params) => getPutUserApi(params))
- const delUserTag = useAjax((params) => delUserTagApi(params))
- const [logVisible, setLogVisible] = useState<boolean>(false)
- const [adgroupId, setAdgroupId] = useState<string>('')
- const [adgroupName, setAdgroupName] = useState<string>('')
- const [accountIdRule, setAccountIdRule] = useState<string>('')
- const [tagVisible, setTagVisible] = useState<boolean>(false)
- const [tagData, setTagData] = useState<any>({})
- const configName = '广告列表3.0'
- const ref = useRef(null)
- const size = useSize(ref)
- const [scrollLeft, setScrollLeft] = useState<number>(0)
- const [totalData, setTotalData] = useState<any>({})
- const [tableField, setTableField] = useState<{ title: string, dataIndex: string }[]>([])
- const [trendVisible, setTrendVisible] = useState<boolean>(false)
- const [trendData, setTrendData] = useState<any>({})
- const syncBatch = useAjax((params) => syncBatchApi(params))
- const modifyStatusBatch = useAjax((params) => modifyStatusBatchApi(params))
- /************************/
- useEffect(() => {
- getList()
- }, [filterForm, queryForm])
- const getList = () => {
- let message = localStorage.getItem(`myAdMonitorConfig1.0.1_${configName}`)
- if (message) {
- message = JSON.parse(message)
- }
- let columns: string[] = []
- if (message && Array.isArray(message)) {
- message.forEach((item: { serverIndex: any; dataIndex: string; }) => {
- if (!['cz', 'cost_speed'].includes(item.dataIndex)) {
- columns.push(item?.serverIndex || 'adgroup_data.' + item.dataIndex)
- }
- })
- } else {
- planAdConfig.forEach((item: any) => {
- item?.data?.forEach((d: { default: any, serverIndex: string, dataIndex: string }) => {
- if (d.default && !['cz', 'cost_speed'].includes(d.dataIndex)) {
- columns.push(d?.serverIndex || 'adgroup_data.' + d.dataIndex)
- }
- })
- })
- }
- getAdList.run({ ...queryForm, ...filterForm, columns })
- }
- useUpdateEffect(() => {
- let data: any = {}
- if (getAdList.data?.data?.sumRecord) {
- data = getAdList.data?.data?.sumRecord
- }
- setTotalData(data)
- }, [getAdList.data])
- useEffect(() => {
- let localData = localStorage.getItem('myAdMonitorConfig1.0.1_广告列表3.0')
- let data: any[] = []
- if (localData) {
- data = JSON.parse(localData)
- } else {
- let newSelectData: any[] = [];
- (planAdConfig as any).forEach((item: { data: { default: any }[] }) => {
- item?.data?.forEach((d: { default: any }) => {
- if (d.default) {
- newSelectData[d.default - 1] = d
- }
- })
- })
- data = newSelectData
- }
- data.unshift({ title: '选择框', dataIndex: 'xzk' })
- data.unshift({ title: '总计', dataIndex: 'zj' })
- setTableField(data)
- }, [localStorage.getItem('myAdMonitorConfig1.0.1_广告列表3.0')])
- useEffect(() => {
- getPutUser.run({ userId })
- }, [userId])
- // 同步
- const sync = useCallback(() => {
- if (selectedRows?.length > 0) {
- let accountAdgroupMaps = [...new Set(selectedRows?.map(item => item.account_id + ',' + item.adgroup_id))]
- syncBatch.run({ accountAdgroupMaps }).then(res => {
- res && getAdList.refresh()
- res ? message.success('同步成功!') : message.error('同步失败!')
- })
- } else {
- message.error('请勾选')
- }
- }, [getAdList, selectedRows])
- // 单个启停
- const onChange = () => {
- getAdList.refresh()
- setSelectedRows([])
- }
- const details = (data: any) => {
- setDetailData(data)
- setDetailShow(true)
- }
- useEffect(() => {
- const headerBodyScroll = (e: any) => {
- let el = document.querySelector(`.expandClassname .expendTable .ant-table-body`);
- if (el) {
- setScrollLeft(e.target.scrollLeft)
- }
- }
- document.querySelector(`.expandClassname .expendTable .ant-table-body`)?.addEventListener('scroll', headerBodyScroll);
- () => {
- document.querySelector(`.expandClassname .expendTable .ant-table-body`)?.removeEventListener('scroll', headerBodyScroll);
- }
- }, [])
- const log = (value: any) => {
- setAccountIdRule(value.account_id)
- setAdgroupId(value.adgroup_id)
- setAdgroupName(value.adgroup_name)
- setLogVisible(true)
- }
- const handleTag = (value: any) => {
- setTagData(value)
- setTagVisible(true)
- }
- const delTag = (value: any) => {
- delUserTag.run({ accountId: value.account_id, adgroupId: value.adgroup_id }).then(res => {
- if (res) {
- message.success('删除成功')
- getAdList.refresh()
- }
- })
- }
- const handleColumnTrend = (value: string) => {
- let message = localStorage.getItem(`myAdMonitorConfig1.0.1_${configName}`)
- if (message) {
- message = JSON.parse(message)
- }
- let columns: string[] = []
- if (message && Array.isArray(message)) {
- message.forEach((item: { serverIndex: any; dataIndex: string; }) => {
- if (!['cz', 'cost_speed'].includes(item.dataIndex)) {
- columns.push(item?.serverIndex || 'adgroup_data.' + item.dataIndex)
- }
- })
- } else {
- planAdConfig.forEach((item: any) => {
- item?.data?.forEach((d: { default: any, serverIndex: string, dataIndex: string }) => {
- if (d.default && !['cz', 'cost_speed'].includes(d.dataIndex)) {
- columns.push(d?.serverIndex || 'adgroup_data.' + d.dataIndex)
- }
- })
- })
- }
- setTrendData({ ...queryForm, ...filterForm, columns, field: value.replace('_total', '') })
- setTrendVisible(true)
- }
- // 批量启停
- const adStatus = (type: boolean) => {
- let newSelectedRows = []
- if (type) {
- newSelectedRows = selectedRows.filter((item: { configuredStatus: string, adgroupId: number }) => item.configuredStatus === 'AD_STATUS_SUSPEND')
- } else {
- newSelectedRows = selectedRows.filter((item: { configuredStatus: string, adgroupId: number }) => item.configuredStatus === 'AD_STATUS_NORMAL')
- }
- if (newSelectedRows.length === 0) {
- message.warn(`所有广告都是${type ? '启动' : '暂停'}状态,无需${type ? '启动' : '暂停'}操作`)
- return
- }
- let accountAdgroupMaps = [...new Set(newSelectedRows?.map(item => item.accountId + ',' + item.adgroupId))]
- modifyStatusBatch.run({ accountAdgroupMaps, suspend: !type }).then(res => {
- message.success(`${type ? '启动' : '暂停'}成功`)
- getAdList.refresh()
- setSelectedRows([])
- })
- }
- const countDecimals = (num: number) => {
- // 匹配数字的小数部分
- const match = String(num).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/);
- // 返回小数位数
- return match ? Math.max(0, (match[1] ? match[1].length : 0) - (match[2] ? +match[2] : 0)) : 0;
- }
- return <div>
- {/* 列表指标趋势 */}
- {trendVisible && <ColumnTrend visible={trendVisible} data={trendData} onClose={() => { setTrendVisible(false) }} />}
- {/* 打标签 */}
- {tagVisible && <PlanTag
- visible={tagVisible}
- data={tagData}
- onClose={() => setTagVisible(false)}
- onChange={() => {
- getAdList.refresh()
- setTagVisible(false)
- }}
- />}
- <Row gutter={[6, 6]} align='middle' style={{ marginBottom: 10 }}>
- <FilterQuery
- queryForm={queryForm}
- setQueryForm={setQueryForm}
- onChange={(value) => {
- setFilterForm({ ...value })
- }}
- />
- </Row>
- <div ref={ref} className='expandClassname'>
- <TableData
- refreshData={getList}
- isCard={false}
- className='expendTable'
- columns={() => tablePlanConfig(onChange, details, log, handleTag, delTag)}
- ajax={getAdList}
- syncAjax={sync}
- fixed={{ left: 2, right: 4 }}
- dataSource={getAdList?.data?.data?.records}
- loading={getAdList?.loading || syncBatch?.loading}
- scroll={{ y: 560 }}
- total={getAdList?.data?.data?.total}
- page={getAdList?.data?.data?.current}
- pageSize={getAdList?.data?.data?.size}
- myKey={'adgroup_id'}
- gutter={[0, 10]}
- config={planAdConfig}
- configName={configName}
- rowClassName={(record) => {
- if (record?.tag_value === 100) {
- return 'row_error'
- } else if (record?.tag_value === 90) {
- return 'row_warning'
- } else {
- return ''
- }
- }}
- leftChild={<Space direction='vertical'>
- <Row gutter={[10, 10]} align='middle'>
- <Col><Button type='primary' style={{ background: '#67c23a', borderColor: '#67c23a' }} loading={modifyStatusBatch.loading} icon={<PlayCircleOutlined />} disabled={selectedRows.length === 0} onClick={() => adStatus(true)}>启动</Button></Col>
- <Col><Button type='primary' style={{ background: '#e6a23c', borderColor: '#e6a23c' }} loading={modifyStatusBatch.loading} icon={<PauseCircleOutlined />} disabled={selectedRows.length === 0} onClick={() => adStatus(false)}>暂停</Button></Col>
- <Col><Button type='primary' icon={<TransactionOutlined />} disabled={selectedRows.length === 0} onClick={() => setUpdate({ visible: true })}>修改出价</Button></Col>
- </Row>
- </Space>}
- rowSelection={{
- selectedRowKeys: selectedRows.map(item => item.adgroup_id.toString()),
- getCheckboxProps: (record: any) => ({
- disabled: record.status === 'STATUS_DELETED'
- }),
- onSelect: (record: { adgroup_id: number, mpName: string }, selected: boolean) => {
- if (selected) {
- selectedRows.push({ ...record })
- setSelectedRows([...selectedRows])
- } else {
- let newSelectAccData = selectedRows.filter((item: { adgroup_id: number }) => item.adgroup_id !== record.adgroup_id)
- setSelectedRows([...newSelectAccData])
- }
- },
- onSelectAll: (selected: boolean, selectedRowss: { adgroup_id: number }[], changeRows: { adgroup_id: number }[]) => {
- if (selected) {
- let newSelectAccData = [...selectedRows]
- changeRows.forEach((item: { adgroup_id: number }) => {
- let index = newSelectAccData.findIndex((ite: { adgroup_id: number }) => ite.adgroup_id === item.adgroup_id)
- if (index === -1) {
- newSelectAccData.push({ ...item })
- }
- })
- setSelectedRows([...newSelectAccData])
- } else {
- let newSelectAccData = selectedRows.filter((item: { adgroup_id: number }) => {
- let index = changeRows.findIndex((ite: { adgroup_id: number }) => ite.adgroup_id === item.adgroup_id)
- if (index !== -1) {
- return false
- } else {
- return true
- }
- })
- setSelectedRows([...newSelectAccData])
- }
- }
- }}
- onChange={(props: any) => {
- let { sortData, pagination } = props
- let { current, pageSize } = pagination
- let newQueryForm = JSON.parse(JSON.stringify(queryForm))
- newQueryForm.pageNum = current
- newQueryForm.pageSize = pageSize
- if (sortData && JSON.stringify('sortData') !== '{}') {
- let { field, order } = sortData // descend 降序 大到小 ascend 升序 小到大
- if (order) {
- newQueryForm.sortColumn = field
- newQueryForm.sortAsc = order === 'ascend'
- } else {
- Object.keys(newQueryForm).forEach(key => {
- if (key === 'sortColumn' || key === 'sortAsc') {
- delete newQueryForm[key]
- }
- })
- }
- } else {
- Object.keys(newQueryForm).forEach(key => {
- if (key === 'sortField' || key === 'sort') {
- delete newQueryForm[key]
- }
- })
- }
- setQueryForm({ ...newQueryForm })
- }}
- expandedRowRender={(data) => <AdExpandedRowRender data={data} scrollLeft={scrollLeft} width={size?.width} />}
- summary={() => (
- <Table.Summary fixed>
- <Table.Summary.Row className='s_summary'>
- {tableField.map((item, index) => {
- let data = totalData[item.dataIndex]
- let value = (data === 0 || data) ? countDecimals(data) > 2 ? data.toFixed(2) : data : '--'
- if (item.dataIndex === 'zj') {
- return <Table.Summary.Cell index={index} key={item.dataIndex} align="center"><strong>总计</strong></Table.Summary.Cell>
- } else if (['ctr_total', 'mp_follow_rate_total',
- 'add_quick_app_rate_total', 'scan_follow_rate_total',
- 'first_day_order_roi_total', 'order_rate_total',
- 'order_roi_total', 'conversions_rate_total'
- ].includes(item.dataIndex)) {
- return <Table.Summary.Cell index={index} key={item.dataIndex} align="center">
- <Space size={4}>
- <strong>
- {value !== '--' ? <Statistic value={value ? value * 100 : 0} precision={2} valueStyle={{ color: '#3f8600' }} suffix="%" /> : '--'}
- </strong>
- {value !== '--' && <a onClick={() => handleColumnTrend(item.dataIndex)}><LineChartOutlined /></a>}
- </Space>
- </Table.Summary.Cell>
- } else {
- return <Table.Summary.Cell index={index} key={item.dataIndex} align="center">
- <Space size={4}>
- <strong><Statistic value={value} /></strong>
- {value !== '--' && <a onClick={() => handleColumnTrend(item.dataIndex)}><LineChartOutlined /></a>}
- </Space>
- </Table.Summary.Cell>
- }
- })}
- </Table.Summary.Row>
- </Table.Summary>
- )}
- />
- </div>
- {detailShow && <Details visible={detailShow} onClose={() => { setDetailShow(false) }} data={detailData} />}
- {logVisible && <RuleAccountLog accountId={accountIdRule} adgroupName={adgroupName} adgroupId={adgroupId} visible={logVisible} onClose={() => setLogVisible(false)} />}
- {/* 修改广告 */}
- {update.visible && <UpdateAd
- {...update}
- selectedRows={selectedRows.map(item => ({ ...item, accountId: item.account_id, adgroupId: item.adgroup_id }))}
- onChange={() => {
- setUpdate({ visible: false })
- getAdList.refresh()
- setSelectedRows([])
- }}
- onClose={() => { setUpdate({ visible: false }) }}
- />}
- </div>
- }
- export default AdPlanList
|