Forráskód Böngészése

适应 大方的代码修改

zhaojijng 2 éve
szülő
commit
b21abebb32

+ 156 - 0
src/services/sgservice/environment.ts

@@ -0,0 +1,156 @@
+/** 登录接口 POST /api/login/account */
+import { request } from 'umi';
+import { projectId } from '@/config/api';
+import UserStorage from '@/config/user';
+
+export async function getMapList(body: any, options?: { [key: string]: any }) {
+  return request<API.MapInfoRes>(
+    `/sgadmin/duoduo-service/setup-service/map/queryMapInfo?${commonParams()}`,
+    {
+      method: 'POST',
+      headers: {
+        'Content-Type': 'application/json',
+      },
+      ...(options || {}),
+      data: body,
+    },
+  );
+}
+export async function getBuildingList(body: any, options?: { [key: string]: any }) {
+  //debugger;
+  return request<API.BuildFloorList>(
+    `/sgadmin/duoduo-service/object-service/object/building/query?${commonParams()}`,
+    {
+      method: 'POST',
+      headers: {
+        'Content-Type': 'application/json',
+      },
+      ...(options || {}),
+      data: body,
+    },
+  );
+}
+export async function getFloorList(body: any, options?: { [key: string]: any }) {
+  // debugger;
+  return request<API.BuildFloorList>(
+    `/sgadmin/duoduo-service/object-service/object/floor/query?${commonParams()}`,
+    {
+      method: 'POST',
+      headers: {
+        'Content-Type': 'application/json',
+      },
+      ...(options || {}),
+      data: body,
+    },
+  );
+}
+export async function queryDeviceTimeManage(params: any, options?: { [key: string]: any }) {
+  //  '/api3/duoduo-service/setup-service/deviceManage/queryDeviceTimeManage'
+  return request<API.DeviceTimeType>(
+    `/sgadmin/duoduo-service/setup-service/deviceManage/queryDeviceTimeManage?${commonParams()}`,
+    {
+      method: 'GET',
+      params: {
+        ...params,
+      },
+      ...(options || {}),
+    },
+  );
+}
+
+function getProjectId() {
+  const id = projectId;
+  return id;
+}
+
+function commonParams() {
+  var userObj = UserStorage.getInstance();
+  const user = userObj.getUser();
+  var pubname = '';
+  if (getProjectId() == 'Pj3301100002') {
+    pubname = 'sgadmin';
+  } else {
+    pubname = 'sagacareAndtenantslink';
+  }
+  return `openid=${user.id}&pubname=${pubname}&projectId=${getProjectId()}&userId=${
+    user.id
+  }&userName=${user.name}`;
+}
+// chart
+export async function queryPropertyData(params: any, options?: { [key: string]: any }) {
+  return request<API.DeviceTimeType>(
+    `/sgadmin/duoduo-service/duoduoenv-service/spaceAdjust/queryPropertyData?${commonParams()}`,
+    {
+      method: 'GET',
+      params: params,
+      ...(options || {}),
+    },
+  );
+}
+export async function queryEnvironmentParam(body: any, otherParam: { [key: string]: any }) {
+  //api/duoduo-service/object-service/object/floor/queryParam
+  return request<API.EnvironmentParam>(
+    `/sgadmin/duoduo-service/object-service/object/floor/queryParam?endTime=${otherParam.endTime}&startTime=${otherParam.startTime}&param=${otherParam.param}`,
+    {
+      method: 'POST',
+      headers: {
+        'Content-Type': 'application/json',
+      },
+      data: body,
+    },
+  );
+}
+
+export async function queryEquipStatistics(params: any, options?: { [key: string]: any }) {
+  //
+  return request<API.EnvironmentParam>(
+    `/sgadmin/duoduo-service/object-service/object/equipment/queryEquipStatistics`,
+    {
+      method: 'GET',
+      headers: {
+        'Content-Type': 'application/json',
+      },
+      ...(options || {}),
+      params: {
+        ...params,
+      },
+    },
+  );
+}
+
+export async function querySpace(body: any, options?: { [key: string]: any }) {
+  //
+  return request<API.EnvironmentParam>(
+    `/sgadmin/duoduo-service/object-service/object/space/query?${commonParams()}`,
+    {
+      method: 'POST',
+      headers: {
+        'Content-Type': 'application/json',
+      },
+      ...(options || {}),
+      data: body,
+    },
+  );
+}
+
+export async function checkToken(header: any, options?: { [key: string]: any }) {
+  return request<API.EnvironmentParam>(`/sgadmin/duoduo-service/setup-service/user/zjCheckToken`, {
+    method: 'GET',
+    headers: {
+      'Content-Type': 'application/json',
+      ...header,
+    },
+    ...(options || {}),
+  });
+}
+//http://10.100.28.79/sgadmin/sso//auth/zjFreshCheckToken
+export async function reFreshCheckToken(header: any, options?: { [key: string]: any }) {
+  return request<API.EnvironmentParam>(`/sgadmin/sso/auth/zjFreshCheckToken`, {
+    method: 'GET',
+    headers: {
+      'Content-Type': 'application/json',
+      ...header,
+    },
+    ...(options || {}),
+  });
+}

+ 146 - 0
src/services/sgservice/equipment.js

@@ -0,0 +1,146 @@
+import { request } from 'umi';
+import { projectId } from '@/config/api.js';
+import UserStorage from '@/config/user';
+
+function getProjectId() {
+    //const id = window.localStorage.getItem('localProjectId')
+    const id = projectId
+    return id;
+}
+
+function commonParams() {
+    var userObj = UserStorage.getInstance();
+     const user = userObj.getUser();
+     var pubname='';
+     if(getProjectId()=='Pj3301100002'){
+        pubname='sgadmin'
+     }else{
+        pubname='sagacareAndtenantslink'
+     }
+    return `openid=${user.id}&pubname=${pubname}&projectId=${getProjectId()}&userId=${user.id}&userName=${user.name}`;
+}
+
+// function commonParams() {
+//     return `openid=9a1ecfbacb6b4f249bf2dd3ec7793ead&pubname=sagacareAndtenantslink&projectId=${getProjectId()}&userName=%E5%AE%89%E5%B0%8F%E9%9C%9E&userPhone=17611228068&userId=9a1ecfbacb6b4f249bf2dd3ec7793ead`;
+// }
+
+
+//窗帘  设置设备
+//窗帘  设置设备
+export const setEquipeHttp = (params) => {
+    return request(`/sgadmin/duoduo-service/duoduoenv-service/object/eqp/infocode/set?${commonParams()}`, {
+        method: 'POST',
+        isNotShowErrorToast: true,
+        errorSave: true,
+        data: JSON.stringify(params),
+        headers: {
+            'Content-Type': 'application/json',
+        },
+    });
+}
+
+//窗帘 获取设备
+export const getObjectDataEqpGroupHttp = (params) => {
+    return request(`/sgadmin/duoduo-service/duoduoenv-service/object/objectDataEqpGroup/query?${commonParams()}`, {
+        method: 'POST',
+        isNotShowErrorToast: true,
+        errorSave: true,
+        data: JSON.stringify(params),
+        headers: {
+            'Content-Type': 'application/json',
+        }
+    });
+}
+
+
+
+// 灯的状态
+export const getLampHttp = (params) => {
+    return request(`/sgadmin/duoduo-service/duoduoenv-service/light/status/query?${commonParams()}&spaceId=${params}`, {
+        timeout:1000, 
+        skipErrorHandler:true,
+        method: 'GET',
+        headers: {
+            'Content-Type': 'application/json',
+        },
+    });
+};
+
+
+// 批量 开关灯
+export const setallLampHttp = (params) => {
+    return request(`/sgadmin/duoduo-service/duoduoenv-service/light/onoff/set?${commonParams()}`, {
+        method: 'POST',
+        isNotShowErrorToast: true,
+        errorSave: true,
+        data: JSON.stringify(params),
+        headers: {
+            'Content-Type': 'application/json',
+        },
+    });
+};
+
+// 开关失败时 定时查询灯状态 
+export const getStatusHttp = (params) => {
+    return request(`/sgadmin/duoduo-service/duoduoenv-service/light/onoff/setSatus?${commonParams()}`, {
+        method: 'POST',
+        isNotShowErrorToast: true,
+        errorSave: true,
+        data: JSON.stringify(params),
+        headers: {
+            'Content-Type': 'application/json',
+        },
+    });
+};
+
+
+//  空调 - 调节文案/空调信息
+export const getFeedbackDocumentsHttp = (params) => {
+    return request(`/sgadmin/duoduo-service/duoduoenv-service/custom/feedback/documents?${commonParams()}`, {
+        isNotShowErrorToast: true,
+        errorSave: true,
+        method: 'POST',
+        data: JSON.stringify(params),
+        headers: {
+            'Content-Type': 'application/json',
+        },
+    });
+};
+
+//  空调 调节
+export const changeAirHttp = (params) => {
+    return request(`/sgadmin/duoduo-service/duoduoenv-service/custom/feedbackCreate/v2?${commonParams()}`, {
+        method: 'POST',
+        isNotShowErrorToast: true,
+        errorSave: true,
+        data: JSON.stringify({ ...params, projectId: getProjectId() }),
+        headers: {
+            'Content-Type': 'application/json',
+        },
+    });
+};
+
+// 空间环境质量
+export const getSpaceAdjustList = (params) => {
+    return request(`/sgadmin/duoduo-service/duoduoenv-service/space/property?${commonParams()}`, {
+        method: 'POST',
+        isNotShowErrorToast: true,
+        errorSave: true,
+        data: params,
+        headers: {
+            'Content-Type': 'application/json',
+        },
+    });
+}
+//  批量空调 调节
+export const changeAllAirHttp = (body) => {
+    return request(`/sgadmin/duoduo-service/duoduoenv-service/custom/feedbackCreate/v2Batch?${commonParams()}`, {
+        method: 'POST',
+        isNotShowErrorToast: true,
+        errorSave: true,
+        data: body,
+        headers: {
+            'Content-Type': 'application/json',
+        },
+    });
+};

+ 145 - 0
src/services/sgservice/typings.d.ts

@@ -0,0 +1,145 @@
+// @ts-ignore
+/* eslint-disable */
+
+declare namespace API {
+  type CurrentUser = {
+    name?: string;
+    avatar?: string;
+    userid?: string;
+    email?: string;
+    signature?: string;
+    title?: string;
+    group?: string;
+    tags?: { key?: string; label?: string }[];
+    notifyCount?: number;
+    unreadCount?: number;
+    country?: string;
+    access?: string;
+    geographic?: {
+      province?: { label?: string; key?: string };
+      city?: { label?: string; key?: string };
+    };
+    address?: string;
+    phone?: string;
+    [key: string]: any;
+  };
+
+  type LoginResult = {
+    status?: string;
+    type?: string;
+    currentAuthority?: string;
+  };
+
+  type PageParams = {
+    current?: number;
+    pageSize?: number;
+  };
+
+  type RuleListItem = {
+    key?: number;
+    disabled?: boolean;
+    href?: string;
+    avatar?: string;
+    name?: string;
+    owner?: string;
+    desc?: string;
+    callNo?: number;
+    status?: number;
+    updatedAt?: string;
+    createdAt?: string;
+    progress?: number;
+  };
+
+  type RuleList = {
+    data?: RuleListItem[];
+    /** 列表的内容总数 */
+    total?: number;
+    success?: boolean;
+  };
+
+  type FakeCaptcha = {
+    code?: number;
+    status?: string;
+  };
+
+  type LoginParams = {
+    username?: string;
+    password?: string;
+    autoLogin?: boolean;
+    type?: string;
+  };
+
+  type ErrorResponse = {
+    /** 业务约定的错误码 */
+    errorCode: string;
+    /** 业务上的错误信息 */
+    errorMessage?: string;
+    /** 业务上的请求是否成功 */
+    success?: boolean;
+  };
+
+  type NoticeIconList = {
+    data?: NoticeIconItem[];
+    /** 列表的内容总数 */
+    total?: number;
+    success?: boolean;
+  };
+
+  type NoticeIconItemType = 'notification' | 'message' | 'event';
+
+  type NoticeIconItem = {
+    id?: string;
+    extra?: string;
+    key?: string;
+    read?: boolean;
+    avatar?: string;
+    title?: string;
+    status?: string;
+    datetime?: string;
+    description?: string;
+    type?: NoticeIconItemType;
+  };
+
+  type MapInfo = {
+    left?: number;
+    top?: number;
+    width?: number;
+    height?: number;
+    value?: number;
+    name?: string;
+    type?: string;
+    [key: string]: any;
+  };
+
+  type MapInfoRes = {
+    data?: {
+      height?: number;
+      width?: number;
+      spaceList?: MapInfo[];
+    };
+    result?: string;
+  };
+
+  //楼层建筑都是这种类型
+  type BuildFloorItem = {
+    name: string;
+    id: string;
+    localName: string;
+    [key: string]: any;
+  };
+  type BuildFloorList = {
+    content?: BuildFloorItem[];
+    result?: string;
+    count?: number;
+  };
+  type DeviceTimeType = {
+    content?: any[];
+    result?: string;
+    [key: string]: any;
+  };
+  type EnvironmentParam = {
+    data?: any;
+    result?: string;
+    [key: string]: any;
+  };
+}

+ 18 - 0
src/sgcomponents/PageHeader/index.less

@@ -0,0 +1,18 @@
+.navHeader {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  height: 50px;
+  .title {
+    color: #000;
+    font-weight: 600;
+    font-size: 24px;
+    &::before {
+      margin-right: 10px;
+      color: #f0da21;
+      font-weight: normal;
+      font-size: 32px;
+      content: '/';
+    }
+  }
+}

+ 33 - 0
src/sgcomponents/PageHeader/index.tsx

@@ -0,0 +1,33 @@
+import React, { useEffect } from 'react';
+import styles from './index.less';
+
+import { useModel, history } from 'umi';
+
+type PageHeaderProps = {
+  title: React.ReactNode;
+  action: React.ReactNode;
+};
+const PageHeader: React.FC<PageHeaderProps> = ({ title, action }) => {
+  //console.log('PageHeader');
+
+  useEffect(() => {
+    //debugger
+    const unlisten = history.listen((location, action) => {
+      console.log('location,action', location, action);
+    });
+    return () => {
+      //console.log('un--PageHeader--useEffect');
+      unlisten();
+    };
+  }, []);
+  return (
+    <>
+      <div className={styles.navHeader}>
+        <div className={styles.title}>{title}</div>
+        {action}
+      </div>
+    </>
+  );
+};
+
+export default PageHeader;

+ 3 - 0
src/sgcomponents/SearchInput/index.less

@@ -0,0 +1,3 @@
+.headerSearch {
+  border-bottom: 1px solid #c4c4c4;
+}

+ 129 - 0
src/sgcomponents/SearchInput/index.tsx

@@ -0,0 +1,129 @@
+import React, { useEffect, useState, useRef } from 'react';
+import styles from './index.less';
+import { Select, Spin } from 'antd';
+//import { mapListData } from '@/hooks/useMapList';
+import { SearchOutlined } from '@ant-design/icons';
+import { useModel } from 'umi';
+type mapResType = {
+  id: string;
+  localName: string;
+  [key: string]: any;
+};
+import { querySpace } from '@/services/sgservice/environment';
+import { projectId } from '@/config/api.js';
+const { Option } = Select;
+
+type SearchInputProps = {
+  // callbackSearch: (s: any) => void;
+  //mapList: API.MapInfo[];
+};
+const SearchInput: React.FC<SearchInputProps> = () => {
+  const [matchData, setMatchData] = useState<mapResType[]>([]);
+  const [value, setValue] = useState<any>();
+  const { changeSearchBuildId, changeSearchFloorId, changeSearchText } = useModel('searchInfo');
+  const [loading, setLoading] = useState<boolean>(false);
+  const ref = useRef<any>(0);
+  const searchQuery = (value: string) => {
+    if (ref.current) {
+      clearTimeout(ref.current);
+    }
+
+    function fake() {
+      setLoading(true);
+      var paramsObj = {
+        criteria: {
+          projectId: projectId,
+          localName: {
+            $like: `%${value}%`,
+          },
+        },
+      };
+      //搜索
+      querySpace(paramsObj).then((res) => {
+        var resContent = res.content || [];
+        console.log('setMatch', 'data');
+        setMatchData(resContent);
+        setLoading(false);
+      });
+    }
+    // debugger;
+    if (value) {
+      //防抖
+      ref.current = setTimeout(fake, 600);
+    } else {
+      setMatchData([]);
+    }
+  };
+  //这是搜索 的下拉列表的显示
+  const handleSearch = (value: string) => {
+    //if (value) {
+    searchQuery(value);
+    // } else {
+    //   setMatchData([]);
+    // }
+  };
+
+  //这是搜索的下拉列表的点击
+  const handleChange = (sel: string) => {
+    setValue(null); //清空输入的值
+    setMatchData([]); //清空搜索匹配列表
+    var filterItem = matchData.filter((item) => {
+      return item.id == sel;
+    });
+    var resItem = filterItem[0] || {};
+    //callbackSearch(resItem);
+    //搜索内容改变
+    changeSearchText({ text: resItem.localName });
+    //改变存储的搜索得到的buildingId floorId
+    changeSearchBuildId(resItem.buildingId);
+    changeSearchFloorId(resItem.floorId);
+  };
+  const handelInputKeyDown = (e) => {
+    // 如果点击回车的操作
+    //console.log('keydown', matchData);
+    if (e.code == 'Enter') {
+      //if (matchData.length == 1) {
+      var resItem = matchData[0] || {};
+      //callbackSearch(resItem);
+      changeSearchText({ text: resItem.localName });
+      changeSearchBuildId(resItem.buildingId);
+      changeSearchFloorId(resItem.floorId);
+      //}
+    }
+  };
+
+  return (
+    <div className={styles.headerSearch}>
+      {/* <SearchOutlined style={{ fontSize: 16 }} /> */}
+      <Select
+        showSearch
+        value={value}
+        placeholder="搜索空间"
+        defaultActiveFirstOption={false}
+        filterOption={false}
+        onSearch={handleSearch}
+        onChange={handleChange}
+        onInputKeyDown={handelInputKeyDown}
+        notFoundContent={null}
+        bordered={false}
+        loading={loading}
+        style={{ width: 150, borderColor: '#c4c4c4' }}
+        //   suffixIcon={
+        //     <AudioOutlined
+        //       style={{
+        //         fontSize: 16,
+        //         color: '#1890ff',
+        //       }}
+        //     />
+        //   }
+      >
+        {matchData.length > 0 &&
+          matchData.map(function (item, index) {
+            return <Option key={item.id}>{item.localName}</Option>;
+          })}
+      </Select>
+    </div>
+  );
+};
+
+export default SearchInput;

+ 0 - 0
src/sgcomponents/map/index.less


+ 245 - 0
src/sgcomponents/map/index.tsx

@@ -0,0 +1,245 @@
+import React, { useState, useEffect, useRef } from 'react';
+import mapstyles from '@/assets/css/map.less';
+import { useModel } from 'umi';
+
+import cx from 'classnames';
+import Icon from '@/tenants-ui/SgIcon';
+
+type MapProps = {
+  type: string;
+  // searchText: any;
+  selFloorId?: string;
+  render: (item: API.MapInfo, index: number) => React.ReactNode;
+  mapList: API.MapInfo[];
+  mapSize: any;
+};
+
+const Map: React.FC<MapProps> = ({ type, selFloorId, render, mapList, mapSize }) => {
+  //useModel 注释掉 不用啦 晚会删
+
+  //   useEffect(() => {
+  //     getMapListData(selFloorId);
+  //   }, [selFloorId]);
+  const {
+    searchText,
+    changeSearchSpace,
+    changeSearchText,
+    changeSearchFloorId,
+    changeSearchBuildId,
+  } = useModel('searchInfo');
+
+  const [startPageX, setStartPageX] = useState<number>(0);
+  const [startPageY, setStartPageY] = useState<number>(0);
+
+  const [translateX, setTranslateX] = useState<number>(0);
+  const [translateY, setTranslateY] = useState<number>(0);
+
+  const [originX, setOriginX] = useState<number>(0);
+  const [originY, setOriginY] = useState<number>(0);
+  const [mscale, setMscale] = useState<number>(1);
+  //最大的缩放比例
+  const [maxscale, setMaxscale] = useState<number>(1.6);
+  const [minscale, setMinscale] = useState<number>(0.3);
+  const [canMove, setCanMove] = useState<boolean>(false);
+
+  const currentFloorId = useRef<any>(null);
+  const mapRef = useRef();
+  //   let mapWidth: number = 3000,
+  //     mapHeight: number = 1200;
+
+  const mouseDownEvent = (event: React.MouseEvent) => {
+    setStartPageX(event.pageX);
+    setStartPageY(event.pageY);
+    //console.log('mouseDownEvent', startPageX, event.pageY);
+    setCanMove(true);
+  };
+  const mouseUpEvent = (event: React.MouseEvent) => {
+    //console.log('mouseUpEvent', event);
+    setCanMove(false);
+  };
+  const mouseMoveEvent = (event: React.MouseEvent) => {
+    if (canMove) {
+      let nowPageX = event.pageX;
+      let nowPageY = event.pageY;
+      setTranslateX(translateX + nowPageX - startPageX);
+      setTranslateY(translateY + nowPageY - startPageY);
+      //console.log('mouseMoveEvent-xx', translateX, nowPageX, startPageX);
+      // console.log('mouseMoveEvent-yy', translateY, nowPageY, startPageY);
+
+      setStartPageX(event.pageX);
+      setStartPageY(event.pageY);
+    }
+  };
+  useEffect(() => {
+    console.log('mapRef', mapRef);
+    // var mapWrapWidth = (mapRef.current || {}).clientWidth || 0;
+    // var mapWrapHeight = (mapRef.current || {}).clientHeight || 0;
+    // var originX = mapWrapWidth / 2 - translateX < 0 ? 0 : mapWrapWidth / 2 - translateX;
+    // var originY = mapWrapHeight / 2 - translateY < 0 ? 0 : mapWrapHeight / 2 - translateY;
+    // setOriginX(originX);
+    // setOriginY(originY);
+    console.log('originX', originX, 'originY', originY);
+  }, [translateX, translateY]);
+
+  const mapZoom = (event: React.MouseEvent) => {
+    event.stopPropagation();
+    if (mscale < maxscale) {
+      var mscaleTemp = Number((mscale + 0.1).toFixed(4));
+      setMscale(mscaleTemp);
+      var changeWidth = mapSize.width * 0.1;
+      var changeHeight = mapSize.height * 0.1;
+      setTranslateX(translateX - changeWidth / 2);
+      setTranslateY(translateY - changeHeight / 2);
+    }
+
+    console.log('mscale', mscale);
+  };
+  const mapReduce = (event: React.MouseEvent) => {
+    event.stopPropagation();
+    //console.log('mapReduce', mscale);
+    if (mscale > minscale) {
+      var mscaleTemp = Number((mscale - 0.1).toFixed(4));
+      setMscale(mscaleTemp);
+      var changeWidth = mapSize.width * 0.1;
+      var changeHeight = mapSize.height * 0.1;
+      setTranslateX(translateX + changeWidth / 2);
+      setTranslateY(translateY + changeHeight / 2);
+    }
+
+    console.log('mscale', mscale);
+  };
+
+  const fixWidth = 1300;
+  useEffect(() => {
+    var scale = Number((fixWidth / mapSize.width).toFixed(4));
+    setMscale(scale);
+    if (scale < 0.3) {
+      console.log('mscale', mscale);
+      setMinscale(scale);
+    }
+  }, [mapSize]);
+
+  //当地图发生改变时 的搜索
+  useEffect(() => {
+    //searchText使用对象 防止修改了 不再重新定位
+    //根据searchText进行搜索 如果mapList 更改了
+
+    if (searchText && searchText.text && mapList.length > 0) {
+      let left: any = 0,
+        top: any = 0;
+
+      var filterItem = mapList.filter((item) => {
+        return item.localName == (searchText && searchText.text);
+      });
+      if (filterItem.length == 0) return;
+      //找到搜索的空间
+      changeSearchSpace(filterItem[0]);
+      console.log('selectSpace2', filterItem[0]);
+      left = -((filterItem[0] || {}).left || 0);
+      top = -((filterItem[0] || {}).top || 0);
+      var mapWrapWidth = (mapRef.current || {}).clientWidth || 0;
+      var mapWrapHeight = (mapRef.current || {}).clientHeight || 0;
+      setTranslateX(left * mscale + mapWrapWidth / 2);
+      setTranslateY(top * mscale + mapWrapHeight / 2);
+      //搜索完成
+      changeSearchBuildId(''); //清空搜索记录  以防两次搜索一样的建筑的 没反应
+      changeSearchFloorId(''); //清空搜索记录 以防两次搜索一样的楼层时 没反应 要不要换位置
+      changeSearchText({}); //清空搜索记录 好进行一些操作
+    } else if (currentFloorId.current != selFloorId) {
+      //如果两次的selFloorId 不一样 才会更改地图的位置为0 0
+      setTranslateX(0);
+      setTranslateY(0);
+    }
+    currentFloorId.current = selFloorId;
+    console.log('selectSpace2');
+  }, [mapList]);
+
+  //搜索信息改变时的搜索
+  useEffect(() => {
+    if (searchText && searchText.text && mapList.length > 0) {
+      let left: any = 0,
+        top: any = 0;
+
+      var filterItem = mapList.filter((item) => {
+        return item.localName == (searchText && searchText.text);
+      });
+      if (filterItem.length == 0) return;
+      //找到搜索的空间
+      changeSearchSpace(filterItem[0]);
+
+      //console.log('selectSpace2', filterItem[0]);
+      left = -((filterItem[0] || {}).left || 0);
+      top = -((filterItem[0] || {}).top || 0);
+      var mapWrapWidth = (mapRef.current || {}).clientWidth || 0;
+      var mapWrapHeight = (mapRef.current || {}).clientHeight || 0;
+      //   left = left * mscale + mapWrapWidth / 2;
+      //   top = top * mscale + mapWrapHeight / 2;
+
+      setTranslateX(left * mscale + mapWrapWidth / 2);
+      setTranslateY(top * mscale + mapWrapHeight / 2);
+      changeSearchBuildId(''); //清空搜索记录  以防两次搜索一样的建筑的 没反应
+      changeSearchFloorId(''); //清空搜索记录 以防两次搜索一样的楼层时 没反应 要不要换位置
+      changeSearchText({});
+    }
+  }, [searchText]);
+
+  useEffect(() => {
+    // todo 要不要用呢
+    document.querySelector('#root').addEventListener(
+      'mouseup',
+      function () {
+        console.log('mouseUpEvent');
+        setCanMove(false);
+      },
+      true,
+    );
+  }, []);
+
+  return (
+    <div
+      className={mapstyles.mapwrap}
+      ref={mapRef}
+      onMouseDown={(event) => {
+        mouseDownEvent(event);
+      }}
+      onMouseUp={(event) => {
+        mouseUpEvent(event);
+      }}
+      onMouseMove={(event) => {
+        mouseMoveEvent(event);
+      }}
+    >
+      <div
+        className={cx(mapstyles.map, { [mapstyles.equipmentMap]: type == 'equipment' })}
+        style={{
+          transform: `translate(${translateX}px,${translateY}px) scale(${mscale},${mscale})`,
+          width: mapSize.width,
+          height: mapSize.height,
+        }}
+      >
+        {mapList.map(function (item, index) {
+          return render(item, index);
+        })}
+      </div>
+      <div className={mapstyles.mapControl}>
+        <div
+          className={cx(mapstyles.zoom, { [mapstyles.disable]: mscale >= maxscale })}
+          onClick={(event) => {
+            mapZoom(event);
+          }}
+        >
+          <Icon className="" type="zoom"></Icon>
+        </div>
+        <div
+          className={cx(mapstyles.zoom, { [mapstyles.disable]: mscale <= minscale })}
+          onClick={(event) => {
+            mapReduce(event);
+          }}
+        >
+          <Icon className="" type="reduce"></Icon>
+        </div>
+      </div>
+    </div>
+  );
+};
+export default Map;

+ 33 - 0
src/sgcomponents/navMenu/index.less

@@ -0,0 +1,33 @@
+.drawerDiv {
+  //   width: 380px;
+  //   height: 340px;
+  padding: 0 24px;
+  background-color: #ffffff;
+  border-radius: 10px;
+  .title {
+    display: flex;
+    align-items: center;
+    height: 120px;
+    font-size: 22px;
+  }
+  .menuList {
+    padding-bottom: 60px;
+
+    .menuItem {
+      display: flex;
+      flex-direction: column;
+      align-items: center;
+      justify-content: center;
+      box-sizing: border-box;
+      height: 120px;
+      color: #656872;
+      font-size: 14px;
+      border: 1px solid #eceff4;
+      border-radius: 20px;
+      cursor: pointer;
+      .name {
+        padding-top: 14px;
+      }
+    }
+  }
+}

+ 49 - 0
src/sgcomponents/navMenu/index.tsx

@@ -0,0 +1,49 @@
+import React, { useEffect } from 'react';
+import { Row, Col } from 'antd';
+import styles from './index.less';
+import Icon from '@/tenants-ui/SgIcon';
+import useMenuList, { menutype } from '@/hooks/useMenuList';
+import { history, useModel, useLocation } from 'umi';
+
+const NavMenu: React.FC = () => {
+  const logo = require('@/assets/images/logo.png');
+  const location = useLocation();
+  const { closeMenu } = useModel('controller');
+  const { menuList } = useMenuList();
+  //debugger;
+  const menuClick = (item: menutype) => {
+    closeMenu();
+    history.push(`/${item.id}`);
+  };
+  //   console.log('navMenu');
+  useEffect(() => {
+    console.log('location', location);
+  }, [location]);
+  return (
+    <div className={styles.drawerDiv}>
+      <div className={styles.title}>
+        <img src={logo} style={{ height: 70 }}></img>
+      </div>
+      <div className={styles.menuList}>
+        <Row gutter={[20, 20]}>
+          {(menuList || []).map((item, index) => {
+            return (
+              <Col span={8} key={'col' + index}>
+                <div
+                  className={styles.menuItem}
+                  onClick={() => {
+                    menuClick(item);
+                  }}
+                >
+                  <Icon className="" type={item.id} style={{ fontSize: 26 }}></Icon>
+                  <div className={styles.name}>{item.name}</div>
+                </div>
+              </Col>
+            );
+          })}
+        </Row>
+      </div>
+    </div>
+  );
+};
+export default NavMenu;

+ 64 - 0
src/sgcomponents/topNavigator/index.less

@@ -0,0 +1,64 @@
+.label {
+  color: #c4c4c4;
+}
+.topnavigator {
+  box-sizing: border-box;
+  //   display: flex;
+  height: 63px;
+  margin-top: 18px;
+  background: #fff;
+  .floor {
+    display: flex;
+    align-items: center;
+    float: left;
+    //justify-content: center;
+    width: 120px;
+    height: 100%;
+    border-right: 1px solid rgba(196, 196, 196, 0.4);
+  }
+  .navigator {
+    display: flex;
+    float: left;
+    height: 100%;
+    .navItem {
+      display: flex;
+      flex-direction: column;
+      align-items: center;
+      justify-content: center;
+      width: 50px;
+      height: 100%;
+      margin: 0 20px;
+      font-size: 12px;
+      border-bottom: 3px solid transparent;
+      cursor: pointer;
+      .text {
+        margin-top: 7px;
+        color: #000;
+        text-align: center;
+      }
+    }
+  }
+  .right {
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+    float: right;
+    width: 220px;
+    height: 100%;
+    white-space: nowrap;
+    .firstLine {
+      font-weight: 500;
+      line-height: 20px;
+    }
+    .value {
+      // color: #e5574f;
+      font-size: 28px;
+    }
+    .unit {
+      // color: #e5574f;
+    }
+    .text {
+      color: #c4c4c4;
+    }
+  }
+}

+ 232 - 0
src/sgcomponents/topNavigator/index.tsx

@@ -0,0 +1,232 @@
+import React, { useState, useEffect, useCallback, useRef } from 'react';
+import styles from './index.less';
+import cx from 'classnames';
+import { Select } from 'antd';
+
+import type { navigatorItem } from '@/pages/Environment/index';
+import { getBuildingList, getFloorList } from '@/services/sgservice/environment';
+import { projectId } from '@/config/api.js';
+import { useModel } from 'umi';
+export type topNavigatorProps = {
+  navigatorList?: navigatorItem[];
+  type: string;
+  navigatorChange?: (item: navigatorItem) => void;
+  // action?: React.ReactElement<topNavRightProps>[];
+  action?: React.ReactNode;
+  changeFloorId?: (data: string) => void;
+  changeBuildId?: (data: string) => void;
+  selParamObj?: any;
+};
+type floorItem = {
+  value: string;
+  [key: string]: any;
+};
+type buildItem = {
+  value: string;
+  [key: string]: any;
+};
+const TopNavigator: React.FC<topNavigatorProps> = ({
+  navigatorList = [],
+  type,
+  navigatorChange,
+  action,
+  changeFloorId,
+  changeBuildId,
+  selParamObj,
+}) => {
+  //存储的 搜索到空间的buildingId floorId
+  const { searchBuildId, searchFloorId } = useModel('searchInfo');
+  const [buildList, setBuildList] = useState<buildItem[]>([]);
+  const [currentBuild, setCurrentBuild] = useState<string>();
+
+  const [floorList, setFloorList] = useState<floorItem[]>([]);
+  const [currentFloor, setCurrentFloor] = useState<string>();
+
+  //const [shishi, setShishi] = useState<string>('22');
+  //则监听searchBuildId的改变    如果buildingId改变 请求楼层列表
+  useEffect(() => {
+    if (searchBuildId && searchFloorId) {
+      if (searchBuildId !== currentBuild) {
+        //如果搜索的buildId 改变
+        setCurrentBuild(searchBuildId);
+      } else {
+        //为了 显示楼层选择
+        setCurrentFloor(searchFloorId);
+        //父亲的floorId
+        //这块 其实只想楼层id改变时调用 建筑id 改变时不调用
+        changeFloorId && changeFloorId(searchFloorId);
+      }
+    }
+  }, [searchBuildId, searchFloorId]);
+
+  //请求建筑的接口
+  useEffect(() => {
+    //console.log('TopNavigator----getBuildingList');
+    getBuildingList({
+      criteria: {
+        projectId: projectId,
+      },
+      orders: [
+        {
+          column: 'localId',
+          asc: true,
+        },
+      ],
+    }).then((res) => {
+      var resData = res.content || [];
+      setBuildList(
+        (resData || []).map((item) => {
+          return { label: item.localName, value: item.id };
+        }),
+      );
+      //   var resData2 = [];
+      //   resData2.push(JSON.parse(JSON.stringify(resData[0])));
+      //   resData2.push(JSON.parse(JSON.stringify(resData[0])));
+      //   resData2[1].id = 'sdfsd';
+      //   resData2[1].localName = 'boruiÎ';
+      setBuildList(
+        (resData || []).map((item) => {
+          return { label: item.localName, value: item.id };
+        }),
+      );
+
+      setCurrentBuild((resData[0] || {}).id); //设置第一个建筑值
+      changeBuildId && changeBuildId((resData[0] || {}).id);
+    });
+  }, []);
+
+  //请求楼层列表的接口
+  useEffect(() => {
+    async function asyncFunction() {
+      var res = await getFloorList({
+        criteria: {
+          buildingId: currentBuild,
+        },
+        orders: [
+          {
+            column: 'localId',
+            asc: true,
+          },
+        ],
+      });
+      var resData = res.content || [];
+      setFloorList(
+        (resData || []).map((item) => {
+          return { label: item.localName, value: item.id };
+        }),
+      );
+      //为了 显示楼层选择
+      setCurrentFloor(searchFloorId || (resData[0] || {}).id); //如果有搜索的楼层id 则用搜索的结果
+      changeFloorId && changeFloorId(searchFloorId || (resData[0] || {}).id); //改变父组件的floorId的值
+    }
+    if (currentBuild) {
+      asyncFunction();
+    }
+
+    // if (currentBuild) {
+    //   getFloorList({
+    //     criteria: {
+    //       buildingId: currentBuild,
+    //       //buildingId: 'Bd1101080259317347f00d0811ebb06b1d2749356f83',
+    //     },
+    //   }).then((res) => {
+    //     var resData = res.content || [];
+    //     setFloorList(
+    //       (resData || []).map((item) => {
+    //         return { label: item.localName, value: item.id };
+    //       }),
+    //     );
+
+    //     setCurrentFloor(searchFloorId || (resData[0] || {}).id); //如果有搜索的楼层id 则用搜索的结果
+    //     changeFloorId && changeFloorId(searchFloorId || (resData[0] || {}).id); //改变父组件的floorId的值
+    //   });
+    // }
+  }, [currentBuild]);
+
+  const changBuildHandle = useCallback((val) => {
+    //console.log('select-onChange', val);
+
+    //changeSearchFloorId('');
+    //setShishi('fsdf');
+    //显示的建筑改变
+    setCurrentBuild(val);
+    //父亲的buildId改变
+    changeBuildId && changeBuildId(val);
+  }, []);
+
+  const changFloorHandle = useCallback((val) => {
+    setCurrentFloor(val);
+
+    changeFloorId && changeFloorId(val);
+  }, []);
+
+  //当前切换导航条时
+  const itemClick = (item: navigatorItem) => {
+    //console.log('itemclick', item);
+    navigatorChange && navigatorChange(item);
+  };
+
+  return (
+    <div className={styles.topnavigator}>
+      <div className={styles.floor}>
+        <Select
+          options={buildList}
+          placeholder="楼栋"
+          value={currentBuild}
+          onChange={changBuildHandle}
+          size="large"
+          dropdownMatchSelectWidth={true}
+          style={{ width: '100%' }}
+          bordered={false}
+          //   labelInValue={true}
+          // fieldNames={{ label: 'name', value: 'id' }}
+        />
+      </div>
+      <div className={styles.floor}>
+        <Select
+          options={floorList}
+          placeholder="楼层"
+          value={currentFloor}
+          onChange={changFloorHandle}
+          size="large"
+          dropdownMatchSelectWidth={true}
+          style={{ width: '100%' }}
+          bordered={false}
+        />
+      </div>
+      <div className={styles.navigator}>
+        {navigatorList.map((item, index) => {
+          return (
+            <div
+              className={cx(styles.navItem, { [styles.sel]: item.id === selParamObj.id })}
+              style={{
+                borderBottom:
+                  item.id === selParamObj.id ? `3px solid  ${item.color}` : '3px solid #ffffff',
+              }}
+              key={'nav' + index}
+              onClick={() => {
+                itemClick(item);
+              }}
+            >
+              <img src={item.src} style={{ height: 20 }}></img>
+              <div className={styles.text}>{item.name}</div>
+            </div>
+          );
+        })}
+      </div>
+      {type === 'enviroment' && (
+        <div className={styles.right}>
+          <div className={styles.firstLine} style={{ color: selParamObj.color }}>
+            <span className={styles.value}>{selParamObj.avgValues}</span>{' '}
+            <span className={styles.unit}>{selParamObj.unit}</span>
+          </div>
+          <div className={styles.text}>当前楼层平均{selParamObj.name}</div>
+        </div>
+      )}
+      {type === 'equipment' && action}
+      {type === 'runtime' && action}
+    </div>
+  );
+};
+
+export default TopNavigator;