Browse Source

开发修改

zhaojijng 3 years ago
parent
commit
5de0d5bc46

+ 292 - 0
mock/environment.ts

@@ -0,0 +1,292 @@
+import { AlignLeftOutlined } from '@ant-design/icons';
+import { Request, Response } from 'express';
+export default {
+  // 支持值为 Object 和 Array
+  'POST /api/environment/map': (req: Request, res: Response) => {
+    debugger;
+    res.send({
+      data: [
+        {
+          left: 0,
+          top: 0,
+          width: 500,
+          height: 400,
+          value: 20,
+          name: '董事办公室',
+          type: 'office',
+          lamp: 'all',
+          air: 'part',
+          curtain: 'part',
+          //device 到时候需要生成
+          //当前设备的状态status all全部开启 part部分开启 close全都关闭
+          //还有设备类型type 包括air lamp curtain
+          device: [
+            { type: 'lamp', status: 'close' },
+            { type: 'air', status: 'part' },
+            { type: 'curtain', status: 'all' },
+          ],
+        },
+        {
+          left: 500,
+          top: 0,
+          width: 500,
+          height: 400,
+          value: 25,
+          name: '休息区',
+          type: 'rest',
+          lamp: 'part',
+          air: 'close',
+          curtain: 'close',
+          device: [
+            { type: 'lamp', status: 'close' },
+            { type: 'air', status: 'close' },
+          ],
+        },
+        {
+          left: 1000,
+          top: 0,
+          width: 500,
+          height: 400,
+          value: 28,
+          name: '会议室',
+          type: 'meeting',
+          lamp: 'close',
+          device: [
+            { type: 'lamp', status: 'all' },
+            { type: 'air', status: 'part' },
+            { type: 'curtain', status: 'part' },
+          ],
+        },
+        {
+          left: 0,
+          top: 400,
+          width: 500,
+          height: 400,
+          value: 16,
+          name: '第一办公区',
+          type: 'work',
+          lamp: 'all',
+          curtain: 'all',
+          device: [
+            { type: 'lamp', status: 'all' },
+
+            { type: 'curtain', status: 'all' },
+          ],
+        },
+        {
+          left: 500,
+          top: 400,
+          width: 500,
+          height: 400,
+          value: 20,
+          name: '收发室',
+          type: 'letter',
+          air: 'close',
+          curtain: 'part',
+          device: [{ type: 'lamp', status: 'all' }],
+        },
+        {
+          left: 1000,
+          top: 400,
+          width: 500,
+          height: 400,
+          value: 23,
+          name: '走廊',
+          type: 'walk',
+          lamp: 'close',
+          air: 'part',
+          curtain: 'close',
+          device: [
+            { type: 'lamp', status: 'part' },
+            { type: 'air', status: 'close' },
+            { type: 'curtain', status: 'close' },
+          ],
+        },
+        {
+          left: 0,
+          top: 800,
+          width: 500,
+          height: 400,
+          value: 16,
+          name: '第一办公区',
+          type: 'work',
+          lamp: 'close',
+          air: 'all',
+          curtain: 'part',
+          device: [
+            { type: 'lamp', status: 'close' },
+            { type: 'air', status: 'close' },
+            { type: 'curtain', status: 'close' },
+          ],
+        },
+        {
+          left: 500,
+          top: 800,
+          width: 500,
+          height: 400,
+          value: 20,
+          name: '收发室',
+          type: 'letter',
+          lamp: 'all',
+
+          curtain: 'all',
+          device: [
+            { type: 'lamp', status: 'part' },
+            { type: 'air', status: 'part' },
+            { type: 'curtain', status: 'part' },
+          ],
+        },
+        {
+          left: 1000,
+          top: 800,
+          width: 500,
+          height: 400,
+          value: 23,
+          name: '走廊',
+          type: 'walk',
+          device: [],
+          lamp: 'all',
+          air: 'all',
+          curtain: 'all',
+        },
+        {
+          left: 1500,
+          top: 0,
+          width: 500,
+          height: 400,
+          value: 20,
+          name: '董事办公室',
+          type: 'office',
+          lamp: 'close',
+          air: 'part',
+          curtain: 'close',
+          device: [{ type: 'curtain', status: 'all' }],
+        },
+        {
+          left: 2000,
+          top: 0,
+          width: 500,
+          height: 400,
+          value: 25,
+          name: '休息区',
+          type: 'rest',
+          lamp: 'part',
+          air: 'part',
+          curtain: 'part',
+          device: [
+            { type: 'lamp', status: 'all' },
+            { type: 'air', status: 'all' },
+            { type: 'curtain', status: 'all' },
+          ],
+        },
+        {
+          left: 2500,
+          top: 0,
+          width: 500,
+          height: 400,
+          value: 28,
+          name: '会议室',
+          type: 'meeting',
+
+          curtain: 'all',
+          device: [
+            { type: 'lamp', status: 'all' },
+            { type: 'air', status: 'close' },
+            { type: 'curtain', status: 'part' },
+          ],
+        },
+        {
+          left: 1500,
+          top: 400,
+          width: 500,
+          height: 400,
+          value: 16,
+          name: '第一办公区',
+          type: 'work',
+          lamp: 'all',
+          air: 'all',
+          device: [
+            { type: 'lamp', status: 'all' },
+            { type: 'air', status: 'part' },
+            { type: 'curtain', status: 'close' },
+          ],
+        },
+        {
+          left: 2000,
+          top: 400,
+          width: 500,
+          height: 400,
+          value: 20,
+          name: '收发室',
+          type: 'letter',
+          lamp: 'close',
+          curtain: 'all',
+          device: [
+            { type: 'lamp', status: 'close' },
+            { type: 'air', status: 'close' },
+            { type: 'curtain', status: 'part' },
+          ],
+        },
+        {
+          left: 2500,
+          top: 400,
+          width: 500,
+          height: 400,
+          value: 23,
+          name: '走廊',
+          type: 'walk',
+          lamp: 'all',
+          air: 'part',
+          curtain: 'all',
+          device: [
+            { type: 'lamp', status: 'part' },
+            { type: 'air', status: 'close' },
+            { type: 'curtain', status: 'all' },
+          ],
+        },
+        {
+          left: 1500,
+          top: 800,
+          width: 500,
+          height: 400,
+          value: 16,
+          name: '第一办公区',
+          type: 'work',
+          device: [{ type: 'curtain', status: 'all' }],
+        },
+        {
+          left: 2000,
+          top: 800,
+          width: 500,
+          height: 400,
+          value: 20,
+          name: '收发室',
+          type: 'letter',
+          device: [
+            { type: 'lamp', status: 'all' },
+            { type: 'air', status: 'all' },
+            { type: 'curtain', status: 'all' },
+          ],
+        },
+        {
+          left: 2500,
+          top: 800,
+          width: 500,
+          height: 400,
+          value: 23,
+          name: '走廊',
+          type: 'walk',
+          lamp: 'part',
+          air: 'part',
+          curtain: 'all',
+          device: [
+            { type: 'lamp', status: 'all' },
+            { type: 'air', status: 'all' },
+            { type: 'curtain', status: 'all' },
+          ],
+        },
+      ],
+      success: true,
+    });
+  },
+};

src/antd-reset.less → src/assets/css/antd-reset.less


src/antd-tenants.less → src/assets/css/antd-tenants.less


+ 79 - 0
src/assets/css/map.less

@@ -0,0 +1,79 @@
+.map {
+  position: relative;
+  width: 100%;
+  //   overflow: hidden;
+  .house {
+    position: absolute;
+    border: 2px solid #fff;
+    border-radius: 6px;
+    .allDevice {
+      position: absolute;
+      top: 6px;
+      left: 6px;
+      z-index: 1;
+      display: flex;
+      width: 100%;
+      .icon {
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        width: 22px;
+        height: 22px;
+        margin-right: 3px;
+        color: #ffffff;
+        font-size: 11px;
+        background: transparent;
+        border-radius: 22px;
+      }
+    }
+    .allTime {
+      position: absolute;
+      top: 4px;
+      left: 4px;
+      z-index: 1;
+      display: flex;
+      width: 100%;
+      color: #4d5262;
+      font-size: 10px;
+      text-shadow: -1px 0 white, 0 1px white, 1px 0 white, 0 -1px white;
+    }
+    .content {
+      display: flex;
+      flex-direction: column;
+      align-items: center;
+      justify-content: center;
+      height: 100%;
+      .name {
+        color: #000000;
+        font-size: 13px;
+        //text-shadow: 1px 1px 1px #ffffff;
+        text-shadow: -1px 0 white, 0 1px white, 1px 0 white, 0 -1px white;
+      }
+    }
+  }
+}
+
+.equipmentMap {
+  .house {
+    cursor: pointer;
+
+    .showModal {
+      position: absolute;
+      right: 6px;
+      bottom: 7px;
+      z-index: 2;
+      display: flex;
+      display: none;
+      align-items: center;
+      justify-content: center;
+      width: 22px;
+      height: 22px;
+      font-size: 12px;
+      background: #ffffff;
+      border-radius: 22px;
+    }
+    &:hover .showModal {
+      display: flex;
+    }
+  }
+}

+ 2 - 2
src/global.less

@@ -1,7 +1,7 @@
 @import '~antd/es/style/variable.less';
 @import '~antd/dist/antd.less'; // 引入官方提供的 less 样式入口文件
-@import './antd-tenants.less';
-@import './antd-reset.less';
+@import './assets/css/antd-tenants.less';
+@import './assets/css/antd-reset.less';
 
 html,
 body,

+ 48 - 32
src/pages/Environment/components/topNavigator/index.jsx

@@ -2,46 +2,59 @@ import React, { useState, useEffect, useCallback } from 'react';
 import styles from './index.less';
 import cx from 'classnames';
 import { Select } from 'antd';
-import EquipNavRight from '@/pages/Equipment/components/topNavRight';
+//import type { topNavRightProps } from '@/pages/Equipment/components/topNavRight';
 import RunNavRight from '@/pages/Runtime/components/topNavRight';
 
-const FloorList = [
-  {
-    label: 'F1',
-    value: 'F1',
-  },
-  {
-    label: 'F2',
-    value: 'F2',
-  },
-  {
-    label: 'F3',
-    value: 'F3',
-  },
-  {
-    label: 'F4',
-    value: 'F4',
-  },
-];
+import type { navigatorItem } from '@/pages/Environment/index';
 
-export default ({ navigatorList = [], type, navigatorChange }) => {
-  const [currentFloor, setCurrentFloor] = useState('F2');
+export type topNavigatorProps = {
+  navigatorList: navigatorItem[];
+  type: string;
+  navigatorChange(item: navigatorItem): void;
+  // action?: React.ReactElement<topNavRightProps>[];
+  action?: React.ReactNode;
+};
+type floorItem = {
+  value: string;
+  [key: string]: any;
+};
 
-  //const [selId, setSelId] = useState('temperature');
-  const [selParamObj, setSelParamObj] = useState({});
+const TopNavigator: React.FC<topNavigatorProps> = ({
+  navigatorList = [],
+  type,
+  navigatorChange,
+  action,
+}) => {
+  const [floorList, setFloorList] = useState<floorItem[]>([
+    {
+      value: 'F1',
+    },
+    {
+      value: 'F2',
+    },
+    {
+      value: 'F3',
+    },
+    {
+      value: 'F4',
+    },
+  ]);
+  const [currentFloor, setCurrentFloor] = useState<string>('F2');
 
-  useEffect(() => {
-    console.log('chartModal-effect');
-    setSelParamObj(navigatorList[0]);
-  }, []);
+  const [selParamObj, setSelParamObj] = useState(navigatorList[0]);
+
+  //   useEffect(() => {
+  //     console.log('chartModal-effect');
+  //     setSelParamObj(navigatorList[0]);
+  //   }, []);
 
   const changHandle = useCallback((val) => {
+    //debugger;
     console.log('select-onChange', val);
     setCurrentFloor(val);
   }, []);
   //当前切换导航条时
-  const itemClick = (item) => {
-    //setSelId(item.id);
+  const itemClick = (item: navigatorItem) => {
     setSelParamObj(item);
     console.log('itemclick', item);
     navigatorChange && navigatorChange(item);
@@ -53,7 +66,7 @@ export default ({ navigatorList = [], type, navigatorChange }) => {
     <div className={styles.topnavigator}>
       <div className={styles.floor}>
         <Select
-          options={FloorList}
+          options={floorList}
           value={currentFloor}
           onChange={changHandle}
           size="large"
@@ -68,7 +81,8 @@ export default ({ navigatorList = [], type, navigatorChange }) => {
             <div
               className={cx(styles.navItem, { [styles.sel]: item.id === selParamObj.id })}
               style={{
-                borderBottom: item.id === selParamObj.id ? `3px solid  ${item.color}` : null,
+                borderBottom:
+                  item.id === selParamObj.id ? `3px solid  ${item.color}` : '3px solid #ffffff',
               }}
               key={'nav' + index}
               onClick={() => {
@@ -90,8 +104,10 @@ export default ({ navigatorList = [], type, navigatorChange }) => {
           <div className={styles.text}>当前楼层平均{selParamObj.name}</div>
         </div>
       )}
-      {type === 'equipment' && <EquipNavRight selParamObj={selParamObj}></EquipNavRight>}
+      {type === 'equipment' && action}
       {type === 'runtime' && <RunNavRight></RunNavRight>}
     </div>
   );
 };
+
+export default TopNavigator;

+ 0 - 155
src/pages/Environment/index.jsx

@@ -1,155 +0,0 @@
-import React, { useState, useEffect, useCallback } from 'react';
-import { FormattedMessage } from 'umi';
-import PageHeader from '@/components/PageHeader';
-// import SearchInput from '@/tenants-ui/SearchInput';
-import TopNavigator from './components/topNavigator';
-import ChartModal from './components/chartModal';
-import { equipImageMap } from '@/config/image.js';
-import { Input } from 'antd';
-
-import styles from './index.less';
-
-export default function Environment() {
-  const {
-    temperMapTop,
-    co2MapTop,
-    maptemp1,
-    maptemp2,
-    envir_temperature,
-    envir_wet,
-    envir_co2,
-    envir_pm25,
-    envir_jiaquan,
-    envir_tvoc,
-  } = equipImageMap;
-
-  const [searchText, setSearchText] = useState();
-  const [showChart, setShowChart] = useState(false);
-  const [explainImg, setExplainImg] = useState(temperMapTop);
-  const [mapImg, setMapImg] = useState(maptemp1);
-
-  const [navigatorList] = useState([
-    {
-      name: '温度',
-      id: 'temperature',
-      src: envir_temperature,
-      sel: false,
-      unit: '℃',
-      num: 24.3,
-      color: '#E5574F',
-    },
-    {
-      name: '湿度',
-      id: 'wet',
-      src: envir_wet,
-      sel: false,
-      unit: '%',
-      num: 70,
-      color: '#9FB7CD',
-    },
-    {
-      name: 'CO₂',
-      id: 'co2',
-      src: envir_co2,
-      sel: false,
-      unit: 'ppm',
-      num: 600,
-      color: '#00DC23',
-    },
-    {
-      name: 'PM2.5',
-      id: 'pm25',
-      src: envir_pm25,
-      sel: false,
-      unit: 'ug/m³',
-      num: 33,
-      color: '#E89E32',
-    },
-    {
-      name: '甲醛',
-      id: 'jiaquan',
-      src: envir_jiaquan,
-      sel: false,
-      unit: 'mg/m³',
-      num: 50,
-      color: '#140050',
-    },
-    {
-      name: 'TVOC',
-      id: 'tvoc',
-      src: envir_tvoc,
-      sel: false,
-      unit: 'mg/m³',
-      num: 36,
-      color: '#2D553E',
-    },
-  ]);
-  const navigatorChange = (item) => {
-    if (item.id == 'temperature') {
-      setExplainImg(temperMapTop);
-      setMapImg(maptemp1);
-    }
-    if (item.id == 'co2') {
-      setExplainImg(co2MapTop);
-      setMapImg(maptemp2);
-    }
-  };
-  const specialRoomClick = () => {
-    console.log('showChart');
-    setShowChart(true);
-  };
-  return (
-    <div>
-      <PageHeader
-        title={<FormattedMessage id="menu.environment" />}
-        action={
-          //   <SearchInput
-          //     placeholder="搜索空间"
-          //     onSearch={(s) => {
-          //       setSearchText(s || undefined);
-          //     }}
-          //     onCancel={() => {
-          //       setSearchText();
-          //     }}
-          //   />
-
-          <Input.Search
-            size="large"
-            allowClear
-            style={{ width: '20%' }}
-            placeholder={'搜索空间'}
-            onSearch={(s) => {
-              setSearchText(s || undefined);
-            }}
-          />
-        }
-      />
-      <div style={{ marginTop: '26px' }}>
-        <TopNavigator
-          navigatorList={navigatorList}
-          type={'enviroment'}
-          navigatorChange={navigatorChange}
-        ></TopNavigator>
-        <div className={styles.mapwrap}>
-          <div className={styles.top}>
-            <div className={styles.right}>
-              <img style={{ width: '100%' }} src={explainImg}></img>
-            </div>
-          </div>
-          <div className={styles.map}>
-            <div className={styles.specialRoom} onClick={specialRoomClick}></div>
-            <img src={mapImg}></img>
-          </div>
-        </div>
-      </div>
-
-      {showChart && (
-        <ChartModal
-          onClose={() => {
-            setShowChart(false);
-          }}
-        ></ChartModal>
-      )}
-    </div>
-  );
-}

+ 21 - 13
src/pages/Environment/index.less

@@ -8,20 +8,28 @@
     padding-top: 10px;
     padding-right: 20px;
     .right {
+      display: flex;
       float: right;
-      width: 210px;
+      .indicatorBox {
+        .text {
+          padding-bottom: 7px;
+          color: #4d5262;
+          font-size: 11px;
+          line-height: 1;
+        }
+        .color {
+          width: 40px;
+          height: 4px;
+        }
+      }
     }
   }
-  .map {
-    position: relative;
-    width: 100%;
-    overflow: hidden;
-  }
-  .specialRoom {
-    position: absolute;
-    top: 0;
-    right: 0;
-    width: 180px;
-    height: 170px;
-  }
+
+  //   .specialRoom {
+  //     position: absolute;
+  //     top: 0;
+  //     right: 0;
+  //     width: 180px;
+  //     height: 170px;
+  //   }
 }

+ 216 - 0
src/pages/Environment/index.tsx

@@ -0,0 +1,216 @@
+import React, { useState, useEffect } from 'react';
+import { FormattedMessage } from 'umi';
+import PageHeader from '@/components/PageHeader';
+// import SearchInput from '@/tenants-ui/SearchInput';
+import TopNavigator from './components/topNavigator';
+import ChartModal from './components/chartModal';
+import { equipImageMap } from '@/config/image.js';
+import { Input } from 'antd';
+import Icon from '@/tenants-ui/Icon';
+
+import styles from './index.less';
+import mapstyles from '@/assets/css/map.less';
+import { getMapList } from '@/services/ant-design-pro/environment';
+
+export type navigatorItem = {
+  name: string;
+  id: string;
+  src: any;
+  unit?: string;
+  num?: number;
+  color: string;
+  colorStr: string;
+  opacity?: number;
+  indicator?: number[];
+  [key: string]: any;
+};
+const Environment: React.FC = () => {
+  const { envir_temperature, envir_wet, envir_co2, envir_pm25, envir_jiaquan } = equipImageMap;
+
+  const [searchText, setSearchText] = useState<string>();
+  const [mapList, setMapList] = useState<API.MapInfo[]>([]);
+  const [showChart, setShowChart] = useState(false);
+  const [navigatorList] = useState<navigatorItem[]>([
+    {
+      name: '温度',
+      id: 'temperature',
+      src: envir_temperature,
+      unit: '℃',
+      num: 24.3,
+      color: '#E5574F',
+      colorStr: '229,87,79,',
+      opacity: 0.2,
+      indicator: [18, 21, 24, 27, 30],
+    },
+    {
+      name: '湿度',
+      id: 'wet',
+      src: envir_wet,
+      unit: '%',
+      num: 70,
+      color: '#9FB7CD',
+      colorStr: '159,183,205,',
+      opacity: 0.2,
+      indicator: [25, 35, 45, 55, 65],
+    },
+    {
+      name: 'CO₂',
+      id: 'co2',
+      src: envir_co2,
+      unit: 'ppm',
+      num: 600,
+      color: '#00DC23',
+      colorStr: '0,220,35,',
+      opacity: 0.2,
+      indicator: [500, 700, 1000, 2000, 3000],
+    },
+    {
+      name: 'PM2.5',
+      id: 'pm25',
+      src: envir_pm25,
+      unit: 'ug/m³',
+      num: 33,
+      color: '#E89E32',
+      colorStr: '232,158,50,',
+      opacity: 0.2,
+      indicator: [15, 25, 35, 75, 90],
+    },
+    {
+      name: '甲醛',
+      id: 'jiaquan',
+      src: envir_jiaquan,
+      unit: 'mg/m³',
+      num: 50,
+      color: '#140050',
+      colorStr: '20,0,80,',
+      opacity: 0.25,
+      indicator: [0.02, 0.05, 0.1, 0.15],
+    },
+  ]);
+  const [selNav, setSelNav] = useState<navigatorItem>(navigatorList[0]);
+  const navigatorChange = (item: navigatorItem) => {
+    if (item.id == 'temperature') {
+    }
+    setSelNav(item);
+  };
+  // const specialRoomClick = () => {
+  //   console.log('showChart');
+  //   setShowChart(true);
+  // };
+  useEffect(() => {
+    getMapList({ floorId: 'sffsdfdsfdf', floorNumber: 22 }).then(function (res) {
+      var data: API.MapInfo[] = res.data || [];
+      setMapList(data);
+    });
+  }, []);
+  //根据指标的值  得到不同的透明度等级 第一级0.2 第二级0.4 依次往后
+  const getColorOpacity = (value: number): number => {
+    var indicator: number[] = selNav.indicator || [];
+    var number = indicator.length;
+    var res = 1;
+    for (var i = 0; i < number; i++) {
+      if (value >= indicator[i] && value < indicator[i + 1]) {
+        res = i + 1;
+        break;
+      }
+    }
+    return res;
+  };
+
+  return (
+    <div>
+      <PageHeader
+        title={<FormattedMessage id="menu.environment" />}
+        action={
+          //   <SearchInput
+          //     placeholder="搜索空间"
+          //     onSearch={(s) => {
+          //       setSearchText(s || undefined);
+          //     }}
+          //     onCancel={() => {
+          //       setSearchText();
+          //     }}
+          //   />
+
+          <Input.Search
+            size="large"
+            allowClear
+            style={{ width: '20%' }}
+            placeholder={'搜索空间'}
+            onSearch={(s) => {
+              setSearchText(s || undefined);
+            }}
+          />
+        }
+      />
+      <div style={{ marginTop: '26px' }}>
+        <TopNavigator
+          navigatorList={navigatorList}
+          type={'enviroment'}
+          navigatorChange={navigatorChange}
+        ></TopNavigator>
+        <div className={styles.mapwrap}>
+          <div className={styles.top}>
+            <div className={styles.right}>
+              {selNav.indicator.map((item, index) => {
+                return (
+                  <div className={styles.indicatorBox} key={index + 'indicator'}>
+                    <div className={styles.text}>{item}</div>
+                    <div
+                      className={styles.color}
+                      style={{
+                        // backgroundColor: selNav.color,
+                        // opacity: selNav.opacity * (index + 1),
+                        backgroundColor:
+                          'rgba(' +
+                          selNav.colorStr +
+                          (selNav.opacity as number) * (index + 1) +
+                          ')',
+                      }}
+                    ></div>
+                  </div>
+                );
+              })}
+            </div>
+          </div>
+          <div className={mapstyles.map}>
+            {mapList.map(function (item, index) {
+              return (
+                <div
+                  key={index + 'house'}
+                  className={mapstyles.house}
+                  style={{
+                    left: item.left,
+                    top: item.top,
+                    width: item.width,
+                    height: item.height,
+                    backgroundColor:
+                      'rgba(' +
+                      selNav.colorStr +
+                      (selNav.opacity as number) * getColorOpacity(item.value) +
+                      ')',
+                  }}
+                >
+                  <div className={mapstyles.content}>
+                    <Icon className="" type={item.type} style={{ fontSize: 20 }}></Icon>
+                    <div className={mapstyles.name}>{item.name}</div>
+                  </div>
+                </div>
+              );
+            })}
+          </div>
+        </div>
+      </div>
+
+      {showChart && (
+        <ChartModal
+          onClose={() => {
+            setShowChart(false);
+          }}
+        ></ChartModal>
+      )}
+    </div>
+  );
+};
+
+export default Environment;

+ 18 - 27
src/pages/Equipment/components/topNavRight/index.jsx

@@ -5,31 +5,20 @@ import Icon from '@/tenants-ui/Icon';
 import { EllipsisOutlined, ExclamationCircleOutlined } from '@ant-design/icons';
 import styles from './index.less';
 import { equipImageMap } from '@/config/image.js';
+import type { navigatorItem } from '@/pages/Environment/index';
 
-export default ({ selParamObj }) => {
-  const { equip_air, equip_lamp, equip_water } = equipImageMap;
-  const [modalvisible, setModalvisible] = useState(false);
-  const [allList] = useState([
-    {
-      name: '空调',
-      id: 'air',
-      src: equip_air,
-      num: 7,
-    },
-    {
-      name: '照明',
-      id: 'lamp',
-      src: equip_lamp,
-      num: 60,
-    },
-    {
-      name: '水机',
-      id: 'water',
-      src: equip_water,
-      num: 33,
-    },
-  ]);
+export type topNavRightProps = {
+  selNavObj: navigatorItem;
+  navigatorList: navigatorItem[];
+};
 
+const TopNavRight: React.FC<topNavRightProps> = ({ selNavObj, navigatorList }) => {
+  // const { equip_air, equip_lamp, equip_water } = equipImageMap;
+  const [modalvisible, setModalvisible] = useState<boolean>(false);
+  const [allList, setAllList] = useState<navigatorItem[]>([]);
+  useEffect(() => {
+    setAllList(navigatorList.slice(1));
+  }, []);
   const menuClick = (key) => {
     console.log('key', key);
   };
@@ -52,7 +41,7 @@ export default ({ selParamObj }) => {
   return (
     <>
       {/* 全部设备 */}
-      {selParamObj.id === 'all' && (
+      {selNavObj.id === 'all' && (
         <div className={styles.right}>
           <div className={styles.title}>运行中的设备</div>
           <div className={styles.allList}>
@@ -68,15 +57,15 @@ export default ({ selParamObj }) => {
         </div>
       )}
       {/* 设备 */}
-      {selParamObj.id !== 'all' && (
+      {selNavObj.id !== 'all' && (
         <div className={styles.right}>
           <div className={styles.title}>运行中的设备</div>
-          <div className={styles.onlyNum}>{selParamObj.num}</div>
+          <div className={styles.onlyNum}>{selNavObj.num}</div>
           <div className={styles.closeButton} onClick={showModal}>
             {/* <Button type="primary"  size={'large'}  icon={<Icon type="closeall"  style={{color:'red',fontSize:20}} />} style={{'background':'rgba(196, 196, 196, 0.2)',border:'none'}} >
               全部关闭
             </Button> */}
-            <Icon type="closeall" style={{ fontSize: 20 }} />
+            <Icon className="" type="closeall" style={{ fontSize: 20 }} />
             <span className={styles.text}>全部关闭</span>
           </div>
           <div className={styles.moreWrap}>
@@ -111,3 +100,5 @@ export default ({ selParamObj }) => {
     </>
   );
 };
+
+export default TopNavRight;

+ 0 - 148
src/pages/Equipment/index.jsx

@@ -1,148 +0,0 @@
-import React, { useState, useEffect, useCallback } from 'react';
-import { FormattedMessage } from 'umi';
-
-// import SearchInput from '@/tenants-ui/SearchInput';
-import PageHeader from '@/components/PageHeader';
-import TopNavigator from '../Environment/components/topNavigator';
-import DeviceModal from './components/deviceModal';
-
-import styles from './index.less';
-import { equipImageMap } from '@/config/image.js';
-import { Input } from 'antd';
-
-export default function Equipment() {
-  const {
-    airMapTop,
-    lampMapTop,
-    maptemp3,
-    maptemp4,
-    maptemp5,
-    envir_all,
-    equip_air,
-    equip_lamp,
-    equip_water,
-    envir_curtain,
-    envir_humidification,
-  } = equipImageMap;
-  const [searchText, setSearchText] = useState();
-  const [showModal, setShowModal] = useState(false);
-  const [mapImg, setMapImg] = useState(maptemp3);
-  const [explainImg, setExplainImg] = useState(null);
-
-  const [navigatorList] = useState([
-    {
-      name: '全部设备',
-      id: 'all',
-      src: envir_all,
-      num: 24.3,
-      color: '#E5574F',
-    },
-    {
-      name: '空调',
-      id: 'air',
-      src: equip_air,
-      num: 11,
-      color: '#5E8BCF',
-    },
-    {
-      name: '照明',
-      id: 'lamp',
-      src: equip_lamp,
-      num: 10,
-      color: '#FFE823',
-    },
-    {
-      name: '水机',
-      id: 'water',
-      src: equip_water,
-      num: 33,
-      color: '#9FB7CD',
-    },
-    {
-      name: '窗帘',
-      id: 'curtain',
-      src: envir_curtain,
-      num: 50,
-      color: '#E89E32',
-    },
-    {
-      name: '加湿器',
-      id: 'humidification',
-      src: envir_humidification,
-      num: 36,
-      color: '#2D553E',
-    },
-  ]);
-  const navigatorChange = (item) => {
-    //debugger;
-    if (item.id == 'all') {
-      setExplainImg(null);
-      setMapImg(maptemp3);
-    }
-    if (item.id == 'air') {
-      setExplainImg(airMapTop);
-      setMapImg(maptemp4);
-    }
-    if (item.id == 'lamp') {
-      setExplainImg(lampMapTop);
-      setMapImg(maptemp5);
-    }
-  };
-  const specialRoomClick = () => {
-    console.log('showChart');
-    setShowModal(true);
-  };
-  return (
-    <div>
-      <PageHeader
-        title={<FormattedMessage id="menu.equipment" />}
-        action={
-          //   <SearchInput
-          //     placeholder="搜索空间"
-          //     onSearch={(s) => {
-          //       setSearchText(s || undefined);
-          //     }}
-          //     onCancel={() => {
-          //       setSearchText();
-          //     }}
-          //   />
-          <Input.Search
-            size="large"
-            allowClear
-            style={{ width: '20%' }}
-            placeholder={'搜索空间'}
-            onSearch={(s) => {
-              setSearchText(s || undefined);
-            }}
-          />
-        }
-      />
-      <div style={{ marginTop: '26px' }}>
-        <TopNavigator
-          navigatorList={navigatorList}
-          type={'equipment'}
-          navigatorChange={navigatorChange}
-        ></TopNavigator>
-        <div className={styles.mapwrap}>
-          <div className={styles.top}>
-            <div className={styles.right}>
-              <img style={{ width: '100%' }} src={explainImg}></img>
-            </div>
-          </div>
-          <div className={styles.map}>
-            <div className={styles.specialRoom} onClick={specialRoomClick}></div>
-            <img src={mapImg}></img>
-          </div>
-        </div>
-      </div>
-
-      {showModal && (
-        <DeviceModal
-          onClose={() => {
-            setShowModal(false);
-          }}
-        ></DeviceModal>
-      )}
-    </div>
-  );
-}

+ 11 - 14
src/pages/Equipment/index.less

@@ -6,22 +6,19 @@
     box-sizing: border-box;
     height: 47px;
     padding-top: 10px;
-    padding-right: 20px;
+
     .right {
+      display: flex;
       float: right;
-      width: 210px;
+      .circle {
+        display: inline-block;
+        width: 10px;
+        height: 10px;
+        margin-right: 4px;
+        margin-left: 18px;
+        background: #5e8bcf;
+        border-radius: 10px;
+      }
     }
   }
-  .map {
-    position: relative;
-    width: 100%;
-    overflow: hidden;
-  }
-  .specialRoom {
-    position: absolute;
-    top: 0;
-    right: 0;
-    width: 180px;
-    height: 170px;
-  }
 }

+ 228 - 0
src/pages/Equipment/index.tsx

@@ -0,0 +1,228 @@
+import React, { useState, useEffect, useCallback } from 'react';
+import { FormattedMessage } from 'umi';
+
+// import SearchInput from '@/tenants-ui/SearchInput';
+import PageHeader from '@/components/PageHeader';
+import TopNavigator from '../Environment/components/topNavigator';
+import TopNavRight from './components/topNavRight';
+import DeviceModal from './components/deviceModal';
+
+import styles from './index.less';
+import mapstyles from '@/assets/css/map.less';
+import cx from 'classnames';
+// import './map.less';
+import { equipImageMap } from '@/config/image.js';
+import { Input } from 'antd';
+import Icon from '@/tenants-ui/Icon';
+import type { navigatorItem } from '@/pages/Environment/index';
+
+import { getMapList } from '@/services/ant-design-pro/environment';
+
+const Environment: React.FC = () => {
+  const { envir_all, equip_air, equip_lamp, envir_curtain } = equipImageMap;
+  const [searchText, setSearchText] = useState<string>('');
+  const [showModal, setShowModal] = useState<boolean>(false);
+  const [navigatorList] = useState<navigatorItem[]>([
+    {
+      name: '全部设备',
+      id: 'all',
+      src: envir_all,
+      //color: '#E5574F',
+      color: '#E89E32',
+      colorStr: '',
+    },
+    {
+      name: '空调',
+      id: 'air',
+      src: equip_air,
+      num: 11,
+      color: '#5E8BCF',
+      colorStr: '94,139,207,',
+    },
+    {
+      name: '照明',
+      id: 'lamp',
+      src: equip_lamp,
+      num: 10,
+      color: '#FFE823',
+      colorStr: '255,232,35,',
+    },
+    {
+      name: '窗帘',
+      id: 'curtain',
+      src: envir_curtain,
+      num: 50,
+      color: '#E89E32',
+      colorStr: '232, 158, 50,',
+    },
+  ]);
+  const [mapList, setMapList] = useState<API.MapInfo[]>([]);
+  useEffect(() => {
+    getMapList({ floorId: 'sffsdfdsfdf', floorNumber: 22 }).then(function (res) {
+      var data: API.MapInfo[] = res.data || [];
+      data.forEach((item, index) => {});
+      setMapList(data);
+    });
+  }, []);
+  const [selNav, setSelNav] = useState<navigatorItem>(navigatorList[0]);
+  const navigatorChange = (item: navigatorItem) => {
+    //debugger;
+    if (item.id == 'all') {
+    }
+    if (item.id == 'air') {
+    }
+    if (item.id == 'lamp') {
+    }
+    setSelNav(item);
+  };
+  const showModalClick = () => {
+    console.log('showChart');
+    setShowModal(true);
+  };
+  //当前设备的状态 all全部开启 part部分开启 close全都关闭  还有类型type 包括air lamp curtain
+  //根据设备状态返回不同的 颜色
+  const getColorOpacity = (value: string, type?: string): string => {
+    //debugger;
+    let colorStr = '';
+    if (selNav.id == 'all') {
+      //全部设备时 colorStr赋值
+      var filterRes = navigatorList.filter(function (item) {
+        return item.id == type;
+      });
+      colorStr = (filterRes[0] || {}).colorStr;
+    } else {
+      colorStr = selNav.colorStr;
+    }
+    if (value == 'part') {
+      return 'rgba(' + colorStr + '0.4)';
+    } else if (value == 'all') {
+      return 'rgba(' + colorStr + '1)';
+    } else {
+      return 'rgba(196, 196, 196, 0.6)';
+    }
+  };
+  return (
+    <div>
+      <PageHeader
+        title={<FormattedMessage id="menu.equipment" />}
+        action={
+          //   <SearchInput
+          //     placeholder="搜索空间"
+          //     onSearch={(s) => {
+          //       setSearchText(s || undefined);
+          //     }}
+          //     onCancel={() => {
+          //       setSearchText();
+          //     }}
+          //   />
+          <Input.Search
+            size="large"
+            allowClear
+            style={{ width: '20%' }}
+            placeholder={'搜索空间'}
+            onSearch={(s) => {
+              setSearchText(s || undefined);
+            }}
+          />
+        }
+      />
+      <div style={{ marginTop: '26px' }}>
+        <TopNavigator
+          navigatorList={navigatorList}
+          type={'equipment'}
+          navigatorChange={navigatorChange}
+          action={<TopNavRight selNavObj={selNav} navigatorList={navigatorList}></TopNavRight>}
+        ></TopNavigator>
+
+        <div className={styles.mapwrap}>
+          <div className={styles.top}>
+            {selNav.id !== 'all' && (
+              <div className={styles.right}>
+                <div>
+                  <span
+                    className={styles.circle}
+                    style={{ backgroundColor: 'rgba(' + selNav.colorStr + '1)' }}
+                  ></span>
+                  <span>开启</span>
+                </div>
+                <div>
+                  <span
+                    className={styles.circle}
+                    style={{ backgroundColor: 'rgba(' + selNav.colorStr + '0.4)' }}
+                  ></span>
+                  <span>部分开启</span>
+                </div>
+                <div>
+                  <span
+                    className={styles.circle}
+                    style={{ backgroundColor: 'rgba(196, 196, 196, 0.6)' }}
+                  ></span>
+                  <span>关闭</span>
+                </div>
+              </div>
+            )}
+          </div>
+          <div className={cx(mapstyles.map, mapstyles.equipmentMap)}>
+            {mapList.map(function (item, index) {
+              return (
+                <div
+                  key={index + 'house'}
+                  className={mapstyles.house}
+                  style={{
+                    left: item.left,
+                    top: item.top,
+                    width: item.width,
+                    height: item.height,
+                    backgroundColor:
+                      selNav.id == 'all'
+                        ? 'rgba(196, 196, 196, 0.2)'
+                        : getColorOpacity(item[selNav.id]),
+                  }}
+                >
+                  {/* {selNav.id == 'all' && (
+                    <div className={mapstyles.allDevice}>
+                      {item.device.map((ditem, dindex: number) => {
+                        return (
+                          <div
+                            key={dindex + 'device'}
+                            className={mapstyles.icon}
+                            style={{
+                              backgroundColor: getColorOpacity(ditem.status, ditem.type),
+                            }}
+                          >
+                            <Icon
+                              className=""
+                              type={ditem.type}
+                              style={{ color: '#ffffff' }}
+                            ></Icon>
+                          </div>
+                        );
+                      })}
+                    </div>
+                  )} */}
+                  <div className={mapstyles.showModal} onClick={showModalClick}>
+                    <Icon className="" type="hover"></Icon>
+                  </div>
+                  <div className={mapstyles.content}>
+                    <Icon className="" type={item.type} style={{ fontSize: 20 }}></Icon>
+                    <div className={mapstyles.name}>{item.name}</div>
+                  </div>
+                </div>
+              );
+            })}
+          </div>
+        </div>
+      </div>
+
+      {showModal && (
+        <DeviceModal
+          onClose={() => {
+            setShowModal(false);
+          }}
+        ></DeviceModal>
+      )}
+    </div>
+  );
+};
+
+export default Environment;

+ 1 - 1
src/pages/Runtime/RecordList/index.less

@@ -1 +1 @@
-@import '/src/antd-tenants.less';
+// @import '/src/antd-tenants.less';

+ 18 - 1
src/pages/Runtime/index.jsx

@@ -4,6 +4,7 @@ import TopNavigator from '../Environment/components/topNavigator';
 import { FormattedMessage, history } from 'umi';
 import SearchInput from '@/tenants-ui/SearchInput';
 import styles from './index.less';
+import mapstyles from '@/assets/css/map.less';
 import Icon from '@/tenants-ui/Icon';
 import { equipImageMap } from '@/config/image.js';
 
@@ -46,9 +47,25 @@ export default function Runtime(props) {
           <div className={styles.top}>
             <div className={styles.right}></div>
           </div>
-          <div className={styles.map}>
+          {/* <div className={styles.map}>
             <div className={styles.specialRoom}></div>
             <img src={mapImg}></img>
+          </div> */}
+
+          <div className={mapstyles.map}>
+            <div
+              className={mapstyles.house}
+              style={{
+                width: 180,
+                height: 100,
+              }}
+            >
+              <div className={mapstyles.allTime}>08:00-23:00</div>
+              <div className={mapstyles.content}>
+                <Icon type="office" style={{ fontSize: 20 }}></Icon>
+                <div className={mapstyles.name}>Jozy Zone</div>
+              </div>
+            </div>
           </div>
         </div>
       </div>

+ 13 - 0
src/services/ant-design-pro/environment.ts

@@ -0,0 +1,13 @@
+/** 登录接口 POST /api/login/account */
+import { request } from 'umi';
+
+export async function getMapList(body: any, options?: { [key: string]: any }) {
+  return request<API.MapList>('/api/environment/map', {
+    method: 'POST',
+    headers: {
+      'Content-Type': 'application/json',
+    },
+    ...(options || {}),
+    data: body,
+  });
+}

+ 2 - 0
src/services/ant-design-pro/index.ts

@@ -4,7 +4,9 @@
 // API 唯一标识:
 import * as api from './api';
 import * as login from './login';
+import * as environment from './environment';
 export default {
   api,
   login,
+  environment,
 };

+ 15 - 0
src/services/ant-design-pro/typings.d.ts

@@ -98,4 +98,19 @@ declare namespace API {
     description?: string;
     type?: NoticeIconItemType;
   };
+
+  type MapInfo = {
+    left?: number;
+    top?: number;
+    width?: number;
+    height?: number;
+    value?: number;
+    name?: string;
+    type?: string;
+    [key: string]: any;
+  };
+  type MapList = {
+    data?: MapInfo[];
+    success?: boolean;
+  };
 }

+ 1 - 1
src/tenants-ui/Icon/index.jsx

@@ -1,7 +1,7 @@
 import { createFromIconfontCN } from '@ant-design/icons';
 
 const Icon = createFromIconfontCN({
-  scriptUrl: '//at.alicdn.com/t/font_3184967_m3fl5qsc7m.js',
+  scriptUrl: '//at.alicdn.com/t/font_3184967_qzvz17l2oz.js',
 });
 
 export default ({ type, className, style = {} }) => {