123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757 |
- import React, { useState, useEffect, useRef, useCallback } from 'react';
- import { FormattedMessage, useModel } from 'umi';
- import SearchInput from '@/sagacare_components/SearchInput';
- import PageHeader from '@/sagacare_components/PageHeader';
- import Map from '@/sagacare_components/map';
- import TopNavigator from '@/sagacare_components/topNavigator';
- import TopNavRight from './components/topNavRight';
- import DeviceModal from './components/deviceModal';
- import styles from './index.less';
- import mapstyles from '@/sagacare_components/map/index.less';
- import cx from 'classnames';
- import { Spin, Modal, message } from 'antd';
- import moment from 'moment';
- import { getMaxScale } from '@/hooks/useMap';
- import { ExclamationCircleOutlined } from '@ant-design/icons';
- import { equipImageMap } from '@/config/sagacare/sagacare_image.js';
- import Icon from '@/tenants-ui/SgIcon';
- import type { navigatorItem } from '@/pages/Environment/index';
- import { projectObj } from '@/config/api.js';
- import {
- getMapList,
- queryEquipStatistics,
- queryDeviceTimeManage,
- queryProjectEquipType,
- } from '@/services/sagacare_service/environment';
- import {
- changeCurtain,
- changeAir,
- changeLight,
- getLamp,
- getAirInfo,
- } from '@/pages/Equipment/equipmentControl';
- //设备状态
- type equipStatus = {
- equipType: string;
- status: number;
- };
- //设备开启数量
- type statistics = {
- equipType: string;
- runCount: number;
- };
- const Environment: React.FC = () => {
- const { hasPersonList, querySpaceAdjustList } = useModel('sagacare_spaceFunc');
- const { changeLastFloorId } = useModel('sagacare_buildFloor');
- const { searchSpace } = useModel('sagacare_searchInfo');
- const { getSpaceFunc } = useModel('sagacare_spaceFunc');
- const { envir_all, equip_air, equip_lamp, envir_curtain } = equipImageMap;
- const [showModal, setShowModal] = useState<boolean>(false);
- const [showSpace, setShowSpace] = useState<API.MapInfo>({}); //当前弹框选中的空间
- const [navigatorList, setNavigatorList] = useState<navigatorItem[]>([
- {
- name: '全部设备',
- id: 'all',
- src: envir_all,
- //color: '#E5574F',
- color: '#E89E32',
- colorStr: '',
- },
- {
- name: '空调',
- id: 'airConditioner',
- src: equip_air,
- num: 0,
- color: '#5E8BCF',
- colorStr: '94,139,207,',
- },
- {
- name: '照明',
- id: 'light',
- src: equip_lamp,
- num: 0,
- color: '#FFE823',
- colorStr: '255,232,35,',
- },
- {
- name: '窗帘',
- id: 'curtain',
- src: envir_curtain,
- num: 0,
- color: '#E89E32',
- colorStr: '232, 158, 50,',
- },
- ]);
- const [scale, setScale] = useState<number>(0.8);
- const [maxScale, setMaxScale] = useState<number>(1);
- const [transXInit, setTransXInit] = useState<number>(0);
- const [mapList, setMapList] = useState<API.MapInfo[]>([]);
- const mapListCopy = useRef<any[]>([]);
- const [mapSize, setMapSize] = useState<any>({});
- const [equipMapList, setEquipMapList] = useState<any[]>([]);
- const [timeMapList, setTimeMapList] = useState<any[]>([]);
- const [selNav, setSelNav] = useState<navigatorItem>(navigatorList[0]);
- const [selFloorId, setSelFloorId] = useState<string>();
- const [mapCombineList, setMapCombineList] = useState<any[]>([]);
- const [loading, setLoading] = useState<boolean>(false);
- const changeFloorId = (data: string) => {
- //debugger;
- setSelFloorId(data);
- };
- //导航条切换
- const navigatorChange = (item: navigatorItem) => {
- setSelNav(item);
- };
- const showModalClick = (item) => {
- // console.log('showChart', item);
- setShowModal(true);
- setShowSpace(item);
- };
- //当前设备的状态 all全部开启 part部分开启 close全都关闭 还有类型type 包括airConditioner light curtain
- //根据设备状态返回不同的 颜色
- const getColorOpacity = (value: any, type?: string): string => {
- 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 (selNav.id == 'curtain' || type == 'curtain') {
- if (value == 'noHave') {
- //没有
- return 'rgba(196, 196, 196, 0)';
- } else {
- return 'rgba(' + colorStr + '1)';
- }
- } else {
- if (value === 2) {
- //2 是部分开启
- return 'rgba(' + colorStr + '0.4)';
- } else if (value === 1) {
- //1 是开启
- return 'rgba(' + colorStr + '1)';
- } else if (value === 0 || value == 'nostatus') {
- //0是关闭
- return 'rgba(196, 196, 196, 0.6)';
- }
- }
- };
- const { confirm } = Modal;
- //单个空间的点击事情
- const spaceControl = (item, index: number) => {
- //全部设备 或者没有房间类型 则不可以点击
- if (selNav.id == 'all' || !item.canClick) return;
- //没有设备时
- if (item[selNav.id] == 'noHave') return;
- if (item[selNav.id] == 'nostatus') {
- message.success('该空间设备离线');
- return;
- }
- if (item[selNav.id] === 2) {
- //半开时
- confirm({
- title: '请确认',
- icon: <ExclamationCircleOutlined />,
- content: `是否进入单空间进行调节?`,
- okText: '确认',
- cancelText: '取消',
- onOk() {
- showModalClick(item);
- },
- onCancel() {
- //console.log('Cancel');
- },
- });
- return;
- }
- var status = item[selNav.id] === 1 ? '关闭' : '打开';
- confirm({
- title: '请确认',
- icon: <ExclamationCircleOutlined />,
- content: `确认${status}该${selNav.name}吗?`,
- okText: '确认',
- cancelText: '取消',
- onOk() {
- //现在加上循环调用 所以把手动去了
- function callback() {
- //这是在手动改变状态
- // var mapCopy = JSON.parse(JSON.stringify(mapCombineList));
- // mapCopy[index][selNav.id] = item[selNav.id] === 1 ? 0 : 1;
- // setMapCombineList(mapCopy);
- }
- //如果是空调
- if (selNav.id == 'airConditioner') {
- changeAir(item, index, callback);
- }
- if (selNav.id == 'light') {
- changeLight('one', [item], callback, status);
- }
- if (selNav.id == 'curtain') {
- changeCurtain('one', [item], callback, status);
- }
- },
- onCancel() {
- //console.log('Cancel');
- },
- });
- };
- //获取地图 mapList
- useEffect(() => {
- if (selFloorId) {
- getProjectEquipType();
- changeLastFloorId(selFloorId);
- setLoading(true);
- getMapList({
- //floorId: 'Fl11010802593241ec348ecb4148806b9034c8957454',
- floorId: selFloorId,
- })
- .then((res) => {
- setLoading(false);
- var data: API.MapInfo[] = (res.data || {}).spaceList || [];
- var bodyWidth = document.body.offsetWidth;
- var mapWidth = (res.data || {}).width || 800;
- if (mapWidth < bodyWidth) {
- var mscale = 1;
- setTransXInit((bodyWidth - mapWidth) / 2);
- } else {
- var mscale = Number((bodyWidth / mapWidth).toFixed(4));
- setTransXInit(0);
- }
- var mapSize: any = {
- width: mapWidth * mscale,
- height: (res.data || {}).height * mscale,
- };
- setMapSize(mapSize);
- //把地图变成 屏幕大小
- data.forEach((item, index) => {
- item.width = item.width * mscale;
- item.height = item.height * mscale;
- item.left = item.left * mscale;
- item.top = item.top * mscale;
- });
- var maxScaleTemp = getMaxScale(data);
- setMaxScale(maxScaleTemp);
- setMapList(data);
- mapListCopy.current = data;
- //setSelNav(navigatorList[0]); //每当重新请求地图时 让选中导航的默认是第一个
- })
- .catch(() => {
- setLoading(false);
- });
- } else {
- setMapList([]);
- }
- }, [selFloorId]);
- const changeMapList = useCallback(
- (mscale, moveWidth, moveHeight) => {
- setScale(mscale);
- console.log('mscale', mscale);
- var mapListTemp = JSON.parse(JSON.stringify(mapListCopy.current));
- var mapListTemp2 = mapListTemp.map((item, index) => {
- if (index == 0) {
- // console.log('mapListTemp', mscale, item.width, item.width * mscale);
- }
- item.width = item.width * mscale;
- item.height = item.height * mscale;
- item.left = item.left * mscale - moveWidth;
- item.top = item.top * mscale - moveHeight;
- return item;
- });
- setMapList(mapListTemp2);
- },
- [mapListCopy],
- );
- const queryDeviceManage = () => {
- //setLoading(true);
- return queryEquipStatistics({
- floorId: selFloorId,
- projectId: projectObj.projectId,
- })
- .then((res) => {
- // setLoading(false);
- //if (!setTimer.current) return;
- var statistics = res.data.statistics || [];
- //赋值 运行中的设备数量
- navigatorList.forEach(function (nItem) {
- var fres = statistics.filter((sItem: statistics) => {
- return sItem.equipType == nItem.id;
- });
- nItem.num = (fres[0] || {}).runCount;
- });
- setNavigatorList(navigatorList);
- //设备空间信息
- var spaceList = res.data.spaceList || [];
- spaceList.forEach((item: any) => {
- var allType = ['airConditioner', 'light', 'curtain'];
- allType.forEach((etype) => {
- var filterEquip = (item.equipList || []).filter((eItem: any) => {
- return eItem.equipType == etype;
- });
- //有当前设备
- if (filterEquip.length > 0) {
- item.equipStatusList = item.equipStatusList ? item.equipStatusList : [];
- var filterRes = (item.equipStatusList || []).filter((eItem: equipStatus) => {
- return eItem.equipType == etype;
- });
- //不存时 赋值not 如果没有设备状态 则说明没有设备 1 是开启 0是关闭
- if (filterRes.length > 0) {
- item[etype] = filterRes[0].status;
- } else {
- item[etype] = 'nostatus';
- item.equipStatusList.push({
- equipType: etype,
- status: 'nostatus',
- });
- }
- } else {
- item[etype] = 'noHave';
- }
- });
- });
- //console.log('spaceList', spaceList);
- //debugger;
- setEquipMapList(spaceList);
- return 'next';
- })
- .catch(() => {
- // setLoading(false);
- });
- };
- let setTimer1 = useRef();
- let setTimer2 = useRef();
- async function getDeviceStatus() {
- await queryDeviceManage().then((res) => {
- setTimer1.current = setTimeout(() => {
- getDeviceStatus();
- }, 8000);
- });
- }
- function getProjectEquipType() {
- // 项目拥有的设备
- return queryProjectEquipType().then((res) => {
- const resData = res.data || [];
- const copynNavigatorList = JSON.parse(JSON.stringify(navigatorList));
- copynNavigatorList.map((item: any, idx: any) => {
- if (idx === 0) return; // 第一个为全部设备,不参与对比
- let hasEquip = false; // 没有此设备
- resData.map((resItem: any) => {
- if (item.id === resItem) {
- hasEquip = true;
- }
- });
- if (!hasEquip) {
- navigatorList.splice(idx, 1);
- setNavigatorList(navigatorList);
- }
- });
- console.log(navigatorList, '-----navigatorList');
- });
- }
- function getSpaceHasPerson(sfId: any) {
- //获取有人无人
- querySpaceAdjustList(sfId).then((res) => {
- //debugger;
- setTimer2.current = setTimeout(() => {
- getSpaceHasPerson(sfId);
- }, 8000);
- });
- }
- //获取设备状态 设备种类
- useEffect(() => {
- if (selFloorId) {
- getDeviceStatus();
- getSpaceHasPerson(selFloorId);
- // queryDeviceManage(); //第一次执行
- // if (setTimer.current) {
- // clearInterval(setTimer.current);
- // setTimer.current = null;
- // }
- // //循环调接口
- // setTimer.current = setInterval(() => {
- // queryDeviceManage();
- // }, 3000);
- }
- return () => {
- //clearInterval(setTimer.current);
- clearTimeout(setTimer1.current);
- clearTimeout(setTimer2.current);
- };
- }, [selFloorId]);
- // useEffect(() => {
- // if (selFloorId) {
- // querySpaceAdjustList(selFloorId);
- // }
- // }, [selFloorId]);
- //获取时间列表 spaceTimeList
- useEffect(() => {
- if (selFloorId) {
- //setLoading(true);
- queryDeviceTimeManage({
- floorId: selFloorId,
- //floorId: 'Fl11010802593241ec348ecb4148806b9034c8957454',
- date: moment().format('YYYYMMDD'),
- })
- .then(function (res) {
- // setLoading(false);
- var resList = res.content || [];
- setTimeMapList(resList);
- })
- .catch(() => {
- // setLoading(false);
- });
- }
- }, [selFloorId]);
- //合并空间设备数据 和 空间数据
- useEffect(() => {
- var combineList: any = [];
- mapList.map(function (mitem) {
- var spaceId = mitem.spaceId;
- var filterSpace1 = equipMapList.filter((ele) => {
- return ele.id == spaceId;
- });
- var filterSpace2 = timeMapList.filter((ele) => {
- return ele.id == spaceId;
- });
- var filterSpace3 = hasPersonList.filter((ele) => {
- return ele.id == spaceId;
- });
- var combine = Object.assign({}, filterSpace3[0], filterSpace1[0], filterSpace2[0], mitem);
- combineList.push(combine);
- });
- setMapCombineList(combineList);
- console.log('combine');
- }, [equipMapList, mapList, timeMapList, hasPersonList]);
- let firtTime: number = 0;
- let lastTime: number = 0;
- return (
- <>
- <PageHeader title={<FormattedMessage id="menu.equipment" />} action={<SearchInput />} />
- <TopNavigator
- navigatorList={navigatorList}
- type={'equipment'}
- navigatorChange={navigatorChange}
- action={
- <TopNavRight
- selNavObj={selNav}
- navigatorList={navigatorList}
- mapList={mapCombineList}
- queryDeviceManage={queryDeviceManage}
- ></TopNavRight>
- }
- changeFloorId={changeFloorId}
- selParamObj={selNav}
- ></TopNavigator>
- <div className={styles.maptop}>
- {selNav.id !== 'all' && selNav.id !== 'curtain' && (
- <div className={styles.left}>
- <span>
- <Icon
- className=""
- type="youren"
- style={{ color: '#CE9F27', fontWeight: 'bold', fontSize: '9px' }}
- ></Icon>
- 有人
- </span>
- <span>
- <Icon
- className=""
- type="wuren"
- style={{ color: '#8B949E', fontWeight: 'bold', fontSize: '9px' }}
- ></Icon>
- 无人
- </span>
- </div>
- )}
- {selNav.id !== 'all' && selNav.id !== 'curtain' && (
- <div className={styles.right}>
- <div className={styles.rightOpen}>
- <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>
- )}
- {selNav.id == 'curtain' && (
- <div className={styles.right}>
- <div>
- <span
- className={styles.circle}
- style={{ backgroundColor: 'rgba(' + selNav.colorStr + '1)' }}
- ></span>
- <span>有</span>
- </div>
- <div>
- <span className={cx(styles.circle, styles.noCurtain)}></span>
- <span>无</span>
- </div>
- </div>
- )}
- </div>
- <Spin spinning={loading} wrapperClassName={mapstyles.spinnclass}>
- {mapCombineList.length > 0 && (
- <Map
- changeMapList={changeMapList}
- mapList={mapCombineList}
- mapSize={mapSize}
- maxscale={maxScale}
- transXInit={transXInit}
- type={'equipment'}
- selFloorId={selFloorId}
- render={(item, index) => {
- return (
- <div
- className={mapstyles.houseWrap}
- key={index + item.id}
- style={{
- left: item.left,
- top: item.top,
- width: item.width,
- height: item.height,
- }}
- >
- <div
- style={{
- backgroundColor: item.canClick
- ? selNav.id == 'all'
- ? 'rgba(196, 196, 196, 0.4)'
- : getColorOpacity(item[selNav.id])
- : '',
- }}
- className={cx(mapstyles.house, {
- [mapstyles.notclick]: !item.canClick || item[selNav.id] == 'noHave',
- [mapstyles.searchSel]: item.spaceId && item.spaceId === searchSpace.spaceId,
- })}
- onClick={(event) => {
- event.stopPropagation();
- if (lastTime - firtTime < 200) {
- spaceControl(item, index);
- }
- }}
- onMouseDown={(event) => {
- //event.stopPropagation();
- firtTime = new Date().getTime();
- }}
- onMouseUp={(event) => {
- //event.stopPropagation();
- lastTime = new Date().getTime();
- }}
- >
- {/* {selNav.id !== 'all' && item[selNav.id] == 'noHave' && (
- <div className={mapstyles.noDevice}>
- <span className={mapstyles.noText}>无设备</span>
- </div>
- style={{ display: item.width > 80 && item.height > 50 ? 'flex' : 'none' }}
- )} */}
- {selNav.id == 'all' && (
- <div
- className={mapstyles.allDevice}
- style={{
- transform:
- scale == maxScale
- ? 'scale(1)'
- : item.width < 24 * (item.equipStatusList || []).length ||
- item.height < 24
- ? 'scale(0.3)'
- : 'scale(1)',
- }}
- >
- {/* 所有设备的图标列表 */}
- {(item.equipStatusList || []).map((ditem: equipStatus, dindex: number) => {
- return (
- <div
- key={dindex + 'device'}
- className={mapstyles.icon}
- style={{
- backgroundColor: getColorOpacity(ditem.status, ditem.equipType),
- }}
- >
- <Icon
- className=""
- type={ditem.equipType}
- style={{ color: '#fff', fontWeight: 'bold', fontSize: '8px' }}
- ></Icon>
- </div>
- );
- })}
- </div>
- )}
- {(selNav.id == 'airConditioner' || selNav.id == 'light') &&
- item.isPassengerPass &&
- item.canClick && (
- <div
- className={mapstyles.hasPerson}
- style={{
- transform:
- scale == maxScale
- ? 'scale(1)'
- : item.width < 46 || item.height < 25
- ? 'scale(0.4)'
- : 'scale(1)',
- }}
- >
- <Icon
- className=""
- type="youren"
- style={{ color: '#CE9F27', fontWeight: 'bold', fontSize: '9px' }}
- ></Icon>
- </div>
- )}
- {(selNav.id == 'airConditioner' || selNav.id == 'light') &&
- item.isPassengerPass == false &&
- item.canClick && (
- <div
- className={mapstyles.hasPerson}
- style={{
- transform:
- scale == maxScale
- ? 'scale(1)'
- : item.width < 46 || item.height < 25
- ? 'scale(0.4)'
- : 'scale(1)',
- }}
- >
- <Icon
- className=""
- type="wuren"
- style={{ color: '#8B949E', fontWeight: 'bold', fontSize: '9px' }}
- ></Icon>
- </div>
- )}
- {item.canClick && item[selNav.id] != 'noHave' && (
- <div
- className={mapstyles.showModal}
- onClick={(event) => {
- event.stopPropagation();
- if (lastTime - firtTime < 400) {
- showModalClick(item);
- }
- }}
- onMouseDown={(event) => {
- //event.stopPropagation();
- firtTime = new Date().getTime();
- }}
- onMouseUp={(event) => {
- //event.stopPropagation();
- lastTime = new Date().getTime();
- }}
- style={{
- transform: `scale(${scale - 0.1 < 1 ? scale - 0.1 : 1})`,
- }}
- >
- <Icon className="" type="hover" style={{ fontSize: '10px' }}></Icon>
- </div>
- )}
- <div className={mapstyles.content}>
- <Icon
- className=""
- type={getSpaceFunc(item.roomFuncType)}
- style={{
- fontSize: 18,
- display: item.width > 28 && item.height > 50 ? 'block' : 'none',
- }}
- ></Icon>
- <div
- className={mapstyles.name}
- style={{
- display:
- (item.width > 64 && item.height > 80) ||
- item.height > 140 ||
- item.width > 120 ||
- scale == maxScale
- ? 'block'
- : 'none',
- }}
- >
- {item.localName}
- </div>
- {(getSpaceFunc(item.roomFuncType) || item.localName) &&
- !(
- (getSpaceFunc(item.roomFuncType) &&
- item.width > 28 &&
- item.height > 50) ||
- (item.localName &&
- ((item.width > 64 && item.height > 80) ||
- item.height > 140 ||
- item.width > 120 ||
- scale == maxScale))
- ) && <div className={mapstyles.pointer}>.</div>}
- </div>
- </div>
- </div>
- );
- }}
- ></Map>
- )}
- </Spin>
- {showModal && (
- <DeviceModal
- showSpace={showSpace}
- onClose={() => {
- setShowModal(false);
- }}
- ></DeviceModal>
- )}
- </>
- );
- };
- export default Environment;
|