planDetail.tsx 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. import Tables from "@/components/Tables";
  2. import useEcharts from "@/Hook/useEcharts";
  3. import { CloudDownloadOutlined, RedoOutlined } from "@ant-design/icons";
  4. import { Button, Card, DatePicker, Modal, Radio, Space, Spin, Statistic, Tag } from "antd";
  5. import moment, { Moment } from "moment";
  6. import React, { useCallback, useEffect, useState } from "react";
  7. import { useModel } from "umi";
  8. import columns from './tableConfig'
  9. import { compare } from '@/utils/utils'
  10. import { formatDate, downloadFile1 } from '@/utils/downloadFile'
  11. import { downLoadSpeedApi } from "@/services/adMonitor/adMonitor";
  12. import '../index.less'
  13. type Props = {
  14. visible?: boolean,
  15. onClose?: () => void,
  16. data?: any,
  17. dataStartTime?: string
  18. dataEndTime?: string
  19. }
  20. function PlanDetail(props: Props) {
  21. const { adgroupId, putUserId, accountId } = props.data
  22. const { getCostSpeed } = useModel('useAdMonitor.useMonitor')
  23. /** 变量start */
  24. const { visible, onClose, dataStartTime, dataEndTime } = props
  25. const { LineMonitor } = useEcharts()
  26. const [lineDis, setLineDis] = useState<any[]>([])
  27. const [queryForm, setQueryForm] = useState<any>({ adgroupId, accountId, sysUserId: putUserId, timeUnit: dataStartTime || dataEndTime ? 'day' : 'hour', dataStartTime: dataStartTime || moment().format('YYYY-MM-DD'), dataEndTime: dataEndTime || moment().format('YYYY-MM-DD') })
  28. const [speedData, setSpeedData] = useState<{ totalCost: string, viewCount: string, clickCount: string, clickRate: string, orderRate: string, costSpeed: string, adCostSpeedVOList: any[] }>()
  29. const [adCostSpeedDtoListOri, setAdCostSpeedDtoListOri] = useState<any[]>([])
  30. const [downLoadLoading, setDownLoadLoading] = useState<boolean>(false)
  31. /** 变量end */
  32. useEffect(() => {
  33. getList()
  34. }, [queryForm])
  35. const getList = useCallback(() => {
  36. getCostSpeed.run(queryForm).then((res: any) => {
  37. if (res?.data) {
  38. setSpeedData(() => res?.data)
  39. setAdCostSpeedDtoListOri(() => [...res?.data?.adCostSpeedVOList])
  40. let spendData: any = { legendName: '花费' }
  41. let exposureData: any = { legendName: '曝光次数' }
  42. res?.data?.adCostSpeedVOList?.forEach((item: { day: string, time: string, cost: string, viewCount: string }) => {
  43. if (queryForm.timeUnit === 'hour') {
  44. spendData[item?.time] = item?.cost
  45. exposureData[item?.time] = item?.viewCount
  46. } else {
  47. spendData[item?.day] = item?.cost
  48. exposureData[item?.day] = item?.viewCount
  49. }
  50. });
  51. setLineDis(() => [spendData, exposureData])
  52. }
  53. })
  54. }, [queryForm, adCostSpeedDtoListOri, speedData])
  55. // 设置获取图标数据区间 设置时间
  56. const setTime = useCallback((str: string[]) => {
  57. setQueryForm({ ...queryForm, dataStartTime: str[0], dataEndTime: str[1] })
  58. }, [queryForm])
  59. const disabledDate = (date: Moment) => {
  60. if (queryForm?.timeUnit === 'hour') {
  61. return date && (date < moment().startOf('day').subtract(9, 'day') || date > moment().endOf('day'))
  62. } else {
  63. return false
  64. }
  65. }
  66. const downLoadExcel = useCallback(() => {
  67. setDownLoadLoading(true)
  68. downLoadSpeedApi(queryForm).then(res => {
  69. setDownLoadLoading(false)
  70. downloadFile1(res, 'octet-stream', formatDate(new Date()) + ".xlsx")
  71. }).catch(() => setDownLoadLoading(false))
  72. }, [queryForm, downLoadLoading])
  73. return <Modal
  74. title={<><Space>
  75. <span style={{ fontSize: 15, color: '#999' }}>计划名称:<span style={{ color: '#40a9ff' }}>{props?.data?.campaignName || '--'}</span></span>
  76. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  77. <span style={{ fontSize: 15, color: '#999' }}>广告名称:<span style={{ color: '#40a9ff' }}>{props?.data?.adgroupName}</span></span>
  78. </Space></>}
  79. visible={visible}
  80. width={900}
  81. bodyStyle={{ padding: '0 5px', backgroundColor: '#f2f2f2' }}
  82. footer={null}
  83. onCancel={() => { onClose && onClose() }}
  84. >
  85. <Space direction='vertical' style={{ width: '100%', marginBottom: 10 }}>
  86. <Card hoverable size='small'>
  87. <div style={{ display: 'flex', justifyContent: 'space-between' }}>
  88. <Space>
  89. <DatePicker.RangePicker disabledDate={disabledDate} allowClear={false} onChange={(mo: any, str: string[]) => { setTime(str) }} value={(queryForm?.dataStartTime && queryForm?.dataEndTime ? [moment(queryForm?.dataStartTime), moment(queryForm?.dataEndTime)] : null) as any} />
  90. <Radio.Group
  91. value={queryForm?.timeUnit}
  92. buttonStyle="solid"
  93. size='small'
  94. onChange={(e) => {
  95. if (e.target.value === 'hour') {
  96. setQueryForm({ ...queryForm, timeUnit: e.target.value, dataStartTime: moment().format('YYYY-MM-DD'), dataEndTime: moment().format('YYYY-MM-DD') })
  97. } else {
  98. setQueryForm({ ...queryForm, timeUnit: e.target.value })
  99. }
  100. }}>
  101. {/* <Radio.Button value="minute">5min</Radio.Button> */}
  102. <Radio.Button value="day">分天</Radio.Button>
  103. <Radio.Button value="hour">小时</Radio.Button>
  104. </Radio.Group>
  105. </Space>
  106. <Space style={{ marginRight: 30 }}>
  107. <span style={{ fontSize: 10, color: '#999' }}>刷新时间:{getCostSpeed?.data?.reqTime}</span>
  108. <Tag color="#2db7f5" onClick={() => { getList() }}><RedoOutlined /> 刷新</Tag>
  109. </Space>
  110. </div>
  111. </Card>
  112. <Card
  113. hoverable
  114. title='数据展示'
  115. >
  116. <Spin spinning={getCostSpeed?.loading}>
  117. <div className='overviewData'>
  118. <div>
  119. <div>总消耗</div>
  120. <Statistic value={speedData?.totalCost || 0} valueStyle={{ color: '#03A613', fontSize: 16 }} />
  121. </div>
  122. <div>
  123. <div>曝光次数</div>
  124. <Statistic value={speedData?.viewCount || 0} valueStyle={{ fontSize: 16 }} />
  125. </div>
  126. <div>
  127. <div>点击次数</div>
  128. <Statistic value={speedData?.clickCount || 0} valueStyle={{ fontSize: 16 }} />
  129. </div>
  130. <div>
  131. <div>点击率</div>
  132. <Statistic value={(speedData?.clickRate ? Number(speedData?.clickRate) * 100 : 0).toFixed(2)} precision={2} valueStyle={{ color: '#3f8600', fontSize: 16 }} suffix="%" />
  133. </div>
  134. <div>
  135. <div>所选时间内平均消耗速度</div>
  136. <Statistic value={speedData?.costSpeed ? Number(speedData?.costSpeed).toFixed(2) : 0} valueStyle={{ color: '#cf1322', fontSize: 16 }} />
  137. </div>
  138. </div>
  139. </Spin>
  140. </Card>
  141. <Card
  142. hoverable
  143. title='趋势图'
  144. >
  145. <div style={{ width: '100%', height: 260, textAlign: 'center' }}>
  146. {getCostSpeed?.loading ? <Spin /> : <LineMonitor style={{ width: '100%', height: 260 }} series smooth data={lineDis} />}
  147. </div>
  148. </Card>
  149. <Card
  150. hoverable
  151. title={<Space>
  152. <div>明细表</div>
  153. <Button size="small" icon={<CloudDownloadOutlined />} loading={downLoadLoading} onClick={downLoadExcel}>下载</Button>
  154. </Space>}
  155. >
  156. <Tables
  157. columns={columns(queryForm?.timeUnit)}
  158. dataSource={speedData?.adCostSpeedVOList || []}
  159. total={speedData?.adCostSpeedVOList?.length}
  160. loading={getCostSpeed?.loading}
  161. size="small"
  162. bordered
  163. sortDirections={['ascend', 'descend', null]}
  164. onChange={(pagination: any, filters: any, sorter: any) => {
  165. if (JSON.stringify(sorter) !== '{}') {
  166. let { field, order } = sorter // descend 降序 大到小 ascend 升序 小到大
  167. if (JSON.stringify(speedData) !== '{}') {
  168. setSpeedData({ ...speedData as any, adCostSpeedVOList: order ? speedData?.adCostSpeedVOList?.sort(compare(field, order)) : [...adCostSpeedDtoListOri] })
  169. }
  170. }
  171. }}
  172. />
  173. </Card>
  174. </Space>
  175. </Modal>
  176. }
  177. export default React.memo(PlanDetail)