Commit 0da354a0 authored by 崔佳豪's avatar 崔佳豪

feat: 添加查看全部历史消息

parent 056f8525
Pipeline #53620 passed with stages
...@@ -110,9 +110,9 @@ ...@@ -110,9 +110,9 @@
"@wisdom-map/arcgismap": "1.4.0-6", "@wisdom-map/arcgismap": "1.4.0-6",
"@wisdom-map/basemap": "1.1.0-2", "@wisdom-map/basemap": "1.1.0-2",
"@wisdom-map/util": "^1.0.27-0", "@wisdom-map/util": "^1.0.27-0",
"@wisdom-utils/components": "0.1.235", "@wisdom-utils/components": "0.1.239",
"@wisdom-utils/runtime": "0.0.32", "@wisdom-utils/runtime": "0.0.32",
"@wisdom-utils/utils": "0.1.275", "@wisdom-utils/utils": "0.1.279",
"animate.css": "^4.1.1", "animate.css": "^4.1.1",
"antd": "^4.20.7", "antd": "^4.20.7",
"compression": "1.7.4", "compression": "1.7.4",
...@@ -145,6 +145,7 @@ ...@@ -145,6 +145,7 @@
"react-helmet": "6.0.0-beta", "react-helmet": "6.0.0-beta",
"react-helmet-async": "^1.0.4", "react-helmet-async": "^1.0.4",
"react-iframe": "^1.8.0", "react-iframe": "^1.8.0",
"react-infinite-scroll-component": "^6.1.0",
"react-intl": "^3.12.1", "react-intl": "^3.12.1",
"react-redux": "7.0.2", "react-redux": "7.0.2",
"react-router-config": "^5.1.1", "react-router-config": "^5.1.1",
......
...@@ -5,13 +5,23 @@ const API = { ...@@ -5,13 +5,23 @@ const API = {
'/CityInterface/rest/services/CountyProduct.svc/SCADAOper/GetInformationInfo', '/CityInterface/rest/services/CountyProduct.svc/SCADAOper/GetInformationInfo',
GET_MQTT_SITE_CODE: GET_MQTT_SITE_CODE:
'/CityInterface/rest/services/CountyProduct.svc/SCADAOper/getMqttSitecode', '/CityInterface/rest/services/CountyProduct.svc/SCADAOper/getMqttSitecode',
GET_ALL_INFORMATION_INFO:
'/PandaWater/CityWater/Notification/GetAllInformationInfo',
POST_INFORMATION_STATUS: POST_INFORMATION_STATUS:
'/CityInterface/rest/services/CountyProduct.svc/SCADAOper/PostInformationStatus', '/PandaWater/CityWater/Notification/PostInformationStatus',
POST_ADD_OPTIONS: POST_ADD_OPTIONS:
'/CityInterface/rest/services/WisdomUnion.svc/CustomerManage/AddOption', '/CityInterface/rest/services/WisdomUnion.svc/CustomerManage/AddOption',
GET_CURRENT_INFO_TYPE:
'PandaWater/CityWater/Notification/GetCurrentInfoType',
}; };
const notificationService = { const notificationService = {
// 获取通知类型列表
getCurrentInfoType: {
url: API.GET_CURRENT_INFO_TYPE,
method: constants.REQUEST_METHOD_GET,
type: constants.REQUEST_HTTP,
},
getInformationInfo: { getInformationInfo: {
url: API.GET_INFORMATION, url: API.GET_INFORMATION,
method: constants.REQUEST_METHOD_GET, method: constants.REQUEST_METHOD_GET,
...@@ -22,9 +32,14 @@ const notificationService = { ...@@ -22,9 +32,14 @@ const notificationService = {
method: constants.REQUEST_METHOD_GET, method: constants.REQUEST_METHOD_GET,
type: constants.REQUEST_HTTP, type: constants.REQUEST_HTTP,
}, },
getAllInformationInfo: {
url: API.GET_ALL_INFORMATION_INFO,
method: constants.REQUEST_METHOD_GET,
type: constants.REQUEST_HTTP,
},
postInformationStatus: { postInformationStatus: {
url: API.POST_INFORMATION_STATUS, url: API.POST_INFORMATION_STATUS,
method: constants.REQUEST_METHOD_POST, method: constants.REQUEST_METHOD_GET,
type: constants.REQUEST_HTTP, type: constants.REQUEST_HTTP,
}, },
postAddOptions: { postAddOptions: {
...@@ -34,12 +49,5 @@ const notificationService = { ...@@ -34,12 +49,5 @@ const notificationService = {
}, },
}; };
export const postInformationStatus = param =>
request({
url: API.POST_INFORMATION_STATUS,
method: constants.REQUEST_METHOD_POST,
data: param.data,
params: param.query,
});
export default notificationService; export default notificationService;
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
...@@ -10,6 +10,7 @@ import { actionCreators } from '../../containers/App/store'; ...@@ -10,6 +10,7 @@ import { actionCreators } from '../../containers/App/store';
import isProd from '../../utils/env'; import isProd from '../../utils/env';
// import NoticeIcon from '../NoticeIcon'; // import NoticeIcon from '../NoticeIcon';
import styles from './index.less'; import styles from './index.less';
import { history } from '@wisdom-utils/runtime';
const { TextArea } = Input; const { TextArea } = Input;
/* eslint-disable */ /* eslint-disable */
...@@ -158,6 +159,19 @@ class NoticeIconView extends Component { ...@@ -158,6 +159,19 @@ class NoticeIconView extends Component {
}); });
}; };
// 消息弹窗Footer
renderNotifierFooter = () => {
const toNotifications = e => {
e.stopPropagation();
history.push && history.push('/system/notifications')
}
return (
<div className={styles.notificationFoter}>
<a onClick={toNotifications}>查看全部历史消息</a>
</div>
)
}
handlerOptions = value => { handlerOptions = value => {
// eslint-disable-next-line no-undef // eslint-disable-next-line no-undef
service service
...@@ -235,6 +249,7 @@ class NoticeIconView extends Component { ...@@ -235,6 +249,7 @@ class NoticeIconView extends Component {
confirmRead={this.notifier.confirmRead} confirmRead={this.notifier.confirmRead}
config={this.props.global} config={this.props.global}
bell={this.props.bell} bell={this.props.bell}
renderFooter={this.renderNotifierFooter}
> >
<NoticeIcon.Tab <NoticeIcon.Tab
list={this.state.noticeData} list={this.state.noticeData}
......
...@@ -672,3 +672,19 @@ ...@@ -672,3 +672,19 @@
padding: 12px 16px 0 16px!important; padding: 12px 16px 0 16px!important;
} }
} }
.notificationFoter {
background-color: #f6f6f6;
border-top: 1px solid #e3e3e3;
& > a {
color: #44acb6;
display: block;
font-size: 14px;
line-height: 20px;
padding: 12px 16px;
text-align: center;
&:hover {
color: #51c6cf;
}
}
}
\ No newline at end of file
/*
** 功能名称
** create by tuwei on 2022/2/20
** 功能路径:src\pages\product\common\CheckAllMessage\CheckAllMessage.js
* */
import React, { useState, useEffect, useRef } from 'react';
import { connect } from 'react-redux';
import { List, message, Avatar, Skeleton, Divider, Select, notification } from 'antd';
import { CheckOutlined } from '@ant-design/icons';
import InfiniteScroll from 'react-infinite-scroll-component';
import classnames from 'classnames';
import { noticeService } from '@/api';
import styles from './index.less';
import { formatDate } from './utils'
const findMenuPath = (flatMenu, url) => {
const [path, param = ''] = url.split('|');
let params = param.split('&').reduce((pre, item) => {
if(!item) return pre;
const [key, value] = item.split('&');
pre[key] = value;
return pre;
}, {});
// const menu = flatMenu.find(item => item.params && item.params.widget === params.widget); // 根据widget匹配菜单
const menu = flatMenu.find(item => item.path.indexOf(path) > -1); // 根据路径匹配菜单
return menu ? menu.path.replace(/^\//, '') : '';
};
const CheckAllMessage = props => {
const { flatMenu } = props;
const [loading, setLoading] = useState(false);
const [data, setData] = useState([]);
const [sortType, setSortType] = useState(1); //排序类型
const [infoTypeList, setInfoTypeList] = useState([]);
const [isRes, setIsRes] = useState(false);
const total = useRef(0);
const pageIndex = useRef(1);
const infoType = useRef('全部');
useEffect(() => {
loadMoreData();
getTypeList();
}, []);
// 获取类型数据
const getTypeList = () => {
noticeService.getCurrentInfoType({ userID: window.globalConfig.userInfo.OID }).then(res => {
if (res.code === 0) {
res.data?.unshift('全部');
res.data && setInfoTypeList(res.data);
}
})
}
// 加载数据
const loadMoreData = () => {
if (loading) {
return;
}
setLoading(true);
let obj = {}
if (infoType.current == '全部') {
obj = {
userID: window.globalConfig.userInfo.OID,
pageIndex: pageIndex.current,
pageSize: 10,
sort: sortType
}
} else {
obj = {
type: infoType.current,
userID: window.globalConfig.userInfo.OID,
pageIndex: pageIndex.current,
pageSize: 10,
sort: sortType
}
}
// userID: window.globalConfig.userInfo.OID,
noticeService
.getAllInformationInfo(obj)
.then(res => {
console.log(res, 'res');
if (res.code === 0) {
pageIndex.current++;
total.current = res.data.totalCount;
res.data.list && setData([...data, ...res.data.list]);
setIsRes(true);
setLoading(false);
}
})
.catch(() => {
setIsRes(true);
setLoading(false);
})
};
// 获取数据
const getData = (obj) => {
noticeService
.getAllInformationInfo(obj)
.then(res => {
console.log(res, 'res');
if (res.code === 0) {
pageIndex.current++;
total.current = res.data.totalCount;
res.data.list && setData(res.data.list);
setLoading(false);
}
})
.catch(() => {
setLoading(false);
})
}
// 监听选择类型
const onChange = e => {
infoType.current = e;
pageIndex.current = 1
let obj = {}
if (infoType.current == '全部') {
obj = {
userID: window.globalConfig.userInfo.OID,
pageIndex: pageIndex.current,
pageSize: 10,
sort: sortType
}
} else {
obj = {
type: infoType.current,
userID: window.globalConfig.userInfo.OID,
pageIndex: pageIndex.current,
pageSize: 10,
sort: sortType
}
}
getData(obj);
};
// title 回显
const messageTitle = (themeName, info) => {
var messInfo = "";
switch (themeName) {
case "工单提醒":
messInfo = `${info.caseType}`;
break;
case "通用报警":
messInfo = `${info.title}`;
break;
case "系统通知":
messInfo = `${info.noticeType}`;
break;
default:
messInfo = info.title;
break;
}
return messInfo;
};
// content回显
const messageContent = (themeName, info) => {
var messInfo = "";
switch (themeName) {
case "工单提醒":
messInfo = `${info.flowName},${info.nodeName},承办意见:${info.content}`;
break;
case "通用报警":
messInfo = `${info.content},${info.deviceCode}`;
break;
case "系统通知":
messInfo = `${info.noticeTitle},${info.noticeContent}`;
break;
default:
messInfo = info.content;
break;
}
return messInfo;
};
// 渲染消息发送时间
const renderTime = value => {
const createTime = new Date(value);
const currentTime = new Date();
const difSeconds = (currentTime.getTime() - createTime.getTime()) / 1000;
let timeMsg = '';
if (difSeconds < 60) {
timeMsg = '刚刚'
} else if (difSeconds / 60 < 60) {
timeMsg = `${parseInt(difSeconds / 60)}分钟前`;
} else if (difSeconds / 3600 < 24) {
timeMsg = `${parseInt(difSeconds / 3600)}小时前`;
} else {
timeMsg = formatDate(createTime, 'yyyy-MM-dd');
}
return timeMsg;
}
const sortChange = value => {
setSortType(value);
pageIndex.current = 1;
let obj = {};
if (infoType.current == '全部') {
obj = {
userID: window.globalConfig.userInfo.OID,
pageIndex: pageIndex.current,
pageSize: 10,
sort: value
};
} else {
obj = {
type: infoType.current,
userID: window.globalConfig.userInfo.OID,
pageIndex: pageIndex.current,
pageSize: 10,
sort: value
};
}
getData(obj);
}
// 渲染头像
const renderImg = val => {
if (val == '通用报警') {
return require('/src/assets/images/system/notifications/icon2.png');
}
if (val == '工单提醒') {
return require('/src/assets/images/system/notifications/icon4.png');
}
if (val == '系统通知') {
return require('/src/assets/images/system/notifications/icon3.png');
}
if (val == '工时审批') {
return require('/src/assets/images/system/notifications/icon1.png')
}
if (val.indexOf('工时填报') != -1) {
return require('/src/assets/images/system/notifications/icon6.png')
}
if (val.indexOf('会议') != -1) {
return require('/src/assets/images/system/notifications/icon7.png')
}
return require('/src/assets/images/system/notifications/icon3.png');
}
// 标记为已读
const hasRead = () => {
noticeService.postInformationStatus({ userID: window.globalConfig.userInfo.OID, isAll: 1 }).then(res => {
if (res.code == 0) {
pageIndex.current = 1;
let obj = {};
if (infoType.current == '全部') {
obj = {
userID: window.globalConfig.userInfo.OID,
pageIndex: pageIndex.current,
pageSize: 10,
sort: sortType
};
} else {
obj = {
type: infoType.current,
userID: window.globalConfig.userInfo.OID,
pageIndex: pageIndex.current,
pageSize: 10,
sort: sortType
};
}
getData(obj);
}
})
}
// 获取参数
const GetUrlParam = (url) => {
let arrObj = url.split("|");
let params = Object.create(null);
if (arrObj.length > 1) {
arrObj = arrObj[1].split("&");
arrObj.forEach((item) => {
item = item.split("=");
params[item[0]] = item[1];
});
}
return params;
}
// 跳转链接
const toLink = val => {
if (!val.web_path) {
notification.error({ message: '提示', duration: 3, description: '未配置跳转路径' });
return;
}
const params = GetUrlParam(val.web_path);
if (!params.widget) {
notification.error({ message: '提示', duration: 3, description: '未配置跳转路径' });
return;
}
let targetMenuPath = findMenuPath(flatMenu, val.web_path);
if (targetMenuPath == '') {
notification.error({ message: '提示', duration: 3, description: '你没有跳转菜单权限,请联系管理员添加权限' });
return;
}
if (val.id == 0) {
sessionStorage.setItem('routerParams', JSON.stringify(params));
window.history.pushState(params, '', `/civbase/${targetMenuPath}`);
} else {
sessionStorage.setItem('routerParams', JSON.stringify(params));
noticeService.postInformationStatus({ userID: window.globalConfig.userInfo.OID, hisID: val.hisID }).then(res => {
window.history.pushState(params, '', `/civbase/${targetMenuPath}`);
})
}
}
return (
<div className={styles.contentPage}>
<div className={styles.messageBox}>
<div className={styles.headerTop}>全部通知</div>
<div className={styles.headerContent}>
{/* 选择类型 */}
<div className={styles.selectForm}>
<div className={styles.lable}>
类型:
</div>
<div className={styles.form}>
<Select
defaultValue="全部"
placeholder="请选择类型"
onChange={onChange}
style={{ width: '154px' }}
>
{infoTypeList.map(item => <Option value={item} key={item}>{item}</Option>)}
</Select>
</div>
</div>
{/* 排序 */}
<div className={styles.sortForm}>
<div className={styles.label}>排序:</div>
<div className={styles.form}>
<div className={styles.sortBox}>
<div className={classnames(styles.tab, { [styles.tabActive]: sortType === 1 })} onClick={() => sortChange(1)}>未读通知在前</div>
<div className={classnames(styles.tab, { [styles.tabActive]: sortType === 0 })} onClick={() => sortChange(0)}>默认时间排序</div>
</div>
</div>
</div>
<div className={styles.haveRead} onClick={hasRead}>
<CheckOutlined style={{ verticalAlign: 'middle', marginRight: '3px', marginTop: '-2px' }} />
全部标记为已读
</div>
</div>
<div
id="scrollableDiv"
className={styles.msgContent}
>
<InfiniteScroll
dataLength={data.length}
next={loadMoreData}
hasMore={data.length < total.current}
loader={<div className={styles.loaderTip}>正在加载更多...</div>}
endMessage={isRes ? (<div className={styles.loaderTip}>没有更多内容了</div>) : ''}
scrollableTarget="scrollableDiv"
>
{data.map((item, index) => (<div className={classnames(styles.msgItem, { [styles.msgHasRead]: item.id == 0 })} key={index} onClick={() => toLink(item)}>
<div className={styles.left}>
<img src={renderImg(item.messType)} alt="" />
</div>
<div className={styles.msgCenter}>
<div className={styles.msgBox}>
<div className={styles.title}>{messageTitle(item.messType, JSON.parse(item.infoContent))}</div>
<div className={styles.msgDesc} title={messageContent(item.messType, JSON.parse(item.infoContent))}>{messageContent(item.messType, JSON.parse(item.infoContent))}</div>
</div>
</div>
<div className={styles.right}>{renderTime(item.createTime)}</div>
</div>))}
</InfiniteScroll>
</div>
</div >
</div >
);
};
const mapStateToProps = state => ({
flatMenu: state.getIn(['global', 'flatMenu'])
});
export default connect(
mapStateToProps,
null,
)(CheckAllMessage);
@import "~antd/es/style/themes/default.less";
@imgSrc: '@/assets/images/system/notifications';
.contentPage {
width: 100%;
height: 100%;
background: url('@{imgSrc}/messageBg.png') no-repeat;
// padding: 20px 300px 0 300px;
.messageBox {
width: 931px;
height: 100%;
background: #FFFFFF;
border-radius: 5px;
margin-left: 50%;
transform: translateX(-50%);
.headerTop {
width: 100%;
height: 50px;
line-height: 50px;
text-align: center;
font-size: 16px;
font-family: Microsoft YaHei;
font-weight: 400;
color: #000000;
opacity: 0.85;
}
.headerContent {
display: flex;
height: 32px;
line-height: 32px;
margin-bottom: 10px;
.selectForm {
display: flex;
flex-grow: 1;
margin-left: 44px;
.form {
// width: 85px;
// // width: 200px;
}
}
.sortForm {
display: flex;
flex-grow: 10;
.form {
.sortBox {
display: flex;
width: 226px;
background: #FFFFFF;
border: 1px solid #E4E6EA;
border-radius: 5px;
cursor: pointer;
.tab {
width: 100%;
text-align: center;
color: #a6a6a6;
}
.tab:nth-of-type(1) {
border-right: 1px solid #E4E6EA;
}
.tabActive {
color: #262626;
// font-weight: 700;
}
}
}
}
.haveRead {
flex-grow: 1;
color: #8D8D90;
font-size: 14px;
cursor: pointer;
}
.haveRead:hover {
color: #1890ff;
}
}
.msgContent {
height: 100%;
width: 878px;
margin-left: 50%;
transform: translateX(-50%);
overflow-y: scroll;
padding-bottom: 100px;
.loaderTip {
width: 200px;
height: 36px;
line-height: 36px;
background-color: #f6f6f6;
border-radius: 5px;
text-align: center;
margin-top: 5px;
margin-left: 50%;
transform: translateX(-50%);
color: #5a5a5f;
}
.msgItem {
position: relative;
display: flex;
height: 85px;
border-bottom: 1px solid #EDEEF1;
cursor: pointer;
.left {
width: 36px;
height: 100%;
line-height: 85px;
margin-left: 17px;
img {
width: 36px;
height: 36px;
}
}
.msgCenter {
flex: 1;
width: 0;
margin-left: 30px;
margin-right: 10px;
// white-space: nowrap;
// // overflow: hidden;
// text-overflow: ellipsis;
.msgBox {
position: relative;
top: 50%;
transform: translateY(-50%);
.title {
color: #000000;
font-weight: 700;
font-size: 14px;
height: 22px;
}
.msgDesc {
color: #000000;
font-size: 14px;
height: 22px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
}
.right {
line-height: 85px;
margin-right: 10px;
}
}
.msgItem:hover {
background-color: #F4F4F5;
}
.msgHasRead {
opacity: 0.5;
}
}
}
:global {
.@{ant-prefix}-tabs-ink-bar.@{ant-prefix}-tabs-ink-bar-animated {
transform: translateZ(0) !important;
}
}
}
\ No newline at end of file
export const formatDate = (date, fmt) => {
if (date === void 0) date = new Date();
if (fmt === void 0) fmt = 'yyyy-MM-dd HH:mm:ss';
if (typeof date === 'string') {
date = new Date(formatTimeByPattern(date));
} else if (typeof date === 'number') {
date = new Date(date);
}
const o = {
'M+': date.getMonth() + 1, // 月份
'd+': date.getDate(), // 日
'h+': date.getHours() % 12 === 0 ? 12 : date.getHours() % 12, // 小时
'H+': date.getHours(), // 小时
'm+': date.getMinutes(), // 分
's+': date.getSeconds(), // 秒
'q+': Math.floor((date.getMonth() + 3) / 3), // 季度
S: date.getMilliseconds(), // 毫秒
};
const week = {
'0': '\u65e5',
'1': '\u4e00',
'2': '\u4e8c',
'3': '\u4e09',
'4': '\u56db',
'5': '\u4e94',
'6': '\u516d',
};
if (/(y+)/.test(fmt)) {
fmt = fmt.replace(RegExp.$1, `${date.getFullYear()}`.substr(4 - RegExp.$1.length));
}
if (/(E+)/.test(fmt)) {
fmt = fmt.replace(
RegExp.$1,
(RegExp.$1.length > 1 ? (RegExp.$1.length > 2 ? '\u661f\u671f' : '\u5468') : '') +
week[`${date.getDay()}`],
);
}
for (let k in o) {
if (new RegExp(`(${k})`).test(fmt)) {
fmt = fmt.replace(
RegExp.$1,
RegExp.$1.length === 1 ? o[k] : `00${o[k]}`.substr(`${o[k]}`.length),
);
}
}
return fmt;
};
\ No newline at end of file
...@@ -9,6 +9,7 @@ import CommonMenu from '../pages/commonMenu'; ...@@ -9,6 +9,7 @@ import CommonMenu from '../pages/commonMenu';
import Iframe from '../pages/iframe'; import Iframe from '../pages/iframe';
import Login from '../pages/user/login'; import Login from '../pages/user/login';
import NoSecret from '../pages/user/login/noSecret'; import NoSecret from '../pages/user/login/noSecret';
import Notifications from '../pages/system/notifications';
export const dyRoutes = (routes, layout, theme) => { export const dyRoutes = (routes, layout, theme) => {
// eslint-disable-next-line no-shadow // eslint-disable-next-line no-shadow
...@@ -58,6 +59,11 @@ export const dyRoutes = (routes, layout, theme) => { ...@@ -58,6 +59,11 @@ export const dyRoutes = (routes, layout, theme) => {
component: CommonMenu, component: CommonMenu,
// name: '菜单收藏' // name: '菜单收藏'
}, },
{
// 历史消息箱
path: '/system/notifications',
component: Notifications,
},
{ {
path: '/iframe', path: '/iframe',
component: Iframe, component: Iframe,
......
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