calc-oa-lib
Version:
calc oa library
507 lines (455 loc) • 14.4 kB
JSX
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
}