view.jsx 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. /*
  2. * @Author: dayan_hjm 产供销价值链
  3. * @Date: 2023-11-10 10:19:34
  4. * @Last Modified by: dayan_hjm
  5. * @Last Modified time: 2023-11-10 16:43:06
  6. */
  7. import React, { useState, useEffect, Component } from "react";
  8. import styles from "./style.less";
  9. import { useHistory, useLocation, withRouter } from "react-router-dom";
  10. import { observer, observable } from "mobx-react";
  11. import { message, Space, Form, Popconfirm, Modal, Tooltip, Icon, Button } from "antd";
  12. import mod from './mod';
  13. import { toJS } from "mobx";
  14. import RightBottomView from "./component/rightBottomView.jsx";
  15. import {
  16. timeService,
  17. numberService,
  18. checkToken,
  19. updateTimeService
  20. } from "./api";
  21. import 'animate.css';
  22. @withRouter
  23. class Gvc extends Component {
  24. // 构造函数,组件的实例创建时,最先执行
  25. constructor(props, context) {
  26. super(props, context);
  27. this.store = mod;
  28. this.state = {
  29. LeftHtml: [
  30. {
  31. txt_name: '碳酸锂',
  32. num1: 1222,
  33. num2: 1000,
  34. },
  35. {
  36. txt_name: '氢氧化钠',
  37. num1: 2525,
  38. num2: 25,
  39. },
  40. {
  41. txt_name: '氯化锂',
  42. num1: 3654,
  43. num2: 7541,
  44. },
  45. {
  46. txt_name: '金属锂',
  47. num1: 45,
  48. num2: 698,
  49. },
  50. ],
  51. updateTime: '',
  52. changGif: false,
  53. plannedCompletionData: [
  54. ],
  55. plannedCompletionNum: 1,
  56. manHourData: [
  57. ],
  58. manHourNum: 1,
  59. };
  60. this.timer = null //定时器,用于检测同步状态
  61. }
  62. componentWillMount() {
  63. if (window.location.host.indexOf("localhost") == -1) {
  64. this.getToken()
  65. }
  66. }
  67. async getToken() {
  68. if (!sessionStorage.getItem("tqcVToken")) {
  69. this.props.history.replace("/home/index");
  70. } else {
  71. await checkToken(sessionStorage.getItem("tqcVToken")).then(({ data, resultCode }) => {
  72. if (data?.userId) {
  73. // this.props.history.push('/')
  74. } else {
  75. this.props.history.replace("/home/index");
  76. }
  77. });
  78. }
  79. }
  80. componentDidMount() {
  81. this.fontMsgChange();
  82. this.getUrl();
  83. this.getUrl2()
  84. this.getUrl3();
  85. setTimeout(() => {
  86. this.videoStart();
  87. }, 200)
  88. setTimeout(() => {
  89. //替换gif
  90. this.setState({ changGif: true });
  91. }, 2000)
  92. }
  93. videoStart() {
  94. /* Chrome 浏览器的视频自动播放策略
  95. 1.始终允许静音模式下自动播放
  96. 2.在以下的情况中,带声音播放会被允许:
  97. ①用户已经与当前的域进行了交互(也就是click,tap事件)。
  98. ②在桌面设备上,用户的媒体参与度指数阈值已经超过,这意味着用户之前播放过有声视频。
  99. ③用户已经将网站添加到移动设备上的主屏幕或允在桌面上安装了PWA。
  100. 3.顶部帧可以将自动播放权限委派给其iframe,来允许自动播放声音
  101. 媒体参与度(Media Engagement)是指用户与媒体内容进行互动的程度,可以通过多个指标来衡量。这些指标主要包括观看时间、观看率、转化率、交互行为等。
  102. 可以通过:chrome://media-engagement/ 查看
  103. */
  104. const video = document.querySelector('.video2');
  105. console.log(video.play());
  106. const model = document.querySelector('.model')
  107. const btn = document.querySelector('button')
  108. // 第一种方法 引导用户去与页面交互实现播放
  109. async function play() {
  110. try {
  111. await video.play();
  112. //使用await的原因是因为video.play()方法返回的是一个Promise,所以在这里我们可以对他进行一些处理
  113. model.style.display = 'none';
  114. btn.removeEventListener('click', play);
  115. // 如果他自动播放了就隐藏按钮,消除点击事件
  116. } catch (err) {
  117. model.style.display = 'block';
  118. btn.addEventListener('click', play);
  119. // 如果Promise返回的是error就引导用户点击按钮,在调用play方法
  120. }
  121. }
  122. play();
  123. //第二种方法比较主流,类似的有网页版抖音以及B站
  124. function play() {
  125. video.muted = true;//设置视频为静音
  126. video.play();//调用播放方法
  127. const ctx = new AudioContext();
  128. const canAutoPlay = ctx.state === 'running'; //通过这个可以判断出视频能不能够自动播放 如何可以它的值就是“running” 否则为"suspended"
  129. // 如果是不能播放我们就执行下面的逻辑,其实就是类似于第一种方法,让用户与其交互
  130. ctx.close();
  131. if (canAutoPlay) {
  132. video.muted = false;
  133. model.style.display = 'none';
  134. btn.removeEventListener('click', play);
  135. }
  136. else {
  137. model.style.display = 'block';
  138. btn.addEventListener('click', play);
  139. }
  140. }
  141. play()
  142. }
  143. async getUrl() {
  144. await timeService().then(({ data = [], resultCode }) => {
  145. if (+resultCode === 0) {
  146. let plannedCompletionData = [], manHourData = [];
  147. data.map((x, i) => {
  148. if (x.indexName == '产量计划完成率') {
  149. plannedCompletionData.push({
  150. name: x.factoryName,
  151. value: x.indexValue * 100,
  152. })
  153. } else {
  154. manHourData.push({
  155. name: x.factoryName,
  156. value: x.indexValue * 100,
  157. })
  158. }
  159. });
  160. this.setState({ plannedCompletionData, manHourData, plannedCompletionNum: 1, manHourNum: 1 });
  161. }
  162. });
  163. }
  164. async getUrl2() {
  165. await numberService().then(({ data = [], resultCode }) => {
  166. if (+resultCode === 0) {
  167. let totalValue = 0, yearDecline = 0, yearSend = 0, productInventory = 0;
  168. data.map((x, i) => {
  169. if (x.indexName == '产值') {
  170. totalValue = x.indexValue
  171. } else if (x.indexName == '年度产量') {
  172. yearDecline = x.indexValue
  173. } else if (x.indexName == '产品库存') {
  174. yearSend = x.indexValue
  175. } else if (x.indexName == '年度发货量') {
  176. productInventory = x.indexValue
  177. }
  178. });
  179. this.store.saveState({ totalValue, yearDecline, yearSend, productInventory });
  180. setTimeout(() => {
  181. $(".shu1").numScroll();
  182. }, 2500)
  183. }
  184. });
  185. }
  186. async getUrl3() {
  187. await updateTimeService().then(({ data = [], resultCode }) => {
  188. if (+resultCode === 0) {
  189. this.setState({ updateTime: data?.[0]?.etlTime || '' })
  190. }
  191. });
  192. }
  193. componentDidCatch() {
  194. clearInterval(this.timer);
  195. this.timer = null;
  196. }
  197. fontMsgChange() {
  198. this.timer = setInterval(() => {
  199. const { plannedCompletionData, plannedCompletionNum, manHourData, manHourNum } = this.state;
  200. //产量计划完成率
  201. var p1 = document.getElementById('plannedCompletionBox');
  202. const datas_ = plannedCompletionData[plannedCompletionNum - 1];
  203. var res = '<div class="topMsg_box animate__animated animate__zoomIn"><span class="topMsg_number shu1">' + datas_?.value.toFixed(2) + '</span><span class="topMsg_number_2" style={{fontSize: "0.75em",color: "#fff"}}>%</span><p class="topMsg_number_p">' + datas_.name + '</p></div>';
  204. p1.innerHTML = res;
  205. //百万工时损工率
  206. var p2 = document.getElementById('manHourBox');
  207. const datas_2 = manHourData[manHourNum - 1];
  208. var res2 = '<div class="topMsg_box animate__animated animate__zoomIn"><span class="topMsg_number shu1">' + datas_2?.value.toFixed(2) + '</span><span class="topMsg_number_2">%</span><p class="topMsg_number_p">' + datas_2.name + '</p></div>';
  209. p2.innerHTML = res2;
  210. const num_ = plannedCompletionNum + 1 >= plannedCompletionData.length ? 1 : plannedCompletionNum + 1;
  211. const num_2 = manHourNum + 1 >= manHourData.length ? 1 : manHourNum + 1;
  212. this.setState({ plannedCompletionNum: num_, manHourNum: num_2 })
  213. }, 4000)
  214. }
  215. getLeftHtml(x, i) {
  216. return (
  217. <li>
  218. <div className={"top_div"}>
  219. <div class="animate__animated animate__pulse animate__slower animate__infinite">
  220. {i === 0 && <img className={"img1"} src={require("@assets/imgs/gvc/qiu1.png").default} alt="" />}
  221. {i === 1 && <img className={"img1"} src={require("@assets/imgs/gvc/qiu2.png").default} alt="" />}
  222. {i === 2 && <img className={"img1"} src={require("@assets/imgs/gvc/qiu3.png").default} alt="" />}
  223. {i === 3 && <img className={"img1"} src={require("@assets/imgs/gvc/qiu4.png").default} alt="" />}
  224. {i === 0 && <img src={require("@assets/imgs/gvc/qiuH1.png").default} alt="" class="img2 animate__animated animate__heartBeat animate__slower animate__infinite" />}
  225. {i === 1 && <img src={require("@assets/imgs/gvc/qiuH2.png").default} alt="" class="img2 animate__animated animate__heartBeat animate__slower animate__infinite" />}
  226. {i === 2 && <img src={require("@assets/imgs/gvc/qiuH3.png").default} alt="" class="img2 animate__animated animate__heartBeat animate__slower animate__infinite" />}
  227. {i === 3 && <img src={require("@assets/imgs/gvc/qiuH4.png").default} alt="" class="img2 animate__animated animate__heartBeat animate__slower animate__infinite" />}
  228. <span>{x.txt_name}</span>
  229. </div>
  230. </div>
  231. <div className="text">
  232. <div>
  233. <p>累计产量</p>
  234. <span class="topMsg_number shu1">{x.num1}</span><span class="topMsg_number_2" style={{ fontSize: "0.75em", color: "#fff" }}>吨</span>
  235. </div>
  236. <div>
  237. <p>产品库存</p>
  238. <span class="topMsg_number shu1">{x.num2}</span><span class="topMsg_number_2" style={{ fontSize: "0.75em", color: "#fff" }}>吨</span>
  239. </div>
  240. </div>
  241. </li>
  242. )
  243. }
  244. render() {
  245. const stores = this.store.state;
  246. let { totalValue, yearDecline, yearSend, productInventory } = this.store.state;
  247. let { LeftHtml, } = this.state;
  248. return (
  249. <div className={[styles.home_box + ' home_box']}>
  250. <div className={"all_box"}>
  251. <div className={"video_box"}>
  252. <video src={require("@assets/imgs/dataVImg/homeVideo2.mp4").default} autoplay="autoplay" loop="loop" class="video2 center_box2 animate__animated animate__fadeIn animate__delay-2s"></video>
  253. </div>
  254. <div className={"gvcHome home cbHome"}>
  255. <div className="leftContent">
  256. <ul>
  257. {
  258. LeftHtml.map((x, i) => {
  259. return this.getLeftHtml(x, i)
  260. })
  261. }
  262. </ul>
  263. </div>
  264. <div className="centerCon">
  265. </div>
  266. {/* 右侧信息栏 */}
  267. <div className="rightContent">
  268. <div class="bottomContent2 animate__animated animate__fadeInDown animate__slower animate__delay-1s">
  269. <div className="bottomContent bigDivPd">
  270. <Tooltip placement="bottom" title={' ● 近三年的碳排放强度、碳排放总量数据'}>
  271. <p className="topMsg_title">碳排放</p>
  272. </Tooltip>
  273. <div className="topMsg_content">
  274. <RightBottomView></RightBottomView>
  275. </div>
  276. </div>
  277. </div>
  278. </div>
  279. <div className="bottom_box">
  280. </div>
  281. </div>
  282. </div>
  283. </div>
  284. )
  285. }
  286. }
  287. export default Gvc;