tableMonitorConfig.tsx 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698
  1. import useCopy from '@/Hook/useCopy'
  2. import { DownOutlined, RiseOutlined } from '@ant-design/icons'
  3. import { Dropdown, Menu, Progress, Statistic, Tooltip } from 'antd'
  4. import { ColumnsType } from 'antd/lib/table'
  5. import React from 'react'
  6. import { ReactComponent as RocketSvg } from '@/assets/rocket.svg'
  7. import './index.less'
  8. import { CHUANGYIZHUANGTAI, CHUJIAFANGSHI, GOUMAILEIXING, GUANGGAOZHUANGTAI, TUIGUANGMUBIAO, YOUHUAMUBIAO } from './enum'
  9. import Box from './components/box'
  10. import { GGStateData } from './data'
  11. function columnsMonitor(planDetail: (id: number) => void, getDetailList: (adId: any, accountId: any[]) => void, details: (id: number) => void, getMinuList: (id: number, accountId: any[]) => void, mode: string) {
  12. const { copy } = useCopy()
  13. return function columns() {
  14. let newArr: ColumnsType<any> = [
  15. {
  16. title: '时间',
  17. dataIndex: 'currTime',
  18. key: 'currTime',
  19. align: 'center',
  20. width: 160,
  21. ellipsis: true
  22. },
  23. {
  24. title: '广告名称',
  25. dataIndex: 'adgroupName',
  26. key: 'adgroupName',
  27. align: 'center',
  28. width: 170,
  29. ellipsis: true,
  30. render: (str, b) => {
  31. return <a style={{ color: '#1890ff', fontSize: 12 }} onClick={() => { getDetailList(b.adgroupId, [b.accountId]) }}>{str}</a>
  32. }
  33. },
  34. {
  35. title: '广告ID',
  36. dataIndex: 'adgroupId',
  37. key: 'adgroupId',
  38. align: 'center',
  39. width: 100,
  40. ellipsis: true,
  41. render: (a: any) => {
  42. return <a onClick={() => { copy(a) }} style={{ color: '#3946c3' }}>{a}</a>
  43. }
  44. },
  45. {
  46. title: '计划名称',
  47. dataIndex: 'campaignName',
  48. key: 'campaignName',
  49. align: 'center',
  50. width: 170,
  51. ellipsis: true,
  52. render: (str, b) => {
  53. return str
  54. }
  55. },
  56. {
  57. title: '计划ID',
  58. dataIndex: 'campaignId',
  59. key: 'campaignId',
  60. align: 'center',
  61. width: 100,
  62. ellipsis: true,
  63. render: (a: any) => {
  64. return <a onClick={() => { copy(a) }} style={{ color: '#3946c3' }}>{a}</a>
  65. }
  66. },
  67. {
  68. title: '广告账户',
  69. dataIndex: 'accountId',
  70. key: 'accountId',
  71. width: 70,
  72. ellipsis: true,
  73. align: 'center'
  74. },
  75. {
  76. title: '投手',
  77. dataIndex: 'putUserName',
  78. key: 'putUserName',
  79. align: 'center',
  80. ellipsis: true,
  81. width: 65
  82. },
  83. {
  84. title: '创意预览',
  85. dataIndex: 'creativePreview',
  86. key: 'creativePreview',
  87. width: 110,
  88. align: 'center',
  89. render: (a: any, b: any) => {
  90. return <Box b={b} />
  91. }
  92. },
  93. // {
  94. // title: '投放位置',
  95. // dataIndex: 'pitchSeat',
  96. // key: 'pitchSeat',
  97. // width: 110,
  98. // align: 'center',
  99. // render: (a: any) => {
  100. // return a
  101. // }
  102. // },
  103. // {
  104. // title: '自动扩量',
  105. // dataIndex: 'autoExpand',
  106. // key: 'autoExpand',
  107. // width: 110,
  108. // align: 'center',
  109. // render: (a: any) => {
  110. // return a
  111. // }
  112. // },
  113. // {
  114. // title: '深度优化目标',
  115. // dataIndex: 'depthOptimizeTarget',
  116. // key: 'depthOptimizeTarget',
  117. // width: 110,
  118. // align: 'center',
  119. // render: (a: any) => {
  120. // return a
  121. // }
  122. // },
  123. // {
  124. // title: '曝光评估',
  125. // dataIndex: 'impressionAppraise',
  126. // key: 'impressionAppraise',
  127. // width: 110,
  128. // align: 'center',
  129. // render: (a: any) => {
  130. // return a
  131. // }
  132. // },
  133. {
  134. title: '投放时间',
  135. dataIndex: 'adBeginTime',
  136. key: 'adBeginTime',
  137. width: 110,
  138. align: 'center',
  139. ellipsis: true
  140. },
  141. {
  142. title: '广告状态',
  143. dataIndex: 'adStatus',
  144. key: 'adStatus',
  145. align: 'center',
  146. width: 105,
  147. ellipsis: true,
  148. render: (a: any) => {
  149. return GGStateData[a] || '--'
  150. }
  151. },
  152. // {
  153. // title: '创意状态',
  154. // dataIndex: 'adCreativeStatus',
  155. // key: 'adCreativeStatus',
  156. // align: 'center',
  157. // width: 115,
  158. // render: (a: any) => {
  159. // return CHUANGYIZHUANGTAI[a] || '--'
  160. // }
  161. // },
  162. {
  163. title: '推广目标',
  164. dataIndex: 'promotedObjectType',
  165. key: 'promotedObjectType',
  166. align: 'center',
  167. width: 80,
  168. ellipsis: true,
  169. render: (a: any) => {
  170. return TUIGUANGMUBIAO[a]
  171. }
  172. },
  173. // {
  174. // title: '购买类型',
  175. // dataIndex: 'adBuyType',
  176. // key: 'adBuyType',
  177. // align: 'center',
  178. // width: 110,
  179. // render: (a: any) => {
  180. // return GOUMAILEIXING[a] || '--'
  181. // }
  182. // },
  183. {
  184. title: '广告预算',
  185. dataIndex: 'dailyBudget',
  186. key: 'dailyBudget',
  187. width: 110,
  188. align: 'center',
  189. ellipsis: true,
  190. render: (a: any) => {
  191. return <Statistic value={a || 0} />
  192. }
  193. },
  194. {
  195. title: '出价方式',
  196. dataIndex: 'bidMode',
  197. key: 'bidMode',
  198. align: 'center',
  199. width: 80,
  200. render: (a: any) => {
  201. return CHUJIAFANGSHI[a] || '--'
  202. }
  203. },
  204. {
  205. title: '当前出价',
  206. dataIndex: 'bidAmount',
  207. key: 'bidAmount',
  208. width: 110,
  209. align: 'center',
  210. ellipsis: true,
  211. render: (a: any) => {
  212. return <div style={a >= 500 ? { backgroundColor: 'rgba(255, 80, 82, .72)', height: 26, color: '#fff', display: 'flex', justifyContent: 'center', alignItems: 'center', fontWeight: 600 } : {}}><Statistic value={a || 0} valueStyle={a >= 500 ? { fontSize: 14 } : {}} /></div>
  213. }
  214. },
  215. // {
  216. // title: '计划预算',
  217. // dataIndex: 'planBudget',
  218. // key: 'planBudget',
  219. // width: 110,
  220. // align: 'center',
  221. // render: (a: any) => {
  222. // return a
  223. // }
  224. // },
  225. {
  226. title: '广告总消耗',
  227. dataIndex: 'costTotal',
  228. key: 'costTotal',
  229. align: 'center',
  230. width: 100,
  231. ellipsis: true,
  232. sorter: true,
  233. render: (a: any) => {
  234. return <div style={{ height: 26, position: 'relative' }}>
  235. <Progress
  236. strokeColor={{
  237. from: '#10c1e9',
  238. to: '#6892d0',
  239. }}
  240. status="active"
  241. showInfo={false}
  242. percent={a ? a / 30000 * 100 : 0}
  243. />
  244. <span style={{ position: 'absolute', left: 0, top: 2, bottom: 0, right: 0 }}><Statistic value={a || 0} valueStyle={a >= 30000 ? { color: '#000', fontWeight: 500 } : { fontWeight: 500 }} /></span>
  245. </div>
  246. }
  247. },
  248. {
  249. title: '今日消耗',
  250. dataIndex: 'costDay',
  251. key: 'costDay',
  252. align: 'center',
  253. width: 105,
  254. sorter: true,
  255. render: (a: any) => {
  256. return <div style={{ height: 26, position: 'relative' }}>
  257. <Progress
  258. strokeColor={{
  259. from: '#ff5900',
  260. to: '#ffd380',
  261. }}
  262. status="active"
  263. showInfo={false}
  264. percent={a ? a / 2000 * 100 : 0}
  265. />
  266. <span style={{ position: 'absolute', left: 0, top: 2, bottom: 0, right: 0 }}><Statistic value={a || 0} valueStyle={a >= 2000 ? { color: '#000', fontWeight: 500 } : { fontWeight: 500 }} /></span>
  267. </div>
  268. }
  269. },
  270. {
  271. title: '当前小时消耗',
  272. dataIndex: 'costHour',
  273. key: 'costHour',
  274. align: 'center',
  275. width: 110,
  276. sorter: true,
  277. render: (a: any) => {
  278. return <div style={{ height: 26, position: 'relative' }}>
  279. <Progress
  280. strokeColor={{
  281. from: '#e7a0f5',
  282. to: '#d161f7',
  283. }}
  284. status="active"
  285. showInfo={false}
  286. percent={a ? a / 300 * 100 : 0}
  287. />
  288. <span style={{ position: 'absolute', left: 0, top: 2, bottom: 0, right: 0 }}><Statistic value={a || 0} valueStyle={a >= 300 ? { color: '#000', fontWeight: 500, fontSize: 15 } : { fontWeight: 500, fontSize: 15 }} /></span>
  289. </div>
  290. }
  291. },
  292. {
  293. title: '前第1小时消耗',
  294. dataIndex: 'costLastHour',
  295. key: 'costLastHour',
  296. align: 'center',
  297. width: 110,
  298. sorter: true,
  299. render: (a: any) => {
  300. return <Statistic value={a || 0} />
  301. }
  302. },
  303. {
  304. title: '前第2小时消耗',
  305. dataIndex: 'costLastTwoHour',
  306. key: 'costLastTwoHour',
  307. align: 'center',
  308. width: 80,
  309. sorter: true,
  310. render: (a: any) => {
  311. return <Statistic value={a || 0} />
  312. }
  313. },
  314. {
  315. title: '前第3小时消耗',
  316. dataIndex: 'costLastThreeHour',
  317. key: 'costLastThreeHour',
  318. align: 'center',
  319. width: 110,
  320. sorter: true,
  321. render: (a: number) => {
  322. return <Statistic value={a || 0} />
  323. },
  324. },
  325. {
  326. title: '当前小时消耗差额',
  327. dataIndex: 'costDiffBeforeHour',
  328. key: 'costDiffBeforeHour',
  329. align: 'center',
  330. width: 125,
  331. sorter: true,
  332. render: (a: any) => {
  333. return <Statistic value={a || 0} valueStyle={a > 0 ? { color: 'red' } : { color: 'green' }} />
  334. }
  335. },
  336. {
  337. title: '前第1小时消耗差额',
  338. dataIndex: 'costDiffBeforeTwoHour',
  339. key: 'costDiffBeforeTwoHour',
  340. align: 'center',
  341. width: 125,
  342. sorter: true,
  343. render: (a: any) => {
  344. return <Statistic value={a || 0} valueStyle={a > 0 ? { color: 'red' } : { color: 'green' }} />
  345. }
  346. },
  347. {
  348. title: "前第2小时消耗差额",
  349. dataIndex: 'costDiffBeforeThreeHour',
  350. key: 'costDiffBeforeThreeHour',
  351. align: 'center',
  352. width: 125,
  353. sorter: true,
  354. render: (a: number) => {
  355. return <Statistic value={a || 0} valueStyle={a > 0 ? { color: 'red' } : { color: 'green' }} />
  356. },
  357. },
  358. {
  359. title: "前三小时消耗趋势",
  360. dataIndex: 'costTrendLastThreeHour',
  361. key: 'costTrendLastThreeHour',
  362. align: 'center',
  363. width: 75,
  364. render: (a: number) => {
  365. return a > 0 ? <RiseOutlined style={{ color: 'red', fontWeight: 900, fontSize: 22 }} /> : '--'
  366. },
  367. },
  368. {
  369. title: '当前5min消耗流速',
  370. dataIndex: 'costSpeed',
  371. key: 'costSpeed',
  372. align: 'center',
  373. width: 115,
  374. render: (a: any) => {
  375. a = a ? parseFloat(a.toFixed(2)) : 0
  376. return <div style={{ height: 26, position: 'relative' }}>
  377. <Progress
  378. strokeColor={{
  379. from: '#00DDFF',
  380. to: '#37A2FF',
  381. }}
  382. status="active"
  383. showInfo={false}
  384. percent={a ? a / 100 * 100 : 0}
  385. />
  386. <span style={{ position: 'absolute', left: 0, top: 2, bottom: 0, right: 0 }}><Statistic value={a || 0} valueStyle={a >= 100 ? { color: '#000', fontWeight: 500 } : { fontWeight: 500 }} /></span>
  387. </div>
  388. }
  389. },
  390. {
  391. title: '曝光量',
  392. dataIndex: 'viewDay',
  393. key: 'viewDay',
  394. align: 'center',
  395. width: 70,
  396. sorter: true,
  397. render: (a: number) => {
  398. return <Statistic value={a || 0} />
  399. },
  400. },
  401. {
  402. title: '千次曝光成本',
  403. dataIndex: 'thousandDisplayPriceDay',
  404. key: 'thousandDisplayPriceDay',
  405. align: 'center',
  406. width: 115,
  407. sorter: true,
  408. render: (a: any) => {
  409. return <Statistic value={a || 0} />
  410. }
  411. },
  412. {
  413. title: '点击量',
  414. dataIndex: 'clickDay',
  415. key: 'clickDay',
  416. align: 'center',
  417. width: 70,
  418. sorter: true,
  419. render: (a: number) => {
  420. return <Statistic value={a || 0} />
  421. },
  422. },
  423. {
  424. title: '点击均价',
  425. dataIndex: 'cpcDay',
  426. key: 'cpcDay',
  427. align: 'center',
  428. width: 115,
  429. sorter: true,
  430. render: (a: any) => {
  431. return <Statistic value={a || 0} />
  432. }
  433. },
  434. {
  435. title: '点击率',
  436. dataIndex: 'ctrDay',
  437. key: 'ctrDay',
  438. align: 'center',
  439. width: 115,
  440. sorter: true,
  441. render: (a: any) => {
  442. a = a ? parseFloat((a * 100).toFixed(2)) : 0
  443. return a + '%'
  444. }
  445. },
  446. {
  447. title: '优化目标',
  448. dataIndex: 'optimizationGoal',
  449. key: 'optimizationGoal',
  450. align: 'center',
  451. width: 115,
  452. render: (a: any) => {
  453. return YOUHUAMUBIAO[a] || '--'
  454. }
  455. },
  456. {
  457. title: '转化目标量',
  458. dataIndex: 'conversionsCountDay',
  459. key: 'conversionsCountDay',
  460. align: 'center',
  461. width: 115,
  462. sorter: true,
  463. render: (a: any) => {
  464. return <Statistic value={a || 0} />
  465. }
  466. },
  467. {
  468. title: '转化目标成本',
  469. dataIndex: 'conversionsCostDay',
  470. key: 'conversionsCostDay',
  471. align: 'center',
  472. width: 115,
  473. sorter: true,
  474. render: (a: any) => {
  475. return <div style={a > 500 ? { backgroundColor: '#efea5b', height: 26, color: '#fff', display: 'flex', alignItems: 'center', justifyContent: 'center', fontWeight: 600 } : {}}><Statistic value={a || 0} /></div>
  476. }
  477. },
  478. {
  479. title: '目标转化率',
  480. dataIndex: 'conversionsRateDay',
  481. key: 'conversionsRateDay',
  482. align: 'center',
  483. width: 115,
  484. sorter: true,
  485. render: (a: any) => {
  486. a = a ? parseFloat((a * 100).toFixed(2)) : 0
  487. return a + '%'
  488. }
  489. },
  490. {
  491. title: '下单量',
  492. dataIndex: 'orderCountDay',
  493. key: 'orderCountDay',
  494. align: 'center',
  495. width: 115,
  496. sorter: true,
  497. render: (a: any) => {
  498. return <Statistic value={a || 0} />
  499. }
  500. },
  501. {
  502. title: '首日新增下单量',
  503. dataIndex: 'firstDayOrderCountDay',
  504. key: 'firstDayOrderCountDay',
  505. align: 'center',
  506. width: 115,
  507. sorter: true,
  508. render: (a: any) => {
  509. return <Statistic value={a || 0} />
  510. }
  511. },
  512. {
  513. title: '下单成本',
  514. dataIndex: 'orderCostDay',
  515. key: 'orderCostDay',
  516. align: 'center',
  517. width: 115,
  518. sorter: true,
  519. render: (a: any) => {
  520. return <Statistic value={a || 0} />
  521. }
  522. },
  523. {
  524. title: '下单率',
  525. dataIndex: 'orderRateDay',
  526. key: 'orderRateDay',
  527. align: 'center',
  528. width: 115,
  529. sorter: true,
  530. render: (a: any) => {
  531. a = a ? parseFloat((a * 100).toFixed(2)) : 0
  532. return a + '%'
  533. }
  534. },
  535. {
  536. title: '下单金额',
  537. dataIndex: 'orderAmountDay',
  538. key: 'orderAmountDay',
  539. align: 'center',
  540. width: 115,
  541. sorter: true,
  542. render: (a: any) => {
  543. return <Statistic value={a || 0} />
  544. }
  545. },
  546. {
  547. title: '首日新增下单金额',
  548. dataIndex: 'firstDayOrderAmountDay',
  549. key: 'firstDayOrderAmountDay',
  550. align: 'center',
  551. width: 115,
  552. sorter: true,
  553. render: (a: any) => {
  554. return <Statistic value={a || 0} />
  555. }
  556. },
  557. {
  558. title: '下单客单价',
  559. dataIndex: 'atvDay',
  560. key: 'atvDay',
  561. align: 'center',
  562. width: 115,
  563. sorter: true,
  564. render: (a: any) => {
  565. return <Statistic value={a || 0} />
  566. }
  567. },
  568. {
  569. title: '下单ROI',
  570. dataIndex: 'orderRoiDay',
  571. key: 'orderRoiDay',
  572. align: 'center',
  573. width: 115,
  574. sorter: true,
  575. render: (a: any) => {
  576. a = a ? parseFloat((a * 100).toFixed(2)) : 0
  577. return a + '%'
  578. }
  579. },
  580. {
  581. title: '首日新增下单ROI',
  582. dataIndex: 'firstDayOrderRoiDay',
  583. key: 'firstDayOrderRoiDay',
  584. align: 'center',
  585. width: 115,
  586. sorter: true,
  587. render: (a: any) => {
  588. a = a ? parseFloat((a * 100).toFixed(2)) : 0
  589. return a + '%'
  590. }
  591. },
  592. {
  593. title: '公众号关注人数',
  594. dataIndex: 'mpFollowUvDay',
  595. key: 'mpFollowUvDay',
  596. align: 'center',
  597. width: 115,
  598. sorter: true,
  599. render: (a: any) => {
  600. return a
  601. }
  602. },
  603. {
  604. title: '公众号关注率',
  605. dataIndex: 'mpFollowRateDay',
  606. key: 'mpFollowRateDay',
  607. align: 'center',
  608. width: 115,
  609. sorter: true,
  610. render: (a: any) => {
  611. a = a ? parseFloat((a * 100).toFixed(2)) : 0
  612. return a + '%'
  613. }
  614. },
  615. {
  616. title: '公众号关注成本',
  617. dataIndex: 'mpFollowCostDay',
  618. key: 'mpFollowCostDay',
  619. align: 'center',
  620. width: 115,
  621. sorter: true,
  622. render: (a: any) => {
  623. return <Statistic value={a || 0} />
  624. }
  625. },
  626. // {
  627. // title: '注册人数',
  628. // dataIndex: 'mpRegisterUserCount',
  629. // key: 'mpRegisterUserCount',
  630. // align: 'center',
  631. // width: 115,
  632. // sorter: true,
  633. // render: (a: any) => {
  634. // return a
  635. // }
  636. // },
  637. // {
  638. // title: '注册次数',
  639. // dataIndex: 'mpRegisterCount',
  640. // key: 'mpRegisterCount',
  641. // align: 'center',
  642. // width: 115,
  643. // sorter: true,
  644. // render: (a: any) => {
  645. // return a
  646. // }
  647. // },
  648. // {
  649. // title: '注册成本',
  650. // dataIndex: 'mpRegisterCost',
  651. // key: 'mpRegisterCost',
  652. // align: 'center',
  653. // width: 115,
  654. // sorter: true,
  655. // render: (a: any) => {
  656. // return <Statistic value={a || 0} />
  657. // }
  658. // },
  659. {
  660. title: '操作',
  661. dataIndex: 'event',
  662. key: 'event',
  663. align: 'center',
  664. width: 90,
  665. render: (a: string, b: any) => (
  666. // <a style={{ color: '#1890ff' }} onClick={() => { planDetail(b) }}>广告详情</a>
  667. <Dropdown overlay={
  668. <Menu>
  669. <Menu.Item key="0">
  670. <a style={{ color: '#1890ff' }} onClick={() => { planDetail(b) }}>广告详情</a>
  671. </Menu.Item>
  672. {mode === 'minute' ? <Menu.Item key="1">
  673. <a style={{ color: '#1890ff' }} onClick={() => { getDetailList(b.adgroupId, [b.accountId]) }}>小时</a>
  674. </Menu.Item> : <Menu.Item key="1">
  675. <a style={{ color: '#1890ff' }} onClick={() => { getMinuList(b?.adgroupId, [b.accountId]) }}>5min</a>
  676. </Menu.Item>}
  677. <Menu.Item key="2">
  678. <div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }} onClick={() => details(b)}>
  679. <RocketSvg /><a style={{ marginLeft: 4, color: '#1890ff' }}>详情</a>
  680. </div>
  681. </Menu.Item>
  682. <Menu.Item key="3">
  683. <a style={{ color: '#1890ff' }} onClick={() => window.open(`https://ad.qq.com/atlas/${b?.accountId}/admanage/adcreative?adgroupid=${b?.adgroupId}&query={%22configured_status%22:[%22AD_STATUS_EXCLUDE_DELETED%22],%22status%22:[]}`)} target="_blank">腾讯广告</a>
  684. </Menu.Item>
  685. </Menu>
  686. } trigger={['click']}>
  687. <a className="ant-dropdown-link" onClick={e => e.preventDefault()}>
  688. 更多 <DownOutlined />
  689. </a>
  690. </Dropdown>
  691. )
  692. }
  693. ]
  694. return newArr
  695. }
  696. }
  697. export default columnsMonitor