Compare commits
	
		
			16 Commits
		
	
	
		
			master
			...
			7ddae1b3a4
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					7ddae1b3a4 | ||
| 
						 | 
					61477cdd30 | ||
| 
						 | 
					6e5badf01a | ||
| 311cdfc5f7 | |||
| 
						 | 
					bc8b68e449 | ||
| 
						 | 
					024f4bcf14 | ||
| 
						 | 
					361aedd4ad | ||
| 
						 | 
					60c6fdda79 | ||
| 
						 | 
					15708c0eef | ||
| 
						 | 
					2996c061dc | ||
| 
						 | 
					9894aeca50 | ||
| 
						 | 
					9f7652d9f3 | ||
| 
						 | 
					e854b966dc | ||
| 
						 | 
					dff017a5a2 | ||
| 
						 | 
					e796a07e66 | ||
| 
						 | 
					43635ff398 | 
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						@@ -1,7 +1,7 @@
 | 
			
		||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
 | 
			
		||||
 | 
			
		||||
# dependencies
 | 
			
		||||
/node_modules
 | 
			
		||||
**/node_modules
 | 
			
		||||
/.pnp
 | 
			
		||||
.pnp.js
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -70,6 +70,7 @@
 | 
			
		||||
  "scripts": {
 | 
			
		||||
    "start": "node scripts/start.js",
 | 
			
		||||
    "build": "node scripts/build.js",
 | 
			
		||||
    "server": "node websocket/server.js",
 | 
			
		||||
    "test": "node scripts/test.js"
 | 
			
		||||
  },
 | 
			
		||||
  "eslintConfig": {
 | 
			
		||||
 
 | 
			
		||||
@@ -29,6 +29,8 @@
 | 
			
		||||
  <body>
 | 
			
		||||
    <noscript>You need to enable JavaScript to run this app.</noscript>
 | 
			
		||||
    <div id="root"></div>
 | 
			
		||||
    <!-- <div id="alarm-list-container"></div> -->
 | 
			
		||||
 | 
			
		||||
    <!--
 | 
			
		||||
      This HTML file is a template.
 | 
			
		||||
      If you open it directly in the browser, you will see an empty page.
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,7 @@ import { Switch } from "antd";
 | 
			
		||||
import { createPortal } from "react-dom";
 | 
			
		||||
 | 
			
		||||
const Menus = ["窑炉总览", "窑炉内部", "退火监测", "质检统计", "能耗分析"];
 | 
			
		||||
 | 
			
		||||
const LUNBO_INTERVAL = 60 * 1000;
 | 
			
		||||
function App() {
 | 
			
		||||
  const { styles, value, setValue } = useSlider(100);
 | 
			
		||||
  const [navActive, setNavActive] = useState("窑炉总览");
 | 
			
		||||
@@ -22,7 +22,7 @@ function App() {
 | 
			
		||||
    if (lunbo) {
 | 
			
		||||
      timer = setInterval(() => {
 | 
			
		||||
        handleMenuChange(Menus[(Menus.indexOf(navActive) + 1) % Menus.length]);
 | 
			
		||||
      }, 5000);
 | 
			
		||||
      }, LUNBO_INTERVAL);
 | 
			
		||||
    }
 | 
			
		||||
    return () => {
 | 
			
		||||
      clearInterval(timer);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								src/assets/Icon/dontknowwhatitis.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 5.9 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/Icon/lightnen.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 7.7 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/Icon/oilstation.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 5.3 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/warn-bg.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 2.0 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/warn-icon.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 2.2 KiB  | 
@@ -109,6 +109,7 @@ function WindFrequence(props) {
 | 
			
		||||
      },
 | 
			
		||||
    };
 | 
			
		||||
  } else {
 | 
			
		||||
    console.log('runstate changeD!......')
 | 
			
		||||
    dataList =
 | 
			
		||||
      runState != null
 | 
			
		||||
        ? Object.keys(runState).map((fan) => ({
 | 
			
		||||
 
 | 
			
		||||
@@ -57,7 +57,7 @@ function WindFrequence(props) {
 | 
			
		||||
        currentTempList[1 + lines.indexOf(dataSource) + "#"]) ||
 | 
			
		||||
        []
 | 
			
		||||
    );
 | 
			
		||||
  }, [dataSource]);
 | 
			
		||||
  }, [dataSource, currentTempList]);
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <GraphBase
 | 
			
		||||
 
 | 
			
		||||
@@ -35,10 +35,10 @@ const EnergyCostRealtime = () => {
 | 
			
		||||
                  paddingRight: "6px",
 | 
			
		||||
                }}
 | 
			
		||||
              >
 | 
			
		||||
                余热发电(实时)
 | 
			
		||||
                余热发电(昨日)
 | 
			
		||||
              </i>
 | 
			
		||||
              <span style={{ fontSize: "17px", color: "#3ce8ff" }}>
 | 
			
		||||
                {(+energyInfo?.elecQty2)?.toFixed(2) || 0}kWh
 | 
			
		||||
                {(+energyInfo?.elecQty1)?.toFixed(2) || 0}kWh
 | 
			
		||||
              </span>
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
@@ -66,7 +66,7 @@ const EnergyCostRealtime = () => {
 | 
			
		||||
                  paddingRight: "6px",
 | 
			
		||||
                }}
 | 
			
		||||
              >
 | 
			
		||||
                水耗量
 | 
			
		||||
                水耗量(昨日)
 | 
			
		||||
              </i>
 | 
			
		||||
              <span style={{ fontSize: "17px", color: "#3ce8ff" }}>
 | 
			
		||||
                {(+energyInfo?.waterQty)?.toFixed(2) || 0}Km³
 | 
			
		||||
@@ -80,7 +80,7 @@ const EnergyCostRealtime = () => {
 | 
			
		||||
                  paddingRight: "6px",
 | 
			
		||||
                }}
 | 
			
		||||
              >
 | 
			
		||||
                天然气I
 | 
			
		||||
                天然气I(累计)
 | 
			
		||||
              </i>
 | 
			
		||||
              <span style={{ fontSize: "17px", color: "#3ce8ff" }}>
 | 
			
		||||
                {energyInfo?.ngQty1 || "0Nm³"}
 | 
			
		||||
@@ -94,7 +94,7 @@ const EnergyCostRealtime = () => {
 | 
			
		||||
                  paddingRight: "6px",
 | 
			
		||||
                }}
 | 
			
		||||
              >
 | 
			
		||||
                电耗量
 | 
			
		||||
                电耗量(昨日)
 | 
			
		||||
              </i>
 | 
			
		||||
              <span style={{ fontSize: "17px", color: "#3ce8ff" }}>
 | 
			
		||||
                {(+energyInfo?.elecQty2)?.toFixed(2) || 0}kWh
 | 
			
		||||
@@ -108,7 +108,7 @@ const EnergyCostRealtime = () => {
 | 
			
		||||
                  paddingRight: "6px",
 | 
			
		||||
                }}
 | 
			
		||||
              >
 | 
			
		||||
                天然气II
 | 
			
		||||
                天然气II(累计)
 | 
			
		||||
              </i>
 | 
			
		||||
              <span style={{ fontSize: "17px", color: "#3ce8ff" }}>
 | 
			
		||||
                {energyInfo?.ngQty2 || "0Nm³"}
 | 
			
		||||
 
 | 
			
		||||
@@ -44,6 +44,7 @@ function GraphBase(props) {
 | 
			
		||||
    selectWidth,
 | 
			
		||||
    legend,
 | 
			
		||||
  } = props;
 | 
			
		||||
  const descSmall = props.descSmall || false;
 | 
			
		||||
  const iconSrc = useIcon(icon);
 | 
			
		||||
  const colors = useMemo(() => ["#ffd160", "#2760ff", "#15e8f5"], []);
 | 
			
		||||
  const [showChart, setShowChart] = useState(true);
 | 
			
		||||
@@ -72,9 +73,9 @@ function GraphBase(props) {
 | 
			
		||||
          <span
 | 
			
		||||
            style={{
 | 
			
		||||
              color: "#fff",
 | 
			
		||||
              fontSize: "14px",
 | 
			
		||||
              fontSize: "calc(14px * var(--scale))",
 | 
			
		||||
              lineHeight: 1,
 | 
			
		||||
              paddingLeft: "12px",
 | 
			
		||||
              paddingLeft: "calc(12px * var(--scale))",
 | 
			
		||||
            }}
 | 
			
		||||
          >
 | 
			
		||||
            - 无 -
 | 
			
		||||
@@ -105,7 +106,7 @@ function GraphBase(props) {
 | 
			
		||||
      <div className={cls.graphBaseTitle}>
 | 
			
		||||
        <img src={iconSrc} alt="#" />
 | 
			
		||||
        <h2>{title}</h2>
 | 
			
		||||
        {desc && <div className={cls.graphBaseDesc}>{desc}</div>}
 | 
			
		||||
        {desc && <div className={`${cls.graphBaseDesc} ${descSmall ? cls.graphBaseDescSmall : ''}`}>{desc}</div>}
 | 
			
		||||
      </div>
 | 
			
		||||
      <div className={cls.graphBaseContent}>
 | 
			
		||||
        {switchOptions && (
 | 
			
		||||
 
 | 
			
		||||
@@ -93,6 +93,11 @@
 | 
			
		||||
	color: #76fff9;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.graphBaseDescSmall {
 | 
			
		||||
	font-size: 16px;
 | 
			
		||||
	color: #76fff9;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.graphBaseSwitch {
 | 
			
		||||
	position: absolute;
 | 
			
		||||
	top: 30px;
 | 
			
		||||
 
 | 
			
		||||
@@ -9,6 +9,7 @@
 | 
			
		||||
 | 
			
		||||
.xc-date-selector-menu .ant-select-item-option-content {
 | 
			
		||||
    text-align: center;
 | 
			
		||||
    font-size: calc(14px * var(--scale));
 | 
			
		||||
 }
 | 
			
		||||
 | 
			
		||||
.xc-date-selector-menu .ant-select-item-option-selected {
 | 
			
		||||
@@ -20,10 +21,16 @@
 | 
			
		||||
    background-color: #02457E !important;
 | 
			
		||||
    color: #fff !important;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.xc-date-selector-menu .ant-select-item-option {
 | 
			
		||||
    /* padding: 5px 8px; */
 | 
			
		||||
    padding: .3em .35em;
 | 
			
		||||
    min-height: unset;
 | 
			
		||||
}
 | 
			
		||||
/* 
 | 
			
		||||
.ant-select-selector::after {
 | 
			
		||||
    content: '\25BC' !important;
 | 
			
		||||
    visibility: visible !important; 
 | 
			
		||||
    visibility: visible !important; L
 | 
			
		||||
    position: absolute;
 | 
			
		||||
    top: 2px;
 | 
			
		||||
    right: 22px;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,4 @@
 | 
			
		||||
import * as echarts from "echarts";
 | 
			
		||||
import { randomInt } from "../../../../utils";
 | 
			
		||||
 | 
			
		||||
export default function getOptions(seriesData, name) {
 | 
			
		||||
  const colors = [
 | 
			
		||||
 
 | 
			
		||||
@@ -33,9 +33,9 @@ const SmokeTrendChart = (props) => {
 | 
			
		||||
    switch (period) {
 | 
			
		||||
      case "day":
 | 
			
		||||
        setDesc(
 | 
			
		||||
          dayjs().subtract(1, "day").format("YYYY.MM.DD") +
 | 
			
		||||
          dayjs().format("YYYY.MM.DD") +
 | 
			
		||||
            " 7点 - " +
 | 
			
		||||
            dayjs().format("YYYY.MM.DD") +
 | 
			
		||||
            dayjs().add(1, "day").format("YYYY.MM.DD") +
 | 
			
		||||
            " 7点"
 | 
			
		||||
        );
 | 
			
		||||
        break;
 | 
			
		||||
 
 | 
			
		||||
@@ -33,10 +33,9 @@ function FaultTotal(props) {
 | 
			
		||||
 | 
			
		||||
  // time hint
 | 
			
		||||
  let timeDesc = "";
 | 
			
		||||
  const now = new Date();
 | 
			
		||||
  switch (currentSelect) {
 | 
			
		||||
    case "日":
 | 
			
		||||
      timeDesc = dayjs().subtract(1, 'day').format('YYYY.MM.DD') + " 7点 - " + dayjs().format('YYYY.MM.DD') + " 7点";
 | 
			
		||||
      timeDesc = dayjs().format('YYYY.MM.DD') + " 7点 - " + dayjs().add(1, 'day').format('YYYY.MM.DD') + " 7点";
 | 
			
		||||
      break;
 | 
			
		||||
    case "周":
 | 
			
		||||
      timeDesc = dayjs().subtract(7, 'day').format('YYYY.MM.DD') + " - " + dayjs().subtract(1, 'day').format('YYYY.MM.DD') ;
 | 
			
		||||
@@ -52,7 +51,6 @@ function FaultTotal(props) {
 | 
			
		||||
    <GraphBase
 | 
			
		||||
      icon="chart"
 | 
			
		||||
      title="产线缺陷统计"
 | 
			
		||||
      dateOptions={["日", "周", "月", "年"]}
 | 
			
		||||
      defaultSelect={currentSelect}
 | 
			
		||||
      onDateChange={handleDateChange}
 | 
			
		||||
      size={bgSize}
 | 
			
		||||
 
 | 
			
		||||
@@ -3,8 +3,8 @@ import GraphBase from "../GraphBase";
 | 
			
		||||
import ReactECharts from "echarts-for-react";
 | 
			
		||||
import { useSelector } from "react-redux";
 | 
			
		||||
import { useEffect, useState } from "react";
 | 
			
		||||
import { randomInt } from "../../../utils";
 | 
			
		||||
import * as echarts from "echarts";
 | 
			
		||||
import dayjs from "dayjs";
 | 
			
		||||
 | 
			
		||||
function FaultType(props) {
 | 
			
		||||
  const [init, setInit] = useState(true);
 | 
			
		||||
@@ -17,6 +17,11 @@ function FaultType(props) {
 | 
			
		||||
      : [];
 | 
			
		||||
  const lines = currentStatistic.map((item) => item.name);
 | 
			
		||||
  const CHART_TYPE = "line"; // "pie" | "line";
 | 
			
		||||
  const timestr =
 | 
			
		||||
    dayjs().format("YYYY.MM.DD") +
 | 
			
		||||
    " 7点 - " +
 | 
			
		||||
    dayjs().add(1, "d").format("YYYY.MM.DD") +
 | 
			
		||||
    " 7点";
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    if (init == false) return;
 | 
			
		||||
@@ -47,6 +52,8 @@ function FaultType(props) {
 | 
			
		||||
    <GraphBase
 | 
			
		||||
      icon="default"
 | 
			
		||||
      title="产线当日缺陷分类"
 | 
			
		||||
      desc={timestr}
 | 
			
		||||
      descSmall={true}
 | 
			
		||||
      dateOptions={[...lines]}
 | 
			
		||||
      defaultSelect={currentLine}
 | 
			
		||||
      onDateChange={handleLineChange}
 | 
			
		||||
@@ -146,7 +153,7 @@ function getOptions(data, chart_type) {
 | 
			
		||||
        axisPointer: {
 | 
			
		||||
          type: "shadow",
 | 
			
		||||
        },
 | 
			
		||||
        symbol: 'rect',
 | 
			
		||||
        symbol: "rect",
 | 
			
		||||
        className: "xc-chart-tooltip",
 | 
			
		||||
        // backgroundColor: ''
 | 
			
		||||
      },
 | 
			
		||||
@@ -210,7 +217,9 @@ function getOptions(data, chart_type) {
 | 
			
		||||
            color: "#fffc",
 | 
			
		||||
          },
 | 
			
		||||
          data: (dataList || []).map((item) =>
 | 
			
		||||
            item.value == null || isNaN(+item.value) ? null : (+item.value).toFixed(0)
 | 
			
		||||
            item.value == null || isNaN(+item.value)
 | 
			
		||||
              ? null
 | 
			
		||||
              : (+item.value).toFixed(0)
 | 
			
		||||
          ),
 | 
			
		||||
        },
 | 
			
		||||
      ],
 | 
			
		||||
 
 | 
			
		||||
@@ -29,9 +29,9 @@ const GoodRateChart = (props) => {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const [timestr, setTimestr] = useState(
 | 
			
		||||
    dayjs().subtract(1, "day").format("YYYY.MM.DD") +
 | 
			
		||||
    dayjs().format("YYYY.MM.DD") +
 | 
			
		||||
      " 7点 - " +
 | 
			
		||||
      dayjs().format("YYYY.MM.DD") +
 | 
			
		||||
      dayjs().add(1, "day").format("YYYY.MM.DD") +
 | 
			
		||||
      " 7点"
 | 
			
		||||
  );
 | 
			
		||||
  function handleDateChange(value) {
 | 
			
		||||
@@ -40,9 +40,9 @@ const GoodRateChart = (props) => {
 | 
			
		||||
    switch (value) {
 | 
			
		||||
      case "日":
 | 
			
		||||
        setTimestr(
 | 
			
		||||
          dayjs().subtract(1, "day").format("YYYY.MM.DD") +
 | 
			
		||||
          dayjs().format("YYYY.MM.DD") +
 | 
			
		||||
            " 7点 - " +
 | 
			
		||||
            dayjs().format("YYYY.MM.DD") +
 | 
			
		||||
            dayjs().add(1, "day").format("YYYY.MM.DD") +
 | 
			
		||||
            " 7点"
 | 
			
		||||
        );
 | 
			
		||||
        break;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										40
									
								
								src/components/Common/VideoMonitor/index.jsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,40 @@
 | 
			
		||||
// import cls from "./index.module.css";
 | 
			
		||||
import "./video-monitor.css";
 | 
			
		||||
 | 
			
		||||
function VideoMonitor(props) {
 | 
			
		||||
  return (
 | 
			
		||||
    <div className="video-monitor">
 | 
			
		||||
      <h2>泡界线监控</h2>
 | 
			
		||||
      <div className="video-container">
 | 
			
		||||
        <div>
 | 
			
		||||
          {/* <video muted autoPlay loop src="https://storage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4"></video> */}
 | 
			
		||||
          <img
 | 
			
		||||
            style={{
 | 
			
		||||
              width: "100%",
 | 
			
		||||
              height: "100%",
 | 
			
		||||
              display: "block",
 | 
			
		||||
              margin: "auto",
 | 
			
		||||
              backgrounColor: "hsl(0, 0%, 25%)",
 | 
			
		||||
            }}
 | 
			
		||||
            src="http://10.70.180.10:8001/video_feed"
 | 
			
		||||
          ></img>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div>
 | 
			
		||||
          {/* <video muted autoPlay loop src="https://storage.googleapis.com/gtv-videos-bucket/sample/ForBiggerEscapes.mp4"></video> */}
 | 
			
		||||
          <img
 | 
			
		||||
            style={{
 | 
			
		||||
              width: "100%",
 | 
			
		||||
              height: "100%",
 | 
			
		||||
              display: "block",
 | 
			
		||||
              margin: "auto",
 | 
			
		||||
              backgrounColor: "hsl(0, 0%, 25%)",
 | 
			
		||||
            }}
 | 
			
		||||
            src="http://10.70.180.10:8000/video_feed"
 | 
			
		||||
          ></img>
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default VideoMonitor;
 | 
			
		||||
							
								
								
									
										35
									
								
								src/components/Common/VideoMonitor/video-monitor.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,35 @@
 | 
			
		||||
.video-monitor {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex-direction: column;
 | 
			
		||||
  margin-left: 80px;
 | 
			
		||||
  height: 200px;
 | 
			
		||||
  width: 500px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.video-monitor > h2 {
 | 
			
		||||
  margin: 0;
 | 
			
		||||
  padding: 10px 0;
 | 
			
		||||
  background: #16253c;
 | 
			
		||||
  color: #fff;
 | 
			
		||||
  font-weight: 400;
 | 
			
		||||
  letter-spacing: 2px;
 | 
			
		||||
  font-size: 18px;
 | 
			
		||||
  text-align: center;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.video-monitor > .video-container {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  gap: 8px;
 | 
			
		||||
  flex: 1;
 | 
			
		||||
  max-height: 150px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.video-container > div {
 | 
			
		||||
  flex: 1;
 | 
			
		||||
  height: 100%;
 | 
			
		||||
  background: #ccc1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.video-container > div > video {
 | 
			
		||||
  width: 100%;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								src/components/Common/WarnAlert/3.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 1.3 KiB  | 
							
								
								
									
										130
									
								
								src/components/Common/WarnAlert/ListContainer.jsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,130 @@
 | 
			
		||||
import WarnAlert from ".";
 | 
			
		||||
import { useSelector } from "react-redux";
 | 
			
		||||
import posMap from "./position.json";
 | 
			
		||||
 | 
			
		||||
const total = `AN_1_1,助燃风故障报警
 | 
			
		||||
AN_1_2,压延机冷却风故障报警
 | 
			
		||||
AN_1_3,L吊墙冷却风机故障报警
 | 
			
		||||
AN_1_4,熔化带及部分澄清部冷却风机故障报警
 | 
			
		||||
AN_2_1,澄清带池壁冷却风机故障报警
 | 
			
		||||
AN_2_2,钢碴碴冷却风机故障报警
 | 
			
		||||
AN_2_3,支通路拐角冷却风机报警
 | 
			
		||||
AN_2_4,吊墙吊钩砖结构温升报警
 | 
			
		||||
AN_3_1,深层水包冷却水温升报警
 | 
			
		||||
AN_3_2,深层水包冷却水断水报警
 | 
			
		||||
AN_3_3,卡脖吊平冷却水断水报警
 | 
			
		||||
AN_3_4,卡脖吊平喧冷却水温升报警
 | 
			
		||||
AN_4_1,液面计冷却水断水报警
 | 
			
		||||
AN_4_2,液面计冷却水温升报警
 | 
			
		||||
AN_4_3,循环水入口压力低报警
 | 
			
		||||
AN_4_4,天然气压力高低报警
 | 
			
		||||
AN_5_1,助燃风风压低报警
 | 
			
		||||
AN_5_2,净化压缩气压力低报警
 | 
			
		||||
AN_5_3,普通压缩空气压力高低报警
 | 
			
		||||
AN_5_4,焦炉煤气气压力高低报警
 | 
			
		||||
AN_6_1,换向过程故障报警
 | 
			
		||||
AN_6_2,空交机换向不到位报警
 | 
			
		||||
AN_6_3,投料机故障报警
 | 
			
		||||
AN_6_4,备用
 | 
			
		||||
AN_7_1,1#压延机冷却水断水报警
 | 
			
		||||
AN_7_2,1#压延机冷却水温升报警
 | 
			
		||||
AN_7_3,1#过渡辊台冷却水断水报警
 | 
			
		||||
AN_7_4,1过渡辊台冷却水温升报警
 | 
			
		||||
AN_8_1,1#线唇砖冷却水断水报警
 | 
			
		||||
AN_8_2,1#线唇砖冷却水温升报警
 | 
			
		||||
AN_8_3,1#退火窑A区风机报警
 | 
			
		||||
AN_8_4,1#退火窑B区风机报警
 | 
			
		||||
AN_9_1,1#退火窑c区风机报警
 | 
			
		||||
AN_9_2,1#退火窑Ret1区风机报警
 | 
			
		||||
AN_9_3,1#退火窑Ret2区风机报警
 | 
			
		||||
AN_9_4,1#退火窑F1区风机报警
 | 
			
		||||
AN_10_1,1#退火窑F2区风机报警
 | 
			
		||||
AN_10_2,1#主传动报警
 | 
			
		||||
AN_10_3,1#压延机报警
 | 
			
		||||
AN_10_4,备用
 | 
			
		||||
AN_11_1,2#压延机冷却水断水报警
 | 
			
		||||
AN_11_2,2#压延机冷却水温升报警
 | 
			
		||||
AN_11_3,2#过渡辊台冷却水断水报警
 | 
			
		||||
AN_11_4,2#过渡辊台冷却水温升报警
 | 
			
		||||
AN_12_1,2#线唇砖冷却水断水报警
 | 
			
		||||
AN_12_2,2#线唇砖冷却水温升报警
 | 
			
		||||
AN_12_3,2#退火窑A区风机报警
 | 
			
		||||
AN_12_4,2#退火窑B区风机报警
 | 
			
		||||
AN_13_1,2#退火窑c区风机报警
 | 
			
		||||
AN_13_2,2#退火窑Ret1区风机报警
 | 
			
		||||
AN_13_3,2#退火窑Ret2区风机报警
 | 
			
		||||
AN_13_4,2#退火窑F1区风机报警
 | 
			
		||||
AN_14_1,2#退火窑F2区风机报警
 | 
			
		||||
AN_14_2,2#主传动报警
 | 
			
		||||
AN_14_3,2#压延机报警
 | 
			
		||||
AN_14_4,备用
 | 
			
		||||
AN_15_1,3#压延机冷却水断水报警
 | 
			
		||||
AN_15_2,3压延机冷却水温升报警
 | 
			
		||||
AN_15_3,3#过渡辊台冷却水断水报警
 | 
			
		||||
AN_15_4,3#过渡辊台冷却水温升报警
 | 
			
		||||
AN_16_1,3#线唇砖冷却水断水报警
 | 
			
		||||
AN_16_2,3#线唇砖冷却水温升报警
 | 
			
		||||
AN_16_3,3#退火窑A区风机报警
 | 
			
		||||
AN_16_4,3#退火窑B区风机报警
 | 
			
		||||
AN_17_1,3#退火窑c区风机报警
 | 
			
		||||
AN_17_2,3#退火窑Ret1区风机报警
 | 
			
		||||
AN_17_3,3#退火窑Ret2区风机报警
 | 
			
		||||
AN_17_4,3#退火窑F1区风机报警
 | 
			
		||||
AN_18_1,3#退火窑F2区风机报警
 | 
			
		||||
AN_18_2,3#主传动报警
 | 
			
		||||
AN_18_3,3#压延机报警
 | 
			
		||||
AN_18_4,备用
 | 
			
		||||
AN_19_1,4#压延机冷却水断水报警
 | 
			
		||||
AN_19_2,4压延机冷却水温升报警
 | 
			
		||||
AN_19_3,4#过渡辊台冷却水断水报警
 | 
			
		||||
AN_19_4,4#过渡辊台冷却水温升报警
 | 
			
		||||
AN_20_1,4#线唇砖冷却水断水报警
 | 
			
		||||
AN_20_2,4#线唇砖冷却水温升报警
 | 
			
		||||
AN_20_3,4#退火窑A区风机报警
 | 
			
		||||
AN_20_4,4#退火窑B区风机报警
 | 
			
		||||
AN_21_1,4#退火窑c区风机报警
 | 
			
		||||
AN_21_2,4#退火窑Ret1区风机报警
 | 
			
		||||
AN_21_3,4#退火窑Ret2区风机报警
 | 
			
		||||
AN_21_4,4#退火窑F1区风机报警
 | 
			
		||||
AN_22_1,4#退火窑F2区风机报警
 | 
			
		||||
AN_22_2,4#主传动报警
 | 
			
		||||
AN_22_3,4#压延机报警
 | 
			
		||||
AN_23_1,5#压延机冷却水断水报警
 | 
			
		||||
AN_23_2,5#压延机冷却水温升报警
 | 
			
		||||
AN_23_3,5#过渡辊台冷却水断水报警
 | 
			
		||||
AN_23_4,5#过渡台冷却水温升报警
 | 
			
		||||
AN_24_1,5#线唇砖冷却水断水报警
 | 
			
		||||
AN_24_2,5#线唇砖冷却水温升报警
 | 
			
		||||
AN_24_3,5#退火窑A区风机报警
 | 
			
		||||
AN_24_4,5#退火窑B区风机报警
 | 
			
		||||
AN_25_1,5#退火窑c区风机报警
 | 
			
		||||
AN_25_2,5#退火窑Ret1区风机报警
 | 
			
		||||
AN_25_3,5#退火窑Ret2区风机报警
 | 
			
		||||
AN_25_4,5#退火窑F1区风机报警
 | 
			
		||||
AN_26_1,5#退火窑F2区风机报警
 | 
			
		||||
AN_26_2,5#主传动报警
 | 
			
		||||
AN_26_3,5#压延机报警
 | 
			
		||||
`;
 | 
			
		||||
 | 
			
		||||
function AlarmListContainer(props) {
 | 
			
		||||
  const alarmList = useSelector((state) => state.alarm.list);
 | 
			
		||||
  // const alarmList = total
 | 
			
		||||
  //   .split("\n")
 | 
			
		||||
  //   .filter((str) => str.trim())
 | 
			
		||||
  //   .map((item) => ({
 | 
			
		||||
  //     id: item.split(",")[0],
 | 
			
		||||
  //     title: item.split(",")[0],
 | 
			
		||||
  //     content: item.split(",")[1],
 | 
			
		||||
  //   }));
 | 
			
		||||
  return alarmList.map((alarm) => (
 | 
			
		||||
    <WarnAlert
 | 
			
		||||
      key={alarm.id}
 | 
			
		||||
      title={alarm.title}
 | 
			
		||||
      content={alarm.content}
 | 
			
		||||
      x={posMap[alarm.title]?.x || 0}
 | 
			
		||||
      y={posMap[alarm.title]?.y || 0}
 | 
			
		||||
    />
 | 
			
		||||
  ));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default AlarmListContainer;
 | 
			
		||||
							
								
								
									
										18
									
								
								src/components/Common/WarnAlert/index.jsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,18 @@
 | 
			
		||||
// import cls from "./index.module.css";
 | 
			
		||||
import "./warn-alert.css";
 | 
			
		||||
import AlertIcon from "./warn-icon.png";
 | 
			
		||||
 | 
			
		||||
function WarnAlert(props) {
 | 
			
		||||
  const { x, y, title, content } = props;
 | 
			
		||||
  return (
 | 
			
		||||
    <div className="warn-alert" style={{ top: `${y}px`, left: `${x}px` }}>
 | 
			
		||||
      <h1 className="">
 | 
			
		||||
        <img src={AlertIcon} width={24} alt="icon" />
 | 
			
		||||
        {title || "test"}
 | 
			
		||||
      </h1>
 | 
			
		||||
      <p>{content || "Lorem ipsum dolor sit amet consectetur."}</p>
 | 
			
		||||
    </div>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default WarnAlert;
 | 
			
		||||
							
								
								
									
										104
									
								
								src/components/Common/WarnAlert/position.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,104 @@
 | 
			
		||||
{
 | 
			
		||||
  "AN_1_1": { "x": 650, "y": 645 },
 | 
			
		||||
  "AN_1_2": { "x": 1450, "y": 540 },
 | 
			
		||||
  "AN_1_3": { "x": 640, "y": 285 },
 | 
			
		||||
  "AN_1_4": { "x": 720, "y": 645 },
 | 
			
		||||
  "AN_2_1": { "x": 1250, "y": 540 },
 | 
			
		||||
  "AN_2_2": { "x": 1200, "y": 540 },
 | 
			
		||||
  "AN_2_3": { "x": 1460, "y": 410 },
 | 
			
		||||
  "AN_2_4": { "x": 650, "y": 420 },
 | 
			
		||||
  "AN_3_1": { "x": 1360, "y": 380 },
 | 
			
		||||
  "AN_3_2": { "x": 1360, "y": 380 },
 | 
			
		||||
  "AN_3_3": { "x": 1360, "y": 420 },
 | 
			
		||||
  "AN_3_4": { "x": 1360, "y": 420 },
 | 
			
		||||
  "AN_4_1": { "x": 1350, "y": 460 },
 | 
			
		||||
  "AN_4_2": { "x": 1350, "y": 460 },
 | 
			
		||||
  "AN_4_3": { "x": 1270, "y": 320 },
 | 
			
		||||
  "AN_4_4": { "x": 900, "y": 420 },
 | 
			
		||||
  "AN_5_1": { "x": 650, "y": 645 },
 | 
			
		||||
  "AN_5_2": { "x": 980, "y": 420 },
 | 
			
		||||
  "AN_5_3": { "x": 1050, "y": 420 },
 | 
			
		||||
  "AN_5_4": { "x": 1130, "y": 420 },
 | 
			
		||||
  "AN_6_1": { "x": 1220, "y": 420 },
 | 
			
		||||
  "AN_6_2": { "x": 1290, "y": 420 },
 | 
			
		||||
  "AN_6_3": { "x": 650, "y": 440 },
 | 
			
		||||
  "AN_6_4": { "x": 1400, "y": 650 },
 | 
			
		||||
  "AN_7_1": { "x": 1450, "y": 540 },
 | 
			
		||||
  "AN_7_2": { "x": 1450, "y": 540 },
 | 
			
		||||
  "AN_7_3": { "x": 1470, "y": 540 },
 | 
			
		||||
  "AN_7_4": { "x": 1470, "y": 540 },
 | 
			
		||||
  "AN_8_1": { "x": 1470, "y": 540 },
 | 
			
		||||
  "AN_8_2": { "x": 1470, "y": 540 },
 | 
			
		||||
  "AN_8_3": { "x": 1480, "y": 540 },
 | 
			
		||||
  "AN_8_4": { "x": 1580, "y": 540 },
 | 
			
		||||
  "AN_9_1": { "x": 1700, "y": 540 },
 | 
			
		||||
  "AN_9_2": { "x": 1760, "y": 540 },
 | 
			
		||||
  "AN_9_3": { "x": 1780, "y": 540 },
 | 
			
		||||
  "AN_9_4": { "x": 1780, "y": 540 },
 | 
			
		||||
  "AN_10_1": { "x": 1780, "y": 540 },
 | 
			
		||||
  "AN_10_2": { "x": 1390, "y": 540 },
 | 
			
		||||
  "AN_10_3": { "x": 1450, "y": 540 },
 | 
			
		||||
  "AN_10_4": { "x": 1400, "y": 650 },
 | 
			
		||||
  "AN_11_1": { "x": 1450, "y": 480 },
 | 
			
		||||
  "AN_11_2": { "x": 1450, "y": 480 },
 | 
			
		||||
  "AN_11_3": { "x": 1450, "y": 480 },
 | 
			
		||||
  "AN_11_4": { "x": 1450, "y": 480 },
 | 
			
		||||
  "AN_12_1": { "x": 1450, "y": 480 },
 | 
			
		||||
  "AN_12_2": { "x": 1450, "y": 480 },
 | 
			
		||||
  "AN_12_3": { "x": 1550, "y": 480 },
 | 
			
		||||
  "AN_12_4": { "x": 1650, "y": 480 },
 | 
			
		||||
  "AN_13_1": { "x": 1750, "y": 480 },
 | 
			
		||||
  "AN_13_2": { "x": 1850, "y": 480 },
 | 
			
		||||
  "AN_13_3": { "x": 1900, "y": 480 },
 | 
			
		||||
  "AN_13_4": { "x": 1910, "y": 480 },
 | 
			
		||||
  "AN_14_1": { "x": 1920, "y": 480 },
 | 
			
		||||
  "AN_14_2": { "x": 1450, "y": 480 },
 | 
			
		||||
  "AN_14_3": { "x": 1450, "y": 480 },
 | 
			
		||||
  "AN_14_4": { "x": 1400, "y": 650 },
 | 
			
		||||
  "AN_15_1": { "x": 1450, "y": 430 },
 | 
			
		||||
  "AN_15_2": { "x": 1450, "y": 430 },
 | 
			
		||||
  "AN_15_3": { "x": 1470, "y": 430 },
 | 
			
		||||
  "AN_15_4": { "x": 1470, "y": 430 },
 | 
			
		||||
  "AN_16_1": { "x": 1470, "y": 430 },
 | 
			
		||||
  "AN_16_2": { "x": 1470, "y": 430 },
 | 
			
		||||
  "AN_16_3": { "x": 1600, "y": 430 },
 | 
			
		||||
  "AN_16_4": { "x": 1700, "y": 430 },
 | 
			
		||||
  "AN_17_1": { "x": 1800, "y": 430 },
 | 
			
		||||
  "AN_17_2": { "x": 1900, "y": 430 },
 | 
			
		||||
  "AN_17_3": { "x": 1950, "y": 430 },
 | 
			
		||||
  "AN_17_4": { "x": 1960, "y": 430 },
 | 
			
		||||
  "AN_18_1": { "x": 1970, "y": 430 },
 | 
			
		||||
  "AN_18_2": { "x": 1450, "y": 430 },
 | 
			
		||||
  "AN_18_3": { "x": 1450, "y": 430 },
 | 
			
		||||
  "AN_18_4": { "x": 1400, "y": 650 },
 | 
			
		||||
  "AN_19_1": { "x": 1450, "y": 370 },
 | 
			
		||||
  "AN_19_2": { "x": 1450, "y": 370 },
 | 
			
		||||
  "AN_19_3": { "x": 1460, "y": 370 },
 | 
			
		||||
  "AN_19_4": { "x": 1460, "y": 370 },
 | 
			
		||||
  "AN_20_1": { "x": 1460, "y": 370 },
 | 
			
		||||
  "AN_20_2": { "x": 1460, "y": 370 },
 | 
			
		||||
  "AN_20_3": { "x": 1500, "y": 370 },
 | 
			
		||||
  "AN_20_4": { "x": 1600, "y": 370 },
 | 
			
		||||
  "AN_21_1": { "x": 1700, "y": 370 },
 | 
			
		||||
  "AN_21_2": { "x": 1800, "y": 370 },
 | 
			
		||||
  "AN_21_3": { "x": 1850, "y": 370 },
 | 
			
		||||
  "AN_21_4": { "x": 1860, "y": 370 },
 | 
			
		||||
  "AN_22_1": { "x": 1870, "y": 370 },
 | 
			
		||||
  "AN_22_2": { "x": 1450, "y": 370 },
 | 
			
		||||
  "AN_22_3": { "x": 1460, "y": 370 },
 | 
			
		||||
  "AN_23_1": { "x": 1460, "y": 320 },
 | 
			
		||||
  "AN_23_2": { "x": 1460, "y": 320 },
 | 
			
		||||
  "AN_23_3": { "x": 1465, "y": 320 },
 | 
			
		||||
  "AN_23_4": { "x": 1465, "y": 320 },
 | 
			
		||||
  "AN_24_1": { "x": 1465, "y": 320 },
 | 
			
		||||
  "AN_24_2": { "x": 1465, "y": 320 },
 | 
			
		||||
  "AN_24_3": { "x": 1480, "y": 320 },
 | 
			
		||||
  "AN_24_4": { "x": 1580, "y": 320 },
 | 
			
		||||
  "AN_25_1": { "x": 1680, "y": 320 },
 | 
			
		||||
  "AN_25_2": { "x": 1780, "y": 320 },
 | 
			
		||||
  "AN_25_3": { "x": 1750, "y": 320 },
 | 
			
		||||
  "AN_25_4": { "x": 1760, "y": 320 },
 | 
			
		||||
  "AN_26_1": { "x": 1770, "y": 320 },
 | 
			
		||||
  "AN_26_2": { "x": 1430, "y": 320 },
 | 
			
		||||
  "AN_26_3": { "x": 1460, "y": 320 }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										65
									
								
								src/components/Common/WarnAlert/warn-alert.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,65 @@
 | 
			
		||||
.warn-alert {
 | 
			
		||||
  position: fixed;
 | 
			
		||||
  top: 200px;
 | 
			
		||||
  left: 200px;
 | 
			
		||||
  /* height: 72px; */
 | 
			
		||||
  z-index: 10000;
 | 
			
		||||
  display: inline-block;
 | 
			
		||||
  /* background: url(../../../assets/warn-bg.png) 0 0 / 116px 100% repeat-x; */
 | 
			
		||||
  background: url(./3.png) 0 0 / 116px 100% repeat-x;
 | 
			
		||||
  box-shadow: 0 0 24px 6px rgba(0, 0, 0, 0.5);
 | 
			
		||||
  user-select: none;
 | 
			
		||||
  transform: scale(0.64);
 | 
			
		||||
  cursor: pointer;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.warn-alert:hover {
 | 
			
		||||
  transform: scale(1.1);
 | 
			
		||||
  box-shadow: 0 0 32px 12px rgba(0, 0, 0, 0.5);
 | 
			
		||||
  z-index: 10001;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.warn-alert::before {
 | 
			
		||||
  box-sizing: border-box;
 | 
			
		||||
  content: "";
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  top: 0;
 | 
			
		||||
  left: -24px;
 | 
			
		||||
  width: 24px;
 | 
			
		||||
  height: 100%;
 | 
			
		||||
  display: inline-block;
 | 
			
		||||
  border: 12px solid transparent;
 | 
			
		||||
  border-right-color: #ff2c2c;
 | 
			
		||||
}
 | 
			
		||||
.warn-alert::after {
 | 
			
		||||
  box-sizing: border-box;
 | 
			
		||||
  content: "";
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  top: 0;
 | 
			
		||||
  right: -24px;
 | 
			
		||||
  width: 24px;
 | 
			
		||||
  height: 100%;
 | 
			
		||||
  display: inline-block;
 | 
			
		||||
  border: 12px solid transparent;
 | 
			
		||||
  border-left-color: #ff2c2c;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.warn-alert > h1 {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  margin: 8px 0 0;
 | 
			
		||||
  align-items: center;
 | 
			
		||||
  color: #fff;
 | 
			
		||||
  font-size: 16px;
 | 
			
		||||
  text-transform: uppercase;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.warn-alert > h1 img {
 | 
			
		||||
  padding-top: 3px;
 | 
			
		||||
  margin-left: 10px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.warn-alert > p {
 | 
			
		||||
  color: #fff;
 | 
			
		||||
  margin: 0 22px 16px 14px;
 | 
			
		||||
  font-size: 14px;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								src/components/Common/WarnAlert/warn-icon.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 2.2 KiB  | 
@@ -2,33 +2,40 @@ import cls from "./index.module.css";
 | 
			
		||||
import GradientText from "../../../Common/GradientText";
 | 
			
		||||
import { useSelector } from "react-redux";
 | 
			
		||||
import { useEffect, useState } from "react";
 | 
			
		||||
import eIcon1 from "../../../../assets/Icon/dontknowwhatitis.png";
 | 
			
		||||
import eIcon2 from "../../../../assets/Icon/lightnen.png";
 | 
			
		||||
 | 
			
		||||
function Energy(props) {
 | 
			
		||||
  const [isPage1, setIsPage1] = useState(true);
 | 
			
		||||
  const [isPage1] = useState(props.page === 1);
 | 
			
		||||
  const energyInfo = useSelector((state) => state.energy?.info);
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    const timer = setInterval(() => {
 | 
			
		||||
      setIsPage1((pre) => !pre);
 | 
			
		||||
    }, 10000);
 | 
			
		||||
  // useEffect(() => {
 | 
			
		||||
  //   const timer = setInterval(() => {
 | 
			
		||||
  //     setIsPage1((pre) => !pre);
 | 
			
		||||
  //   }, 10000);
 | 
			
		||||
 | 
			
		||||
    return () => {
 | 
			
		||||
      clearInterval(timer);
 | 
			
		||||
    }
 | 
			
		||||
  }, []);
 | 
			
		||||
  //   return () => {
 | 
			
		||||
  //     clearInterval(timer);
 | 
			
		||||
  //   }
 | 
			
		||||
  // }, []);
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <div className={" " + cls.layout} style={{ color: "#fff" }}>
 | 
			
		||||
      <span
 | 
			
		||||
        className={cls.shadowBorder}
 | 
			
		||||
        className={`${cls.shadowBorder} ${cls.border}`}
 | 
			
		||||
        style={{
 | 
			
		||||
          gridRow: "1 / 3",
 | 
			
		||||
          paddingTop: "104px",
 | 
			
		||||
          paddingLeft: "32px",
 | 
			
		||||
          userSelect: "none",
 | 
			
		||||
          textAlign: "center",
 | 
			
		||||
          paddingTop: "96px",
 | 
			
		||||
        }}
 | 
			
		||||
      >
 | 
			
		||||
        <GradientText text="能源" />
 | 
			
		||||
        {isPage1 ? (
 | 
			
		||||
          <img src={eIcon1} width={32} alt="eicon1" />
 | 
			
		||||
        ) : (
 | 
			
		||||
          <img src={eIcon2} width={32} alt="eicon2" />
 | 
			
		||||
        )}
 | 
			
		||||
        <GradientText text={"\u2002\u2002能源"} />
 | 
			
		||||
      </span>
 | 
			
		||||
      {!isPage1 && (
 | 
			
		||||
        <div
 | 
			
		||||
@@ -65,7 +72,9 @@ function Energy(props) {
 | 
			
		||||
              {(+energyInfo?.elecQty7)?.toFixed(2) || 0}
 | 
			
		||||
            </span>
 | 
			
		||||
          </div>
 | 
			
		||||
          <div className={cls.shadowBorder + " " + cls.infoText}>
 | 
			
		||||
          <div
 | 
			
		||||
            className={cls.shadowBorder + " " + cls.infoText + " " + cls.border}
 | 
			
		||||
          >
 | 
			
		||||
            <span style={{ lineHeight: 1.5 }}>智慧能源光伏发电(总量)/kWh</span>
 | 
			
		||||
            <span
 | 
			
		||||
              style={{
 | 
			
		||||
@@ -77,7 +86,9 @@ function Energy(props) {
 | 
			
		||||
              {(+energyInfo?.elecQty4)?.toFixed(2) || 0}
 | 
			
		||||
            </span>
 | 
			
		||||
          </div>
 | 
			
		||||
          <div className={cls.shadowBorder + " " + cls.infoText}>
 | 
			
		||||
          <div
 | 
			
		||||
            className={cls.shadowBorder + " " + cls.infoText + " " + cls.border}
 | 
			
		||||
          >
 | 
			
		||||
            <span style={{ lineHeight: 1.5 }}>许昌安彩光伏发电(总量)/kWh</span>
 | 
			
		||||
            <span
 | 
			
		||||
              style={{
 | 
			
		||||
@@ -105,7 +116,7 @@ function Energy(props) {
 | 
			
		||||
              style={{ flex: 1 }}
 | 
			
		||||
              className={cls.shadowBorder + " " + cls.infoText}
 | 
			
		||||
            >
 | 
			
		||||
              <span style={{ lineHeight: 1.5 }}>余热发电(实时)/kWh</span>
 | 
			
		||||
              <span style={{ lineHeight: 1.5 }}>余热发电(昨日)/kWh</span>
 | 
			
		||||
              <span
 | 
			
		||||
                style={{
 | 
			
		||||
                  lineHeight: 1.5,
 | 
			
		||||
@@ -118,7 +129,9 @@ function Energy(props) {
 | 
			
		||||
            </div>
 | 
			
		||||
            <div
 | 
			
		||||
              style={{ flex: 1 }}
 | 
			
		||||
              className={cls.shadowBorder + " " + cls.infoText}
 | 
			
		||||
              className={
 | 
			
		||||
                cls.shadowBorder + " " + cls.infoText + " " + cls.border
 | 
			
		||||
              }
 | 
			
		||||
            >
 | 
			
		||||
              <span style={{ lineHeight: 1.5 }}>余热发电(总量)/kWh</span>
 | 
			
		||||
              <span
 | 
			
		||||
@@ -133,25 +146,29 @@ function Energy(props) {
 | 
			
		||||
            </div>
 | 
			
		||||
          </div>
 | 
			
		||||
          <span className={cls.shadowBorder + " " + cls.infoText}>
 | 
			
		||||
            <span style={{ lineHeight: 1.5 }}>水耗量/Km³</span>
 | 
			
		||||
            <span style={{ lineHeight: 1.5 }}>水耗量(昨日)/Km³</span>
 | 
			
		||||
            <span style={{ lineHeight: 1.5 }}>
 | 
			
		||||
              {(+energyInfo?.waterQty)?.toFixed(2) || 0}
 | 
			
		||||
            </span>
 | 
			
		||||
          </span>
 | 
			
		||||
          <span className={cls.shadowBorder + " " + cls.infoText}>
 | 
			
		||||
            <span style={{ lineHeight: 1.5 }}>天然气I/Nm³</span>
 | 
			
		||||
            <span style={{ lineHeight: 1.5 }}>天然气I(累计)/Nm³</span>
 | 
			
		||||
            <span style={{ lineHeight: 1.5 }}>
 | 
			
		||||
              {energyInfo?.ngQty1?.replace("Nm³", "") || "0Nm³"}
 | 
			
		||||
            </span>
 | 
			
		||||
          </span>
 | 
			
		||||
          <span className={cls.shadowBorder + " " + cls.infoText}>
 | 
			
		||||
            <span style={{ lineHeight: 1.5 }}>电耗量/kWh</span>
 | 
			
		||||
          <span
 | 
			
		||||
            className={cls.shadowBorder + " " + cls.infoText + " " + cls.border}
 | 
			
		||||
          >
 | 
			
		||||
            <span style={{ lineHeight: 1.5 }}>电耗量(昨日)/kWh</span>
 | 
			
		||||
            <span style={{ lineHeight: 1.5 }}>
 | 
			
		||||
              {(+energyInfo?.elecQty2)?.toFixed(2) || 0}
 | 
			
		||||
            </span>
 | 
			
		||||
          </span>
 | 
			
		||||
          <span className={cls.shadowBorder + " " + cls.infoText}>
 | 
			
		||||
            <span style={{ lineHeight: 1.5 }}>天然气II/Nm³</span>
 | 
			
		||||
          <span
 | 
			
		||||
            className={cls.shadowBorder + " " + cls.infoText + " " + cls.border}
 | 
			
		||||
          >
 | 
			
		||||
            <span style={{ lineHeight: 1.5 }}>天然气II(累计)/Nm³</span>
 | 
			
		||||
            <span style={{ lineHeight: 1.5 }}>
 | 
			
		||||
              {energyInfo?.ngQty2?.replace("Nm³", "") || "0Nm³"}
 | 
			
		||||
            </span>
 | 
			
		||||
 
 | 
			
		||||
@@ -4,7 +4,8 @@
 | 
			
		||||
  /* grid-template-columns: 133px 158px 292px 292px; */
 | 
			
		||||
  grid-template-columns: 125px 250px 250px 250px;
 | 
			
		||||
  /* grid-template-rows: 60px 60px; */
 | 
			
		||||
  grid-template-rows: 129px 129px;
 | 
			
		||||
  grid-template-rows: auto;
 | 
			
		||||
  height: 100%;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.shadowBorder {
 | 
			
		||||
@@ -13,6 +14,29 @@
 | 
			
		||||
  padding: 4px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.shadowBorder.border {
 | 
			
		||||
  position: relative;
 | 
			
		||||
  border-bottom: 2px solid #00fff7;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.shadowBorder.border::before,
 | 
			
		||||
.shadowBorder.border::after {
 | 
			
		||||
  content: "";
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  bottom: 0;
 | 
			
		||||
  display: inline-block;
 | 
			
		||||
  height: 100%;
 | 
			
		||||
  width: 2px;
 | 
			
		||||
  background: linear-gradient(to top, #00fff7, #00fff708, transparent);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.shadowBorder.border::before {
 | 
			
		||||
  left: 0;
 | 
			
		||||
}
 | 
			
		||||
.shadowBorder.border::after {
 | 
			
		||||
  right: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.infoText {
 | 
			
		||||
  text-align: center;
 | 
			
		||||
  font-size: 22px;
 | 
			
		||||
@@ -27,6 +51,6 @@
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.infoText > span:last-child {
 | 
			
		||||
  color: #00FFF7;
 | 
			
		||||
  color: #00fff7;
 | 
			
		||||
  font-size: 24px;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -6,17 +6,38 @@ import { useState } from "react";
 | 
			
		||||
import * as echarts from "echarts";
 | 
			
		||||
import dayjs from "dayjs";
 | 
			
		||||
 | 
			
		||||
function getTimeStr(period) {
 | 
			
		||||
  return {
 | 
			
		||||
    日:
 | 
			
		||||
      dayjs().format("YYYY.MM.DD") +
 | 
			
		||||
      " 7点 - " +
 | 
			
		||||
      dayjs().add(1, "d").format("YYYY.MM.DD") +
 | 
			
		||||
      " 7点",
 | 
			
		||||
    年:
 | 
			
		||||
      dayjs().subtract(1, "year").endOf("year").format("YYYY.MM.") +
 | 
			
		||||
      "29 - " +
 | 
			
		||||
      dayjs().endOf("year").format("YYYY.MM.") +
 | 
			
		||||
      "28",
 | 
			
		||||
    周:
 | 
			
		||||
      dayjs().subtract(7, "day").format("YYYY.MM.DD") +
 | 
			
		||||
      " - " +
 | 
			
		||||
      dayjs().subtract(1, "day").format("YYYY.MM.DD"),
 | 
			
		||||
    月:
 | 
			
		||||
      dayjs().subtract(1, "month").format("YYYY.MM.") +
 | 
			
		||||
      "29 - " +
 | 
			
		||||
      dayjs().format("YYYY.MM.") +
 | 
			
		||||
      "28",
 | 
			
		||||
  }[period];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function NO(props) {
 | 
			
		||||
  const dayTrend = useSelector((state) => state.smoke?.dayTrend);
 | 
			
		||||
  const weekTrend = useSelector((state) => state.smoke?.weekTrend);
 | 
			
		||||
  const monthTrend = useSelector((state) => state.smoke?.monthTrend);
 | 
			
		||||
  const yearTrend = useSelector((state) => state.smoke?.yearTrend);
 | 
			
		||||
  const [period, setPeriod] = useState("日");
 | 
			
		||||
  const [timestr, setTimestr] = useState(
 | 
			
		||||
    dayjs().subtract(7, "day").format("YYYY.MM.DD") +
 | 
			
		||||
      " - " +
 | 
			
		||||
      dayjs().subtract(1, "day").format("YYYY.MM.DD")
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  let timestr = getTimeStr(period);
 | 
			
		||||
 | 
			
		||||
  const currentTrend =
 | 
			
		||||
    period === "日"
 | 
			
		||||
@@ -33,35 +54,13 @@ function NO(props) {
 | 
			
		||||
 | 
			
		||||
  function handleDateChange(value) {
 | 
			
		||||
    setPeriod(value);
 | 
			
		||||
    setTimestr(
 | 
			
		||||
      {
 | 
			
		||||
        日:
 | 
			
		||||
          dayjs().subtract(1, "day").format("YYYY.MM.DD") +
 | 
			
		||||
          " 7点 - " +
 | 
			
		||||
          dayjs().format("YYYY.MM.DD") +
 | 
			
		||||
          " 7点",
 | 
			
		||||
        年:
 | 
			
		||||
          dayjs().subtract(1, "year").endOf("year").format("YYYY.MM.") +
 | 
			
		||||
          "29 - " +
 | 
			
		||||
          dayjs().endOf("year").format("YYYY.MM.") +
 | 
			
		||||
          "28",
 | 
			
		||||
        周:
 | 
			
		||||
          dayjs().subtract(7, "day").format("YYYY.MM.DD") +
 | 
			
		||||
          " - " +
 | 
			
		||||
          dayjs().subtract(1, "day").format("YYYY.MM.DD"),
 | 
			
		||||
        月:
 | 
			
		||||
          dayjs().subtract(1, "month").format("YYYY.MM.") +
 | 
			
		||||
          "29 - " +
 | 
			
		||||
          dayjs().format("YYYY.MM.") +
 | 
			
		||||
          "28",
 | 
			
		||||
      }[value]
 | 
			
		||||
    );
 | 
			
		||||
    timestr = getTimeStr(value);
 | 
			
		||||
  }
 | 
			
		||||
  return (
 | 
			
		||||
    <GraphBase
 | 
			
		||||
      icon="smoke"
 | 
			
		||||
      title="氮氧化物"
 | 
			
		||||
      desc={`能耗趋势图  ${timestr}`}
 | 
			
		||||
      desc={`烟气趋势图  ${timestr}`}
 | 
			
		||||
      switchOptions={false}
 | 
			
		||||
      defaultSelect={period}
 | 
			
		||||
      onSwitch={handleSwitch}
 | 
			
		||||
 
 | 
			
		||||
@@ -6,17 +6,38 @@ import { useState } from "react";
 | 
			
		||||
import * as echarts from "echarts";
 | 
			
		||||
import dayjs from "dayjs";
 | 
			
		||||
 | 
			
		||||
function getTimeStr(period) {
 | 
			
		||||
  return {
 | 
			
		||||
    日:
 | 
			
		||||
      dayjs().format("YYYY.MM.DD") +
 | 
			
		||||
      " 7点 - " +
 | 
			
		||||
      dayjs().add(1, 'd').format("YYYY.MM.DD") +
 | 
			
		||||
      " 7点",
 | 
			
		||||
    年:
 | 
			
		||||
      dayjs().subtract(1, "year").endOf("year").format("YYYY.MM.") +
 | 
			
		||||
      "29 - " +
 | 
			
		||||
      dayjs().endOf("year").format("YYYY.MM.") +
 | 
			
		||||
      "28",
 | 
			
		||||
    周:
 | 
			
		||||
      dayjs().subtract(7, "day").format("YYYY.MM.DD") +
 | 
			
		||||
      " - " +
 | 
			
		||||
      dayjs().subtract(1, "day").format("YYYY.MM.DD"),
 | 
			
		||||
    月:
 | 
			
		||||
      dayjs().subtract(1, "month").format("YYYY.MM.") +
 | 
			
		||||
      "29 - " +
 | 
			
		||||
      dayjs().format("YYYY.MM.") +
 | 
			
		||||
      "28",
 | 
			
		||||
  }[period];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function Dust(props) {
 | 
			
		||||
  const dayTrend = useSelector((state) => state.smoke?.dayTrend);
 | 
			
		||||
  const weekTrend = useSelector((state) => state.smoke?.weekTrend);
 | 
			
		||||
  const monthTrend = useSelector((state) => state.smoke?.monthTrend);
 | 
			
		||||
  const yearTrend = useSelector((state) => state.smoke?.yearTrend);
 | 
			
		||||
  const [period, setPeriod] = useState("日");
 | 
			
		||||
  const [timestr, setTimestr] = useState(
 | 
			
		||||
    dayjs().subtract(7, "day").format("YYYY.MM.DD") +
 | 
			
		||||
      " - " +
 | 
			
		||||
      dayjs().subtract(1, "day").format("YYYY.MM.DD")
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  let timestr = getTimeStr(period);
 | 
			
		||||
  const currentTrend =
 | 
			
		||||
    period === "日"
 | 
			
		||||
      ? dayTrend
 | 
			
		||||
@@ -32,36 +53,14 @@ function Dust(props) {
 | 
			
		||||
 | 
			
		||||
  function handleDateChange(value) {
 | 
			
		||||
    setPeriod(value);
 | 
			
		||||
    setTimestr(
 | 
			
		||||
      {
 | 
			
		||||
        日:
 | 
			
		||||
          dayjs().subtract(1, "day").format("YYYY.MM.DD") +
 | 
			
		||||
          " 7点 - " +
 | 
			
		||||
          dayjs().format("YYYY.MM.DD") +
 | 
			
		||||
          " 7点",
 | 
			
		||||
        年:
 | 
			
		||||
          dayjs().subtract(1, "year").endOf("year").format("YYYY.MM.") +
 | 
			
		||||
          "29 - " +
 | 
			
		||||
          dayjs().endOf("year").format("YYYY.MM.") +
 | 
			
		||||
          "28",
 | 
			
		||||
        周:
 | 
			
		||||
          dayjs().subtract(7, "day").format("YYYY.MM.DD") +
 | 
			
		||||
          " - " +
 | 
			
		||||
          dayjs().subtract(1, "day").format("YYYY.MM.DD"),
 | 
			
		||||
        月:
 | 
			
		||||
          dayjs().subtract(1, "month").format("YYYY.MM.") +
 | 
			
		||||
          "29 - " +
 | 
			
		||||
          dayjs().format("YYYY.MM.") +
 | 
			
		||||
          "28",
 | 
			
		||||
      }[value]
 | 
			
		||||
    );
 | 
			
		||||
    timestr = getTimeStr(value);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <GraphBase
 | 
			
		||||
      icon="smoke"
 | 
			
		||||
      title="颗粒物"
 | 
			
		||||
      desc={`能耗趋势图  ${timestr}`}
 | 
			
		||||
      desc={`烟气趋势图  ${timestr}`}
 | 
			
		||||
      switchOptions={false}
 | 
			
		||||
      defaultSelect={period}
 | 
			
		||||
      onSwitch={handleSwitch}
 | 
			
		||||
 
 | 
			
		||||
@@ -8,7 +8,8 @@ import { lunarYear } from "../../../../utils/energeChartOption";
 | 
			
		||||
import dayjs from "dayjs";
 | 
			
		||||
 | 
			
		||||
function NatGas(props) {
 | 
			
		||||
  const elecTrend = useSelector((state) => state.energy.trend.natGas1);
 | 
			
		||||
  const natGasTrend = useSelector((state) => state.energy.trend.natGas1);
 | 
			
		||||
  const gasTrend = useSelector((state) => state.energy.trend.natGas2);
 | 
			
		||||
  const [period, setPeriod] = useState("周");
 | 
			
		||||
  const [timestr, setTimestr] = useState(
 | 
			
		||||
    dayjs().subtract(7, "day").format("YYYY.MM.DD") +
 | 
			
		||||
@@ -18,7 +19,7 @@ function NatGas(props) {
 | 
			
		||||
 | 
			
		||||
  const options = getOptions(
 | 
			
		||||
    { 周: "week", 月: "month", 年: "year" }[period],
 | 
			
		||||
    elecTrend ?? { week: [], month: [], year: [] }
 | 
			
		||||
    [natGasTrend, gasTrend] ?? { week: [], month: [], year: [] }
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  function handleSwitch(v) {
 | 
			
		||||
@@ -50,7 +51,7 @@ function NatGas(props) {
 | 
			
		||||
  return (
 | 
			
		||||
    <GraphBase
 | 
			
		||||
      icon="battery"
 | 
			
		||||
      title="天然气I"
 | 
			
		||||
      title="天然气"
 | 
			
		||||
      desc={`能耗趋势图  ${timestr}`}
 | 
			
		||||
      switchOptions={false}
 | 
			
		||||
      onSwitch={handleSwitch}
 | 
			
		||||
@@ -60,6 +61,45 @@ function NatGas(props) {
 | 
			
		||||
      onDateChange={handleDateChange}
 | 
			
		||||
      size={["long", "middle"]}
 | 
			
		||||
    >
 | 
			
		||||
      <div
 | 
			
		||||
        className="nat-gas-legend"
 | 
			
		||||
        style={{
 | 
			
		||||
          position: "absolute",
 | 
			
		||||
          top: 28,
 | 
			
		||||
          right: 144,
 | 
			
		||||
          display: "flex",
 | 
			
		||||
          gap: "24px",
 | 
			
		||||
        }}
 | 
			
		||||
      >
 | 
			
		||||
        <div className="legend-item">
 | 
			
		||||
          <div
 | 
			
		||||
            className="legend-color"
 | 
			
		||||
            style={{
 | 
			
		||||
              display: "inline-block",
 | 
			
		||||
              width: "12px",
 | 
			
		||||
              height: "12px",
 | 
			
		||||
              borderRadius: "2px",
 | 
			
		||||
              marginRight: "8px",
 | 
			
		||||
              backgroundColor: "#FFD160",
 | 
			
		||||
            }}
 | 
			
		||||
          />
 | 
			
		||||
          <span style={{ color: "#fff" }}>天然气I</span>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div className="legend-item">
 | 
			
		||||
          <div
 | 
			
		||||
            className="legend-color"
 | 
			
		||||
            style={{
 | 
			
		||||
              display: "inline-block",
 | 
			
		||||
              width: "12px",
 | 
			
		||||
              height: "12px",
 | 
			
		||||
              borderRadius: "2px",
 | 
			
		||||
              marginRight: "8px",
 | 
			
		||||
              backgroundColor: "#12FFF5",
 | 
			
		||||
            }}
 | 
			
		||||
          />
 | 
			
		||||
          <span style={{ color: "#fff" }}>天然气II</span>
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
      {/* real echarts here */}
 | 
			
		||||
      {options && (
 | 
			
		||||
        <ReactECharts
 | 
			
		||||
@@ -89,8 +129,9 @@ function NatGas(props) {
 | 
			
		||||
 | 
			
		||||
export default NatGas;
 | 
			
		||||
 | 
			
		||||
function getOptions(period, trend) {
 | 
			
		||||
  if (trend[period].length === 0) return null;
 | 
			
		||||
function getOptions(period, trendArr) {
 | 
			
		||||
  if (trendArr[0][period].length === 0 || trendArr[1][period].length === 0)
 | 
			
		||||
    return null;
 | 
			
		||||
  // export default function getOptions(seriesData, name) {
 | 
			
		||||
  const today = new Date();
 | 
			
		||||
  const currentYear = today.getFullYear();
 | 
			
		||||
@@ -185,21 +226,38 @@ function getOptions(period, trend) {
 | 
			
		||||
        },
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
    series: {
 | 
			
		||||
      data: trend[period].map((item) =>
 | 
			
		||||
        item != null ? (+item).toFixed(2) : null
 | 
			
		||||
      ),
 | 
			
		||||
      type: "line",
 | 
			
		||||
      symbol: "circle",
 | 
			
		||||
      symbolSize: 6,
 | 
			
		||||
      areaStyle: {
 | 
			
		||||
        color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
 | 
			
		||||
          { offset: 0, color: colors[0] + "40" },
 | 
			
		||||
          { offset: 0.5, color: colors[0] + "20" },
 | 
			
		||||
          { offset: 1, color: colors[0] + "00" },
 | 
			
		||||
        ]),
 | 
			
		||||
    series: [
 | 
			
		||||
      {
 | 
			
		||||
        data: trendArr[0][period].map((item) =>
 | 
			
		||||
          item != null ? (+item).toFixed(2) : null
 | 
			
		||||
        ),
 | 
			
		||||
        type: "line",
 | 
			
		||||
        symbol: "circle",
 | 
			
		||||
        symbolSize: 6,
 | 
			
		||||
        areaStyle: {
 | 
			
		||||
          color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
 | 
			
		||||
            { offset: 0, color: colors[0] + "40" },
 | 
			
		||||
            { offset: 0.5, color: colors[0] + "20" },
 | 
			
		||||
            { offset: 1, color: colors[0] + "00" },
 | 
			
		||||
          ]),
 | 
			
		||||
        },
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
      {
 | 
			
		||||
        data: trendArr[1][period].map((item) =>
 | 
			
		||||
          item != null ? (+item).toFixed(2) : null
 | 
			
		||||
        ),
 | 
			
		||||
        type: "line",
 | 
			
		||||
        symbol: "circle",
 | 
			
		||||
        symbolSize: 6,
 | 
			
		||||
        areaStyle: {
 | 
			
		||||
          color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
 | 
			
		||||
            { offset: 0, color: colors[1] + "40" },
 | 
			
		||||
            { offset: 0.5, color: colors[1] + "20" },
 | 
			
		||||
            { offset: 1, color: colors[1] + "00" },
 | 
			
		||||
          ]),
 | 
			
		||||
        },
 | 
			
		||||
      },
 | 
			
		||||
    ],
 | 
			
		||||
    // series: seriesData.map((arr, index) => ({
 | 
			
		||||
    // 	name: index + 1 + '#' + name,
 | 
			
		||||
    // 	data: arr,
 | 
			
		||||
 
 | 
			
		||||
@@ -6,17 +6,37 @@ import { useState } from "react";
 | 
			
		||||
import * as echarts from "echarts";
 | 
			
		||||
import dayjs from "dayjs";
 | 
			
		||||
 | 
			
		||||
function getTimeStr(period) {
 | 
			
		||||
  return {
 | 
			
		||||
    日:
 | 
			
		||||
      dayjs().format("YYYY.MM.DD") +
 | 
			
		||||
      " 7点 - " +
 | 
			
		||||
      dayjs().add(1, "d").format("YYYY.MM.DD") +
 | 
			
		||||
      " 7点",
 | 
			
		||||
    年:
 | 
			
		||||
      dayjs().subtract(1, "year").endOf("year").format("YYYY.MM.") +
 | 
			
		||||
      "29 - " +
 | 
			
		||||
      dayjs().endOf("year").format("YYYY.MM.") +
 | 
			
		||||
      "28",
 | 
			
		||||
    周:
 | 
			
		||||
      dayjs().subtract(7, "day").format("YYYY.MM.DD") +
 | 
			
		||||
      " - " +
 | 
			
		||||
      dayjs().subtract(1, "day").format("YYYY.MM.DD"),
 | 
			
		||||
    月:
 | 
			
		||||
      dayjs().subtract(1, "month").format("YYYY.MM.") +
 | 
			
		||||
      "29 - " +
 | 
			
		||||
      dayjs().format("YYYY.MM.") +
 | 
			
		||||
      "28",
 | 
			
		||||
  }[period];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function Oxygen(props) {
 | 
			
		||||
  const dayTrend = useSelector((state) => state.smoke?.dayTrend);
 | 
			
		||||
  const weekTrend = useSelector((state) => state.smoke?.weekTrend);
 | 
			
		||||
  const monthTrend = useSelector((state) => state.smoke?.monthTrend);
 | 
			
		||||
  const yearTrend = useSelector((state) => state.smoke?.yearTrend);
 | 
			
		||||
  const [period, setPeriod] = useState("日");
 | 
			
		||||
  const [timestr, setTimestr] = useState(
 | 
			
		||||
    dayjs().subtract(7, "day").format("YYYY.MM.DD") +
 | 
			
		||||
      " - " +
 | 
			
		||||
      dayjs().subtract(1, "day").format("YYYY.MM.DD")
 | 
			
		||||
  );
 | 
			
		||||
  let timestr = getTimeStr(period);
 | 
			
		||||
 | 
			
		||||
  const currentTrend =
 | 
			
		||||
    period === "日"
 | 
			
		||||
@@ -33,35 +53,13 @@ function Oxygen(props) {
 | 
			
		||||
 | 
			
		||||
  function handleDateChange(value) {
 | 
			
		||||
    setPeriod(value);
 | 
			
		||||
    setTimestr(
 | 
			
		||||
      {
 | 
			
		||||
        日:
 | 
			
		||||
          dayjs().subtract(1, "day").format("YYYY.MM.DD") +
 | 
			
		||||
          " 7点 - " +
 | 
			
		||||
          dayjs().format("YYYY.MM.DD") +
 | 
			
		||||
          " 7点",
 | 
			
		||||
        年:
 | 
			
		||||
          dayjs().subtract(1, "year").endOf("year").format("YYYY.MM.") +
 | 
			
		||||
          "29 - " +
 | 
			
		||||
          dayjs().endOf("year").format("YYYY.MM.") +
 | 
			
		||||
          "28",
 | 
			
		||||
        周:
 | 
			
		||||
          dayjs().subtract(7, "day").format("YYYY.MM.DD") +
 | 
			
		||||
          " - " +
 | 
			
		||||
          dayjs().subtract(1, "day").format("YYYY.MM.DD"),
 | 
			
		||||
        月:
 | 
			
		||||
          dayjs().subtract(1, "month").format("YYYY.MM.") +
 | 
			
		||||
          "29 - " +
 | 
			
		||||
          dayjs().format("YYYY.MM.") +
 | 
			
		||||
          "28",
 | 
			
		||||
      }[value]
 | 
			
		||||
    );
 | 
			
		||||
    timestr = getTimeStr(value);
 | 
			
		||||
  }
 | 
			
		||||
  return (
 | 
			
		||||
    <GraphBase
 | 
			
		||||
      icon="smoke"
 | 
			
		||||
      title="氧气含量"
 | 
			
		||||
      desc={`能耗趋势图  ${timestr}`}
 | 
			
		||||
      desc={`烟气趋势图  ${timestr}`}
 | 
			
		||||
      switchOptions={false}
 | 
			
		||||
      defaultSelect={period}
 | 
			
		||||
      onSwitch={handleSwitch}
 | 
			
		||||
 
 | 
			
		||||
@@ -6,6 +6,30 @@ import { useState } from "react";
 | 
			
		||||
import * as echarts from "echarts";
 | 
			
		||||
import dayjs from "dayjs";
 | 
			
		||||
 | 
			
		||||
function getTimeStr(period) {
 | 
			
		||||
  return {
 | 
			
		||||
    日:
 | 
			
		||||
      dayjs().format("YYYY.MM.DD") +
 | 
			
		||||
      " 7点 - " +
 | 
			
		||||
      dayjs().add(1, 'd').format("YYYY.MM.DD") +
 | 
			
		||||
      " 7点",
 | 
			
		||||
    年:
 | 
			
		||||
      dayjs().subtract(1, "year").endOf("year").format("YYYY.MM.") +
 | 
			
		||||
      "29 - " +
 | 
			
		||||
      dayjs().endOf("year").format("YYYY.MM.") +
 | 
			
		||||
      "28",
 | 
			
		||||
    周:
 | 
			
		||||
      dayjs().subtract(7, "day").format("YYYY.MM.DD") +
 | 
			
		||||
      " - " +
 | 
			
		||||
      dayjs().subtract(1, "day").format("YYYY.MM.DD"),
 | 
			
		||||
    月:
 | 
			
		||||
      dayjs().subtract(1, "month").format("YYYY.MM.") +
 | 
			
		||||
      "29 - " +
 | 
			
		||||
      dayjs().format("YYYY.MM.") +
 | 
			
		||||
      "28",
 | 
			
		||||
  }[period];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function SO2(props) {
 | 
			
		||||
  const dayTrend = useSelector((state) => state.smoke?.dayTrend);
 | 
			
		||||
  const weekTrend = useSelector((state) => state.smoke?.weekTrend);
 | 
			
		||||
@@ -21,47 +45,22 @@ function SO2(props) {
 | 
			
		||||
      : period === "月"
 | 
			
		||||
      ? monthTrend
 | 
			
		||||
      : yearTrend;
 | 
			
		||||
  const [timestr, setTimestr] = useState(
 | 
			
		||||
    dayjs().subtract(7, "day").format("YYYY.MM.DD") +
 | 
			
		||||
      " - " +
 | 
			
		||||
      dayjs().subtract(1, "day").format("YYYY.MM.DD")
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  let timestr = getTimeStr(period);
 | 
			
		||||
  const options = getOptions("SO2_float", period, currentTrend);
 | 
			
		||||
 | 
			
		||||
  function handleSwitch(v) {}
 | 
			
		||||
 | 
			
		||||
  function handleDateChange(value) {
 | 
			
		||||
    setPeriod(value);
 | 
			
		||||
    setTimestr(
 | 
			
		||||
      {
 | 
			
		||||
        日:
 | 
			
		||||
          dayjs().subtract(1, "day").format("YYYY.MM.DD") +
 | 
			
		||||
          " 7点 - " +
 | 
			
		||||
          dayjs().format("YYYY.MM.DD") +
 | 
			
		||||
          " 7点",
 | 
			
		||||
        年:
 | 
			
		||||
          dayjs().subtract(1, "year").endOf("year").format("YYYY.MM.") +
 | 
			
		||||
          "29 - " +
 | 
			
		||||
          dayjs().endOf("year").format("YYYY.MM.") +
 | 
			
		||||
          "28",
 | 
			
		||||
        周:
 | 
			
		||||
          dayjs().subtract(7, "day").format("YYYY.MM.DD") +
 | 
			
		||||
          " - " +
 | 
			
		||||
          dayjs().subtract(1, "day").format("YYYY.MM.DD"),
 | 
			
		||||
        月:
 | 
			
		||||
          dayjs().subtract(1, "month").format("YYYY.MM.") +
 | 
			
		||||
          "29 - " +
 | 
			
		||||
          dayjs().format("YYYY.MM.") +
 | 
			
		||||
          "28",
 | 
			
		||||
      }[value]
 | 
			
		||||
    );
 | 
			
		||||
    timestr = getTimeStr(value);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <GraphBase
 | 
			
		||||
      icon="smoke"
 | 
			
		||||
      title="二氧化硫"
 | 
			
		||||
      desc={`能耗趋势图  ${timestr}`}
 | 
			
		||||
      desc={`烟气趋势图  ${timestr}`}
 | 
			
		||||
      switchOptions={false}
 | 
			
		||||
      defaultSelect={period}
 | 
			
		||||
      onSwitch={handleSwitch}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,21 +1,23 @@
 | 
			
		||||
import cls from "./index.module.css";
 | 
			
		||||
import GradientText from "../../../Common/GradientText";
 | 
			
		||||
import { useSelector } from "react-redux";
 | 
			
		||||
import eIcon1 from '../../../../assets/Icon/oilstation.png';
 | 
			
		||||
 | 
			
		||||
function SmokeHandle(props) {
 | 
			
		||||
  const smokeInfo = useSelector((state) => state.smoke?.info);
 | 
			
		||||
  return (
 | 
			
		||||
    <div className={" " + cls.smoke} style={{ color: "#fff" }}>
 | 
			
		||||
      <span
 | 
			
		||||
        className={cls.shadowBorder}
 | 
			
		||||
        className={cls.shadowBorder + " " + cls.border}
 | 
			
		||||
        style={{
 | 
			
		||||
          gridRow: "1 / 3",
 | 
			
		||||
          paddingTop: "96px",
 | 
			
		||||
          paddingLeft: "32px",
 | 
			
		||||
          userSelect: "none",
 | 
			
		||||
          textAlign: "center",
 | 
			
		||||
        }}
 | 
			
		||||
      >
 | 
			
		||||
        <GradientText text="烟气处理" />
 | 
			
		||||
        <img src={eIcon1} width={32} alt="eIcon1" />
 | 
			
		||||
        <GradientText text={"\u2002\u2002烟气处理"} />
 | 
			
		||||
      </span>
 | 
			
		||||
      <span
 | 
			
		||||
        className={cls.shadowBorder + " " + cls.infoText}
 | 
			
		||||
@@ -32,13 +34,13 @@ function SmokeHandle(props) {
 | 
			
		||||
          {(+smokeInfo?.NOX_float)?.toFixed(2) || 0}
 | 
			
		||||
        </span>
 | 
			
		||||
      </span>
 | 
			
		||||
      <span className={cls.shadowBorder + " " + cls.infoText}>
 | 
			
		||||
      <span className={cls.shadowBorder + " " + cls.infoText + " " + cls.border}>
 | 
			
		||||
        <span style={{ lineHeight: 1.5 }}>二氧化硫浓度 mg/m³</span>
 | 
			
		||||
        <span style={{ lineHeight: 1.5 }}>
 | 
			
		||||
          {(+smokeInfo?.SO2_float)?.toFixed(2) || 0}
 | 
			
		||||
        </span>
 | 
			
		||||
      </span>
 | 
			
		||||
      <span className={cls.shadowBorder + " " + cls.infoText}>
 | 
			
		||||
      <span className={cls.shadowBorder + " " + cls.infoText + " " + cls.border}>
 | 
			
		||||
        <span style={{ lineHeight: 1.5 }}>颗粒物浓度 mg/m³</span>
 | 
			
		||||
        <span style={{ lineHeight: 1.5 }}>
 | 
			
		||||
          {(+smokeInfo?.dust_float)?.toFixed(2) || 0}
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,8 @@
 | 
			
		||||
  gap: 6px;
 | 
			
		||||
  grid-template-columns: 187px 347px 347px;
 | 
			
		||||
  /* grid-template-rows: 60px 60px; */
 | 
			
		||||
  grid-template-rows: 129px 129px;
 | 
			
		||||
  /* grid-template-rows: 129px 129px; */
 | 
			
		||||
  grid-template-rows: auto;
 | 
			
		||||
  height: 100%;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -13,6 +14,29 @@
 | 
			
		||||
  padding: 4px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.shadowBorder.border {
 | 
			
		||||
  position: relative;
 | 
			
		||||
  border-bottom: 2px solid #00fff7;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.shadowBorder.border::before,
 | 
			
		||||
.shadowBorder.border::after {
 | 
			
		||||
  content: "";
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  bottom: 0;
 | 
			
		||||
  display: inline-block;
 | 
			
		||||
  height: 100%;
 | 
			
		||||
  width: 2px;
 | 
			
		||||
  background: linear-gradient(to top, #00fff7, #00fff708, transparent);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.shadowBorder.border::before {
 | 
			
		||||
  left: 0;
 | 
			
		||||
}
 | 
			
		||||
.shadowBorder.border::after {
 | 
			
		||||
  right: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.infoText {
 | 
			
		||||
  text-align: center;
 | 
			
		||||
  font-size: 24px;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,7 @@
 | 
			
		||||
import React from 'react';
 | 
			
		||||
import Item2 from './RightTable';
 | 
			
		||||
import Item1 from '../../../Common/TimeFireDir';
 | 
			
		||||
// import Item1 from '../../../Common/TimeFireDir';
 | 
			
		||||
import Item1 from '../../../Common/VideoMonitor';
 | 
			
		||||
 | 
			
		||||
import cls from './index.module.scss';
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -17,6 +17,10 @@ export default function useSlider(defaultSize) {
 | 
			
		||||
 | 
			
		||||
	const v = (value / 100).toFixed(2);
 | 
			
		||||
 | 
			
		||||
	useEffect(() => {
 | 
			
		||||
		document.documentElement.style.setProperty('--scale', v);
 | 
			
		||||
	}, [v])
 | 
			
		||||
 | 
			
		||||
	const styles = {
 | 
			
		||||
		transform: `scale(${v})`,
 | 
			
		||||
		// transform: `scale(${v * 24 / 33}, ${v})`,
 | 
			
		||||
 
 | 
			
		||||
@@ -37,19 +37,22 @@ function EnergyAnalysis(props) {
 | 
			
		||||
          <NatGas />
 | 
			
		||||
        </div>
 | 
			
		||||
        <div style={{ gridRow: 3 }}>
 | 
			
		||||
          <Gas />
 | 
			
		||||
          {/* <Gas /> */}
 | 
			
		||||
          <ElecCost />
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
 | 
			
		||||
      <div className={cls.vvgrid + " col-4"}>
 | 
			
		||||
        <div className=" electronic">
 | 
			
		||||
          <Energy />
 | 
			
		||||
          <Energy key="2" page={2} />
 | 
			
		||||
        </div>
 | 
			
		||||
        <div className=" gas">
 | 
			
		||||
          <SmokeHandle />
 | 
			
		||||
          <Energy key="1" page={1} />
 | 
			
		||||
          {/* <SmokeHandle /> */}
 | 
			
		||||
        </div>
 | 
			
		||||
        <div style={{ height: "100%" }}>
 | 
			
		||||
          <ElecCost />
 | 
			
		||||
          {/* <ElecCost /> */}
 | 
			
		||||
          <SmokeHandle />
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
 
 | 
			
		||||
@@ -27,10 +27,18 @@
 | 
			
		||||
	gap: 24px;
 | 
			
		||||
	grid-template-rows: 128px 389px 389px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.vvgrid {
 | 
			
		||||
	display: grid;
 | 
			
		||||
	gap: 24px;
 | 
			
		||||
	grid-template-rows: 258px 258px 389px;
 | 
			
		||||
	display: flex;
 | 
			
		||||
	flex-direction: column;
 | 
			
		||||
	gap: 32px;
 | 
			
		||||
	/* display: grid;
 | 
			
		||||
	gap: 32px;
 | 
			
		||||
	grid-template-rows: 280px 280px 410px; */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.vvgrid > div {
 | 
			
		||||
	flex: 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.shadowBorder {
 | 
			
		||||
 
 | 
			
		||||
@@ -13,6 +13,9 @@ import QualityCheckRight from "../../components/Modules/QualityCheck/RightSide";
 | 
			
		||||
import { useSelector } from "react-redux";
 | 
			
		||||
import { useEffect, useRef } from "react";
 | 
			
		||||
import useRefresh from "../../hooks/useRefresh";
 | 
			
		||||
import TimeFireDir from "../../components/Common/TimeFireDir";
 | 
			
		||||
 | 
			
		||||
import WarnAlertList from "../../components/Common/WarnAlert/ListContainer";
 | 
			
		||||
 | 
			
		||||
export default function Home({ active }) {
 | 
			
		||||
  useRefresh(true);
 | 
			
		||||
@@ -33,8 +36,22 @@ export default function Home({ active }) {
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <div className="Main">
 | 
			
		||||
      {active == "窑炉总览" && (
 | 
			
		||||
        <div
 | 
			
		||||
          style={{
 | 
			
		||||
            position: "fixed",
 | 
			
		||||
            top: "210px",
 | 
			
		||||
            left: "50%",
 | 
			
		||||
            transform: "translateX(-40%)",
 | 
			
		||||
          }}
 | 
			
		||||
        >
 | 
			
		||||
          <TimeFireDir />
 | 
			
		||||
        </div>
 | 
			
		||||
      )}
 | 
			
		||||
      {active != "窑炉总览" && <div className="bgDitu"></div>}
 | 
			
		||||
      {active == "窑炉总览" && <div className="bgOverview"></div>}
 | 
			
		||||
      {active == "窑炉总览" && (
 | 
			
		||||
        <div className="bgOverview" id="bgOverview"></div>
 | 
			
		||||
      )}
 | 
			
		||||
      <AnimatePresence mode="wait">
 | 
			
		||||
        <div
 | 
			
		||||
          className="left-side"
 | 
			
		||||
@@ -54,6 +71,9 @@ export default function Home({ active }) {
 | 
			
		||||
      <div className="Center">
 | 
			
		||||
        {active == "窑炉总览" && (
 | 
			
		||||
          <>
 | 
			
		||||
            <div id="alarm-list-container">
 | 
			
		||||
              <WarnAlertList />
 | 
			
		||||
            </div>
 | 
			
		||||
            <AnimatePresence>
 | 
			
		||||
              <motion.div
 | 
			
		||||
                key="center-top"
 | 
			
		||||
@@ -103,38 +123,6 @@ export default function Home({ active }) {
 | 
			
		||||
              )}
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
            {/* {fireDir && fireDir == "东火" && (
 | 
			
		||||
              <video
 | 
			
		||||
                src="/video/fire_little_top.webm"
 | 
			
		||||
                muted
 | 
			
		||||
                autoPlay
 | 
			
		||||
                loop
 | 
			
		||||
                width={4200}
 | 
			
		||||
                style={{
 | 
			
		||||
                  position: "absolute",
 | 
			
		||||
                  top: "-160px",
 | 
			
		||||
                  left: "-910px",
 | 
			
		||||
                  zIndex: -1,
 | 
			
		||||
                }}
 | 
			
		||||
              ></video>
 | 
			
		||||
            )}
 | 
			
		||||
 | 
			
		||||
            {fireDir && fireDir == "西火" && (
 | 
			
		||||
              <video
 | 
			
		||||
                src="/video/fire_little_down.webm"
 | 
			
		||||
                muted
 | 
			
		||||
                autoPlay
 | 
			
		||||
                loop
 | 
			
		||||
                width={4200}
 | 
			
		||||
                style={{
 | 
			
		||||
                  position: "absolute",
 | 
			
		||||
                  top: "-180px",
 | 
			
		||||
                  left: "-910px",
 | 
			
		||||
                  zIndex: -1,
 | 
			
		||||
                }}
 | 
			
		||||
              ></video>
 | 
			
		||||
            )} */}
 | 
			
		||||
 | 
			
		||||
            <div key="bottom-bar" className="Button">
 | 
			
		||||
              <BottomBar />
 | 
			
		||||
            </div>
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										30
									
								
								src/store/features/alarmSlice.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,30 @@
 | 
			
		||||
import { createSlice } from "@reduxjs/toolkit";
 | 
			
		||||
 | 
			
		||||
export const initialState = {
 | 
			
		||||
  list: [],
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const alarmSlice = createSlice({
 | 
			
		||||
  name: "alarm",
 | 
			
		||||
  initialState,
 | 
			
		||||
  reducers: {
 | 
			
		||||
    setList(state, action) {
 | 
			
		||||
      // action.payload 是 { 'A1_1_1': 'detail' } 的结构
 | 
			
		||||
      console.log("[alarm store] setting list ---> ", action);
 | 
			
		||||
      const rawData = action.payload;
 | 
			
		||||
      const list = [];
 | 
			
		||||
      Object.entries(rawData).forEach(([key, value]) => {
 | 
			
		||||
        const n = [key, value];
 | 
			
		||||
        list.push({
 | 
			
		||||
          id: key,
 | 
			
		||||
          title: n[0],
 | 
			
		||||
          content: n[1],
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
      state.list = list;
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
export default alarmSlice.reducer;
 | 
			
		||||
export const { setList } = alarmSlice.actions;
 | 
			
		||||
@@ -14,9 +14,12 @@ import annealFanFrequenceReducer from "./features/annealFanFrequenceSlice";
 | 
			
		||||
import annealFanInfoReducer from "./features/annealFanInfoSlice";
 | 
			
		||||
import cuttingReducer from "./features/cuttingSlice";
 | 
			
		||||
import smokeReducer from "./features/smokeSlice";
 | 
			
		||||
import alarmSlice from "./features/alarmSlice";
 | 
			
		||||
 | 
			
		||||
export const store = configureStore({
 | 
			
		||||
  reducer: {
 | 
			
		||||
    // 报警信息
 | 
			
		||||
    alarm: alarmSlice,
 | 
			
		||||
    // 窑炉信息
 | 
			
		||||
    kiln: kilnReducer,
 | 
			
		||||
    // 投料机信息
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +1,7 @@
 | 
			
		||||
import { store } from "../store";
 | 
			
		||||
import { MessageItem } from "./checkTypeHelper";
 | 
			
		||||
 | 
			
		||||
export default function handler(msg: MessageEvent) {
 | 
			
		||||
  let serializedData: MessageItem | null = null;
 | 
			
		||||
export default function handler(msg) {
 | 
			
		||||
  let serializedData = null;
 | 
			
		||||
  try {
 | 
			
		||||
    serializedData = JSON.parse(msg.data);
 | 
			
		||||
  } catch (error) {
 | 
			
		||||
@@ -1,26 +0,0 @@
 | 
			
		||||
type CheckTypeItem = {
 | 
			
		||||
  checkDiscard?: boolean;
 | 
			
		||||
  checkType: string;
 | 
			
		||||
  checkNum: number;
 | 
			
		||||
  ip?: string;
 | 
			
		||||
  israDefectType?: string;
 | 
			
		||||
  israSeriousGrade?: string;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
type ProductLineItem = {
 | 
			
		||||
  name: string;
 | 
			
		||||
  sum: number;
 | 
			
		||||
  data: CheckTypeItem[];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export type MessageItem = {
 | 
			
		||||
  type: string;
 | 
			
		||||
  name: string;
 | 
			
		||||
  detData: {
 | 
			
		||||
    checkType: string[];
 | 
			
		||||
    dayStatistic?: ProductLineItem[];
 | 
			
		||||
    weekStatistic?: ProductLineItem[];
 | 
			
		||||
    monthStatistic?: ProductLineItem[];
 | 
			
		||||
    yearStatistic?: ProductLineItem[];
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
@@ -1,30 +1,14 @@
 | 
			
		||||
import { store } from "../store";
 | 
			
		||||
type TableDataType = {
 | 
			
		||||
  name: "table";
 | 
			
		||||
  type: "cutting";
 | 
			
		||||
  data: any[];
 | 
			
		||||
};
 | 
			
		||||
type ChartDataType = {
 | 
			
		||||
  name: "chart";
 | 
			
		||||
  type: "cutting";
 | 
			
		||||
  nightPushData: any[];
 | 
			
		||||
  dayPushData: any[];
 | 
			
		||||
  allPushData: any[];
 | 
			
		||||
  dateType: "day" | "week" | "month" | "year";
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default function handler(msg: MessageEvent) {
 | 
			
		||||
  let serializedData: TableDataType | ChartDataType | null = null;
 | 
			
		||||
export default function handler(msg) {
 | 
			
		||||
  let serializedData = null;
 | 
			
		||||
  try {
 | 
			
		||||
    serializedData = JSON.parse(msg.data);
 | 
			
		||||
  } catch (error) {
 | 
			
		||||
    console.log("[*] websocket: [unable to serialize] --->  ", msg);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  console.log("[CUTTING DATA] ---> ", serializedData);
 | 
			
		||||
 | 
			
		||||
  if (serializedData == null) return;
 | 
			
		||||
 | 
			
		||||
  switch (serializedData.name) {
 | 
			
		||||
    case "table":
 | 
			
		||||
      store.dispatch({
 | 
			
		||||
@@ -1,13 +1,18 @@
 | 
			
		||||
import { store } from "../store";
 | 
			
		||||
import { setList } from "../store/features/alarmSlice";
 | 
			
		||||
 | 
			
		||||
export default function handler(msg: MessageEvent) {
 | 
			
		||||
  let serializedData: { type: string; data: any } | null = null;
 | 
			
		||||
export default function handler(msg) {
 | 
			
		||||
  let serializedData = null;
 | 
			
		||||
  try {
 | 
			
		||||
    serializedData = JSON.parse(msg.data);
 | 
			
		||||
  } catch (error) {
 | 
			
		||||
    console.log("[*] websocket: [unable to serialize] --->  ", msg);
 | 
			
		||||
  }
 | 
			
		||||
  switch (serializedData?.type) {
 | 
			
		||||
    case "alarmList": {
 | 
			
		||||
      store.dispatch(setList(serializedData.data));
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case "KilnInfo": {
 | 
			
		||||
      store.dispatch({
 | 
			
		||||
        type: "kiln/setKilnInfo",
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
import { store } from "../store";
 | 
			
		||||
 | 
			
		||||
export default function handler(msg: MessageEvent) {
 | 
			
		||||
  let serializedData: { type: string; data: any } | null = null;
 | 
			
		||||
export default function handler(msg) {
 | 
			
		||||
  let serializedData = null;
 | 
			
		||||
  try {
 | 
			
		||||
    serializedData = JSON.parse(msg.data);
 | 
			
		||||
  } catch (error) {
 | 
			
		||||
@@ -88,9 +88,6 @@ export function getOptions(period, source, trend, options = {}) {
 | 
			
		||||
          color: "#213259a0",
 | 
			
		||||
        },
 | 
			
		||||
      },
 | 
			
		||||
      // interval: 10,
 | 
			
		||||
      // min: 0,
 | 
			
		||||
      // max: 100,
 | 
			
		||||
    },
 | 
			
		||||
    series: [
 | 
			
		||||
      {
 | 
			
		||||
@@ -123,7 +120,6 @@ export function getOptions(period, source, trend, options = {}) {
 | 
			
		||||
        type: "shadow",
 | 
			
		||||
      },
 | 
			
		||||
      className: "xc-chart-tooltip",
 | 
			
		||||
      // backgroundColor: ''
 | 
			
		||||
    },
 | 
			
		||||
    ...options,
 | 
			
		||||
  };
 | 
			
		||||
 
 | 
			
		||||
@@ -9,28 +9,22 @@ import smokeHandler from "./smoke";
 | 
			
		||||
 * new XClient('ws://192.168.1.12:8081/xc-screen/websocket/xc001', 'DCS')
 | 
			
		||||
 */
 | 
			
		||||
class XClient {
 | 
			
		||||
  url: string;
 | 
			
		||||
  name: string;
 | 
			
		||||
  ws: WebSocket;
 | 
			
		||||
  timeout: number = 1000 * 5;
 | 
			
		||||
  heartbeatDelay: number = 1000 * 60 * 3;
 | 
			
		||||
  reconnectCount: number = 0;
 | 
			
		||||
  onmessage: (msg: MessageEvent) => void;
 | 
			
		||||
  hb: number = 0;
 | 
			
		||||
  // url;
 | 
			
		||||
  // name;
 | 
			
		||||
  // ws;
 | 
			
		||||
  // timeout = 1000 * 5;
 | 
			
		||||
  // heartbeatDelay = 1000 * 60 * 3;
 | 
			
		||||
  // reconnectCount = 0;
 | 
			
		||||
  // onmessage = (msg) => console.log(msg);
 | 
			
		||||
  // hb = 0;
 | 
			
		||||
 | 
			
		||||
  constructor(
 | 
			
		||||
    config: {
 | 
			
		||||
      url: string;
 | 
			
		||||
      name: string;
 | 
			
		||||
      timeout?: number;
 | 
			
		||||
      reconnectCount?: number;
 | 
			
		||||
    },
 | 
			
		||||
    onmessage: (msg: MessageEvent) => void
 | 
			
		||||
  ) {
 | 
			
		||||
  constructor(config, onmessage = (msg) => console.log(msg)) {
 | 
			
		||||
    this.url = config.url;
 | 
			
		||||
    this.name = config.name;
 | 
			
		||||
    this.ws = new WebSocket(config.url);
 | 
			
		||||
    this.timeout = config.timeout || 1000 * 5;
 | 
			
		||||
    this.heartbeatDelay = 1000 * 60 * 3;
 | 
			
		||||
    this.reconnectCount = 0;
 | 
			
		||||
 | 
			
		||||
    this.ws.onopen = () => {
 | 
			
		||||
      console.log(`[*] ${this.name} 初始化连接成功`);
 | 
			
		||||
@@ -113,6 +107,7 @@ const newUser = uuidv4();
 | 
			
		||||
new XClient(
 | 
			
		||||
  {
 | 
			
		||||
    url: "ws://10.70.180.10:8081/xc-screen/websocket/xc001" + newUser,
 | 
			
		||||
    // url: "ws://127.0.0.1:9800/alarm?user=" + newUser,
 | 
			
		||||
    name: "DCS_DATA",
 | 
			
		||||
    // "ws://m306416y13.yicp.fun:35441/xc-screen/websocket/xc001",
 | 
			
		||||
    // "ws://192.168.1.114:8081/xc-screen/websocket/xc001",
 | 
			
		||||
@@ -164,7 +159,7 @@ new XClient(
 | 
			
		||||
  smokeHandler
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
export function randomInt(min: number, max: number, includeMax = false) {
 | 
			
		||||
export function randomInt(min, max, includeMax = false) {
 | 
			
		||||
  let Fn = includeMax ? Math.ceil : Math.floor;
 | 
			
		||||
  let num = Fn(Math.random() * max);
 | 
			
		||||
  while (num < min) {
 | 
			
		||||
@@ -1,4 +0,0 @@
 | 
			
		||||
export type MessageEvent = {
 | 
			
		||||
    type: string;
 | 
			
		||||
    data: any;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										32
									
								
								src/utils/smoke.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,32 @@
 | 
			
		||||
import { store } from "../store";
 | 
			
		||||
 | 
			
		||||
export default function handler(msg) {
 | 
			
		||||
  let serializedData = null;
 | 
			
		||||
  try {
 | 
			
		||||
    serializedData = JSON.parse(msg.data);
 | 
			
		||||
  } catch (error) {
 | 
			
		||||
    console.log("[*] websocket: [unable to serialize] --->  ", msg);
 | 
			
		||||
  }
 | 
			
		||||
  switch (serializedData?.type) {
 | 
			
		||||
    case "exhaustGas": {
 | 
			
		||||
      store.dispatch({
 | 
			
		||||
        type: "smoke/setInfo",
 | 
			
		||||
        payload: serializedData.realtime,
 | 
			
		||||
      });
 | 
			
		||||
      store.dispatch({
 | 
			
		||||
        type: "smoke/setTrend",
 | 
			
		||||
        payload: {
 | 
			
		||||
          dayTrend: serializedData.dayTrend,
 | 
			
		||||
          weekTrend: serializedData.weekTrend,
 | 
			
		||||
          monthTrend: serializedData.monthTrend,
 | 
			
		||||
          yearTrend: serializedData.yearTrend,
 | 
			
		||||
        },
 | 
			
		||||
      });
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    default: {
 | 
			
		||||
      console.log("websocket message: [unknown] --->  ", msg.data);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,114 +0,0 @@
 | 
			
		||||
import { store } from "../store";
 | 
			
		||||
 | 
			
		||||
type SmokeMessageItem = {
 | 
			
		||||
  type: string;
 | 
			
		||||
  realtime: {
 | 
			
		||||
    SO2_float: number;
 | 
			
		||||
    NOX_float: number;
 | 
			
		||||
    O2_float: number;
 | 
			
		||||
    dust_float: number;
 | 
			
		||||
  };
 | 
			
		||||
  dayTrend: {
 | 
			
		||||
    SO2_float: Array<{
 | 
			
		||||
      time: string;
 | 
			
		||||
      value: number;
 | 
			
		||||
    }>;
 | 
			
		||||
    NOX_float: Array<{
 | 
			
		||||
      time: string;
 | 
			
		||||
      value: number;
 | 
			
		||||
    }>;
 | 
			
		||||
    O2_float: Array<{
 | 
			
		||||
      time: string;
 | 
			
		||||
      value: number;
 | 
			
		||||
    }>;
 | 
			
		||||
    dust_float: Array<{
 | 
			
		||||
      time: string;
 | 
			
		||||
      value: number;
 | 
			
		||||
    }>;
 | 
			
		||||
  };
 | 
			
		||||
  weekTrend: {
 | 
			
		||||
    SO2_float: Array<{
 | 
			
		||||
      time: string;
 | 
			
		||||
      value: number;
 | 
			
		||||
    }>;
 | 
			
		||||
    NOX_float: Array<{
 | 
			
		||||
      time: string;
 | 
			
		||||
      value: number;
 | 
			
		||||
    }>;
 | 
			
		||||
    O2_float: Array<{
 | 
			
		||||
      time: string;
 | 
			
		||||
      value: number;
 | 
			
		||||
    }>;
 | 
			
		||||
    dust_float: Array<{
 | 
			
		||||
      time: string;
 | 
			
		||||
      value: number;
 | 
			
		||||
    }>;
 | 
			
		||||
  };
 | 
			
		||||
  monthTrend: {
 | 
			
		||||
    SO2_float: Array<{
 | 
			
		||||
      time: string;
 | 
			
		||||
      value: number;
 | 
			
		||||
    }>;
 | 
			
		||||
    NOX_float: Array<{
 | 
			
		||||
      time: string;
 | 
			
		||||
      value: number;
 | 
			
		||||
    }>;
 | 
			
		||||
    O2_float: Array<{
 | 
			
		||||
      time: string;
 | 
			
		||||
      value: number;
 | 
			
		||||
    }>;
 | 
			
		||||
    dust_float: Array<{
 | 
			
		||||
      time: string;
 | 
			
		||||
      value: number;
 | 
			
		||||
    }>;
 | 
			
		||||
  };
 | 
			
		||||
  yearTrend: {
 | 
			
		||||
    SO2_float: Array<{
 | 
			
		||||
      time: string;
 | 
			
		||||
      value: number;
 | 
			
		||||
    }>;
 | 
			
		||||
    NOX_float: Array<{
 | 
			
		||||
      time: string;
 | 
			
		||||
      value: number;
 | 
			
		||||
    }>;
 | 
			
		||||
    O2_float: Array<{
 | 
			
		||||
      time: string;
 | 
			
		||||
      value: number;
 | 
			
		||||
    }>;
 | 
			
		||||
    dust_float: Array<{
 | 
			
		||||
      time: string;
 | 
			
		||||
      value: number;
 | 
			
		||||
    }>;
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default function handler(msg: MessageEvent) {
 | 
			
		||||
  let serializedData: SmokeMessageItem | null = null;
 | 
			
		||||
  try {
 | 
			
		||||
    serializedData = JSON.parse(msg.data);
 | 
			
		||||
  } catch (error) {
 | 
			
		||||
    console.log("[*] websocket: [unable to serialize] --->  ", msg);
 | 
			
		||||
  }
 | 
			
		||||
  switch (serializedData?.type) {
 | 
			
		||||
    case "exhaustGas": {
 | 
			
		||||
      store.dispatch({
 | 
			
		||||
        type: "smoke/setInfo",
 | 
			
		||||
        payload: serializedData.realtime,
 | 
			
		||||
      });
 | 
			
		||||
      store.dispatch({
 | 
			
		||||
        type: "smoke/setTrend",
 | 
			
		||||
        payload: {
 | 
			
		||||
          dayTrend: serializedData.dayTrend,
 | 
			
		||||
          weekTrend: serializedData.weekTrend,
 | 
			
		||||
          monthTrend: serializedData.monthTrend,
 | 
			
		||||
          yearTrend: serializedData.yearTrend,
 | 
			
		||||
        },
 | 
			
		||||
      });
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    default: {
 | 
			
		||||
      console.log("websocket message: [unknown] --->  ", msg.data);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										109
									
								
								tsconfig.json
									
									
									
									
									
								
							
							
						
						@@ -1,109 +0,0 @@
 | 
			
		||||
{
 | 
			
		||||
  "compilerOptions": {
 | 
			
		||||
    /* Visit https://aka.ms/tsconfig to read more about this file */
 | 
			
		||||
 | 
			
		||||
    /* Projects */
 | 
			
		||||
    // "incremental": true,                              /* Save .tsbuildinfo files to allow for incremental compilation of projects. */
 | 
			
		||||
    // "composite": true,                                /* Enable constraints that allow a TypeScript project to be used with project references. */
 | 
			
		||||
    // "tsBuildInfoFile": "./.tsbuildinfo",              /* Specify the path to .tsbuildinfo incremental compilation file. */
 | 
			
		||||
    // "disableSourceOfProjectReferenceRedirect": true,  /* Disable preferring source files instead of declaration files when referencing composite projects. */
 | 
			
		||||
    // "disableSolutionSearching": true,                 /* Opt a project out of multi-project reference checking when editing. */
 | 
			
		||||
    // "disableReferencedProjectLoad": true,             /* Reduce the number of projects loaded automatically by TypeScript. */
 | 
			
		||||
 | 
			
		||||
    /* Language and Environment */
 | 
			
		||||
    "target": "es2016",                                  /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
 | 
			
		||||
    // "lib": [],                                        /* Specify a set of bundled library declaration files that describe the target runtime environment. */
 | 
			
		||||
    "jsx": "preserve",                                /* Specify what JSX code is generated. */
 | 
			
		||||
    // "experimentalDecorators": true,                   /* Enable experimental support for legacy experimental decorators. */
 | 
			
		||||
    // "emitDecoratorMetadata": true,                    /* Emit design-type metadata for decorated declarations in source files. */
 | 
			
		||||
    // "jsxFactory": "",                                 /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
 | 
			
		||||
    // "jsxFragmentFactory": "",                         /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
 | 
			
		||||
    // "jsxImportSource": "",                            /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */
 | 
			
		||||
    // "reactNamespace": "",                             /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */
 | 
			
		||||
    // "noLib": true,                                    /* Disable including any library files, including the default lib.d.ts. */
 | 
			
		||||
    // "useDefineForClassFields": true,                  /* Emit ECMAScript-standard-compliant class fields. */
 | 
			
		||||
    // "moduleDetection": "auto",                        /* Control what method is used to detect module-format JS files. */
 | 
			
		||||
 | 
			
		||||
    /* Modules */
 | 
			
		||||
    "module": "commonjs",                                /* Specify what module code is generated. */
 | 
			
		||||
    // "rootDir": "./",                                  /* Specify the root folder within your source files. */
 | 
			
		||||
    // "moduleResolution": "node10",                     /* Specify how TypeScript looks up a file from a given module specifier. */
 | 
			
		||||
    // "baseUrl": "./",                                  /* Specify the base directory to resolve non-relative module names. */
 | 
			
		||||
    // "paths": {},                                      /* Specify a set of entries that re-map imports to additional lookup locations. */
 | 
			
		||||
    // "rootDirs": [],                                   /* Allow multiple folders to be treated as one when resolving modules. */
 | 
			
		||||
    // "typeRoots": [],                                  /* Specify multiple folders that act like './node_modules/@types'. */
 | 
			
		||||
    // "types": [],                                      /* Specify type package names to be included without being referenced in a source file. */
 | 
			
		||||
    // "allowUmdGlobalAccess": true,                     /* Allow accessing UMD globals from modules. */
 | 
			
		||||
    // "moduleSuffixes": [],                             /* List of file name suffixes to search when resolving a module. */
 | 
			
		||||
    // "allowImportingTsExtensions": true,               /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */
 | 
			
		||||
    // "resolvePackageJsonExports": true,                /* Use the package.json 'exports' field when resolving package imports. */
 | 
			
		||||
    // "resolvePackageJsonImports": true,                /* Use the package.json 'imports' field when resolving imports. */
 | 
			
		||||
    // "customConditions": [],                           /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */
 | 
			
		||||
    // "resolveJsonModule": true,                        /* Enable importing .json files. */
 | 
			
		||||
    // "allowArbitraryExtensions": true,                 /* Enable importing files with any extension, provided a declaration file is present. */
 | 
			
		||||
    // "noResolve": true,                                /* Disallow 'import's, 'require's or '<reference>'s from expanding the number of files TypeScript should add to a project. */
 | 
			
		||||
 | 
			
		||||
    /* JavaScript Support */
 | 
			
		||||
    "allowJs": true,                                  /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
 | 
			
		||||
    // "checkJs": true,                                  /* Enable error reporting in type-checked JavaScript files. */
 | 
			
		||||
    // "maxNodeModuleJsDepth": 1,                        /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
 | 
			
		||||
 | 
			
		||||
    /* Emit */
 | 
			
		||||
    // "declaration": true,                              /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
 | 
			
		||||
    // "declarationMap": true,                           /* Create sourcemaps for d.ts files. */
 | 
			
		||||
    // "emitDeclarationOnly": true,                      /* Only output d.ts files and not JavaScript files. */
 | 
			
		||||
    // "sourceMap": true,                                /* Create source map files for emitted JavaScript files. */
 | 
			
		||||
    // "inlineSourceMap": true,                          /* Include sourcemap files inside the emitted JavaScript. */
 | 
			
		||||
    // "outFile": "./",                                  /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
 | 
			
		||||
    // "outDir": "./",                                   /* Specify an output folder for all emitted files. */
 | 
			
		||||
    // "removeComments": true,                           /* Disable emitting comments. */
 | 
			
		||||
    // "noEmit": true,                                   /* Disable emitting files from a compilation. */
 | 
			
		||||
    // "importHelpers": true,                            /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
 | 
			
		||||
    // "importsNotUsedAsValues": "remove",               /* Specify emit/checking behavior for imports that are only used for types. */
 | 
			
		||||
    // "downlevelIteration": true,                       /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
 | 
			
		||||
    // "sourceRoot": "",                                 /* Specify the root path for debuggers to find the reference source code. */
 | 
			
		||||
    // "mapRoot": "",                                    /* Specify the location where debugger should locate map files instead of generated locations. */
 | 
			
		||||
    // "inlineSources": true,                            /* Include source code in the sourcemaps inside the emitted JavaScript. */
 | 
			
		||||
    // "emitBOM": true,                                  /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
 | 
			
		||||
    // "newLine": "crlf",                                /* Set the newline character for emitting files. */
 | 
			
		||||
    // "stripInternal": true,                            /* Disable emitting declarations that have '@internal' in their JSDoc comments. */
 | 
			
		||||
    // "noEmitHelpers": true,                            /* Disable generating custom helper functions like '__extends' in compiled output. */
 | 
			
		||||
    // "noEmitOnError": true,                            /* Disable emitting files if any type checking errors are reported. */
 | 
			
		||||
    // "preserveConstEnums": true,                       /* Disable erasing 'const enum' declarations in generated code. */
 | 
			
		||||
    // "declarationDir": "./",                           /* Specify the output directory for generated declaration files. */
 | 
			
		||||
    // "preserveValueImports": true,                     /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
 | 
			
		||||
 | 
			
		||||
    /* Interop Constraints */
 | 
			
		||||
    // "isolatedModules": true,                          /* Ensure that each file can be safely transpiled without relying on other imports. */
 | 
			
		||||
    // "verbatimModuleSyntax": true,                     /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */
 | 
			
		||||
    // "allowSyntheticDefaultImports": true,             /* Allow 'import x from y' when a module doesn't have a default export. */
 | 
			
		||||
    "esModuleInterop": true,                             /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
 | 
			
		||||
    // "preserveSymlinks": true,                         /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
 | 
			
		||||
    "forceConsistentCasingInFileNames": true,            /* Ensure that casing is correct in imports. */
 | 
			
		||||
 | 
			
		||||
    /* Type Checking */
 | 
			
		||||
    "strict": true,                                      /* Enable all strict type-checking options. */
 | 
			
		||||
    // "noImplicitAny": true,                            /* Enable error reporting for expressions and declarations with an implied 'any' type. */
 | 
			
		||||
    // "strictNullChecks": true,                         /* When type checking, take into account 'null' and 'undefined'. */
 | 
			
		||||
    // "strictFunctionTypes": true,                      /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
 | 
			
		||||
    // "strictBindCallApply": true,                      /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */
 | 
			
		||||
    // "strictPropertyInitialization": true,             /* Check for class properties that are declared but not set in the constructor. */
 | 
			
		||||
    // "noImplicitThis": true,                           /* Enable error reporting when 'this' is given the type 'any'. */
 | 
			
		||||
    // "useUnknownInCatchVariables": true,               /* Default catch clause variables as 'unknown' instead of 'any'. */
 | 
			
		||||
    // "alwaysStrict": true,                             /* Ensure 'use strict' is always emitted. */
 | 
			
		||||
    // "noUnusedLocals": true,                           /* Enable error reporting when local variables aren't read. */
 | 
			
		||||
    // "noUnusedParameters": true,                       /* Raise an error when a function parameter isn't read. */
 | 
			
		||||
    // "exactOptionalPropertyTypes": true,               /* Interpret optional property types as written, rather than adding 'undefined'. */
 | 
			
		||||
    // "noImplicitReturns": true,                        /* Enable error reporting for codepaths that do not explicitly return in a function. */
 | 
			
		||||
    // "noFallthroughCasesInSwitch": true,               /* Enable error reporting for fallthrough cases in switch statements. */
 | 
			
		||||
    // "noUncheckedIndexedAccess": true,                 /* Add 'undefined' to a type when accessed using an index. */
 | 
			
		||||
    // "noImplicitOverride": true,                       /* Ensure overriding members in derived classes are marked with an override modifier. */
 | 
			
		||||
    // "noPropertyAccessFromIndexSignature": true,       /* Enforces using indexed accessors for keys declared using an indexed type. */
 | 
			
		||||
    // "allowUnusedLabels": true,                        /* Disable error reporting for unused labels. */
 | 
			
		||||
    // "allowUnreachableCode": true,                     /* Disable error reporting for unreachable code. */
 | 
			
		||||
 | 
			
		||||
    /* Completeness */
 | 
			
		||||
    // "skipDefaultLibCheck": true,                      /* Skip type checking .d.ts files that are included with TypeScript. */
 | 
			
		||||
    "skipLibCheck": true                                 /* Skip type checking all .d.ts files. */
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										120
									
								
								websocket/fakedata/alarmList.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,120 @@
 | 
			
		||||
const total = `AN_1_1,助燃风故障报警
 | 
			
		||||
AN_1_2,压延机冷却风故障报警
 | 
			
		||||
AN_1_3,L吊墙冷却风机故障报警
 | 
			
		||||
AN_1_4,熔化带及部分澄清部冷却风机故障报警
 | 
			
		||||
AN_2_1,澄清带池壁冷却风机故障报警
 | 
			
		||||
AN_2_2,钢碴碴冷却风机故障报警
 | 
			
		||||
AN_2_3,支通路拐角冷却风机报警
 | 
			
		||||
AN_2_4,吊墙吊钩砖结构温升报警
 | 
			
		||||
AN_3_1,深层水包冷却水温升报警
 | 
			
		||||
AN_3_2,深层水包冷却水断水报警
 | 
			
		||||
AN_3_3,卡脖吊平冷却水断水报警
 | 
			
		||||
AN_3_4,卡脖吊平喧冷却水温升报警
 | 
			
		||||
AN_4_1,液面计冷却水断水报警
 | 
			
		||||
AN_4_2,液面计冷却水温升报警
 | 
			
		||||
AN_4_3,循环水入口压力低报警
 | 
			
		||||
AN_4_4,天然气压力高低报警
 | 
			
		||||
AN_5_1,助燃风风压低报警
 | 
			
		||||
AN_5_2,净化压缩气压力低报警
 | 
			
		||||
AN_5_3,普通压缩空气压力高低报警
 | 
			
		||||
AN_5_4,焦炉煤气气压力高低报警
 | 
			
		||||
AN_6_1,换向过程故障报警
 | 
			
		||||
AN_6_2,空交机换向不到位报警
 | 
			
		||||
AN_6_3,投料机故障报警
 | 
			
		||||
AN_6_4,备用
 | 
			
		||||
AN_7_1,1#压延机冷却水断水报警
 | 
			
		||||
AN_7_2,1#压延机冷却水温升报警
 | 
			
		||||
AN_7_3,1#过渡辊台冷却水断水报警
 | 
			
		||||
AN_7_4,1过渡辊台冷却水温升报警
 | 
			
		||||
AN_8_1,1#线唇砖冷却水断水报警
 | 
			
		||||
AN_8_2,1#线唇砖冷却水温升报警
 | 
			
		||||
AN_8_3,1#退火窑A区风机报警
 | 
			
		||||
AN_8_4,1#退火窑B区风机报警
 | 
			
		||||
AN_9_1,1#退火窑c区风机报警
 | 
			
		||||
AN_9_2,1#退火窑Ret1区风机报警
 | 
			
		||||
AN_9_3,1#退火窑Ret2区风机报警
 | 
			
		||||
AN_9_4,1#退火窑F1区风机报警
 | 
			
		||||
AN_10_1,1#退火窑F2区风机报警
 | 
			
		||||
AN_10_2,1#主传动报警
 | 
			
		||||
AN_10_3,1#压延机报警
 | 
			
		||||
AN_10_4,备用
 | 
			
		||||
AN_11_1,2#压延机冷却水断水报警
 | 
			
		||||
AN_11_2,2#压延机冷却水温升报警
 | 
			
		||||
AN_11_3,2#过渡辊台冷却水断水报警
 | 
			
		||||
AN_11_4,2#过渡辊台冷却水温升报警
 | 
			
		||||
AN_12_1,2#线唇砖冷却水断水报警
 | 
			
		||||
AN_12_2,2#线唇砖冷却水温升报警
 | 
			
		||||
AN_12_3,2#退火窑A区风机报警
 | 
			
		||||
AN_12_4,2#退火窑B区风机报警
 | 
			
		||||
AN_13_1,2#退火窑c区风机报警
 | 
			
		||||
AN_13_2,2#退火窑Ret1区风机报警
 | 
			
		||||
AN_13_3,2#退火窑Ret2区风机报警
 | 
			
		||||
AN_13_4,2#退火窑F1区风机报警
 | 
			
		||||
AN_14_1,2#退火窑F2区风机报警
 | 
			
		||||
AN_14_2,2#主传动报警
 | 
			
		||||
AN_14_3,2#压延机报警
 | 
			
		||||
AN_14_4,备用
 | 
			
		||||
AN_15_1,3#压延机冷却水断水报警
 | 
			
		||||
AN_15_2,3压延机冷却水温升报警
 | 
			
		||||
AN_15_3,3#过渡辊台冷却水断水报警
 | 
			
		||||
AN_15_4,3#过渡辊台冷却水温升报警
 | 
			
		||||
AN_16_1,3#线唇砖冷却水断水报警
 | 
			
		||||
AN_16_2,3#线唇砖冷却水温升报警
 | 
			
		||||
AN_16_3,3#退火窑A区风机报警
 | 
			
		||||
AN_16_4,3#退火窑B区风机报警
 | 
			
		||||
AN_17_1,3#退火窑c区风机报警
 | 
			
		||||
AN_17_2,3#退火窑Ret1区风机报警
 | 
			
		||||
AN_17_3,3#退火窑Ret2区风机报警
 | 
			
		||||
AN_17_4,3#退火窑F1区风机报警
 | 
			
		||||
AN_18_1,3#退火窑F2区风机报警
 | 
			
		||||
AN_18_2,3#主传动报警
 | 
			
		||||
AN_18_3,3#压延机报警
 | 
			
		||||
AN_18_4,备用
 | 
			
		||||
AN_19_1,4#压延机冷却水断水报警
 | 
			
		||||
AN_19_2,4压延机冷却水温升报警
 | 
			
		||||
AN_19_3,4#过渡辊台冷却水断水报警
 | 
			
		||||
AN_19_4,4#过渡辊台冷却水温升报警
 | 
			
		||||
AN_20_1,4#线唇砖冷却水断水报警
 | 
			
		||||
AN_20_2,4#线唇砖冷却水温升报警
 | 
			
		||||
AN_20_3,4#退火窑A区风机报警
 | 
			
		||||
AN_20_4,4#退火窑B区风机报警
 | 
			
		||||
AN_21_1,4#退火窑c区风机报警
 | 
			
		||||
AN_21_2,4#退火窑Ret1区风机报警
 | 
			
		||||
AN_21_3,4#退火窑Ret2区风机报警
 | 
			
		||||
AN_21_4,4#退火窑F1区风机报警
 | 
			
		||||
AN_22_1,4#退火窑F2区风机报警
 | 
			
		||||
AN_22_2,4#主传动报警
 | 
			
		||||
AN_22_3,4#压延机报警
 | 
			
		||||
AN_23_1,5#压延机冷却水断水报警
 | 
			
		||||
AN_23_2,5#压延机冷却水温升报警
 | 
			
		||||
AN_23_3,5#过渡辊台冷却水断水报警
 | 
			
		||||
AN_23_4,5#过渡台冷却水温升报警
 | 
			
		||||
AN_24_1,5#线唇砖冷却水断水报警
 | 
			
		||||
AN_24_2,5#线唇砖冷却水温升报警
 | 
			
		||||
AN_24_3,5#退火窑A区风机报警
 | 
			
		||||
AN_24_4,5#退火窑B区风机报警
 | 
			
		||||
AN_25_1,5#退火窑c区风机报警
 | 
			
		||||
AN_25_2,5#退火窑Ret1区风机报警
 | 
			
		||||
AN_25_3,5#退火窑Ret2区风机报警
 | 
			
		||||
AN_25_4,5#退火窑F1区风机报警
 | 
			
		||||
AN_26_1,5#退火窑F2区风机报警
 | 
			
		||||
AN_26_2,5#主传动报警
 | 
			
		||||
AN_26_3,5#压延机报警
 | 
			
		||||
`;
 | 
			
		||||
 | 
			
		||||
// const totalAlarmList = total.split("\n");
 | 
			
		||||
const getRandomAlarmList = function (num) {
 | 
			
		||||
  const totalAlarmList = total.split("\n");
 | 
			
		||||
  let alarmList = [];
 | 
			
		||||
  for (let i = 0; i < num; i++) {
 | 
			
		||||
    let index = Math.floor(Math.random() * totalAlarmList.length);
 | 
			
		||||
    const chosen = totalAlarmList[index];
 | 
			
		||||
    totalAlarmList.splice(index, 1);
 | 
			
		||||
    alarmList.push(chosen);
 | 
			
		||||
  }
 | 
			
		||||
  return alarmList;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
module.exports = {
 | 
			
		||||
  getRandomAlarmList,
 | 
			
		||||
};
 | 
			
		||||
@@ -1,18 +0,0 @@
 | 
			
		||||
import utils from '../utils';
 | 
			
		||||
 | 
			
		||||
function genKilnInfo() {
 | 
			
		||||
	return {
 | 
			
		||||
		kilnPressure: utils.rand(0, 100) + 'Kpa',
 | 
			
		||||
		waterTemp: utils.rand(0, 100) + '℃',
 | 
			
		||||
		waterFlow: utils.rand(30, 90) + 'm³/h',
 | 
			
		||||
		waterPressure: utils.rand(10, 50) + 'Kpa',
 | 
			
		||||
		windPressure: utils.rand(10, 30) + 'Kpa',
 | 
			
		||||
		gasPressure: utils.rand(10, 30) + 'Kpa',
 | 
			
		||||
		// 碹顶加权温度
 | 
			
		||||
		topTemp: utils.rand(30, 60) + '℃',
 | 
			
		||||
		// 融化加权温度
 | 
			
		||||
		meltTemp: utils.rand(100, 200) + '℃',
 | 
			
		||||
	};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default genKilnInfo;
 | 
			
		||||
@@ -1,13 +0,0 @@
 | 
			
		||||
// 天然气
 | 
			
		||||
import utils from '../utils';
 | 
			
		||||
 | 
			
		||||
function getNavGasInfo(type: 'history' | 'realtime') {
 | 
			
		||||
	switch (type) {
 | 
			
		||||
		case 'history':
 | 
			
		||||
			break;
 | 
			
		||||
		case 'realtime':
 | 
			
		||||
			break;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default getNavGasInfo;
 | 
			
		||||
							
								
								
									
										44
									
								
								websocket/package-lock.json
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,44 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "ws-server",
 | 
			
		||||
  "version": "0.0.1",
 | 
			
		||||
  "lockfileVersion": 2,
 | 
			
		||||
  "requires": true,
 | 
			
		||||
  "packages": {
 | 
			
		||||
    "": {
 | 
			
		||||
      "name": "ws-server",
 | 
			
		||||
      "version": "0.0.1",
 | 
			
		||||
      "license": "ISC",
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "ws": "^8.16.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/ws": {
 | 
			
		||||
      "version": "8.16.0",
 | 
			
		||||
      "resolved": "https://registry.npmmirror.com/ws/-/ws-8.16.0.tgz",
 | 
			
		||||
      "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==",
 | 
			
		||||
      "engines": {
 | 
			
		||||
        "node": ">=10.0.0"
 | 
			
		||||
      },
 | 
			
		||||
      "peerDependencies": {
 | 
			
		||||
        "bufferutil": "^4.0.1",
 | 
			
		||||
        "utf-8-validate": ">=5.0.2"
 | 
			
		||||
      },
 | 
			
		||||
      "peerDependenciesMeta": {
 | 
			
		||||
        "bufferutil": {
 | 
			
		||||
          "optional": true
 | 
			
		||||
        },
 | 
			
		||||
        "utf-8-validate": {
 | 
			
		||||
          "optional": true
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "ws": {
 | 
			
		||||
      "version": "8.16.0",
 | 
			
		||||
      "resolved": "https://registry.npmmirror.com/ws/-/ws-8.16.0.tgz",
 | 
			
		||||
      "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==",
 | 
			
		||||
      "requires": {}
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										15
									
								
								websocket/package.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,15 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "ws-server",
 | 
			
		||||
  "version": "0.0.1",
 | 
			
		||||
  "description": "a simple dev ws-server",
 | 
			
		||||
  "main": "server.js",
 | 
			
		||||
  "scripts": {
 | 
			
		||||
    "test": "echo \"Error: no test specified\" && exit 1",
 | 
			
		||||
    "start": "node server.js"
 | 
			
		||||
  },
 | 
			
		||||
  "author": "",
 | 
			
		||||
  "license": "ISC",
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "ws": "^8.16.0"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										105
									
								
								websocket/server copy.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,105 @@
 | 
			
		||||
import { WebSocket, WebSocketServer } from "ws";
 | 
			
		||||
import template from "./template.json";
 | 
			
		||||
import utils from "./utils";
 | 
			
		||||
 | 
			
		||||
const wss = new WebSocketServer({ port: 9800 });
 | 
			
		||||
const frequency = 10; // seconds
 | 
			
		||||
const frequency1 = 1200; // seconds
 | 
			
		||||
wss.on("connection", function (ws, req) {
 | 
			
		||||
  // console.log("ws", ws);
 | 
			
		||||
  console.log(
 | 
			
		||||
    "Client in: ",
 | 
			
		||||
    req.socket.remoteAddress,
 | 
			
		||||
    "current users:",
 | 
			
		||||
    wss.clients.size
 | 
			
		||||
  );
 | 
			
		||||
  // ws.on("error", console.error);
 | 
			
		||||
  // ws.emit("message", "connected");
 | 
			
		||||
  ws.on("open", function () {
 | 
			
		||||
    console.log("connected");
 | 
			
		||||
    ws.send("connected");
 | 
			
		||||
  });
 | 
			
		||||
  ws.on("message", function (msg) {
 | 
			
		||||
    console.log("message from client", msg);
 | 
			
		||||
    ws.send("echo " + msg.toString());
 | 
			
		||||
  });
 | 
			
		||||
  ws.on("error", console.error);
 | 
			
		||||
 | 
			
		||||
  const timer = setInterval(() => {
 | 
			
		||||
    sendMsg(ws, "kiln-info"); // 窑炉信息
 | 
			
		||||
    sendMsg(ws, "energy-cost"); // 运行状态
 | 
			
		||||
    sendMsg(ws, "run-state"); // 运行状态
 | 
			
		||||
    sendMsg(ws, "realtime");
 | 
			
		||||
    sendMsg(ws, "his-trend");
 | 
			
		||||
    // sendMsg(ws, 'gas');
 | 
			
		||||
    // sendMsg(ws, 'kiln-top');
 | 
			
		||||
    // sendMsg(ws, 'kiln-bottom');
 | 
			
		||||
  }, frequency * 1000);
 | 
			
		||||
 | 
			
		||||
  const timer1 = setInterval(() => {
 | 
			
		||||
    // sendMsg(ws, 'run-state'); // 运行状态
 | 
			
		||||
  }, frequency1 * 1000);
 | 
			
		||||
 | 
			
		||||
  ws.on("close", function () {
 | 
			
		||||
    console.log("停止监听");
 | 
			
		||||
    clearInterval(timer);
 | 
			
		||||
    clearInterval(timer1);
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function sendMsg(ws, type) {
 | 
			
		||||
  let data = {};
 | 
			
		||||
  switch (type) {
 | 
			
		||||
    case "kiln-info":
 | 
			
		||||
      for (const key in template.kilnInfo) {
 | 
			
		||||
        data[key] = utils.getRandom(template.kilnInfo[key]);
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
    case "energy-cost":
 | 
			
		||||
      for (const key in template.energyCost) {
 | 
			
		||||
        data[key] = utils.getRandom(template.energyCost[key]);
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
    case "run-state":
 | 
			
		||||
      data = template.runState;
 | 
			
		||||
      data.fireDirection =
 | 
			
		||||
        Math.floor(Math.random() * 10) % 2 === 0 ? "南火" : "北火";
 | 
			
		||||
      break;
 | 
			
		||||
    case "realtime":
 | 
			
		||||
      /** 天然气 实时流量 */
 | 
			
		||||
      data.gasii = template.realtime.gasii.map((v) => utils.getRandom(v));
 | 
			
		||||
      /** 助燃风 实时流量 */
 | 
			
		||||
      data.wind = template.realtime.wind.map((v) => utils.getRandom(v));
 | 
			
		||||
      break;
 | 
			
		||||
    case "his-trend":
 | 
			
		||||
      const hisTrend = {
 | 
			
		||||
        gas: {},
 | 
			
		||||
        wind: {},
 | 
			
		||||
      };
 | 
			
		||||
      Object.keys(template.hisTrend.gas).forEach((key) => {
 | 
			
		||||
        hisTrend.gas[key] = template.hisTrend.gas[key].map((v) =>
 | 
			
		||||
          utils.getRandom(v)
 | 
			
		||||
        );
 | 
			
		||||
      });
 | 
			
		||||
      Object.keys(template.hisTrend.wind).forEach((key) => {
 | 
			
		||||
        hisTrend.wind[key] = template.hisTrend.wind[key].map((v) =>
 | 
			
		||||
          utils.getRandom(v)
 | 
			
		||||
        );
 | 
			
		||||
      });
 | 
			
		||||
      data = hisTrend;
 | 
			
		||||
      break;
 | 
			
		||||
    case "gas":
 | 
			
		||||
      // data = template.gas;
 | 
			
		||||
      break;
 | 
			
		||||
    case "kiln-top":
 | 
			
		||||
      // data = template.kilnTop;
 | 
			
		||||
      break;
 | 
			
		||||
    case "kiln-bottom":
 | 
			
		||||
      // data = template.kilnBottom;
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      // data = 'You are connected!';
 | 
			
		||||
      break;
 | 
			
		||||
  }
 | 
			
		||||
  ws.send(JSON.stringify({ type, data }));
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										95
									
								
								websocket/server.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,95 @@
 | 
			
		||||
const { WebSocket } = require("ws");
 | 
			
		||||
const { getRandomAlarmList } = require("./fakedata/alarmList");
 | 
			
		||||
 | 
			
		||||
const wss = new WebSocket.Server({ port: 9800 });
 | 
			
		||||
console.log('[websocket] server created');
 | 
			
		||||
 | 
			
		||||
wss.on("connection", function (ws, req) {
 | 
			
		||||
  console.log(
 | 
			
		||||
    "[用户连接]: ",
 | 
			
		||||
    req.socket.remoteAddress,
 | 
			
		||||
    "当前总用户数:",
 | 
			
		||||
    wss.clients.size
 | 
			
		||||
  );
 | 
			
		||||
  ws.on("open", function () {
 | 
			
		||||
    console.log('[websocket] opened');
 | 
			
		||||
    ws.send("connected");
 | 
			
		||||
  });
 | 
			
		||||
  ws.on("message", function (msg) {
 | 
			
		||||
    console.log("[==>]", msg);
 | 
			
		||||
  });
 | 
			
		||||
  ws.on("error", console.error);
 | 
			
		||||
 | 
			
		||||
  const timer = setInterval(() => {
 | 
			
		||||
    sendMsg(ws, "alarmList"); // 报警信息
 | 
			
		||||
  }, 10 * 1000);
 | 
			
		||||
 | 
			
		||||
  ws.on("close", function () {
 | 
			
		||||
    console.log("停止监听");
 | 
			
		||||
    clearInterval(timer);
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function sendMsg(ws, type) {
 | 
			
		||||
  let data = {};
 | 
			
		||||
  switch (type) {
 | 
			
		||||
    case "alarmList":
 | 
			
		||||
      const alarmList = getRandomAlarmList(Math.floor(Math.random() * 10) + 1);
 | 
			
		||||
      alarmList.forEach((str) => {
 | 
			
		||||
        const [code, detail] = str.split(",");
 | 
			
		||||
        data[code] = detail;
 | 
			
		||||
      });
 | 
			
		||||
      break;
 | 
			
		||||
    case "kiln-info":
 | 
			
		||||
      for (const key in template.kilnInfo) {
 | 
			
		||||
        data[key] = utils.getRandom(template.kilnInfo[key]);
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
    case "energy-cost":
 | 
			
		||||
      for (const key in template.energyCost) {
 | 
			
		||||
        data[key] = utils.getRandom(template.energyCost[key]);
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
    case "run-state":
 | 
			
		||||
      data = template.runState;
 | 
			
		||||
      data.fireDirection =
 | 
			
		||||
        Math.floor(Math.random() * 10) % 2 === 0 ? "南火" : "北火";
 | 
			
		||||
      break;
 | 
			
		||||
    case "realtime":
 | 
			
		||||
      /** 天然气 实时流量 */
 | 
			
		||||
      data.gasii = template.realtime.gasii.map((v) => utils.getRandom(v));
 | 
			
		||||
      /** 助燃风 实时流量 */
 | 
			
		||||
      data.wind = template.realtime.wind.map((v) => utils.getRandom(v));
 | 
			
		||||
      break;
 | 
			
		||||
    case "his-trend":
 | 
			
		||||
      const hisTrend = {
 | 
			
		||||
        gas: {},
 | 
			
		||||
        wind: {},
 | 
			
		||||
      };
 | 
			
		||||
      Object.keys(template.hisTrend.gas).forEach((key) => {
 | 
			
		||||
        hisTrend.gas[key] = template.hisTrend.gas[key].map((v) =>
 | 
			
		||||
          utils.getRandom(v)
 | 
			
		||||
        );
 | 
			
		||||
      });
 | 
			
		||||
      Object.keys(template.hisTrend.wind).forEach((key) => {
 | 
			
		||||
        hisTrend.wind[key] = template.hisTrend.wind[key].map((v) =>
 | 
			
		||||
          utils.getRandom(v)
 | 
			
		||||
        );
 | 
			
		||||
      });
 | 
			
		||||
      data = hisTrend;
 | 
			
		||||
      break;
 | 
			
		||||
    case "gas":
 | 
			
		||||
      // data = template.gas;
 | 
			
		||||
      break;
 | 
			
		||||
    case "kiln-top":
 | 
			
		||||
      // data = template.kilnTop;
 | 
			
		||||
      break;
 | 
			
		||||
    case "kiln-bottom":
 | 
			
		||||
      // data = template.kilnBottom;
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      // data = 'You are connected!';
 | 
			
		||||
      break;
 | 
			
		||||
  }
 | 
			
		||||
  ws.send(JSON.stringify({ type, data }));
 | 
			
		||||
}
 | 
			
		||||
@@ -1,133 +0,0 @@
 | 
			
		||||
import { WebSocket, WebSocketServer } from 'ws';
 | 
			
		||||
import template from './template.json';
 | 
			
		||||
import utils from './utils';
 | 
			
		||||
 | 
			
		||||
const wss = new WebSocketServer({ port: 9800 });
 | 
			
		||||
const frequency = 10; // seconds
 | 
			
		||||
const frequency1 = 1200; // seconds
 | 
			
		||||
wss.on('connection', function (ws, req) {
 | 
			
		||||
	// console.log("ws", ws);
 | 
			
		||||
	console.log(
 | 
			
		||||
		'Client in: ',
 | 
			
		||||
		req.socket.remoteAddress,
 | 
			
		||||
		'current users:',
 | 
			
		||||
		wss.clients.size,
 | 
			
		||||
	);
 | 
			
		||||
	// ws.on("error", console.error);
 | 
			
		||||
	// ws.emit("message", "connected");
 | 
			
		||||
	ws.on('open', function () {
 | 
			
		||||
		console.log('connected');
 | 
			
		||||
		ws.send('connected');
 | 
			
		||||
	});
 | 
			
		||||
	ws.on('message', function (msg) {
 | 
			
		||||
		console.log('message from client', msg);
 | 
			
		||||
		ws.send('echo ' + msg.toString());
 | 
			
		||||
	});
 | 
			
		||||
	ws.on('error', console.error);
 | 
			
		||||
 | 
			
		||||
	const timer = setInterval(() => {
 | 
			
		||||
		sendMsg(ws, 'kiln-info'); // 窑炉信息
 | 
			
		||||
		sendMsg(ws, 'energy-cost'); // 运行状态
 | 
			
		||||
		sendMsg(ws, 'run-state'); // 运行状态
 | 
			
		||||
		sendMsg(ws, 'realtime');
 | 
			
		||||
		sendMsg(ws, 'his-trend');
 | 
			
		||||
		// sendMsg(ws, 'gas');
 | 
			
		||||
		// sendMsg(ws, 'kiln-top');
 | 
			
		||||
		// sendMsg(ws, 'kiln-bottom');
 | 
			
		||||
	}, frequency * 1000);
 | 
			
		||||
 | 
			
		||||
	const timer1 = setInterval(() => {
 | 
			
		||||
		// sendMsg(ws, 'run-state'); // 运行状态
 | 
			
		||||
	}, frequency1 * 1000);
 | 
			
		||||
 | 
			
		||||
	ws.on('close', function () {
 | 
			
		||||
		console.log('停止监听');
 | 
			
		||||
		clearInterval(timer);
 | 
			
		||||
		clearInterval(timer1);
 | 
			
		||||
	});
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
type MsgType =
 | 
			
		||||
	| 'kiln-info'
 | 
			
		||||
	| 'run-state'
 | 
			
		||||
	| 'energy-cost'
 | 
			
		||||
	| 'realtime'
 | 
			
		||||
	| 'his-trend'
 | 
			
		||||
	| 'fan'
 | 
			
		||||
	| 'gas'
 | 
			
		||||
	| 'kiln-top'
 | 
			
		||||
	| 'kiln-bottom';
 | 
			
		||||
 | 
			
		||||
type ResponseData = {
 | 
			
		||||
	[key: string]: string | string[];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
type ResponseDataComplex = {
 | 
			
		||||
	[key: string]: ResponseData;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function sendMsg(ws: WebSocket, type: MsgType) {
 | 
			
		||||
	let data: ResponseData | ResponseDataComplex = {};
 | 
			
		||||
	switch (type) {
 | 
			
		||||
		case 'kiln-info':
 | 
			
		||||
			for (const key in template.kilnInfo) {
 | 
			
		||||
				data[key] = utils.getRandom(
 | 
			
		||||
					template.kilnInfo[key as keyof typeof template.kilnInfo],
 | 
			
		||||
				);
 | 
			
		||||
			}
 | 
			
		||||
			break;
 | 
			
		||||
		case 'energy-cost':
 | 
			
		||||
			for (const key in template.energyCost) {
 | 
			
		||||
				data[key] = utils.getRandom(
 | 
			
		||||
					template.energyCost[key as keyof typeof template.energyCost],
 | 
			
		||||
				);
 | 
			
		||||
			}
 | 
			
		||||
			break;
 | 
			
		||||
		case 'run-state':
 | 
			
		||||
			data = template.runState;
 | 
			
		||||
			data.fireDirection =
 | 
			
		||||
				Math.floor(Math.random() * 10) % 2 === 0 ? '南火' : '北火';
 | 
			
		||||
			break;
 | 
			
		||||
		case 'realtime':
 | 
			
		||||
			/** 天然气 实时流量 */
 | 
			
		||||
			data.gasii = template.realtime.gasii.map((v) => utils.getRandom(v));
 | 
			
		||||
			/** 助燃风 实时流量 */
 | 
			
		||||
			data.wind = template.realtime.wind.map((v) => utils.getRandom(v));
 | 
			
		||||
			break;
 | 
			
		||||
		case 'his-trend':
 | 
			
		||||
			const hisTrend: {
 | 
			
		||||
				gas: ResponseData;
 | 
			
		||||
				wind: ResponseData;
 | 
			
		||||
			} = {
 | 
			
		||||
				gas: {},
 | 
			
		||||
				wind: {},
 | 
			
		||||
			};
 | 
			
		||||
			Object.keys(template.hisTrend.gas).forEach((key) => {
 | 
			
		||||
				hisTrend.gas[key] = template.hisTrend.gas[
 | 
			
		||||
					key as keyof typeof template.hisTrend.gas
 | 
			
		||||
				].map((v) => utils.getRandom(v));
 | 
			
		||||
			});
 | 
			
		||||
			Object.keys(template.hisTrend.wind).forEach((key) => {
 | 
			
		||||
				hisTrend.wind[key] = template.hisTrend.wind[
 | 
			
		||||
					key as keyof typeof template.hisTrend.wind
 | 
			
		||||
				].map((v) => utils.getRandom(v));
 | 
			
		||||
			});
 | 
			
		||||
			data = hisTrend;
 | 
			
		||||
			break;
 | 
			
		||||
		case 'gas':
 | 
			
		||||
			// data = template.gas;
 | 
			
		||||
			break;
 | 
			
		||||
		case 'kiln-top':
 | 
			
		||||
			// data = template.kilnTop;
 | 
			
		||||
			break;
 | 
			
		||||
		case 'kiln-bottom':
 | 
			
		||||
			// data = template.kilnBottom;
 | 
			
		||||
			break;
 | 
			
		||||
		default:
 | 
			
		||||
			// data = 'You are connected!';
 | 
			
		||||
			break;
 | 
			
		||||
	}
 | 
			
		||||
	// console.log("sendMsg: ", ws);
 | 
			
		||||
	// ws.emit("message", JSON.stringify(data));
 | 
			
		||||
	ws.send(JSON.stringify({ type, data }));
 | 
			
		||||
}
 | 
			
		||||
@@ -1,109 +0,0 @@
 | 
			
		||||
{
 | 
			
		||||
	"compilerOptions": {
 | 
			
		||||
		/* Visit https://aka.ms/tsconfig to read more about this file */
 | 
			
		||||
 | 
			
		||||
		/* Projects */
 | 
			
		||||
		// "incremental": true,                              /* Save .tsbuildinfo files to allow for incremental compilation of projects. */
 | 
			
		||||
		// "composite": true,                                /* Enable constraints that allow a TypeScript project to be used with project references. */
 | 
			
		||||
		// "tsBuildInfoFile": "./.tsbuildinfo",              /* Specify the path to .tsbuildinfo incremental compilation file. */
 | 
			
		||||
		// "disableSourceOfProjectReferenceRedirect": true,  /* Disable preferring source files instead of declaration files when referencing composite projects. */
 | 
			
		||||
		// "disableSolutionSearching": true,                 /* Opt a project out of multi-project reference checking when editing. */
 | 
			
		||||
		// "disableReferencedProjectLoad": true,             /* Reduce the number of projects loaded automatically by TypeScript. */
 | 
			
		||||
 | 
			
		||||
		/* Language and Environment */
 | 
			
		||||
		"target": "es2016" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,
 | 
			
		||||
		// "lib": [],                                        /* Specify a set of bundled library declaration files that describe the target runtime environment. */
 | 
			
		||||
		// "jsx": "preserve",                                /* Specify what JSX code is generated. */
 | 
			
		||||
		// "experimentalDecorators": true,                   /* Enable experimental support for legacy experimental decorators. */
 | 
			
		||||
		// "emitDecoratorMetadata": true,                    /* Emit design-type metadata for decorated declarations in source files. */
 | 
			
		||||
		// "jsxFactory": "",                                 /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
 | 
			
		||||
		// "jsxFragmentFactory": "",                         /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
 | 
			
		||||
		// "jsxImportSource": "",                            /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */
 | 
			
		||||
		// "reactNamespace": "",                             /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */
 | 
			
		||||
		// "noLib": true,                                    /* Disable including any library files, including the default lib.d.ts. */
 | 
			
		||||
		// "useDefineForClassFields": true,                  /* Emit ECMAScript-standard-compliant class fields. */
 | 
			
		||||
		// "moduleDetection": "auto",                        /* Control what method is used to detect module-format JS files. */
 | 
			
		||||
 | 
			
		||||
		/* Modules */
 | 
			
		||||
		"module": "commonjs" /* Specify what module code is generated. */,
 | 
			
		||||
		// "rootDir": "./",                                  /* Specify the root folder within your source files. */
 | 
			
		||||
		// "moduleResolution": "node10",                     /* Specify how TypeScript looks up a file from a given module specifier. */
 | 
			
		||||
		// "baseUrl": "./",                                  /* Specify the base directory to resolve non-relative module names. */
 | 
			
		||||
		// "paths": {},                                      /* Specify a set of entries that re-map imports to additional lookup locations. */
 | 
			
		||||
		// "rootDirs": [],                                   /* Allow multiple folders to be treated as one when resolving modules. */
 | 
			
		||||
		// "typeRoots": [],                                  /* Specify multiple folders that act like './node_modules/@types'. */
 | 
			
		||||
		// "types": [],                                      /* Specify type package names to be included without being referenced in a source file. */
 | 
			
		||||
		// "allowUmdGlobalAccess": true,                     /* Allow accessing UMD globals from modules. */
 | 
			
		||||
		// "moduleSuffixes": [],                             /* List of file name suffixes to search when resolving a module. */
 | 
			
		||||
		// "allowImportingTsExtensions": true,               /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */
 | 
			
		||||
		// "resolvePackageJsonExports": true,                /* Use the package.json 'exports' field when resolving package imports. */
 | 
			
		||||
		// "resolvePackageJsonImports": true,                /* Use the package.json 'imports' field when resolving imports. */
 | 
			
		||||
		// "customConditions": [],                           /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */
 | 
			
		||||
		"resolveJsonModule": true /* Enable importing .json files. */,
 | 
			
		||||
		// "allowArbitraryExtensions": true,                 /* Enable importing files with any extension, provided a declaration file is present. */
 | 
			
		||||
		// "noResolve": true,                                /* Disallow 'import's, 'require's or '<reference>'s from expanding the number of files TypeScript should add to a project. */
 | 
			
		||||
 | 
			
		||||
		/* JavaScript Support */
 | 
			
		||||
		// "allowJs": true,                                  /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
 | 
			
		||||
		// "checkJs": true,                                  /* Enable error reporting in type-checked JavaScript files. */
 | 
			
		||||
		// "maxNodeModuleJsDepth": 1,                        /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
 | 
			
		||||
 | 
			
		||||
		/* Emit */
 | 
			
		||||
		// "declaration": true,                              /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
 | 
			
		||||
		// "declarationMap": true,                           /* Create sourcemaps for d.ts files. */
 | 
			
		||||
		// "emitDeclarationOnly": true,                      /* Only output d.ts files and not JavaScript files. */
 | 
			
		||||
		// "sourceMap": true,                                /* Create source map files for emitted JavaScript files. */
 | 
			
		||||
		// "inlineSourceMap": true,                          /* Include sourcemap files inside the emitted JavaScript. */
 | 
			
		||||
		// "outFile": "./",                                  /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
 | 
			
		||||
		// "outDir": "./",                                   /* Specify an output folder for all emitted files. */
 | 
			
		||||
		// "removeComments": true,                           /* Disable emitting comments. */
 | 
			
		||||
		// "noEmit": true,                                   /* Disable emitting files from a compilation. */
 | 
			
		||||
		// "importHelpers": true,                            /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
 | 
			
		||||
		// "importsNotUsedAsValues": "remove",               /* Specify emit/checking behavior for imports that are only used for types. */
 | 
			
		||||
		// "downlevelIteration": true,                       /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
 | 
			
		||||
		// "sourceRoot": "",                                 /* Specify the root path for debuggers to find the reference source code. */
 | 
			
		||||
		// "mapRoot": "",                                    /* Specify the location where debugger should locate map files instead of generated locations. */
 | 
			
		||||
		// "inlineSources": true,                            /* Include source code in the sourcemaps inside the emitted JavaScript. */
 | 
			
		||||
		// "emitBOM": true,                                  /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
 | 
			
		||||
		// "newLine": "crlf",                                /* Set the newline character for emitting files. */
 | 
			
		||||
		// "stripInternal": true,                            /* Disable emitting declarations that have '@internal' in their JSDoc comments. */
 | 
			
		||||
		// "noEmitHelpers": true,                            /* Disable generating custom helper functions like '__extends' in compiled output. */
 | 
			
		||||
		// "noEmitOnError": true,                            /* Disable emitting files if any type checking errors are reported. */
 | 
			
		||||
		// "preserveConstEnums": true,                       /* Disable erasing 'const enum' declarations in generated code. */
 | 
			
		||||
		// "declarationDir": "./",                           /* Specify the output directory for generated declaration files. */
 | 
			
		||||
		// "preserveValueImports": true,                     /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
 | 
			
		||||
 | 
			
		||||
		/* Interop Constraints */
 | 
			
		||||
		// "isolatedModules": true,                          /* Ensure that each file can be safely transpiled without relying on other imports. */
 | 
			
		||||
		// "verbatimModuleSyntax": true,                     /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */
 | 
			
		||||
		// "allowSyntheticDefaultImports": true,             /* Allow 'import x from y' when a module doesn't have a default export. */
 | 
			
		||||
		"esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */,
 | 
			
		||||
		// "preserveSymlinks": true,                         /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
 | 
			
		||||
		"forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */,
 | 
			
		||||
 | 
			
		||||
		/* Type Checking */
 | 
			
		||||
		"strict": true /* Enable all strict type-checking options. */,
 | 
			
		||||
		// "noImplicitAny": true,                            /* Enable error reporting for expressions and declarations with an implied 'any' type. */
 | 
			
		||||
		// "strictNullChecks": true,                         /* When type checking, take into account 'null' and 'undefined'. */
 | 
			
		||||
		// "strictFunctionTypes": true,                      /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
 | 
			
		||||
		// "strictBindCallApply": true,                      /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */
 | 
			
		||||
		// "strictPropertyInitialization": true,             /* Check for class properties that are declared but not set in the constructor. */
 | 
			
		||||
		// "noImplicitThis": true,                           /* Enable error reporting when 'this' is given the type 'any'. */
 | 
			
		||||
		// "useUnknownInCatchVariables": true,               /* Default catch clause variables as 'unknown' instead of 'any'. */
 | 
			
		||||
		// "alwaysStrict": true,                             /* Ensure 'use strict' is always emitted. */
 | 
			
		||||
		// "noUnusedLocals": true,                           /* Enable error reporting when local variables aren't read. */
 | 
			
		||||
		// "noUnusedParameters": true,                       /* Raise an error when a function parameter isn't read. */
 | 
			
		||||
		// "exactOptionalPropertyTypes": true,               /* Interpret optional property types as written, rather than adding 'undefined'. */
 | 
			
		||||
		// "noImplicitReturns": true,                        /* Enable error reporting for codepaths that do not explicitly return in a function. */
 | 
			
		||||
		// "noFallthroughCasesInSwitch": true,               /* Enable error reporting for fallthrough cases in switch statements. */
 | 
			
		||||
		// "noUncheckedIndexedAccess": true,                 /* Add 'undefined' to a type when accessed using an index. */
 | 
			
		||||
		// "noImplicitOverride": true,                       /* Ensure overriding members in derived classes are marked with an override modifier. */
 | 
			
		||||
		// "noPropertyAccessFromIndexSignature": true,       /* Enforces using indexed accessors for keys declared using an indexed type. */
 | 
			
		||||
		// "allowUnusedLabels": true,                        /* Disable error reporting for unused labels. */
 | 
			
		||||
		// "allowUnreachableCode": true,                     /* Disable error reporting for unreachable code. */
 | 
			
		||||
 | 
			
		||||
		/* Completeness */
 | 
			
		||||
		// "skipDefaultLibCheck": true,                      /* Skip type checking .d.ts files that are included with TypeScript. */
 | 
			
		||||
		"skipLibCheck": true /* Skip type checking all .d.ts files. */
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										49
									
								
								websocket/utils/index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,49 @@
 | 
			
		||||
export default {
 | 
			
		||||
  // 生成随机数
 | 
			
		||||
  randomNum({ min, max }, isFloat = false) {
 | 
			
		||||
    if (isFloat) return (Math.random() * (max - min) + min).toFixed(2);
 | 
			
		||||
    return Math.floor(Math.random() * (max - min + 1) + min);
 | 
			
		||||
  },
 | 
			
		||||
  getMinmax(type) {
 | 
			
		||||
    // : '*' | '.' | '+' | '$'
 | 
			
		||||
    let min, max;
 | 
			
		||||
    switch (type) {
 | 
			
		||||
      case "*":
 | 
			
		||||
        min = 30;
 | 
			
		||||
        max = 150;
 | 
			
		||||
        break;
 | 
			
		||||
      case ".":
 | 
			
		||||
        min = 60;
 | 
			
		||||
        max = 200;
 | 
			
		||||
        break;
 | 
			
		||||
      case "+":
 | 
			
		||||
        min = 20;
 | 
			
		||||
        max = 70;
 | 
			
		||||
        break;
 | 
			
		||||
      case "$":
 | 
			
		||||
        min = 1;
 | 
			
		||||
        max = 100;
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    return { min, max };
 | 
			
		||||
  },
 | 
			
		||||
  getRandom(value) {
 | 
			
		||||
    value = value.replace(
 | 
			
		||||
      "***",
 | 
			
		||||
      "" + this.randomNum({ ...this.getMinmax("*") })
 | 
			
		||||
    );
 | 
			
		||||
    value = value.replace(
 | 
			
		||||
      "...",
 | 
			
		||||
      "" + this.randomNum({ ...this.getMinmax(".") })
 | 
			
		||||
    );
 | 
			
		||||
    value = value.replace(
 | 
			
		||||
      "+++",
 | 
			
		||||
      "" + this.randomNum({ ...this.getMinmax("+") })
 | 
			
		||||
    );
 | 
			
		||||
    value = value.replace(
 | 
			
		||||
      "$$$",
 | 
			
		||||
      "" + this.randomNum({ ...this.getMinmax("$") }, true)
 | 
			
		||||
    );
 | 
			
		||||
    return value;
 | 
			
		||||
  },
 | 
			
		||||
};
 | 
			
		||||
@@ -1,7 +0,0 @@
 | 
			
		||||
function rand(min: number, max: number) {
 | 
			
		||||
	return Math.floor(Math.random() * (max - min + 1)) + min;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
	rand,
 | 
			
		||||
};
 | 
			
		||||
@@ -1,48 +0,0 @@
 | 
			
		||||
export default {
 | 
			
		||||
	// 生成随机数
 | 
			
		||||
	randomNum({ min, max }: { min: number; max: number }, isFloat = false) {
 | 
			
		||||
		if (isFloat) return (Math.random() * (max - min) + min).toFixed(2);
 | 
			
		||||
		return Math.floor(Math.random() * (max - min + 1) + min);
 | 
			
		||||
	},
 | 
			
		||||
	getMinmax(type: '*' | '.' | '+' | '$') {
 | 
			
		||||
		let min: number, max: number;
 | 
			
		||||
		switch (type) {
 | 
			
		||||
			case '*':
 | 
			
		||||
				min = 30;
 | 
			
		||||
				max = 150;
 | 
			
		||||
				break;
 | 
			
		||||
			case '.':
 | 
			
		||||
				min = 60;
 | 
			
		||||
				max = 200;
 | 
			
		||||
				break;
 | 
			
		||||
			case '+':
 | 
			
		||||
				min = 20;
 | 
			
		||||
				max = 70;
 | 
			
		||||
				break;
 | 
			
		||||
			case '$':
 | 
			
		||||
				min = 1;
 | 
			
		||||
				max = 100;
 | 
			
		||||
				break;
 | 
			
		||||
		}
 | 
			
		||||
		return { min, max };
 | 
			
		||||
	},
 | 
			
		||||
	getRandom(value: string) {
 | 
			
		||||
		value = value.replace(
 | 
			
		||||
			'***',
 | 
			
		||||
			'' + this.randomNum({ ...this.getMinmax('*') }),
 | 
			
		||||
		);
 | 
			
		||||
		value = value.replace(
 | 
			
		||||
			'...',
 | 
			
		||||
			'' + this.randomNum({ ...this.getMinmax('.') }),
 | 
			
		||||
		);
 | 
			
		||||
		value = value.replace(
 | 
			
		||||
			'+++',
 | 
			
		||||
			'' + this.randomNum({ ...this.getMinmax('+') }),
 | 
			
		||||
		);
 | 
			
		||||
		value = value.replace(
 | 
			
		||||
			'$$$',
 | 
			
		||||
			'' + this.randomNum({ ...this.getMinmax('$') }, true),
 | 
			
		||||
		);
 | 
			
		||||
		return value;
 | 
			
		||||
	},
 | 
			
		||||
};
 | 
			
		||||