index.tsx 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. import React, { useEffect, useState } from "react"
  2. import { useAjax } from "@/Hook/useAjax"
  3. import { getNovelGDTListApi, GetNovelGDTListProps, getNovelGDTTotalApi } from "@/services/iaaData"
  4. import TablePro from "@/components/TablePro"
  5. import columns12 from "./tableConfig"
  6. import moment from "moment"
  7. import { useModel } from "umi"
  8. import { Button, Dropdown, message, Select, Space, Switch } from "antd"
  9. import { modifyStatusBatchApi } from "@/services/gameData"
  10. import { DeleteOutlined, DownOutlined, PauseCircleOutlined, PlayCircleOutlined } from "@ant-design/icons"
  11. import DayAd from "./dayAd"
  12. import QueryFormNovel from "@/components/QueryForm/queryFormNovel"
  13. import UpdateAd3 from "@/pages/iaaData/components/UpdateAd3"
  14. import AutoAcquisitionSet from "./autoAcquisitionSet"
  15. import AutoAcquisitionSetTask from "@/pages/iaaData/components/AutoAcquisitionSet/autoAcquisitionSetTask"
  16. /**
  17. * 腾讯广告列表
  18. * @returns
  19. */
  20. const TencentNovelAd: React.FC<{ configName?: string, dayConfigName?: string }> = ({ configName, dayConfigName }) => {
  21. /****************************************/
  22. const { initialState } = useModel('@@initialState');
  23. const [selectedRows, setSelectedRows] = useState<any[]>([])
  24. const [queryForm, setQueryForm] = useState<GetNovelGDTListProps>({
  25. pageNum: 1,
  26. pageSize: 30,
  27. dataTimeMin: moment().format('YYYY-MM-DD'),
  28. dataTimeMax: moment().format('YYYY-MM-DD'),
  29. })
  30. const [totalData, setTotalData] = useState<any[]>([])
  31. const [visible, setVisible] = useState<boolean>(false)
  32. const [promotionId, setPromotionId] = useState<number>()
  33. const [adName, setAdName] = useState<string>('')
  34. const [updateData, setUpdateDate] = useState<{ visible: boolean, type: '修改出价' | '修改名称' | '修改日限额' | '修改投放时间' | '删除' | '深度优化ROI' | '修改投放首日开始时间' }>({ visible: false, type: '修改出价' })
  35. const [autoAcqVisible, setAutoAcqVisible] = useState<boolean>(false)
  36. const [handleType, setHandleType] = useState<number>(1)
  37. const [isZj, setIsZj] = useState<boolean>(true)
  38. const modifyStatusBatch = useAjax((params) => modifyStatusBatchApi(params))
  39. const getGDTList = useAjax((params) => getNovelGDTListApi(params))
  40. const getGDTTotal = useAjax((params) => getNovelGDTTotalApi(params))
  41. /****************************************/
  42. useEffect(() => {
  43. getList()
  44. }, [queryForm, initialState?.iaaApp, initialState?.productType])
  45. const getList = () => {
  46. if (initialState?.iaaApp?.length && initialState?.productType) {
  47. getGDTList.run({ ...queryForm, appId: initialState.iaaApp, productType: initialState.productType })
  48. getGDTTotal.run({ ...queryForm, appId: initialState.iaaApp, productType: initialState.productType }).then((res: { data: { id: number; accountId: string } }) => {
  49. if (res?.data) {
  50. let data = res?.data
  51. data.id = 1
  52. data.accountId = '总计'
  53. setTotalData([data])
  54. } else {
  55. setTotalData([{ id: 1, accountId: '总计' }])
  56. }
  57. })
  58. } else {
  59. setTotalData([{ id: 1, accountId: '总计' }])
  60. getGDTList.mutate({ data: undefined })
  61. }
  62. }
  63. const dayHandle = (data: any) => {
  64. setVisible(true)
  65. setAdName(data.adgroupName)
  66. setPromotionId(data.adgroupId)
  67. }
  68. // 批量启停
  69. const adStatus = (type: boolean) => {
  70. let newSelectedRows = []
  71. if (type) {
  72. newSelectedRows = selectedRows.filter((item: { configuredStatus: string, adgroupId: number }) => item.configuredStatus === 'AD_STATUS_SUSPEND')
  73. } else {
  74. newSelectedRows = selectedRows.filter((item: { configuredStatus: string, adgroupId: number }) => item.configuredStatus === 'AD_STATUS_NORMAL')
  75. }
  76. if (newSelectedRows.length === 0) {
  77. message.warn(`所有广告都是${type ? '启动' : '暂停'}状态,无需${type ? '启动' : '暂停'}操作`)
  78. return
  79. }
  80. let accountAdgroupMaps = [...new Set(newSelectedRows?.map(item => item.accountId + ',' + item.adgroupId))]
  81. modifyStatusBatch.run({ accountAdgroupMaps, suspend: !type }).then(res => {
  82. if (res?.data?.failIdList?.length === 0) {
  83. message.success(`${type ? '启动' : '暂停'}成功`)
  84. getGDTList.refresh()
  85. setSelectedRows([])
  86. } else {
  87. message.success(`${type ? '启动' : '暂停'}失败,${JSON.stringify(res?.data?.list)}`)
  88. }
  89. })
  90. }
  91. return <div>
  92. <TablePro
  93. czChild={<Space>
  94. <Switch checkedChildren="开启全选" unCheckedChildren="关闭全选" checked={!isZj} onChange={(e) => { setIsZj(!e); }} />
  95. <Select
  96. style={{ width: 120 }}
  97. onChange={(e) => {
  98. setHandleType(e)
  99. setSelectedRows([])
  100. }}
  101. value={handleType}
  102. dropdownMatchSelectWidth={false}
  103. options={[{ label: '广告操作', value: 1 }, { label: '修改首日付费 ROI', value: 3 }, { label: '修改首日变现 ROI', value: 4 }]}
  104. />
  105. <Button type='primary' style={{ background: '#67c23a', borderColor: '#67c23a' }} loading={modifyStatusBatch.loading} icon={<PlayCircleOutlined />} disabled={selectedRows.length === 0} onClick={() => adStatus(true)}>启动</Button>
  106. <Button type='primary' style={{ background: '#e6a23c', borderColor: '#e6a23c' }} loading={modifyStatusBatch.loading} icon={<PauseCircleOutlined />} disabled={selectedRows.length === 0} onClick={() => adStatus(false)}>暂停</Button>
  107. {handleType === 1 ? <>
  108. <Button type='primary' danger icon={<DeleteOutlined />} disabled={selectedRows.length === 0} onClick={() => {
  109. setUpdateDate({ visible: true, type: '删除' })
  110. }}>删除</Button>
  111. <Dropdown
  112. menu={{
  113. items: [
  114. {
  115. label: <span style={{ display: 'inline-block', width: 120 }}>修改出价</span>,
  116. key: '1',
  117. disabled: selectedRows.length === 0,
  118. onClick: () => { setUpdateDate({ visible: true, type: '修改出价' }) }
  119. },
  120. {
  121. label: '修改名称',
  122. key: '2',
  123. disabled: selectedRows.length === 0,
  124. onClick: () => { setUpdateDate({ visible: true, type: '修改名称' }) }
  125. },
  126. {
  127. label: '修改日限额',
  128. key: '3',
  129. disabled: selectedRows.length === 0,
  130. onClick: () => { setUpdateDate({ visible: true, type: '修改日限额' }) }
  131. },
  132. {
  133. label: '修改投放日期',
  134. key: '4',
  135. disabled: selectedRows.length === 0,
  136. onClick: () => { setUpdateDate({ visible: true, type: '修改投放时间' }) }
  137. },
  138. {
  139. label: '修改投放首日开始时间',
  140. key: '5',
  141. disabled: selectedRows.length === 0,
  142. onClick: () => { setUpdateDate({ visible: true, type: '修改投放首日开始时间' }) }
  143. },
  144. {
  145. label: '一键起量',
  146. key: '6',
  147. disabled: selectedRows.length === 0,
  148. onClick: () => { setAutoAcqVisible(true) }
  149. }
  150. ]
  151. }}
  152. placement="bottomLeft"
  153. arrow
  154. >
  155. <Button>
  156. <Space>
  157. 修改广告
  158. <DownOutlined />
  159. </Space>
  160. </Button>
  161. </Dropdown>
  162. <AutoAcquisitionSetTask
  163. selectAdList={selectedRows}
  164. />
  165. </> : handleType === 3 ? <>
  166. <Button type='primary' disabled={selectedRows.length === 0} onClick={() => {
  167. setUpdateDate({ visible: true, type: '深度优化ROI' })
  168. }}>修改首日付费 ROI</Button>
  169. </> : handleType === 4 ? <>
  170. <Button type='primary' disabled={selectedRows.length === 0} onClick={() => {
  171. setUpdateDate({ visible: true, type: '深度优化ROI' })
  172. }}>修改首日变现 ROI</Button>
  173. </> : null}
  174. <span style={{ color: 'red' }}>操作完数据结果延时5分钟之内,即时结果去腾讯后台查看</span>
  175. </Space>}
  176. leftChild={<QueryFormNovel
  177. initialValues={{ day3: [moment(), moment()] }}
  178. isAccountId
  179. isPutUserIdList
  180. isAdgroupId
  181. isAdgroupName
  182. isMarketingGoal
  183. isMarketingTargetType
  184. isMemo
  185. isRemark
  186. isBookNameList
  187. isDeleted
  188. isStatus
  189. isPromotedObjectName
  190. isPromotedObjectType
  191. isOptimizationGoal
  192. isCostTotalMin
  193. isThousandDisplayPriceTotalMin
  194. isConversionsCountTotalMin
  195. isIncomeRoi1
  196. isRegCost
  197. isRegCostPla
  198. isCpc
  199. day1={{ placeholder: ['广告创建日期开始', '广告创建日期结束'] }}
  200. day2={{ placeholder: ['投放日期开始', '投放日期结束'] }}
  201. day3={{ placeholder: ['消耗日期开始', '消耗日期结束'] }}
  202. onChange={(data: any) => {
  203. console.log(data)
  204. const { day1, day2, day3, bookNameList, ...params } = data
  205. let newQueryForm = JSON.parse(JSON.stringify(queryForm))
  206. newQueryForm.pageNum = 1
  207. if (day1 && day1?.length === 2) {
  208. newQueryForm['adCreateTimeMin'] = moment(day1[0]).format('YYYY-MM-DD')
  209. newQueryForm['adCreateTimeMax'] = moment(day1[1]).format('YYYY-MM-DD')
  210. } else {
  211. delete newQueryForm['adCreateTimeMin']
  212. delete newQueryForm['adCreateTimeMax']
  213. }
  214. if (day2 && day2?.length === 2) {
  215. newQueryForm['putDateBegin'] = moment(day2[0]).format('YYYY-MM-DD')
  216. newQueryForm['putDateEnd'] = moment(day2[1]).format('YYYY-MM-DD')
  217. } else {
  218. delete newQueryForm['putDateBegin']
  219. delete newQueryForm['putDateEnd']
  220. }
  221. if (day3 && day3?.length === 2) {
  222. newQueryForm['dataTimeMin'] = moment(day3[0]).format('YYYY-MM-DD')
  223. newQueryForm['dataTimeMax'] = moment(day3[1]).format('YYYY-MM-DD')
  224. } else {
  225. delete newQueryForm['dataTimeMin']
  226. delete newQueryForm['dataTimeMax']
  227. }
  228. if (bookNameList) {
  229. newQueryForm['bookNameList'] = bookNameList.replace(/[,,\s]/g, ',').split(',').filter((a: any) => a)
  230. } else {
  231. delete newQueryForm['bookNameList']
  232. }
  233. setQueryForm({ ...newQueryForm, ...params })
  234. }}
  235. />}
  236. isZj={isZj}
  237. totalData={totalData}
  238. config={columns12(dayHandle, () => { getList() })}
  239. configName={configName || '腾讯小说广告列表'}
  240. fixed={{ left: 4, right: 2 }}
  241. scroll={{ x: 1000, y: 620 }}
  242. title='腾讯广告列表'
  243. loading={getGDTList.loading}
  244. ajax={getGDTList}
  245. page={queryForm?.pageNum || 1}
  246. pageSize={queryForm?.pageSize || 20}
  247. total={getGDTList?.data?.data?.total || 0}
  248. dataSource={getGDTList?.data?.data?.records?.map((item: any) => ({ ...item, id: item.adgroupId, deepConversionSpec: item?.deepConversionSpecJson ? JSON.parse(item.deepConversionSpecJson) : {} }))}
  249. onChange={(pagination: any, _: any, sortData: any) => {
  250. let { current, pageSize } = pagination
  251. let newQueryForm = JSON.parse(JSON.stringify(queryForm))
  252. if (sortData && sortData?.order) {
  253. newQueryForm['sortAsc'] = sortData?.order === 'ascend' ? true : false
  254. newQueryForm['sortFiled'] = sortData?.field
  255. } else {
  256. delete newQueryForm['sortAsc']
  257. delete newQueryForm['sortFiled']
  258. }
  259. newQueryForm.pageNum = current || newQueryForm.pageNum
  260. newQueryForm.pageSize = pageSize || newQueryForm.pageSize
  261. setQueryForm({ ...newQueryForm })
  262. }}
  263. rowSelection={{
  264. selectedRowKeys: selectedRows.map(item => item.adgroupId + ''),
  265. getCheckboxProps: (record: any) => ({
  266. disabled:
  267. handleType === 3 ? record.status === 'STATUS_DELETED' || record?.accountId === '总计' || !(record?.deepConversionSpec?.deepConversionWorthSpec?.goal === 'GOAL_1DAY_PURCHASE_ROAS') :
  268. handleType === 4 ? record.status === 'STATUS_DELETED' || record?.accountId === '总计' || !(record?.deepConversionSpec?.deepConversionWorthSpec?.goal === 'GOAL_1DAY_MONETIZATION_ROAS') :
  269. record.status === 'STATUS_DELETED' || record?.accountId === '总计'
  270. }),
  271. onSelect: (record: { adgroupId: number }, selected: boolean) => {
  272. if (selected) {
  273. selectedRows.push({ ...record })
  274. setSelectedRows([...selectedRows])
  275. } else {
  276. let newSelectAccData = selectedRows.filter((item: { adgroupId: number }) => item.adgroupId !== record.adgroupId)
  277. setSelectedRows([...newSelectAccData])
  278. }
  279. },
  280. onSelectAll: (selected: boolean, selectedRowss: { adgroupId: number }[], changeRows: { adgroupId: number }[]) => {
  281. if (selected) {
  282. let newSelectAccData = [...selectedRows]
  283. changeRows.forEach((item: { adgroupId: number }) => {
  284. let index = newSelectAccData.findIndex((ite: { adgroupId: number }) => ite.adgroupId === item.adgroupId)
  285. if (index === -1) {
  286. newSelectAccData.push({ ...item })
  287. }
  288. })
  289. setSelectedRows([...newSelectAccData])
  290. } else {
  291. let newSelectAccData = selectedRows.filter((item: { adgroupId: number }) => {
  292. let index = changeRows.findIndex((ite: { adgroupId: number }) => ite.adgroupId === item.adgroupId)
  293. if (index !== -1) {
  294. return false
  295. } else {
  296. return true
  297. }
  298. })
  299. setSelectedRows([...newSelectAccData])
  300. }
  301. }
  302. }}
  303. />
  304. {visible && <DayAd configName={dayConfigName} appId={initialState?.iaaApp as number[]} productType={initialState?.productType as string} adName={adName} visible={visible} onClose={() => { setVisible(false); setPromotionId(undefined) }} queryForm={{ costDayBegin: queryForm?.dataTimeMin, costDayEnd: queryForm?.dataTimeMax }} promotionId={promotionId} />}
  305. {/* 修改广告 */}
  306. {updateData.visible && <UpdateAd3
  307. {...updateData}
  308. updateData={selectedRows}
  309. onClose={() => {
  310. setUpdateDate({ visible: false, type: '修改出价' })
  311. }}
  312. onChange={() => {
  313. setUpdateDate({ visible: false, type: '修改出价' })
  314. getGDTList.refresh()
  315. if (updateData.type === '删除') {
  316. setSelectedRows([])
  317. }
  318. }}
  319. />}
  320. {/* 批量一键起量 */}
  321. {autoAcqVisible && <AutoAcquisitionSet
  322. selectAdList={selectedRows}
  323. visible={autoAcqVisible}
  324. onClose={() => {
  325. setAutoAcqVisible(false)
  326. }}
  327. onChange={() => {
  328. setAutoAcqVisible(false)
  329. getGDTList.refresh()
  330. setSelectedRows([])
  331. }}
  332. />}
  333. </div>
  334. }
  335. export default TencentNovelAd