react 提示消息队列 (支持动态添加,删除,多实例化)

import React from 'react'
import PropTypes from 'prop-types'

import AnimationOperateFeedbackInfo from '../AnimationOperateFeedbackInfo'
import OperateFeedbackInfo from '../OperateFeedbackInfo'

import './index.less'

const OPERATE_ARRAY_MAX_LENGTH = 5

export default function AssistantOperateFeedbackArea({
  processingOperateList, failedOperateList, onClickCleanFailedOperateBtn, animationEndCallback,
}) {
  const operateWrapStyle = {
    width: '200px',
    height: '28px',
    color: '#fff',
  }

  return (
    
{ processingOperateList.length > 0 && ( <div className="operate-feedback-area" style={{ // queueMaxLength + 1 省略区域高度 height: `${processingOperateList.length > OPERATE_ARRAY_MAX_LENGTH ? (OPERATE_ARRAY_MAX_LENGTH + 1) * 28 : processingOperateList.length * 28}px`, }} > { processingOperateList.slice(0, OPERATE_ARRAY_MAX_LENGTH).map((item) => { return ( <AnimationOperateFeedbackInfo operateId={item.operateId} operate={item.operate} operateType={item.state} animationEndCallback={animationEndCallback} style={operateWrapStyle} key={item.operateId} /> ) }) } { processingOperateList.length > OPERATE_ARRAY_MAX_LENGTH && ( <div style={operateWrapStyle} className="ellipsis-operate-info" > ... ...
) }
) } { failedOperateList.length > 0 && ( <div className="operate-feedback-area" style={{ // queueMaxLength + 1 省略区域高度 height: `${failedOperateList.length > OPERATE_ARRAY_MAX_LENGTH ? (OPERATE_ARRAY_MAX_LENGTH + 1) * 28 : failedOperateList.length * 28}px`, }} > { failedOperateList.slice(0, OPERATE_ARRAY_MAX_LENGTH).map((item) => { return (
<OperateFeedbackInfo operate={item.operate} style={operateWrapStyle} iconRotate={false} iconPath={require('~/shared/assets/image/red-white-warn-icon-60-60.png')} />
) }) } <div className="clean-failed-feedback-info-btn" onClick={onClickCleanFailedOperateBtn} tabIndex={0} role="button" > 清除所有异常
{ failedOperateList.length > OPERATE_ARRAY_MAX_LENGTH && ( <div style={operateWrapStyle} className="ellipsis-operate-info" > ... ...
) }
) } { processingOperateList.length === 0 && failedOperateList.length === 0 && (
暂无对教师端操作
) }
) } AssistantOperateFeedbackArea.propTypes = { processingOperateList: PropTypes.array, failedOperateList: PropTypes.array, onClickCleanFailedOperateBtn: PropTypes.func, animationEndCallback: PropTypes.func, } AssistantOperateFeedbackArea.defaultProps = { processingOperateList: [], failedOperateList: [], animationEndCallback: () => {}, onClickCleanFailedOperateBtn: () => {}, }
import React, { useRef, useLayoutEffect } from 'react'
import PropTypes from 'prop-types'
import CX from 'classnames'

import './index.less'

export default function OperateFeedbackInfo({
  operate, iconPath, style, iconRotate, resetAnimation,
}) {
  const imgRef = useRef(null)

  useLayoutEffect(() => {
    if (resetAnimation === true) {
      const imgElem = imgRef.current
      imgElem.className = ''

      // 触发一次重绘 同步所有旋转的icon动画
      imgElem.height = imgElem.offsetHeight

      imgElem.className = 'operate-icon-rotate'
    }
  })

  return (
    <div
      className="operate-feedback-Info"
      style={style}
    >
      
{operate}
<img className={CX({ 'operate-icon-rotate': iconRotate, })} src={iconPath} alt="" ref={imgRef} />
) } OperateFeedbackInfo.propTypes = { operate: PropTypes.string.isRequired, iconPath: PropTypes.string.isRequired, iconRotate: PropTypes.bool, resetAnimation: PropTypes.bool, style: PropTypes.object, } OperateFeedbackInfo.defaultProps = { style: {}, resetAnimation: false, iconRotate: false, }
import React from 'react'
import PropTypes from 'prop-types'

import CX from 'classnames'
import OperateFeedbackInfo from '../OperateFeedbackInfo'

import './index.less'

export default function AnimationOperateFeedbackInfo({
  operateId, operate, operateType, animationEndCallback, style,
}) {
  return (
    <div
      className={CX({
        'animation-operate-feedback-info-wrap': true,
        'animation-operate-feedback-processing-state': operateType === 'processing',
        'animation-operate-feedback-success-state': operateType === 'success',
      })}
      onAnimationEnd={() => {
        if (operateType === 'success') {
          animationEndCallback(operateId)
        }
      }}
    >
      <OperateFeedbackInfo
        resetAnimation={operateType !== 'success'}
        operate={operate}
        style={style}
        iconRotate={operateType !== 'success'}
        iconPath={operateType === 'success' ? require('~/shared/assets/image/icon-success-green-white-100-100.png') : require('~/shared/assets/image/processing-icon.svg')}
      />
    
) } AnimationOperateFeedbackInfo.propTypes = { operateId: PropTypes.string, operate: PropTypes.string, operateType: PropTypes.string, animationEndCallback: PropTypes.func, style: PropTypes.object, } AnimationOperateFeedbackInfo.defaultProps = { operateId: '', operate: '', operateType: '', animationEndCallback: () => {}, style: {}, }

 

以上是所有UI部分(包括交互):效果如下:

react 提示消息队列 (支持动态添加,删除,多实例化)_第1张图片

 

下面是hoc逻辑部分:

import React, { Component } from 'react'
import {
  observable,
  action,
} from 'mobx'
import {
  observer,
} from 'mobx-react'

import uid from 'uuid'

import { AssistantOperateFeedbackArea } from '@dby-h5-clients/pc-1vn-components'
import { Rnd } from 'react-rnd'
import _ from 'lodash'

const operateListClump = observable.object({
  failedOperateList: [],
  processingOperateList: [],
})

class OperateState {
  @action
  constructor(operate = '') {
    this.operateId = uid()
    this.operate = operate
    operateListClump.processingOperateList.push({ operate, operateId: this.operateId, state: 'processing' })
  }

  operateId

  operate

  @action
  success(operate = '') {
    const operateIndex = _.findIndex(operateListClump.processingOperateList, { operateId: this.operateId })
    operateListClump.processingOperateList[operateIndex] = { operate: operate || this.operate, operateId: this.operateId, state: 'success' }
  }

  @action
  failed(operate = '') {
    operateListClump.failedOperateList.push({ operate: operate || this.operate, operateId: this.operateId, state: 'failed' })
    _.remove(operateListClump.processingOperateList, { operateId: this.operateId })
  }
}

@observer
class AssistantOperateList extends Component {
  static addOperate = action((operate) => {
    return new OperateState(operate)
  })

  @action
  removeSuccessOperate = (operateId) => {
    _.remove(operateListClump.processingOperateList, { operateId })
  }

  @action
  handleCleanAllFailedFeedbackInfo = () => {
    operateListClump.failedOperateList = []
  }

  render() {
    return (
      <Rnd
        bounds=".main-space-wrap"
        dragHandleClassName="assistant-operate-feedback-area-wrap"
        lockAspectRatio={16 / 9}
        enableResizing={{
          top: false,
          right: false,
          bottom: false,
          left: false,
          topRight: false,
          bottomRight: false,
          bottomLeft: false,
          topLeft: false,
        }}
        default={{
          x: 30,
          y: 30,
        }}
      >
        <AssistantOperateFeedbackArea
          failedOperateList={operateListClump.failedOperateList.toJSON()}
          processingOperateList={operateListClump.processingOperateList.toJSON()}
          animationEndCallback={this.removeSuccessOperate}
          onClickCleanFailedOperateBtn={this.handleCleanAllFailedFeedbackInfo}
        />
      
    )
  }
}

export default AssistantOperateList

 

 

使用说明:

在其它组件中导入:

import AssistantOperateList from '../AssistantOperateList'
const msg = AssistantOperateList.addOperate('协助开启答题器')
msg.success()
msg.failed()

 

转载于:https://www.cnblogs.com/chenbeibei520/p/11490676.html

你可能感兴趣的:(react 提示消息队列 (支持动态添加,删除,多实例化))