Commit 302f9e28 authored by 叶飞's avatar 叶飞

feat: notice

parent 175a10ee
......@@ -23,8 +23,7 @@ class HttpRequest {
// }
// ------------------------------------------------------------------------------------
if (!config.ignoreSite && this.getSite()) {
// config.headers['civ-site'] = this.getSite();
config.headers['civ-site'] = "192_168_19_105_site_c8de50fc";
config.headers['civ-site'] = this.getSite();
}
this.removePending(config); //在一个ajax发送前执行一下取消操作
config.cancelToken = new cancelToken(c => {
......
......@@ -8,8 +8,6 @@ const API = {
GET_USER_INFO: '/CityInterface/rest/services.svc/getUserInfo',
GET_OA: '/CityInterface/rest/services/OA.svc/getLoginInfo',
GET_LOGS: '/CityInterface/rest/services/portal.svc/OMMonitor/SaveLoginInfo',
GET_INFORMATION:'/CityInterface/rest/services/CountyProduct.svc/SCADAOper/GetInformationInfo',
GET_MQTT_SITE_CODE:'/CityInterface/rest/services/CountyProduct.svc/SCADAOper/getMqttSitecode',
GET_CITY: 'https://pv.sohu.com/cityjson?ie=utf-8',
GET_ALL_GROUPS_INFO_FORUSER:
'CityInterface/rest/Services/Portal.svc/AuthorityManage/GetAllGroupsInfoForUser',
......@@ -35,12 +33,6 @@ export default vm => {
vm.writeLogs = (data = {}, config = {}) =>
vm.post(API.GET_LOGS, data, config).then(res => Promise.resolve(res));
vm.getInformationInfo = (data = {}) =>
vm.get(API.GET_INFORMATION, data).then(res => Promise.resolve(res));
vm.getMqttSiteCode = (data = {}) =>
vm.get(API.GET_MQTT_SITE_CODE, data).then(res => Promise.resolve(res));
vm.getCity = () => vm.get(API.GET_CITY).then(res => Promise.resolve(res));
vm.generateTokenQuick = (data = {}) =>
......
import http from './apiConfig';
import BaseService from './baseService';
import NotificationService from './notificationService';
BaseService(http);
NotificationService(http);
export default http
import { params } from 'kit_utils';
import qs from 'qs';
const API = {
GET_INFORMATION:
'/CityInterface/rest/services/CountyProduct.svc/SCADAOper/GetInformationInfo',
GET_MQTT_SITE_CODE:
'/CityInterface/rest/services/CountyProduct.svc/SCADAOper/getMqttSitecode',
POST_INFORMATION_STATUS:
'/CityInterface/rest/services/CountyProduct.svc/SCADAOper/PostInformationStatus',
};
export default vm => {
vm.getInformationInfo = (data = {}) =>
vm.get(API.GET_INFORMATION, data).then(res => Promise.resolve(res));
vm.getMqttSiteCode = (data = {}) =>
vm.get(API.GET_MQTT_SITE_CODE, data).then(res => Promise.resolve(res));
vm.postInformationStatus = (params = {}) =>{
let paramsStr=qs.stringify(params, { arrayFormat: 'brackets' });
return vm.post(API.POST_INFORMATION_STATUS+"?"+paramsStr).then(res => Promise.resolve(res));
}
};
......@@ -9,19 +9,25 @@ import styles from './index.less';
import Notifier, {NEW_MESSAGE} from '../Notifier';
class NoticeIconView extends Component {
state = {
constructor(props){
super(props);
this.state = {
count: 0,
noticeData: [],
};
this.notifier = new Notifier(this.props.global.userInfo);
}
async componentDidMount() {
let notifier = new Notifier(this.props.global.userInfo);
notifier.subscribe("NEW_MESSAGE",this.onNewMessage.bind(this));
notifier.start();
this.notifier.subscribe(NEW_MESSAGE,this.onNewMessage.bind(this));
this.notifier.start();
}
componentWillUnmount(){
this.notifier && this.notifier.stop();
}
onNewMessage = messages => {
debugger;
this.setState({
count:messages.totalCount,
noticeData:messages.messages
......@@ -84,13 +90,12 @@ class NoticeIconView extends Component {
return (
<NoticeIcon
className={styles.action}
count={this.state.count > 99 ? 99 : this.state.count}
count={this.state.count}
onItemClick={item => {
this.changeReadState(item);
}}
loading={fetchingNotices}
clearText="清空"
viewMoreText="查看更多"
confirmRead={this.notifier.confirmRead.bind(this.notifier)}
onClear={this.handleNoticeClear}
onPopupVisibleChange={onNoticeVisibleChange}
onViewMore={() => message.info('Click on view more')}
......@@ -102,6 +107,7 @@ class NoticeIconView extends Component {
title="通知"
emptyText="你已查看所有通知"
showViewMore
confirmRead={this.notifier.confirmRead.bind(this.notifier)}
/>
</NoticeIcon>
);
......
import { Button, Result } from 'antd';
import React from 'react';
const NoFoundPage = (props) => {
return (
<Result
status="404"
title="404"
subTitle="Sorry, the page you visited does not exist."
extra={
<Button type="primary" onClick={() => {props.history.push('/civbase')}}>
Back Home
</Button>
}
/>
)
};
export default NoFoundPage;
import React from 'react';
import {
Avatar,
List,
} from 'antd';
import { Avatar, List } from 'antd';
import classNames from 'classnames';
import styles from './NoticeList.less';
import Alarm from './Templates/Alarm';
import Case from './Templates/Case';
import Notice from './Templates/Notice';
import Unknown from './Templates/Unknown';
const NoticeList = ({
data = [],
onClick,
onClear,
title,
onViewMore,
emptyText,
showClear = true,
clearText,
viewMoreText,
showViewMore = false,
}) => {
if (!data || data.length === 0) {
return (
const Empty = ({ emptyText }) => (
<div className={styles.notFound}>
<img
src="https://gw.alipayobjects.com/zos/rmsportal/sAuJeJzSKbUmHfBQRzmZ.svg"
......@@ -29,9 +16,12 @@ const NoticeList = ({
/>
<div>{emptyText}</div>
</div>
);
}
);
const NoticeList = ({ data = [], onGoToWidget, emptyText, confirmRead }) => {
if (!data || data.length === 0) {
return <Empty emptyText={emptyText} />;
}
return (
<div>
<List
......@@ -41,65 +31,37 @@ const NoticeList = ({
const itemCls = classNames(styles.item, {
[styles.read]: item.read,
});
// eslint-disable-next-line no-nested-ternary
const leftIcon = item.avatar ? (
typeof item.avatar === 'string' ? (
<Avatar className={styles.avatar} src={item.avatar} />
) : (
<span className={styles.iconElement}>{item.avatar}</span>
)
) : null;
const content = item.InfoContent.replace('\n', '');
console.log(content);
return (
<List.Item
className={itemCls}
key={item.key || i}
onClick={() => onClick && onClick(item)}
>
<List.Item.Meta
className={styles.meta}
avatar={leftIcon}
title={
<div className={styles.title}>
{item.title}
<div
className={styles.extra}
dangerouslySetInnerHTML={{
__html: content,
}}
/>
</div>
}
description={
<div>
<div className={styles.description}>{item.description}</div>
<div className={styles.datetime}>{item.datetime}</div>
</div>
let messageTemplate = <></>;
switch (item.infoType) {
case 'scadaType':
messageTemplate = (
<Alarm message={item} confirmRead={confirmRead} />
);
break;
case 'caseType':
messageTemplate = (
<Case message={item} confirmRead={confirmRead} />
);
break;
case 'sysType':
messageTemplate = (
<Notice message={item} confirmRead={confirmRead} />
);
break;
default:
messageTemplate = (
<Unknown message={item} confirmRead={confirmRead} />
);
break;
}
/>
return (
<List.Item className={itemCls} key={item.id || i}>
{messageTemplate}
</List.Item>
);
}}
/>
<div className={styles.bottomBar}>
{showClear ? (
<div onClick={onClear}>
{clearText} {title}
</div>
) : null}
{showViewMore ? (
<div
onClick={e => {
if (onViewMore) {
onViewMore(e);
}
}}
>
{viewMoreText}
</div>
) : null}
</div>
<div className={styles.bottomBar}>下拉加载更多</div>
</div>
);
};
......
......@@ -7,63 +7,19 @@
display: none;
}
.item {
padding-right: 24px;
padding-left: 24px;
overflow: hidden;
cursor: pointer;
transition: all 0.3s;
.meta {
width: 100%;
}
.avatar {
margin-top: 4px;
background: @component-background;
}
.iconElement {
font-size: 32px;
}
&.read {
opacity: 0.4;
&:hover {
background-color: @primary-1;
}
&:last-child {
border-bottom: 0;
}
&:hover {
background: @primary-1;
}
.title {
margin-bottom: 8px;
font-weight: normal;
}
.description {
font-size: 12px;
line-height: @line-height-base;
}
.datetime {
margin-top: 4px;
font-size: 12px;
line-height: @line-height-base;
}
.extra {
float: right;
margin-top: -1.5px;
margin-right: 0;
color: @text-color-secondary;
font-weight: normal;
}
}
.loadMore {
padding: 8px 0;
color: @primary-6;
text-align: center;
cursor: pointer;
&.loadedAll {
color: rgba(0, 0, 0, 0.25);
cursor: unset;
}
}
}
......
import React from 'react';
import styles from './index.less';
import commonStyles from '../common.less';
import classNames from 'classnames';
import { useHistory } from 'react-router-dom';
export class AlarmContent {
constructor({
alarmType,
deviceCode,
alarmDevice,
alarmContent,
alarmValue,
alarmThreshold,
time,
} = content) {
this.alarmType = alarmType;
this.deviceCode = deviceCode;
this.alarmDevice = alarmDevice;
this.alarmContent = alarmContent;
this.alarmValue = alarmValue;
this.alarmThreshold = alarmThreshold;
this.time = time;
}
}
const Alarm = ({ message, confirmRead }) => {
let alarmContent = message.infoContent;
const history = useHistory();
const goPath = (item) => {
confirmRead(false,[message.id]);
let path= item.webPath ? `/civweb4/${item.webPath}` : `/civweb4/product/scada/AlertMonitoring/AlertMonitoring`
history.push(path);
}
return (
<div className={classNames(styles.scada,commonStyles.messageContainer) } title="点击查看详情" onClick={()=> goPath(message)}>
<div className={commonStyles.title}>
<span>消息</span>
<img
className={commonStyles.confirm}
title="点击标为已读"
onClick={() => {
confirmRead(false,[message.id]);
}}
src="https://panda-water.cn/Web4/assets/images/message/%E5%8B%BE%E6%B5%85.png"
/>
</div>
<div className={commonStyles.content}>
<p>
<i>{alarmContent.alarmType}</i>
{alarmContent.alarmDevice}
</p>
<p>{alarmContent.alarmContent}</p>
<p>
<font style={{ color: '#ff0000' }} title="点击查看详情">
{alarmContent.alarmValue.split(' ')[0]}
</font>
{alarmContent.alarmValue.split(' ')[1] +
' / ' +
alarmContent.alarmThreshold.split(' ').join('')}
</p>
<p className={commonStyles.messageTime}>{message.time}</p>
</div>
</div>
);
};
export default Alarm;
.scada {
background: url(https://panda-water.cn/Web4/assets/images/message/%E6%B6%88%E6%81%AF.png)
16px 10px no-repeat;
}
import React from 'react';
import styles from './index.less';
import commonStyles from '../common.less';
import classNames from 'classnames';
import { useHistory } from 'react-router-dom';
//"caseType":"待办工单","flowName":"维修处理流程","nodeName":"审核关单","content":"请迅速到现场处理","time":"2020-11-03 09:11:12"
export class CaseContent {
constructor({
caseType,
flowName,
nodeName,
content,
time
} = content) {
this.caseType = caseType;
this.flowName = flowName;
this.nodeName = nodeName;
this.content = content;
this.time = time;
}
}
const Case = ({ message, confirmRead }) => {
let caseContent = message.infoContent;
const history = useHistory();
const goPath = (item) => {
confirmRead(false,[message.id]);
let path= item.webPath ? `/civweb4/${item.webPath}` : `/civweb4/product/maintenance/CaseManage/CaseDoingBox/StardCaseDoingBoxView|isDelay=1`
history.push(path);
}
return (
<div className={classNames(styles.case,commonStyles.messageContainer)} title="点击查看详情" onClick={()=> goPath(message)}>
<div className={commonStyles.title}>
<span>消息</span>
<img
className={commonStyles.confirm}
title="点击标为已读"
onClick={() => {
confirmRead(false,[message.id]);
}}
src="https://panda-water.cn/Web4/assets/images/message/%E5%8B%BE%E6%B5%85.png"
/>
</div>
<div className={commonStyles.content}>
<p>
<i>{caseContent.caseType}</i>
{caseContent.flowName}
</p>
<p>{caseContent.nodeName} : {caseContent.content}</p>
<p className={commonStyles.messageTime}>{message.time}</p>
</div>
</div>
);
};
export default Case;
.case {
background: url(https://panda-water.cn/Web4/assets/images/message/%E6%B6%88%E6%81%AF.png)
16px 10px no-repeat;
}
\ No newline at end of file
import React from 'react';
import styles from './index.less';
import commonStyles from '../common.less';
import classNames from 'classnames';
import { useHistory } from 'react-router-dom';
//'平台公告','{"noticeTitle":"光谷智慧园停水","noticeType":"停水公告","noticeContent":"从今天中午20点开始停水,停三个小时!","time":"2020-11-03 09:11:12"
export class NoticeContent {
constructor({
noticeTitle,
noticeType,
noticeContent,
time
} = content) {
this.noticeTitle = noticeTitle;
this.noticeType = noticeType;
this.noticeContent = noticeContent;
this.time = time;
}
}
const Notice = ({ message, confirmRead }) => {
let noticeContent = message.infoContent;
const history = useHistory();
const goPath = (item) => {
confirmRead(false,[message.id]);
let path= item.webPath ? `/civweb4/${item.webPath}` : `/civweb4/product/notification/HistoryNotice/HistoryNotice`
history.push(path);
}
return (
<div className={classNames(styles.notice,commonStyles.messageContainer)} title="点击查看详情" onClick={()=> goPath(message)}>
<div className={commonStyles.title}>
<span>公告</span>
<img
className={commonStyles.confirm}
title="点击标为已读"
onClick={() => {
confirmRead(false,[message.id]);
}}
src="https://panda-water.cn/Web4/assets/images/message/%E5%8B%BE%E6%B5%85.png"
/>
</div>
<div className={commonStyles.content}>
<p>
<i>{noticeContent.noticeType}</i>
{noticeContent.noticeTitle}
</p>
<p>{noticeContent.noticeContent}</p>
<p className={commonStyles.messageTime}>{message.time}</p>
</div>
</div>
);
};
export default Notice;
.notice {
background: url(https://panda-water.cn/Web4/assets/images/message/%E6%B6%88%E6%81%AF.png)
16px 10px no-repeat;
}
\ No newline at end of file
import React from 'react';
import styles from './index.less';
import commonStyles from '../common.less';
import classNames from 'classnames';
const Unknown = ({ message, confirmRead }) => {
let alarmContent = message.infoContent;
return (
<div className={classNames(styles.unknown,commonStyles.messageContainer) } title="点击查看详情">
<div className={commonStyles.title}>
<span>消息</span>
<img
className={commonStyles.confirm}
title="点击标为已读"
onClick={() => {
confirmRead(false,[message.id]);
}}
src="https://panda-water.cn/Web4/assets/images/message/%E5%8B%BE%E6%B5%85.png"
/>
</div>
<div className={commonStyles.content}>
<p>{message.infoContent}</p>
<p className={commonStyles.messageTime}>{message.time}</p>
</div>
</div>
);
};
export default Unknown;
.unknown {
background: url(https://panda-water.cn/Web4/assets/images/message/%E6%B6%88%E6%81%AF.png)
16px 10px no-repeat;
}
.messageContainer {
padding-left: 50px;
padding-right: 20px;
padding-top: 8px;
width: 100%;
.title {
display: flex;
justify-content: space-between;
span {
font-size: 16px;
color: #666;
font-weight: normal;
text-shadow: none;
letter-spacing: 0;
}
.confirm {
margin-right: 20px;
width: 20px;
height: 16px;
}
}
.content {
margin-top: 10px;
p {
i {
font-size: 14px;
text-shadow: none;
color: #000;
font-style: normal;
color: #1ba6f9;
margin-right: 10px;
}
margin-bottom: 5px;
}
.messageTime {
float: right;
margin-right: 30px;
}
}
}
\ No newline at end of file
import React from 'react';
import {
Badge,
Tabs,
} from 'antd';
import { Badge, Tabs } from 'antd';
import classNames from 'classnames';
import { connect } from 'react-redux';
import useMergeValue from 'use-merge-value';
......@@ -13,41 +10,56 @@ import Icon from '@ant-design/icons';
import HeaderDropdown from '../HeaderDropdown';
import styles from './index.less';
import NoticeList from './NoticeList';
import http from '../../api';
const { TabPane } = Tabs;
const messageSvg = () => (
<svg version="1.1" x="0px" y="0px"
width="24px" height="24px" viewBox="0 0 24 24" enable-background="new 0 0 24 24" space="preserve">
<path fill="#5F718C" d="M20.486,16.373l-1.721-2.246v-0.984v-0.352V9.924c0-1.919-0.664-3.698-1.871-5.007
<svg
version="1.1"
x="0px"
y="0px"
width="24px"
height="24px"
viewBox="0 0 24 24"
enable-background="new 0 0 24 24"
space="preserve"
>
<path
fill="#5F718C"
d="M20.486,16.373l-1.721-2.246v-0.984v-0.352V9.924c0-1.919-0.664-3.698-1.871-5.007
c-0.712-0.776-1.57-1.349-2.551-1.705c-0.091-0.514-0.35-0.983-0.737-1.335c-0.879-0.791-2.334-0.791-3.21,0
c-0.394,0.354-0.653,0.823-0.741,1.336C8.676,3.568,7.817,4.14,7.105,4.917C5.899,6.229,5.234,8.008,5.234,9.923l0.005,4.194
l-1.708,2.234c-0.241,0.256-0.372,0.584-0.372,0.932v1.092c0,0.75,0.615,1.357,1.372,1.357H19.47c0.757,0,1.371-0.607,1.371-1.357
v-1.092C20.841,16.936,20.71,16.607,20.486,16.373z M4.899,17.996v1.016l-0.001-2.061l1.628-2.154
c0.227-0.244,0.353-0.561,0.353-0.893v-4.05c0-1.516,0.509-2.914,1.436-3.935c0.459-0.506,1.001-0.895,1.608-1.166
c1.276-0.565,2.883-0.565,4.155,0c0.609,0.273,1.15,0.667,1.608,1.168c0.925,1.021,1.437,2.417,1.437,3.934v2.762v0.338v0.949
c0,0.334,0.123,0.654,0.336,0.875l1.642,2.164l0.013,1.037L4.899,17.996z"/>
<path fill="#5F718C" d="M13.685,20.236c-0.101,0.238-0.248,0.453-0.444,0.631c-0.677,0.617-1.799,0.615-2.473,0.002
c0,0.334,0.123,0.654,0.336,0.875l1.642,2.164l0.013,1.037L4.899,17.996z"
/>
<path
fill="#5F718C"
d="M13.685,20.236c-0.101,0.238-0.248,0.453-0.444,0.631c-0.677,0.617-1.799,0.615-2.473,0.002
c-0.194-0.18-0.344-0.396-0.446-0.633H8.895c0.146,0.627,0.474,1.199,0.955,1.639c0.588,0.543,1.354,0.841,2.158,0.841
c0.801,0,1.566-0.298,2.154-0.837c0.481-0.439,0.808-1.012,0.954-1.641L13.685,20.236z"/>
c0.801,0,1.566-0.298,2.154-0.837c0.481-0.439,0.808-1.012,0.954-1.641L13.685,20.236z"
/>
</svg>
)
const BellOutlined = props => <Icon component={messageSvg} {...props} style={{transform: 'scale(0.88)'}}/>;
);
const BellOutlined = props => <Icon component={messageSvg} {...props} />;
const NoticeIcon = props => {
const getNotificationBox = () => {
const {
children,
loading,
confirmRead,
onClear,
onTabChange,
onItemClick,
onViewMore,
clearText,
viewMoreText,
} = props;
if (!children) {
return null;
}
const panes = [];
React.Children.forEach(children, child => {
if (!child) {
return;
......@@ -66,8 +78,6 @@ const NoticeIcon = props => {
panes.push(
<NoticeList
{...child.props}
clearText={clearText}
viewMoreText={viewMoreText}
data={list}
key={child}
onClear={() => onClear && onClear(title, tabKey)}
......@@ -82,8 +92,8 @@ const NoticeIcon = props => {
return (
<>
<div className={styles.header}>
<span>通知</span>
<span>全部标记已读</span>
<span className={styles.title}>通知</span>
<span onClick={()=>{confirmRead(true)}}>全部标记已读</span>
</div>
{panes}
</>
......@@ -103,6 +113,8 @@ const NoticeIcon = props => {
<span className={classNames(noticeButtonClass, { opened: visible })}>
<Badge
count={props.count}
overflowCount={99}
offset={[-8, 8]}
style={{ boxShadow: 'none' }}
className={styles.badge}
>
......
......@@ -39,10 +39,17 @@
padding: 8px;
display: flex;
justify-content: space-between;
.title{
font-size: 16px;
font-weight: bold;
margin-left: 5px;
color: rgb(102,102,102);
}
span {
&:last-child {
cursor: pointer;
color: @primary-color;
font-size: 12px;
}
}
}
\ No newline at end of file
import MqttClient from './mqttws31';
import mock from './mock.json';
export const NEW_MESSAGE = 'NEW_MESSAGE';
export class Message {
constructor() {
this.CreateTime,
this.HisCreateTime,
this.HisID,
this.ID,
this.InfoContent,
this.InfoDist,
this.InfoLevel,
this.InfoType,
this.IsRead,
this.MessType,
this.ToUsers,
this.UserID,
this.app_config,
this.app_path,
this.web_config,
this.web_path,
this.time;
constructor({
id,
infoContent,
infoLevel,
time,
infoType,
dateTime,
webConfig,
webPath,
messType,
} = message) {
this.id = id;
this.infoContent = infoContent;
this.infoLevel = infoLevel;
this.time = time;
this.infoType = infoType; // 方案类型 - 工单 报警 公告 定时推送
this.dateTime = dateTime;
this.webConfig = webConfig;
this.webPath = webPath;
this.messType = messType; //方案名称 - 大类型下细类型
}
}
class Notifier {
constructor(userInfo) {
// this.userInfo=userInfo;
this.userInfo = {
site: '192_168_19_105_site_c8de50fc',
OID: 5,
};
this.userInfo = userInfo;
this.messageCache = {
totalCount: 0,
messages: [],
......@@ -60,12 +57,15 @@ class Notifier {
// 对外接口
async start() {
this._getMqttSiteCode().then(() => {
this.loadHisMessages({ userID: this.userInfo.OID });
this.connectMQTTServer();
});
}
stop() {
this.disconnectMQTTServer();
}
subscribe(type, handler) {
if (!(type in this._subscribers)) {
this._subscribers[type] = [];
......@@ -102,9 +102,49 @@ class Notifier {
});
}
confirmRead(isAll = false, hisIDs = []) {
let list = [];
if (
this.messageCache &&
this.messageCache.totalCount == 0 &&
this.messageCache.messages.length == 0
)
return;
if (isAll) hisIDs = this.messageCache.messages.map(item => item.id);
let me = this;
Http.postInformationStatus({
userID: this.userInfo.OID,
hisID: hisIDs.join(','),
isAll: isAll ? 1 : '',
})
.then(res => {
if (res.statusCode != '0000') {
console.log(res.errMsg);
return;
}
if (isAll) {
me.messageCache.totalCount = 0;
me.messageCache.messages = [];
} else {
hisIDs.forEach(id => {
let index = me.messageCache.messages.findIndex(
item => item.id == id,
);
if (index != -1) {
me.messageCache.messages.splice(index, 1);
me.messageCache.totalCount--;
}
});
}
me.publish(NEW_MESSAGE, me.messageCache);
})
.catch(err => {
console.log('postInformationStatus调用失败' + err);
});
}
// mqtt
async connectMQTTServer() {
this._getMqttSiteCode().then(() => {
let hostname = this._siteConfig.TcpIP,
port = this._siteConfig.TcpPort,
clientId = 'client-' + this._createGuid(),
......@@ -132,13 +172,13 @@ class Notifier {
password: password,
onSuccess: this.onMQTTConnect.bind(this),
onFailure: function(e) {
debugger;
console.log(e);
},
};
this.MQTTClient.connect(this.MQTTOptions);
this.MQTTClient.onConnectionLost = this.onMQTTConnectionLost.bind(this);
this.MQTTClient.onMessageArrived = this.onMessageArrived.bind(this);
});
}
disconnectMQTTServer() {
if (this.MQTTClient) {
......@@ -169,7 +209,7 @@ class Notifier {
this.MQTTClient.subscribe(UserTopic);
}
onMQTTConnectionLost(responseObject) {
debugger;
console.log('连接丢失', responseObject);
var me = this;
if (this.IsNeedReconnect) {
this.MQTTClient.connect(me.MQTTOptions);
......@@ -182,12 +222,12 @@ class Notifier {
}, 1000);
}
}
onMessageArrived(message) {
onMessageArrived(buffer) {
let me = this;
try {
console.log('收到消息:' + message.payloadString);
let temp = JSON.parse(message.payloadString);
let infoType = this._typeInfo(temp);
console.log('收到消息:' + buffer.payloadString);
let temp = JSON.parse(buffer.payloadString);
let infoType = this._typeInfo(temp.infoType);
if (
temp.tousers == '' ||
me.userInfo.OID == temp.tousers ||
......@@ -195,12 +235,6 @@ class Notifier {
temp.tousers.includes(',' + me.userInfo.OID)
) {
let messContent = temp.content;
if (
me._siteConfig.MessageLevel &&
me._siteConfig.MessageLevel == '2.0'
) {
messContent = me._messageThrome(infoType, JSON.parse(temp.content));
}
let timeH = (new Date() - new Date(temp.createTime)) / 1000 / 60;
let timeMss =
Math.abs(timeH) > 1440
......@@ -211,24 +245,29 @@ class Notifier {
? timeH.toFixed(0) + '分钟前'
: '刚刚';
let messString = {
ID: temp.infoId,
Info: messContent,
InfoLevel: temp.level,
id: temp.ID,
infoContent: messContent,
infoLevel: temp.level,
time: `${timeMss}`,
infoType: infoType,
messageType: '',
dateTime: temp.createTime,
web_config: temp.web_config,
web_path: temp.web_path,
webConfig: temp.web_config,
webPath: temp.web_path,
messType: temp.MessType,
};
let message = me._handleMqttToMessage(messString);
if (this._IsVersion1())
messString.infoContent = this._handleMessageStrToJSON(
infoType,
messString,
);
else messString.infoContent = JSON.parse(messString.content);
let message = new Message(messString);
this.messageCache.totalCount += 1;
this.messageCache.messages.push(message);
me.publish(NEW_MESSAGE, this.messageCache);
}
} catch (e) {
console.log('收到消息处理异常:'+e.message);
console.log('收到消息处理异常:' + e.message);
}
}
......@@ -243,7 +282,7 @@ class Notifier {
}).then(res => {
let result = {
totalCount: res.totalRcdNum,
messages: res.getMe.map(this._handleHisToMessage),
messages: res.getMe.map(this._handleHisToMessage.bind(this)),
};
this.messageCache.totalCount += result.totalCount;
this.messageCache.messages.push(...result.messages);
......@@ -294,9 +333,9 @@ class Notifier {
})
.toUpperCase();
}
_typeInfo(temp) {
var infoType = 'scadaType';
switch (temp.infoType) {
_typeInfo(infoTypeStr) {
var infoType = 'unknown';
switch (infoTypeStr) {
case '工单流程':
infoType = 'caseType';
break;
......@@ -313,63 +352,110 @@ class Notifier {
case '消息提醒':
infoType = 'remindType';
break;
case 'SCADA报警':
infoType = 'scadaType';
default:
break;
}
return infoType;
}
_messageThrome(themeName, info) {
var messInfo = '';
switch (themeName) {
case 'caseType':
case '工单提醒':
messInfo = `【${info.caseType}${info.flowName}\\n${
info.nodeName
}\\n承办意见:${info.content}`;
break;
_handleHisToMessage(hisMessage) {
var timeH = (new Date() - new Date(hisMessage.HisCreateTime)) / 1000 / 60;
var timeMss =
Math.abs(timeH) > 1440
? hisMessage.HisCreateTime.split('.')[0]
: Math.abs(timeH) > 60
? (timeH / 60).toFixed(0) + '小时前'
: Math.abs(timeH) > 1
? timeH.toFixed(0) + '分钟前'
: '刚刚';
let message = {
id: hisMessage.HisID,
infoContent: hisMessage.InfoContent,
time: `${timeMss}`,
infoType: this._typeInfo(hisMessage.InfoType),
dateTime: hisMessage.HisCreateTime,
infoLevel: hisMessage.InfoLevel,
webConfig: hisMessage.web_config,
webPath: hisMessage.web_path,
messType: hisMessage.MessType,
};
if (this._IsVersion1())
message.infoContent = this._handleMessageStrToJSON(
message.infoType,
message,
);
else message.infoContent = JSON.parse(message.infoContent);
return new Message(message);
}
// 1.0 解析规则
_IsVersion1() {
return (
!this._siteConfig.MessageLevel || this._siteConfig.MessageLevel != '2.0'
);
}
_handleMessageStrToJSON(infoType, messString) {
let infoContent = messString;
switch (infoType) {
case 'scadaType':
case '通用报警':
messInfo = `【${info.alarmType}${info.alarmDevice}\\n${
info.alarmContent
}\\n${info.alarmValue} / ${info.alarmThreshold}\\n${info.deviceCode}`;
infoContent = this._analysisAlarm(messString);
break;
case 'caseType':
infoContent = this._analysisCase(messString);
break;
case 'sysType':
case '系统通知':
messInfo = `【${info.noticeType}${info.noticeTitle}\\n${
info.noticeContent
}`;
infoContent = this._analysisNotice(messString);
break;
case 'saveWaType':
break;
case 'EIMType':
break;
// case "remindType": case "remindType":
// messInfo = ``;
// break;
default:
break;
}
return messInfo;
return infoContent;
}
_handleHisToMessage(hisMessage) {
let message = new Message();
message = {
...hisMessage,
...{
ToUsers: hisMessage.Tousers,
},
_analysisCase(messString) {
let attr = messString.infoContent.split('\\n');
let caseContent = {
caseType: attr[0].split('】')[0].split('【')[1],
flowName: attr[0].split('】')[1],
nodeName: attr[1],
content: attr[2],
time: messString.dateTime,
};
return caseContent;
}
_analysisAlarm(messString) {
let attr = messString.infoContent.split('\\n');
let alarmContent = {
alarmType: attr[0].split('】')[0].split('【')[1],
deviceCode: '',
alarmDevice: attr[0].split('】')[1],
alarmContent: attr[1],
alarmThreshold: attr[2].includes(' / ')
? attr[2].split('/')[1].trim(' ')
: '',
alarmValue: attr[2].includes(' / ')
? attr[2].split('/')[0].trim(' ')
: attr[2].includes(':')
? attr[2].split(':')[1]
: '',
time: messString.dateTime,
};
return alarmContent;
}
_analysisNotice(messString) {
let attr = messString.infoContent.split('\\n');
let noticeContent = {
noticeType: attr[0].split('】')[0].split('【')[1],
noticeTitle: attr[0].split('】')[1],
noticeContent: attr[1],
time: messString.dateTime,
};
delete message['Tousers'];
return message;
}
_handleMqttToMessage(mqttMessage) {
let message = new Message();
message.ID = mqttMessage.ID;
message.InfoContent = mqttMessage.Info;
message.InfoLevel = mqttMessage.InfoLevel;
message.time = mqttMessage.time;
message.infoType = mqttMessage.infoType;
message.CreateTime = mqttMessage.dateTime;
message.web_config = mqttMessage.web_config;
message.web_path = mqttMessage.web_path;
message.MessType = mqttMessage.messType;
return message;
return noticeContent;
}
}
......
......@@ -3,7 +3,7 @@ import React from 'react';
import { Helmet } from 'react-helmet';
import { connect } from 'react-redux';
import { renderRoutes } from 'react-router-config';
import { BrowserRouter as Router, Switch } from 'react-router-dom';
import { BrowserRouter as Router, Switch,Redirect } from 'react-router-dom';
import { dyRoutes } from '../../routes/config';
......@@ -25,7 +25,11 @@ function App(props) {
/>
</Helmet>
<Router basename="civbase">
<Switch>{renderRoutes(dyRoutes(props.menu || []).routes)}</Switch>
<Switch>
{renderRoutes(dyRoutes(props.menu || []).routes)}
{/* <Redirect to="/notFound" /> */}
</Switch>
</Router>
</>
);
......
......@@ -4,6 +4,7 @@ import BootPage from '../pages/bootpage';
import Login from '../pages/user/login';
export const dyRoutes = routes => {
debugger;
const dyRoutes = routes;
return {
routes: [
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment