tableConfig.tsx 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483
  1. import React from 'react'
  2. import { Space, Switch, Image, Popover, TableProps, Typography, Badge } from 'antd'
  3. import '../index.less'
  4. import { copy } from '@/utils/utils'
  5. import { DELIVERY_MODE, DYNAMIC_CREATIVE_TYPE } from '../const'
  6. import { ELEMENT_ENUM, SITE_SET_ENUM, creativeTemplate } from '../../tencentAdPutIn/const'
  7. import { AD_STATUS } from '.'
  8. const { Text } = Typography;
  9. function tableConfig(reviewStatusDetails: (value: any) => void, suspendHandle: (b: any, suspend: '启动' | '暂停') => void): any {
  10. return [
  11. {
  12. title: '启停',
  13. dataIndex: 'configuredStatus',
  14. key: 'configuredStatus',
  15. align: 'center',
  16. width: 40,
  17. fixed: 'left',
  18. render: (a: string, b: any) => {
  19. return <Switch size="small" checked={a === 'AD_STATUS_NORMAL'} onChange={(checked) => { suspendHandle(b, checked ? '启动' : '暂停') }} />
  20. }
  21. },
  22. {
  23. title: '品牌形象',
  24. dataIndex: 'brand',
  25. key: 'brand',
  26. width: 110,
  27. ellipsis: true,
  28. render: (_: any[], b: any) => {
  29. let brand = b?.creativeComponents?.brand
  30. return brand?.length > 0 ? <Space>
  31. <img src={brand?.[0]?.value?.brandImageUrl} height={18} />
  32. <span>{brand?.[0]?.value?.brandName}</span>
  33. </Space> : '--'
  34. }
  35. },
  36. {
  37. title: '文本标题',
  38. dataIndex: 'title',
  39. key: 'title',
  40. width: 140,
  41. ellipsis: true,
  42. render: (_: any[], b: any) => {
  43. let title = b?.creativeComponents?.title
  44. return title?.length > 0 ? title.map((item: { value: { content: any } }, index: number) => `标题${index + 1}:${item?.value?.content}`)?.toString() : '--'
  45. }
  46. },
  47. {
  48. title: '文本描述',
  49. dataIndex: 'description',
  50. key: 'description',
  51. width: 140,
  52. ellipsis: true,
  53. render: (_: any[], b: any) => {
  54. let description = b?.creativeComponents?.description
  55. return description?.length > 0 ? description.map((item: { value: { content: any } }, index: number) => `描述${index + 1}:${item?.value?.content}`)?.toString() : '--'
  56. }
  57. },
  58. {
  59. title: '单图片',
  60. dataIndex: 'image',
  61. key: 'image',
  62. width: 140,
  63. ellipsis: true,
  64. render: (_: any[], b: any) => {
  65. let image = b?.creativeComponents?.image
  66. return <div style={{ minHeight: 50, display: 'flex', alignItems: 'center' }}>
  67. {image?.length > 0 ? <div className='tableScrollbar' style={{ overflow: 'hidden', overflowX: 'auto' }}>
  68. <Image.PreviewGroup>
  69. {image?.map((item: { componentId: string; value: { imageUrl: string | undefined } }, index: string) => <Image key={item?.componentId + '_' + index} src={item?.value?.imageUrl} height={45} />)}
  70. </Image.PreviewGroup>
  71. </div> : '--'}
  72. </div>
  73. }
  74. },
  75. {
  76. title: '图集',
  77. dataIndex: 'imageList',
  78. key: 'imageList',
  79. width: 140,
  80. ellipsis: true,
  81. render: (_: any[], b: any) => {
  82. let imageList = b?.creativeComponents?.imageList
  83. return imageList?.length > 0 ? <div className='tableScrollbar' style={{ overflow: 'hidden', overflowX: 'auto', display: 'flex', gap: 10 }}>
  84. {imageList?.map((item: { value: { list: any[] } }, index: React.Key | null | undefined) => <Image.PreviewGroup key={index}>
  85. {item?.value?.list?.map((list: any, i: number) => <Image key={i} src={list?.imageUrl} height={45} />)}
  86. </Image.PreviewGroup>)}
  87. </div> : '--'
  88. }
  89. },
  90. {
  91. title: '视频',
  92. dataIndex: 'video',
  93. key: 'video',
  94. width: 140,
  95. ellipsis: true,
  96. render: (_: any[], b: any) => {
  97. let video = b?.creativeComponents?.video
  98. return video?.length > 0 ? <Popover
  99. placement='right'
  100. content={< div >
  101. <Space style={{ maxWidth: 300, display: 'flex', flexFlow: 'row wrap', margin: '10px 0' }}>
  102. {video?.map((item: { value: { videoUrl: string | undefined } }, index: React.Key | null | undefined) => <video key={index} src={item?.value?.videoUrl} style={{ width: 250 }} controls />)}
  103. </Space>
  104. </div >}
  105. destroyTooltipOnHide
  106. mouseEnterDelay={0.5}
  107. >
  108. <Space style={{ width: '100%' }}>
  109. <video src={video?.[0]?.value?.videoUrl} style={{ maxHeight: 40, maxWidth: 60 }} />
  110. </Space>
  111. </Popover> : '--'
  112. }
  113. },
  114. {
  115. title: '轮播',
  116. dataIndex: 'floatingZone',
  117. key: 'floatingZone',
  118. width: 150,
  119. ellipsis: true,
  120. render: (_: any[], b: any) => {
  121. let floatingZone = b?.creativeComponents?.floatingZone
  122. return floatingZone?.length > 0 ? <div className='tableScrollbar' style={{ overflow: 'hidden', overflowX: 'auto' }}>
  123. {floatingZone?.map((item: { value: { floatingZoneImageUrl: string | undefined; floatingZoneName: boolean | React.ReactChild | React.ReactFragment | React.ReactPortal | null | undefined; floatingZoneDesc: boolean | React.ReactChild | React.ReactFragment | React.ReactPortal | null | undefined } }, index: React.Key | null | undefined) => <div key={index} style={{ display: 'flex', alignItems: 'center', gap: 1 }}>
  124. <div style={{ width: 40 }}>
  125. <Image src={item?.value?.floatingZoneImageUrl} width={40} height={40} />
  126. </div>
  127. <div>
  128. <span>{item?.value?.floatingZoneName}</span><br />
  129. <span>{item?.value?.floatingZoneDesc}</span>
  130. </div>
  131. </div>)}
  132. </div> : '--'
  133. }
  134. },
  135. {
  136. title: '所属账号',
  137. dataIndex: 'accountId',
  138. key: 'accountId',
  139. align: 'center',
  140. width: 80,
  141. ellipsis: true,
  142. render: (a: string) => {
  143. return <Space>
  144. <a onClick={() => copy(a)} >{a}</a>
  145. </Space>
  146. }
  147. },
  148. {
  149. title: '广告ID',
  150. dataIndex: 'adgroupId',
  151. key: 'adgroupId',
  152. align: 'center',
  153. width: 100,
  154. ellipsis: true,
  155. render: (a: string, b: any) => {
  156. return <Space>
  157. <a onClick={() => copy(a)} >{a}</a>
  158. </Space>
  159. }
  160. },
  161. {
  162. title: '创意名称',
  163. dataIndex: 'dynamicCreativeName',
  164. key: 'dynamicCreativeName',
  165. align: 'center',
  166. width: 120,
  167. ellipsis: true
  168. },
  169. {
  170. title: '创意ID',
  171. dataIndex: 'dynamicCreativeId',
  172. key: 'dynamicCreativeId',
  173. align: 'center',
  174. width: 100,
  175. ellipsis: true,
  176. render: (a: string, b: any) => {
  177. return <a onClick={() => copy(a)} >{a}</a>
  178. }
  179. },
  180. {
  181. title: '是否已删除',
  182. dataIndex: 'isDeleted',
  183. key: 'isDeleted',
  184. align: 'center',
  185. width: 60,
  186. render: (a: any) => {
  187. return <Badge status={!a ? "processing" : "error"} text={a ? '是' : '否'} />
  188. }
  189. },
  190. {
  191. title: '投放模式',
  192. dataIndex: 'deliveryMode',
  193. key: 'deliveryMode',
  194. align: 'center',
  195. width: 120,
  196. render: (a: string) => {
  197. return DELIVERY_MODE[a as keyof typeof DELIVERY_MODE]
  198. }
  199. },
  200. {
  201. title: '创意形式匹配方式',
  202. dataIndex: 'dynamicCreativeType',
  203. key: 'dynamicCreativeType',
  204. align: 'center',
  205. width: 120,
  206. render: (a: string) => {
  207. return DYNAMIC_CREATIVE_TYPE[a as keyof typeof DYNAMIC_CREATIVE_TYPE]
  208. }
  209. },
  210. {
  211. title: '创意形式',
  212. dataIndex: 'creativeTemplateId',
  213. key: 'creativeTemplateId',
  214. align: 'center',
  215. width: 120,
  216. ellipsis: true,
  217. render: (a: string) => {
  218. return creativeTemplate[a as keyof typeof creativeTemplate] || '--'
  219. }
  220. },
  221. {
  222. title: '审核状态',
  223. dataIndex: 'reviewStatusCn',
  224. key: 'reviewStatusCn',
  225. align: 'center',
  226. width: 100,
  227. render: (a: string, b: any) => {
  228. return <Space direction="vertical" size={0}>
  229. <span style={{ fontSize: 12 }}>{a}</span>
  230. <a style={{ fontSize: 12 }} onClick={() => { reviewStatusDetails(b) }}>详情</a>
  231. </Space>
  232. }
  233. }
  234. ]
  235. }
  236. export const tableConfigDetail = (): TableProps<any>['columns'] => {
  237. return [
  238. {
  239. title: '创意组件',
  240. dataIndex: 'componentInfo',
  241. key: 'componentInfo',
  242. width: 180,
  243. render: (value) => {
  244. if (value) {
  245. let { componentId, componentType } = value
  246. return <Space direction="vertical" size={0}>
  247. <Text style={{ fontSize: 12 }}>{ELEMENT_ENUM[componentType as keyof typeof ELEMENT_ENUM]}</Text>
  248. <Text type="secondary" style={{ fontSize: 12 }}>{componentId}</Text>
  249. </Space>
  250. }
  251. return null
  252. },
  253. onCell: (record) => ({
  254. rowSpan: record.rowSpan
  255. })
  256. },
  257. {
  258. title: '组件审核结果',
  259. dataIndex: 'temReviewStatus',
  260. key: 'temReviewStatus',
  261. width: 120,
  262. render: (_, records) => {
  263. if (!records?.componentInfo) {
  264. return null
  265. }
  266. return <span style={{ fontSize: 12 }}>{AD_STATUS[records?.componentInfo?.reviewStatus as keyof typeof AD_STATUS]}</span>
  267. }
  268. },
  269. {
  270. title: '组件元素',
  271. dataIndex: 'elementName',
  272. key: 'elementName',
  273. width: 155,
  274. render: (value, records) => {
  275. return <>
  276. <Text type="secondary" style={{ fontSize: 12 }}>{value}</Text>
  277. <div style={{ maxWidth: 178 }}>
  278. {records.elementType === 'VIDEO' ? <Popover
  279. placement='right'
  280. content={< div >
  281. <Space style={{ maxWidth: 300, display: 'flex', flexFlow: 'row wrap', margin: '10px 0' }}>
  282. <video src={records.elementValue} style={{ width: 250 }} controls />
  283. </Space>
  284. </div >}
  285. destroyTooltipOnHide
  286. mouseEnterDelay={0.5}
  287. >
  288. <video src={records.elementValue} style={{ maxHeight: 40, maxWidth: 60 }} />
  289. </Popover> : records.elementType === 'IMAGE' ? <img src={records.elementValue} style={{ maxHeight: 40, maxWidth: 60 }} />
  290. : <Text style={{ fontSize: 12 }} ellipsis strong>{records.elementValue}</Text>}
  291. </div>
  292. </>
  293. }
  294. },
  295. {
  296. title: '元素审核结果',
  297. dataIndex: 'reviewStatus',
  298. key: 'reviewStatus',
  299. width: 120,
  300. render: (value) => {
  301. return <span style={{ fontSize: 12 }}>{AD_STATUS[value as keyof typeof AD_STATUS]}</span>
  302. }
  303. },
  304. {
  305. title: '驳回原因',
  306. dataIndex: 'elementRejectDetailInfo',
  307. key: 'elementRejectDetailInfo',
  308. width: 560,
  309. render: (value) => {
  310. return value ? <Text style={{ fontSize: 12 }}>{value?.map((item: { reason: any }) => item.reason)?.join(',')}</Text> : null
  311. }
  312. },
  313. {
  314. title: '影响版位',
  315. dataIndex: 'siteSetList',
  316. key: 'siteSetList',
  317. width: 125,
  318. render: (_, records) => {
  319. let siteSetList = records?.elementRejectDetailInfo?.siteSetList
  320. return siteSetList ? <Text style={{ fontSize: 12 }}>{siteSetList?.map((item: { siteSet: any }) => SITE_SET_ENUM[item?.siteSet as keyof typeof SITE_SET_ENUM])?.join(',')}</Text> : null
  321. }
  322. },
  323. ]
  324. }
  325. export const columnsLog = (): TableProps<any>['columns'] => [
  326. {
  327. title: '创意名称',
  328. dataIndex: 'creativeName',
  329. key: 'creativeName',
  330. width: 280,
  331. ellipsis: true,
  332. fixed: 'left',
  333. render: (value) => {
  334. return <span style={{ fontSize: "12px" }}>{value}</span>
  335. }
  336. },
  337. {
  338. title: '创意ID',
  339. dataIndex: 'creativeId',
  340. key: 'creativeId',
  341. align: 'center',
  342. width: 100,
  343. ellipsis: true,
  344. fixed: 'left',
  345. render: (value) => {
  346. return <span style={{ fontSize: "12px", cursor: 'pointer' }}>{value}</span>
  347. }
  348. },
  349. {
  350. title: '所属账号',
  351. dataIndex: 'accountId',
  352. key: 'accountId',
  353. align: 'center',
  354. width: 80,
  355. ellipsis: true,
  356. render: (value) => {
  357. return <span style={{ fontSize: "12px" }}>{value}</span>
  358. }
  359. },
  360. {
  361. title: '广告ID',
  362. dataIndex: 'adgroupId',
  363. key: 'adgroupId',
  364. align: 'center',
  365. width: 100,
  366. ellipsis: true,
  367. render: (value) => {
  368. return <span style={{ fontSize: "12px", cursor: 'pointer' }}>{value}</span>
  369. }
  370. },
  371. {
  372. title: '执行时间',
  373. dataIndex: 'createTime',
  374. key: 'createTime',
  375. width: 140,
  376. align: 'center',
  377. render: (value) => {
  378. return <span style={{ fontSize: 12 }}>{value}</span>
  379. }
  380. },
  381. {
  382. title: '操作者名字',
  383. dataIndex: 'operationByName',
  384. key: 'operationByName',
  385. width: 65,
  386. align: 'center',
  387. render: (value) => {
  388. return <span style={{ fontSize: 12 }}>{value}</span>
  389. }
  390. },
  391. {
  392. title: '操作类型名称',
  393. dataIndex: 'operationName',
  394. key: 'operationName',
  395. width: 70,
  396. align: 'center',
  397. render: (value) => {
  398. return <span style={{ fontSize: 12 }}>{value}</span>
  399. }
  400. },
  401. {
  402. title: '操作数',
  403. dataIndex: 'operationCount',
  404. key: 'operationCount',
  405. width: 60,
  406. align: 'center',
  407. render: (value) => {
  408. return <span style={{ fontSize: 12 }}>{value}</span>
  409. }
  410. },
  411. {
  412. title: '成功数',
  413. dataIndex: 'successCount',
  414. key: 'successCount',
  415. width: 60,
  416. align: 'center',
  417. render: (value) => {
  418. return <span style={{ fontSize: 12 }}>{value}</span>
  419. }
  420. },
  421. {
  422. title: '失败数',
  423. dataIndex: 'failCount',
  424. key: 'failCount',
  425. width: 60,
  426. align: 'center',
  427. render: (value) => {
  428. return <span style={value > 0 ? { color: 'red', fontSize: 12 } : { fontSize: 12 }}>{value}</span>
  429. }
  430. },
  431. {
  432. title: '状态',
  433. dataIndex: 'status',
  434. key: 'status',
  435. width: 70,
  436. align: 'center',
  437. render: (a: any) => {
  438. let obj = {
  439. '成功': 'success',
  440. '失败': 'error',
  441. '执行中': 'warning'
  442. }
  443. return <Badge status={obj[a as keyof typeof obj] as any} text={a} />
  444. }
  445. },
  446. {
  447. title: '完成时间',
  448. dataIndex: 'updateTime',
  449. key: 'updateTime',
  450. width: 140,
  451. align: 'center',
  452. render: (a: string) => {
  453. return <span style={{ fontSize: 12 }}>{a}</span>
  454. }
  455. },
  456. {
  457. title: '错误消息',
  458. dataIndex: 'errorMsg',
  459. key: 'errorMsg',
  460. width: 400,
  461. ellipsis: true,
  462. render: (value) => {
  463. return <span style={{ fontSize: 12 }}>{value || '--'}</span>
  464. }
  465. },
  466. {
  467. title: '操作参数',
  468. dataIndex: 'requestJson',
  469. key: 'requestJson',
  470. width: 400,
  471. ellipsis: true,
  472. render: (value) => {
  473. return <span style={{ fontSize: 12 }}>{value || '--'}</span>
  474. }
  475. },
  476. ]
  477. export default tableConfig