• 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 = {
         '200px',
        height: '28px',
        color: '#fff',
      }
    
      return (
        <div className="assistant-operate-feedback-area-wrap">
          {
            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"
                    >
                      ... ...
                    </div>
                  )
                }
              </div>
            )
          }
          {
            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 (
                      <div className="operate-feedback-info-wrap">
                        <OperateFeedbackInfo
                          operate={item.operate}
                          style={operateWrapStyle}
                          iconRotate={false}
                          iconPath={require('~/shared/assets/image/red-white-warn-icon-60-60.png')}
                        />
                      </div>
                    )
                  })
                }
                <div
                  className="clean-failed-feedback-info-btn"
                  onClick={onClickCleanFailedOperateBtn}
                  tabIndex={0}
                  role="button"
                >
                  清除所有异常
                </div>
                {
                  failedOperateList.length > OPERATE_ARRAY_MAX_LENGTH && (
                    <div
                      style={operateWrapStyle}
                      className="ellipsis-operate-info"
                    >
                      ... ...
                    </div>
                  )
                }
              </div>
            )
          }
          {
            processingOperateList.length === 0 && failedOperateList.length === 0 && (
              <div className="no-feedback-info-tip">
                暂无对教师端操作
              </div>
            )
          }
        </div>
      )
    }
    
    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}
        >
          <div className="operate-feedback-content">{operate}</div>
          <div className="operate-feedback-state-icon">
            <img
              className={CX({
                'operate-icon-rotate': iconRotate,
              })}
              src={iconPath}
              alt=""
              ref={imgRef}
            />
          </div>
        </div>
      )
    }
    
    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')}
          />
        </div>
      )
    }
    
    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部分(包括交互):效果如下:

    下面是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}
            />
          </Rnd>
        )
      }
    }
    
    export default AssistantOperateList

    使用说明:

    在其它组件中导入:

    import AssistantOperateList from '../AssistantOperateList'
    const msg = AssistantOperateList.addOperate('协助开启答题器')
    msg.success()
    msg.failed()
  • 相关阅读:
    [ jquery 选择器 总览 ] jquery选择器总览
    [ jquery 选择器 :empty ] 此方法选取所有不包含子元素或者文本的空元素
    [ jquery 选择器 :contains(text) ] 此方法选取包含给定文本的元素
    [ jquery 选择器 :header ] 此方法选取匹配如 h1, h2, h3之类的标题元素
    [ jquery 选择器 :last ] 此方法选取jquery对象中的最后一个对象
    [ jquery 选择器 :gt(index) ] 此方法选取匹配大于指定索引值的所有元素
    [ jquery 选择器 :lt(index) ] 此方法选取匹配小于指定索引值的所有元素
    [ jquery 选择器 :eq(index) ] 此方法精确选取指定jquery对象中的指定下角标的对象
    剑指Offer 35 复杂链表的复制 && LeetCode 138 复制带随机指针的链表 哈希
    LeetCode 102. 二叉树的层序遍历 && 剑指 Offer 32
  • 原文地址:https://www.cnblogs.com/chenbeibei520/p/11490676.html
Copyright © 2020-2023  润新知