标签:remove reac http color less || off current llb
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 ( <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()
标签:remove reac http color less || off current llb
原文地址:https://www.cnblogs.com/chenbeibei520/p/11490676.html