UNPKG

calc-oa-lib

Version:

calc oa library

507 lines (455 loc) 14.4 kB
import PropTypes from "prop-types"; import React from "react"; import $calc from "../../utils/common"; import styleObj from "./index.module.scss"; export default class CalcSlidingVerifier extends React.Component { //#region 属性 & 构造函数 // 属性类型校验 static propTypes = { lv: PropTypes.number, customClass: PropTypes.string, isPassing: PropTypes.bool, width: PropTypes.number, height: PropTypes.number, text: PropTypes.string, successText: PropTypes.string, handlerBg: PropTypes.string, textSize: PropTypes.string, textColor: PropTypes.string, background: PropTypes.string, progressBarBg: PropTypes.string, completedBg: PropTypes.string, circle: PropTypes.bool, radius: PropTypes.string, // 拖拽句柄是否完全填充验证器高度 handlerFullFilling: PropTypes.bool, handlerIcon: PropTypes.string, successIcon: PropTypes.string, handlerIconColor: PropTypes.string, successIconColor: PropTypes.string, // hooks updateIsPassing: PropTypes.func, handlerMove: PropTypes.func, handlerVerifyFail: PropTypes.func, handlerVerifySuccess: PropTypes.func, }; // 属性默认值 static defaultProps = { lv: 7, customClass: "custom-calc-sliding-verifier", isPassing: false, width: 250, height: 40, text: "Swiping to right side for verifying", successText: "Verified successfully", handlerBg: "#ffffff", textSize: "14px", textColor: "#333333", background: "#eeeee", // progressBarBg: "#76c61d", // completedBg: "#76c61d", progressBarBg: "#3db25e", completedBg: "#3db25e", circle: false, radius: "4px", handlerFullFilling: true, handlerIcon: "calc-oa-verification", successIcon: "calc-oa-drag-done", handlerIconColor: "#666666", successIconColor: "#3db25e", updateIsPassing: (val) => { console.log(`updateIsPassing`, val); }, handlerMove: () => { console.log(`handlerMove`); }, handlerVerifyFail: () => { console.log(`handlerVerifyFail`); }, handlerVerifySuccess: () => { console.log(`handlerVerifySuccess`); }, }; constructor(props) { super(props); this.state = { isMoving: false, x: 0, isOk: false, }; } dragVerifyRef = React.createRef(); progressBarRef = React.createRef(); messageRef = React.createRef(); handlerRef = React.createRef(); get message() { const _self = this; return _self.props.isPassing ? _self.props.successText : _self.props.text; } get textStyle() { const _self = this; return { height: `${_self.props.height}px`, width: `${_self.props.width}px`, fontSize: _self.props.textSize, }; } get dragVerifyStyle() { const _self = this; return { width: `${_self.props.width}px`, height: `${_self.props.height}px`, lineHeight: `${_self.props.height}px`, background: _self.props.background, borderRadius: _self.props.circle ? `${_self.props.height / 2}px` : _self.props.radius, }; } get progressBarStyle() { const _self = this; return { background: _self.props.progressBarBg, height: `${_self.props.height}px`, borderRadius: _self.props.circle ? `${_self.props.height / 2}px 0 0 ${_self.props.height / 2}px` : _self.props.radius, }; } get handlerStyle() { const _self = this; let height = _self.props.height || 0; let styleObj = {}; if (_self.props.fullFilling && height >= 2) { styleObj = { width: `${_self.props.height}px`, height: `${_self.props.height}px`, background: _self.props.handlerBg, }; } else { let margin = 2; height = height - margin - margin; styleObj = { width: `${height}px`, height: `${height}px`, background: _self.props.handlerBg, margin: `${margin}px`, borderRadius: `3px`, }; } return styleObj; } get handlerIconStyle() { const _self = this; let styleObj = {}; styleObj["color"] = _self.props.isPassing ? _self.props.successIconColor : _self.props.handlerIconColor; // console.log( // `handlerIconStyle`, // `isPassing:${_self.props.isPassing}`, // styleObj // ); return styleObj; } //#endregion //#region hooks render() { const _self = this; return ( <div className={`${styleObj["calc-sliding-verifier-scoped"]}`}> <div ref={_self.dragVerifyRef} className={`calc-sliding-verifier ${_self.props.customClass}`} style={_self.dragVerifyStyle} onMouseMove={(e) => { _self.dragMoving(e); }} onMouseUp={(e) => { _self.dragFinish(e); }} onMouseLeave={(e) => { _self.dragFinish(e); }} onTouchMove={(e) => { // console.log(`onTouchMove`, e); _self.dragMoving(e); }} onTouchEnd={(e) => { // console.log(`onTouchEnd`, e); _self.dragFinish(e); }} > <div ref={_self.progressBarRef} className={`dv_progress_bar ${_self.state.isOk ? "goFirst2" : ""}`} style={_self.progressBarStyle} ></div> <div ref={_self.messageRef} className="dv_text" style={_self.textStyle} > {_self.message} </div> <div ref={_self.handlerRef} className={`dv_handler dv_handler_bg ${ _self.state.isOk ? "goFirst" : "" }`} style={_self.handlerStyle} onMouseDown={(e) => { _self.dragStart(e); }} onTouchStart={(e) => { // console.log(`onTouchStart`, e); _self.dragStart(e); }} > <i className={`${_self.props.handlerIcon} handler-icon`} style={_self.handlerIconStyle} ></i> </div> </div> </div> ); } componentDidMount() { const _self = this; // 1>任务初始化 _self.initTask(() => {}); } shouldComponentUpdate(nextProps, nextState) { const _self = this; // 若子组件无属性变化及状态更新, 则无需更新组件 const removeProps = ["children"]; const nextPropsClone = $calc.tool.deepClone(nextProps, removeProps); const curPropsClone = $calc.tool.deepClone(_self.props, removeProps); const nextStateClone = $calc.tool.deepClone(nextState, removeProps); const curnextStateClone = $calc.tool.deepClone(_self.state, removeProps); const needRender = JSON.stringify(nextPropsClone) != JSON.stringify(curPropsClone) || JSON.stringify(nextStateClone) != JSON.stringify(curnextStateClone); // console.log("calc-sliding-verifier shouldComponentUpdate...", needRender); if (needRender) { return true; } return false; // return true; } componentDidUpdate(prevProps, prevState) { // const _self = this; // console.log(`componentDidUpdate`, _self.props); } componentWillUnmount() {} //#endregion //#region methods /** * 任务初始化 * @param {function} callBack 回调函数 * @return {void} */ initTask(callBack) { const _self = this; // 1>定义样式变量 _self.definedStyleVariable(); callBack && callBack(); } /** * 定义样式变量 * @return {void} */ definedStyleVariable() { const _self = this; const dragEl = _self.dragVerifyRef.current; if (!dragEl) { return false; } dragEl.style.setProperty("--textColor", _self.props.textColor); dragEl.style.setProperty( "--width", `${Math.floor(_self.props.width / 2)}px` ); dragEl.style.setProperty( "--pwidth", `${-Math.floor(_self.props.width / 2)}px` ); } dragStart(e) { const _self = this; // console.log(`dragStart`, e.button); if (e.button && e.button != 0) { return false; } // console.log(`dragStart-isPassing`, _self.props.isPassing); if (!_self.props.isPassing) { _self.setState( { isMoving: true, x: e.pageX || e.touches[0].pageX, }, () => { _self.props.handlerMove && _self.props.handlerMove(); // console.log(`dragStart-state`, _self.state); } ); } else { _self.props.handlerMove && _self.props.handlerMove(); } } dragMoving(e) { const _self = this; // console.log( // `dragMoving`, // `isMoving:${_self.state.isMoving}`, // `isPassing:${_self.props.isPassing}` // ); // console.log(`dragMoving`, e); if (_self.state.isMoving && !_self.props.isPassing) { const _x = (e.pageX || e.touches[0].pageX) - _self.state.x; if (_x > 0 && _x <= _self.props.width - _self.props.height) { _self.handlerRef.current.style.left = _x + "px"; if (_self.props.fullFilling) { _self.progressBarRef.current.style.width = `${ _x + _self.props.height / 2 }px`; } else { _self.progressBarRef.current.style.width = `${ _x + _self.props.height }px`; } } else if (_x > _self.props.width - _self.props.height) { _self.handlerRef.current.style.left = `${ _self.props.width - _self.props.height }px`; if (_self.props.fullFilling) { _self.progressBarRef.current.style.width = `${ _self.props.width - _self.props.height / 2 }px`; } else { _self.progressBarRef.current.style.width = `${_self.props.width}px`; } _self.passVerify(); } } } dragFinish(e) { const _self = this; // console.log(`dragFinish`, e); // console.log( // `dragFinish outer`, // `isMoving:${_self.state.isMoving}`, // `isPassing:${_self.props.isPassing}` // ); if (_self.state.isMoving && !_self.props.isPassing) { const _x = (e.pageX || e.changedTouches[0].pageX) - _self.state.x; // console.log( // `dragFinish inner`, // `_x:${_x}`, // `_self.props.width:${_self.props.width}`, // `_self.props.height:${_self.props.height}` // ); if (_x < _self.props.width - _self.props.height) { const that = this; _self.setState( { isOk: true, }, () => { setTimeout(() => { that.handlerRef.current.style.left = "0"; that.progressBarRef.current.style.width = "0"; that.setState({ isOk: false, }); }, 500); } ); _self.props.handlerVerifyFail && _self.props.handlerVerifyFail(); } else { _self.handlerRef.current.style.left = `${ _self.props.width - _self.props.height }px`; if (_self.props.fullFilling) { _self.progressBarRef.current.style.width = `${ _self.props.width - _self.props.height / 2 }px`; } else { _self.progressBarRef.current.style.width = `${_self.props.width}px`; } _self.passVerify(); } _self.setState( { isMoving: false, }, () => {} ); } } passVerify() { const _self = this; // console.log(`passVerify`); _self.props.updateIsPassing && _self.props.updateIsPassing(true); _self.handlerRef.current.children[0].className = _self.props.successIcon; _self.progressBarRef.current.style.background = _self.props.completedBg; _self.messageRef.current.style["-webkit-text-fill-color"] = "unset"; _self.messageRef.current.style.animation = "slidetounlock2 3s infinite"; _self.messageRef.current.style.color = "#ffffff"; _self.props.handlerVerifySuccess && _self.props.handlerVerifySuccess(); _self.setState( { isMoving: false, }, () => {} ); } reset() { const _self = this; // const oriData = _self.$options.data(); // for (const key in oriData) { // if (Object.prototype.hasOwnProperty.call(oriData, key)) { // this[key] = oriData[key]; // } // } // var handler = _self.$refs.handler; // var message = _self.$refs.message; // handler.style.left = "0"; // _self.$refs.progressBar.style.width = "0"; // handler.children[0].className = _self.handlerIcon; // message.style["-webkit-text-fill-color"] = "transparent"; // message.style.animation = "slidetounlock 3s infinite"; // message.style.color = _self.background; // console.log(`reset`); // 初始化验证器成功标志位 _self.props.updateIsPassing && _self.props.updateIsPassing(false); // 设置状态 _self.setState( { isMoving: false, x: 0, isOk: false, }, () => { // // dragVerifyRef = React.createRef(); // progressBarRef = React.createRef(); // messageRef = React.createRef(); // handlerRef = React.createRef(); const { handlerIcon, handlerIconColor } = _self.props; const progressBar = _self.progressBarRef.current; const handler = _self.handlerRef.current; const message = _self.messageRef.current; progressBar.style.width = "0"; handler.style.left = "0"; handler.children[0].className = handlerIcon; handler.children[0].style.color = handlerIconColor; message.style["-webkit-text-fill-color"] = "transparent"; message.style.animation = "slidetounlock 3s infinite"; // message.style.color = _self.background; } ); } //#endregion }