trade.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. import { connect } from 'dva/index';
  2. import React, { Component } from 'react';
  3. import { Form, Tooltip as TooltipAntd, Radio, Spin } from 'antd';
  4. import {
  5. sldLlineRtextAddGoodsAddMargin,
  6. sldComLanguage,
  7. sldSvgIcon,
  8. getSldHorLineBgColor, formatNum,
  9. } from '@/utils/utils';
  10. import global from '@/global.less';
  11. import stat from '@/assets/css/stat.less';
  12. import SldScrollbars from '@/components/SldScrollbars';
  13. import moment from 'moment';
  14. import SldStatDate from '@/components/SldStatDate';
  15. import TradeOther from './trade_other';
  16. import TweenOne from 'rc-tween-one';
  17. import Children from 'rc-tween-one/lib/plugin/ChildrenPlugin';
  18. import defaultSettings from '@/defaultSettings';
  19. TweenOne.plugins.push(Children);
  20. @connect(({ common, global }) => ({
  21. common, global,
  22. }))
  23. @Form.create()
  24. export default class StatisticsTrade extends Component {
  25. constructor(props) {
  26. super(props);
  27. this.state = {
  28. loadedFlag: false,//顶部数据是否加载完成
  29. overViewLoading: false,//总览数据loading
  30. screenW: document.body.clientWidth,//屏幕宽度
  31. pvData: [
  32. {
  33. children: [
  34. {
  35. label: `${sldComLanguage('浏览量')}`,
  36. num: '',
  37. differenceNum: '',
  38. isUp: false,
  39. tip: `${sldComLanguage('统计时间内,全平台所有页面被访问的次数总和')}`,
  40. mapValue: 'viewNum',
  41. mapDifferentValue: 'previousViewNum',
  42. },
  43. {
  44. label: `${sldComLanguage('访客数')}`,
  45. num: '',
  46. differenceNum: '',
  47. isUp: false,
  48. tip: `${sldComLanguage('统计时间内,全平台所有页面的去重人数总和')}`,
  49. mapValue: 'visitorNum',
  50. mapDifferentValue: 'previousVisitorNum',
  51. },
  52. ],
  53. },
  54. // {
  55. // children: [
  56. // {
  57. // label: `${sldComLanguage('下单金额(元)')}`,
  58. // num: '',
  59. // differenceNum: '',
  60. // isUp: false,
  61. // tip: `${sldComLanguage('统计时间内,全平台用户成功提交订单的金额总和')}`,
  62. // mapValue: 'orderSubmitAmount',
  63. // mapDifferentValue: 'previousOrderSubmitAmount',
  64. // isMoney: true,
  65. // },
  66. // {
  67. // label: `${sldComLanguage('下单数')}`,
  68. // num: '',
  69. // differenceNum: '',
  70. // isUp: false,
  71. // tip: `${sldComLanguage('统计时间内,全平台用户成功提交订单的笔数总和')}`,
  72. // mapValue: 'orderSubmitNum',
  73. // mapDifferentValue: 'previousOrderSubmitNum',
  74. // },
  75. // {
  76. // label: `${sldComLanguage('下单人数')}`,
  77. // num: '',
  78. // differenceNum: '',
  79. // isUp: false,
  80. // tip: `${sldComLanguage('统计时间内,全平台成功提交订单的去重人数总和')}`,
  81. // mapValue: 'orderSubmitMemberNum',
  82. // mapDifferentValue: 'previousOrderSubmitMemberNum',
  83. // },
  84. // {
  85. // label: `${sldComLanguage('下单客单价(元)')}`,
  86. // num: '',
  87. // differenceNum: '',
  88. // isUp: false,
  89. // tip: `${sldComLanguage('统计时间内,全平台下单金额/下单人数')}`,
  90. // mapValue: 'orderSubmitAtv',
  91. // mapDifferentValue: 'previousOrderSubmitAtv',
  92. // isMoney: true,
  93. // },
  94. // ],
  95. // },
  96. // {
  97. // children: [
  98. // {
  99. // label: `${sldComLanguage('支付金额(元)')}`,
  100. // num: '',
  101. // differenceNum: '',
  102. // isUp: false,
  103. // tip: `${sldComLanguage('统计时间内,全平台用户成功支付的金额总和')}`,
  104. // mapValue: 'orderPayAmount',
  105. // mapDifferentValue: 'previousOrderPayAmount',
  106. // isMoney: true,
  107. //
  108. // },
  109. // {
  110. // label: `${sldComLanguage('支付订单数')}`,
  111. // num: '',
  112. // differenceNum: '',
  113. // isUp: false,
  114. // tip: `${sldComLanguage('统计时间内,全平台用户成功支付的订单数量总和')}`,
  115. // mapValue: 'orderPayNum',
  116. // mapDifferentValue: 'previousOrderPayNum',
  117. // },
  118. // {
  119. // label: `${sldComLanguage('支付人数')}`,
  120. // num: '',
  121. // differenceNum: '',
  122. // isUp: false,
  123. // tip: `${sldComLanguage('统计时间内,全平台成功付款的去重人数总和')}`,
  124. // mapValue: 'orderPayMemberNum',
  125. // mapDifferentValue: 'previousOrderPayMemberNum',
  126. // },
  127. // {
  128. // label: `${sldComLanguage('支付客单价(元)')}`,
  129. // num: '',
  130. // differenceNum: '',
  131. // isUp: false,
  132. // tip: `${sldComLanguage('统计时间内,全平台支付金额/下单人数')}`,
  133. // mapValue: 'orderPayAtv',
  134. // mapDifferentValue: 'previousOrderPayAtv',
  135. // isMoney: true,
  136. // },
  137. // ],
  138. // },
  139. ],
  140. tradeOverviewParams: {
  141. startTime: (moment().subtract(1, 'days').format('YYYY-MM-DD') + ' 00:00:00'),
  142. endTime: (moment().subtract(1, 'days').format('YYYY-MM-DD') + ' 23:59:59:999'),
  143. },
  144. curTradeOverview: 'all',//交易总览的终端类型,默认为all 全部
  145. chartsInfoData: {},
  146. };
  147. };
  148. componentDidMount() {
  149. this.resize();
  150. this.props.dispatch({
  151. type: 'global/getLayoutCollapsed',
  152. });
  153. window.addEventListener('resize', this.resize, { passive: true });
  154. this.getTradeOverview();
  155. //解决柱形图在各别电脑会出现抖动的问题
  156. document.querySelector('section.ant-layout:not(.ant-layout-has-sider)').style.width = '100vw';
  157. }
  158. resize = () => {
  159. this.setState({ screenW: document.body.clientWidth });
  160. };
  161. //获取交易总览的数据
  162. getTradeOverview = () => {
  163. const { dispatch } = this.props;
  164. const { pvData, tradeOverviewParams, curTradeOverview, chartsInfoData } = this.state;
  165. let params = { ...tradeOverviewParams };
  166. if (curTradeOverview != 'all') {
  167. params.terminalType = curTradeOverview;
  168. }
  169. this.setState({ overViewLoading: true });
  170. dispatch({
  171. type: 'statistics/get_analysis_trade_overview',
  172. payload: params,
  173. callback: (res) => {
  174. if (res.state === 200) {
  175. chartsInfoData.pvPayRate = res.data.pvPayRate || '--';
  176. chartsInfoData.pvSubmitRate = res.data.pvSubmitRate || '--';
  177. chartsInfoData.submitPayRate = res.data.submitPayRate || '--';
  178. pvData.forEach((item, index) => {
  179. item.children.forEach((item2, index2) => {
  180. if (res.data[item2.mapDifferentValue] && res.data[item2.mapDifferentValue].indexOf('-') != 0) {
  181. //上涨
  182. item2['differenceNum'] = '+' + res.data[item2.mapDifferentValue];
  183. item2.isUp = true;
  184. } else {
  185. //下降
  186. item2['differenceNum'] = res.data[item2.mapDifferentValue];
  187. item2.isUp = false;
  188. }
  189. if (!res.data[item2.mapValue]) {
  190. item2['num'] = '';
  191. return;
  192. }
  193. item2['num'] = item2.isMoney ? parseFloat(res.data[item2.mapValue]).toFixed(2) : res.data[item2.mapValue];
  194. });
  195. });
  196. this.setState({ pvData, chartsInfoData });
  197. }
  198. this.setState({ overViewLoading: false, loadedFlag: true });
  199. },
  200. });
  201. };
  202. //tab切换事件
  203. handleChangeTab = (e, type) => {
  204. this.setState({ [type]: e.target.value }, () => {
  205. if (type == 'curTradeOverview') {
  206. this.getTradeOverview();
  207. }
  208. });
  209. };
  210. //时间筛选器返回的时间数据
  211. updateSelectDate = (date, index) => {
  212. let { tradeOverviewParams } = this.state;
  213. let _this = this;
  214. if (index == '_trade_over_view') {
  215. //交易总览的时间筛选
  216. tradeOverviewParams = { ...tradeOverviewParams, ...date };
  217. this.setState({ tradeOverviewParams }, () => {
  218. _this.getTradeOverview();
  219. });
  220. }
  221. };
  222. render() {
  223. const { chartsInfoData, pvData, curTradeOverview, screenW, overViewLoading, loadedFlag } = this.state;
  224. const leftW = this.props.global != undefined && this.props.global.collapsed != undefined && this.props.global.collapsed ? 90 : 150;
  225. let topItemW = (screenW - leftW - 20 - 40 - 400 - 44) / 4;
  226. return (
  227. <div className={`${stat.trade_stat} ${stat.stat_part}`}
  228. style={{ flex: 1, overflow: 'auto' }}>
  229. <SldScrollbars
  230. autoHeight
  231. autoHeightMin={100}
  232. autoHeightMax={document.body.clientHeight - 60}
  233. >
  234. <div className={`${stat.label_panel} ${global.flex_row_start_center}`}>
  235. {sldLlineRtextAddGoodsAddMargin(defaultSettings.primaryColor, `${sldComLanguage('交易总览')}`, 10, 0, 0)}
  236. <div style={{ marginLeft: 10 }}>
  237. <SldStatDate idIndex={'_trade_over_view'}
  238. updateSelectDate={(date) => this.updateSelectDate(date, '_trade_over_view')}/>
  239. </div>
  240. </div>
  241. {getSldHorLineBgColor(1, 'rgba(216, 216, 216, .5)')}
  242. <div className={`${stat.change_trend_radio}`} style={{ marginLeft: 25, marginTop: 15, marginBottom: 15 }}>
  243. <span>{sldComLanguage('筛选项:')}</span>
  244. <Radio.Group size={'small'} onChange={(e) => this.handleChangeTab(e, 'curTradeOverview')}
  245. defaultValue={curTradeOverview}>
  246. <Radio.Button value="all">全部</Radio.Button>
  247. <Radio.Button value="android">Android</Radio.Button>
  248. <Radio.Button value="ios">IOS</Radio.Button>
  249. <Radio.Button value="pc">PC</Radio.Button>
  250. <Radio.Button value="xcx">微信小程序</Radio.Button>
  251. <Radio.Button value="h5">H5</Radio.Button>
  252. </Radio.Group>
  253. </div>
  254. <Spin spinning={overViewLoading}>
  255. <div className={`${stat.preview_stat_panel}`}>
  256. <div className={`${stat.charts_panel} ${stat.funnel}`}>
  257. <div className={stat.part}>
  258. {/*<div className={global.flex_column_center_center}>*/}
  259. {/* <div className={stat.center_item_top}>*/}
  260. {/* <div className={`${stat.top_content} ${global.flex_row_center_center}`}>*/}
  261. {/* <img className={stat.funnel_center_img} src={require('@/assets/charts_li_icon-3.png')} alt=''/>*/}
  262. {/* <span className={stat.funnel_center_img_desc}>{sldComLanguage('访问')}</span>*/}
  263. {/* </div>*/}
  264. {/* </div>*/}
  265. {/* <div className={stat.center_item_center}>*/}
  266. {/* <div className={`${stat.center_content} ${global.flex_row_center_center}`}>*/}
  267. {/* <img className={stat.funnel_center_img} src={require('@/assets/charts_li_icon-1.png')} alt=''/>*/}
  268. {/* <span className={stat.funnel_center_img_desc}>{sldComLanguage('下单')}</span>*/}
  269. {/* </div>*/}
  270. {/* </div>*/}
  271. {/* <div className={stat.center_item_bottom}>*/}
  272. {/* <div className={`${stat.bottom_content} ${global.flex_row_center_center}`}>*/}
  273. {/* <img className={stat.funnel_center_img} src={require('@/assets/charts_li_icon-2.png')} alt=''/>*/}
  274. {/* <span className={stat.funnel_center_img_desc}>{sldComLanguage('支付')}</span>*/}
  275. {/* </div>*/}
  276. {/* </div>*/}
  277. {/*</div>*/}
  278. {/*<div className={stat.left_top_line}></div>*/}
  279. {/*<div className={stat.left_bottom_line}></div>*/}
  280. {/*<div className={stat.right_line}></div>*/}
  281. {/*<div className={stat.left_top_content}>*/}
  282. {/* <p className={stat.side_content_desc}>{sldComLanguage('访问-下单转化率')}</p>*/}
  283. {/* <p className={stat.side_content_desc}>{chartsInfoData.pvSubmitRate || '--'}</p>*/}
  284. {/*</div>*/}
  285. {/*<div className={stat.left_bottom_content}>*/}
  286. {/* <p className={stat.side_content_desc}>{sldComLanguage('下单-支付转化率')}</p>*/}
  287. {/* <p className={stat.side_content_desc}>{chartsInfoData.submitPayRate || '--'}</p>*/}
  288. {/*</div>*/}
  289. {/*<div className={stat.right_content}>*/}
  290. {/* <p className={stat.side_content_desc}>{sldComLanguage('访问-支付转化率')}</p>*/}
  291. {/* <p className={stat.side_content_desc}>{chartsInfoData.pvPayRate || '--'}</p>*/}
  292. {/*</div>*/}
  293. </div>
  294. </div>
  295. {pvData.map((item2, index2) => (
  296. <div key={index2} className={`${stat.stat_item}`}>
  297. <ul className={`${global.flex_row_start_center}`}>
  298. {item2.children.map((item, index) => (
  299. <li key={index} style={{ width: topItemW }}>
  300. <div className={`${stat.up_label} ${global.flex_row_start_center}`}>
  301. <span>{item.label}</span>
  302. <TooltipAntd placement="right" title={item.tip}>
  303. <img src={require('@/assets/pv_icon.png')} alt=''/>
  304. </TooltipAntd>
  305. </div>
  306. <div style={{ marginLeft: item.isMoney ? '-6px' : '' }}
  307. className={`${stat.num}`}
  308. title={item.num ? item.num : 0}>
  309. {loadedFlag && (
  310. item.num > 10000
  311. ? formatNum(item.num, item.isMoney ? 2 : 0)
  312. : <TweenOne animation={{
  313. Children: {
  314. value: item.num, floatLength: item.isMoney ? 2 : 0,
  315. formatMoney: true,
  316. },
  317. duration: 1000,
  318. }}/>
  319. )}
  320. </div>
  321. <div className={`${stat.down_difference}`}>
  322. <span className={`${stat.label}`}>{sldComLanguage('较上期')}</span>
  323. {item.differenceNum ? (<span style={{ color: item.isUp ? '#52C41A' : '#C41A1A' }}
  324. className={`${stat.difference_num}`}>{item.differenceNum}<span
  325. className={`${stat.custom_svg_iconfont}`}>{sldSvgIcon(item.isUp ? '#52C41A' : '#C41A1A', 16, 16, item.isUp ? 'shangsheng' : 'xiajiang')}</span></span>) : (
  326. <span>--</span>)}
  327. </div>
  328. </li>
  329. ))}
  330. </ul>
  331. </div>
  332. ))}
  333. </div>
  334. </Spin>
  335. <TradeOther/>
  336. </SldScrollbars>
  337. </div>
  338. );
  339. }
  340. }