index.js 13.9 KB
Newer Older
1 2 3 4
/* eslint-disable import/no-unresolved */
/* eslint-disable no-underscore-dangle */
/* eslint-disable global-require */
/* eslint-disable eqeqeq */
5 6 7 8 9 10 11 12 13 14
/*
 ** 功能名称
 ** 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';
15
// eslint-disable-next-line import/no-unresolved
16 17 18
import classnames from 'classnames';
import { noticeService } from '@/api';
import styles from './index.less';
19
import { formatDate } from './utils';
20 21 22

const findMenuPath = (flatMenu, url) => {
  const [path, param = ''] = url.split('|');
23 24
  const params = param.split('&').reduce((pre, item) => {
    if (!item) return pre;
25
    const [key, value] = item.split('=');
26 27 28
    pre[key] = value;
    return pre;
  }, {});
29 30
  const menu = flatMenu.find(item => item.params && item.params.widget === params.widget); // 根据widget匹配菜单
  // const menu = flatMenu.find(item => item.path.indexOf(path) > -1); // 根据路径匹配菜单
31 32 33 34 35 36 37
  return menu ? menu.path.replace(/^\//, '') : '';
};

const CheckAllMessage = props => {
  const { flatMenu } = props;
  const [loading, setLoading] = useState(false);
  const [data, setData] = useState([]);
38
  const [sortType, setSortType] = useState(1); // 排序类型
39 40 41 42
  const [infoTypeList, setInfoTypeList] = useState([]);
  const [isRes, setIsRes] = useState(false);
  const total = useRef(0);
  const pageIndex = useRef(1);
43
  const pageSize = useRef(20);
44 45 46 47 48 49 50 51
  const infoType = useRef('全部');
  // 获取类型数据
  const getTypeList = () => {
    noticeService.getCurrentInfoType({ userID: window.globalConfig.userInfo.OID }).then(res => {
      if (res.code === 0) {
        res.data?.unshift('全部');
        res.data && setInfoTypeList(res.data);
      }
52 53
    });
  };
54 55 56 57 58 59
  // 加载数据
  const loadMoreData = () => {
    if (loading) {
      return;
    }
    setLoading(true);
60 61
    let obj = {};
    if (infoType.current === '全部') {
62 63 64
      obj = {
        userID: window.globalConfig.userInfo.OID,
        pageIndex: pageIndex.current,
65
        pageSize: pageSize.current,
66 67
        sort: sortType,
      };
68 69 70 71 72
    } else {
      obj = {
        type: infoType.current,
        userID: window.globalConfig.userInfo.OID,
        pageIndex: pageIndex.current,
73
        pageSize: pageSize.current,
74 75
        sort: sortType,
      };
76 77 78 79 80 81
    }
    // userID: window.globalConfig.userInfo.OID,
    noticeService
      .getAllInformationInfo(obj)
      .then(res => {
        if (res.code === 0) {
82
          // eslint-disable-next-line no-plusplus
83 84
          pageIndex.current++;
          total.current = res.data.totalCount;
85
          // eslint-disable-next-line no-use-before-define
86
          res.data.list && setData([...data, ...deaflData(res.data.list)]);
87 88 89 90 91 92 93
          setIsRes(true);
          setLoading(false);
        }
      })
      .catch(() => {
        setIsRes(true);
        setLoading(false);
94
      });
95
  };
96 97 98 99 100
  useEffect(() => {
    loadMoreData();
    getTypeList();
  }, []);
  // eslint-disable-next-line no-shadow, arrow-body-style
101 102 103 104
  const deaflData = (data = []) => {
    return data.map(item => {
      let content = '';
      try {
105
        content = JSON.parse(item.infoContent);
106 107 108 109
        content = item.infoContent;
      } catch (error) {
        content = '{}';
      }
110 111 112
      return { ...item, infoContent: content };
    });
  };
113
  // 获取数据
114
  const getData = obj => {
115 116 117 118
    noticeService
      .getAllInformationInfo(obj)
      .then(res => {
        if (res.code === 0) {
119
          // eslint-disable-next-line no-plusplus
120 121
          pageIndex.current++;
          total.current = res.data.totalCount;
122
          res.data.list && setData(deaflData(res.data.list));
123 124 125 126 127
          setLoading(false);
        }
      })
      .catch(() => {
        setLoading(false);
128 129
      });
  };
130 131 132
  // 监听选择类型
  const onChange = e => {
    infoType.current = e;
133 134 135
    pageIndex.current = 1;
    let obj = {};
    if (infoType.current === '全部') {
136 137 138
      obj = {
        userID: window.globalConfig.userInfo.OID,
        pageIndex: pageIndex.current,
139
        pageSize: pageSize.current,
140 141
        sort: sortType,
      };
142 143 144 145 146
    } else {
      obj = {
        type: infoType.current,
        userID: window.globalConfig.userInfo.OID,
        pageIndex: pageIndex.current,
147
        pageSize: pageSize.current,
148 149
        sort: sortType,
      };
150 151 152 153
    }
    getData(obj);
  };
  // title 回显
154 155 156 157 158
  const messageTitle = (item, info) => {
    const { messType, title } = item;
    let messInfo = '';
    switch (messType) {
      case '工单提醒':
159 160
        messInfo = `${info.caseType}`;
        break;
161
      case '通用报警':
162 163
        messInfo = `${info.title}`;
        break;
164
      case '系统通知':
165 166 167
        messInfo = `${info.noticeType}`;
        break;
      default:
168
        messInfo = title || info.title;
169 170 171 172 173
        break;
    }
    return messInfo;
  };
  // content回显
174 175 176 177 178
  const messageContent = (item, info) => {
    const { messType, defaultContent } = item;
    let messInfo = '';
    switch (messType) {
      case '工单提醒':
179 180
        messInfo = `${info.flowName},${info.nodeName},承办意见:${info.content}`;
        break;
181
      case '通用报警':
182 183
        messInfo = `${info.content},${info.deviceCode}`;
        break;
184
      case '系统通知':
185 186 187
        messInfo = `${info.noticeTitle},${info.noticeContent}`;
        break;
      default:
188
        messInfo = info.content || defaultContent;
189 190 191 192 193 194
        break;
    }
    return messInfo;
  };
  // 渲染消息发送时间
  const renderTime = value => {
195
    if (!value) return '';
196 197 198 199 200
    const createTime = new Date(value);
    const currentTime = new Date();
    const difSeconds = (currentTime.getTime() - createTime.getTime()) / 1000;
    let timeMsg = '';
    if (difSeconds < 60) {
201
      timeMsg = '刚刚';
202
    } else if (difSeconds / 60 < 60) {
203
      // eslint-disable-next-line radix
204 205
      timeMsg = `${parseInt(difSeconds / 60)}分钟前`;
    } else if (difSeconds / 3600 < 24) {
206
      // eslint-disable-next-line radix
207 208 209 210 211
      timeMsg = `${parseInt(difSeconds / 3600)}小时前`;
    } else {
      timeMsg = formatDate(createTime, 'yyyy-MM-dd');
    }
    return timeMsg;
212
  };
213 214 215 216
  const sortChange = value => {
    setSortType(value);
    pageIndex.current = 1;
    let obj = {};
217
    if (infoType.current === '全部') {
218 219 220
      obj = {
        userID: window.globalConfig.userInfo.OID,
        pageIndex: pageIndex.current,
221
        pageSize: pageSize.current,
222
        sort: value,
223 224 225 226 227 228
      };
    } else {
      obj = {
        type: infoType.current,
        userID: window.globalConfig.userInfo.OID,
        pageIndex: pageIndex.current,
229
        pageSize: pageSize.current,
230
        sort: value,
231 232 233
      };
    }
    getData(obj);
234 235 236 237 238 239 240
  };
  // 渲染头像
  const renderImg = item => {
    const { messType, webIcon } = item;
    if (webIcon) return `${window.location.origin}/${webIcon}`;
    if (messType === '通用报警') {
      return require('../../../assets/images/system/notifications/icon2.png');
241
    }
242 243
    if (messType === '工单提醒') {
      return require('../../../assets/images/system/notifications/icon4.png');
244
    }
245 246
    if (messType === '系统通知') {
      return require('../../../assets/images/system/notifications/icon3.png');
247
    }
248 249
    if (messType === '工时审批') {
      return require('../../../assets/images/system/notifications/icon1.png');
250
    }
251 252
    if (messType.indexOf('工时填报') != -1) {
      return require('../../../assets/images/system/notifications/icon6.png');
253
    }
254 255
    if (messType.indexOf('会议') != -1) {
      return require('../../../assets/images/system/notifications/icon7.png');
256
    }
257
    return require('../../../layouts/AppLayout/notifier/images/types/other.png');
258
  };
259 260 261 262 263 264 265 266 267 268
  // 标记为已读
  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,
269
            pageSize: pageSize.current,
270
            sort: sortType,
271 272 273 274 275 276
          };
        } else {
          obj = {
            type: infoType.current,
            userID: window.globalConfig.userInfo.OID,
            pageIndex: pageIndex.current,
277
            pageSize: pageSize.current,
278
            sort: sortType,
279 280 281 282
          };
        }
        getData(obj);
      }
283 284
    });
  };
285
  // 获取参数
286 287 288
  const GetUrlParam = url => {
    let arrObj = url.split('|');
    const params = Object.create(null);
289
    if (arrObj.length > 1) {
290 291 292 293
      arrObj = arrObj[1].split('&');
      arrObj.forEach(item => {
        item = item.split('=');
        // eslint-disable-next-line prefer-destructuring
294 295 296 297
        params[item[0]] = item[1];
      });
    }
    return params;
298
  };
299 300 301 302 303 304 305
  // 跳转链接
  const toLink = val => {
    if (!val.web_path) {
      notification.error({ message: '提示', duration: 3, description: '未配置跳转路径' });
      return;
    }

杨思琦's avatar
杨思琦 committed
306 307 308 309 310 311 312 313 314 315 316 317 318 319
    if (/^((http|https):)?\/\/([\w.]+\/?)\S*/.test(val.web_path)) {
      if (val.id == 0) {
        window.open(val.web_path);
      } else {
        noticeService
          .postInformationStatus({ userID: window.globalConfig.userInfo.OID, hisID: val.hisID })
          .then(res => {
            sortChange(1);
            window.open(val.web_path);
          });
      }
      return;
    }

320 321 322 323 324 325
    const params = GetUrlParam(val.web_path);
    if (!params.widget) {
      notification.error({ message: '提示', duration: 3, description: '未配置跳转路径' });
      return;
    }

326
    const targetMenuPath = findMenuPath(flatMenu, val.web_path);
327 328 329 330
    if (targetMenuPath == '') {
      notification.error({ message: '提示', duration: 3, description: '你没有跳转菜单权限,请联系管理员添加权限' });
      return;
    }
331 332 333
    // 添加消息来源和目标标识,便于判断
    params._source = '消息通知';
    params._target = val.web_path;
334 335 336 337 338 339 340
    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}`);
341
      });
342
    }
343
  };
344 345 346 347 348 349 350
  return (
    <div className={styles.contentPage}>
      <div className={styles.messageBox}>
        <div className={styles.headerTop}>全部通知</div>
        <div className={styles.headerContent}>
          {/* 选择类型 */}
          <div className={styles.selectForm}>
351
            <div className={styles.lable}>类型:</div>
352
            <div className={styles.form}>
353 354 355 356 357 358 359
              <Select defaultValue="全部" placeholder="请选择类型" onChange={onChange} style={{ width: '154px' }}>
                {infoTypeList.map(item => (
                  // eslint-disable-next-line react/jsx-no-undef
                  <Option value={item} key={item}>
                    {item}
                  </Option>
                ))}
360 361 362 363 364 365 366 367
              </Select>
            </div>
          </div>
          {/* 排序 */}
          <div className={styles.sortForm}>
            <div className={styles.label}>排序:</div>
            <div className={styles.form}>
              <div className={styles.sortBox}>
368 369 370 371 372 373 374 375 376 377 378 379
                <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>
380 381 382 383 384 385 386 387 388
              </div>
            </div>
          </div>
          <div className={styles.haveRead} onClick={hasRead}>
            <CheckOutlined style={{ verticalAlign: 'middle', marginRight: '3px', marginTop: '-2px' }} />
            全部标记为已读
          </div>
        </div>

389
        <div id="scrollableDiv" className={styles.msgContent}>
390 391 392 393 394
          <InfiniteScroll
            dataLength={data.length}
            next={loadMoreData}
            hasMore={data.length < total.current}
            loader={<div className={styles.loaderTip}>正在加载更多...</div>}
395
            endMessage={isRes ? <div className={styles.loaderTip}>没有更多内容了</div> : ''}
396 397
            scrollableTarget="scrollableDiv"
          >
398 399 400 401 402 403 404 405 406
            {data.map((item, index) => (
              <div
                className={classnames(styles.msgItem, { [styles.msgHasRead]: item.id == 0 })}
                // eslint-disable-next-line react/no-array-index-key
                key={index}
                onClick={() => toLink(item)}
              >
                <div className={styles.left}>
                  <img src={renderImg(item)} alt="" />
407
                </div>
408 409 410 411 412 413 414 415
                <div className={styles.msgCenter}>
                  <div className={styles.msgBox}>
                    <div className={styles.title}>{messageTitle(item, JSON.parse(item.infoContent))}</div>
                    <div className={styles.msgDesc} title={messageContent(item, JSON.parse(item.infoContent))}>
                      {messageContent(item, JSON.parse(item.infoContent))}
                    </div>
                  </div>
                </div>
416
                <div className={styles.right}>{renderTime(item.hisCreateTime || item.createTime)}</div>
417
              </div>
418
            ))}
419 420
          </InfiniteScroll>
        </div>
421 422
      </div>
    </div>
423 424 425
  );
};
const mapStateToProps = state => ({
426
  flatMenu: state.getIn(['global', 'flatMenu']),
427 428 429 430 431
});
export default connect(
  mapStateToProps,
  null,
)(CheckAllMessage);