wodax-login-qrcode.react
Version:
login component with qrcode for WodaX applications
721 lines (642 loc) • 25.2 kB
JavaScript
'use strict';
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
var _extends = _interopDefault(require('@babel/runtime/helpers/extends'));
var _regeneratorRuntime = _interopDefault(require('@babel/runtime/regenerator'));
var _asyncToGenerator = _interopDefault(require('@babel/runtime/helpers/asyncToGenerator'));
var _assertThisInitialized = _interopDefault(require('@babel/runtime/helpers/assertThisInitialized'));
var _inheritsLoose = _interopDefault(require('@babel/runtime/helpers/inheritsLoose'));
var React = require('react');
var React__default = _interopDefault(React);
var QRCode = _interopDefault(require('qrcode.react'));
var PropTypes = _interopDefault(require('prop-types'));
var StateQrCodeLogin = {
ready: "ready",
// 准备阶段,二维码未获取,界面准备阶段
loginFailed: "loginFailed",
// 登录反馈阶段:二维码扫描登录失败
loginSuccess: "loginSuccess",
// 登录反馈阶段:二维码扫描登录成功
scanComplete: "scanComplete",
// 登录反馈阶段: 二维码已经扫描,等待用户授权
codeOutWork: "codeOutWork",
// 登录反馈阶段: 二维码失效
networkLost: "networkLost",
// 登录反馈阶段:长连接丢失
qrCodeGetting: "qrCodeGetting",
// 信息获取:二维码获取...
qrCodeGetSuccess: "qrCodeGetSuccess",
// 信息获取:二维码获取成功
qrCodeGetFailed: "qrCodeGetFailed" // 信息获取:二维码获取失败
};
var ErrorType = {
eventSourceError: 0 // eventSource error
};
var noop = function noop() {};
var GlobalDebugEnable = false;
var debugLog = function debugLog(type) {
try {
if (GlobalDebugEnable) {
for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
args[_key - 1] = arguments[_key];
}
console[type || "log"].apply(console, [' [WODAX_DEBUG]: '].concat(args));
} else {
noop();
}
} catch (e) {
console.error(e);
}
};
var WodaXLoginWithQrCode =
/*#__PURE__*/
function (_PureComponent) {
_inheritsLoose(WodaXLoginWithQrCode, _PureComponent);
function WodaXLoginWithQrCode() {
var _this;
for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
args[_key2] = arguments[_key2];
}
_this = _PureComponent.call.apply(_PureComponent, [this].concat(args)) || this;
_this.state = {
// 默认状态
currentQrLoginState: StateQrCodeLogin.ready,
// 初始二维码值,二维码值来源于内部封装服务或者外部服务
qrcode: "",
// 接收到的事件存储起来
sseEvents: []
};
_this.updateQrCode = function () {
var _this$props = _this.props,
options = _this$props.options,
fetchQrCodeHandler = _this$props.fetchQrCodeHandler;
var oldQrCode = _this.state.qrcode;
var useEventSourceForFetchQrCode = options.useEventSourceForFetchQrCode;
_this.setState({
currentQrLoginState: StateQrCodeLogin.qrCodeGetting
}, function () {
if (!useEventSourceForFetchQrCode) {
_asyncToGenerator(
/*#__PURE__*/
_regeneratorRuntime.mark(function _callee() {
var response, code, data;
return _regeneratorRuntime.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
if (!fetchQrCodeHandler) {
_context.next = 12;
break;
}
_context.prev = 1;
_context.next = 4;
return fetchQrCodeHandler(_assertThisInitialized(_this));
case 4:
response = _context.sent;
code = response.code, data = response.data;
if (code === 0) {
if (oldQrCode === data) {
_this.setState({
currentQrLoginState: StateQrCodeLogin.qrCodeGetSuccess
});
} else {
_this.uninstallEventSource();
_this.setState({
currentQrLoginState: StateQrCodeLogin.qrCodeGetSuccess,
qrcode: data
}, function () {
_this.installEventSource({
qrcode: data
});
});
}
} else {
_this.uninstallEventSource();
_this.setState({
currentQrLoginState: StateQrCodeLogin.qrCodeGetFailed
});
}
_context.next = 12;
break;
case 9:
_context.prev = 9;
_context.t0 = _context["catch"](1);
console.error(_context.t0);
case 12:
case "end":
return _context.stop();
}
}
}, _callee, null, [[1, 9]]);
}))();
} else {
_this.uninstallEventSource();
_this.installEventSource();
}
});
};
_this.installEventSource = function (config) {
if (config === void 0) {
config = {};
}
var defaultOptions = WodaXLoginWithQrCode.defaultProps.options;
var _this$props2 = _this.props,
options = _this$props2.options,
onReceiveMessageHandler = _this$props2.onReceiveMessageHandler,
debugEnable = _this$props2.debugEnable; // 设置全局DebugEnable
GlobalDebugEnable = debugEnable; // 获取默认设置的EventSource可以处理的消息类型
var _defaultOptions$optio = _extends({}, defaultOptions, {}, options),
clientEventSource = _defaultOptions$optio.clientEventSource;
var url = clientEventSource.url,
params = clientEventSource.params,
messageTypes = clientEventSource.messageTypes,
withCredentials = clientEventSource.withCredentials,
saveAllEvents = clientEventSource.saveAllEvents;
var paramsString = Object.entries(_extends({}, params, {}, config)).map(function (_ref2) {
var key = _ref2[0],
value = _ref2[1];
return key + "=" + value;
}).join("&"); // 获取服务地址
var serviceUrl = encodeURI("" + url + (paramsString.length > 0 ? "?" : "") + paramsString);
debugLog("log", "---> SSE url", serviceUrl);
if (EventSource) {
// 判断当前存在的sse的url是否已经创建过
if (_this.sse) {
var _url = _this.sse.url;
if (_url === serviceUrl) {
return;
} else {
_this.uninstallEventSource();
}
} // 创建 EventSource 实例
debugLog("log", "--> installEventSource");
_this.sse = new EventSource(serviceUrl, {
withCredentials: !!withCredentials
}); // 注册事件监听
var sseMsgTypes = messageTypes || [];
sseMsgTypes = sseMsgTypes.includes("message") ? sseMsgTypes : sseMsgTypes.concat(["message"]);
sseMsgTypes.forEach(function (type) {
_this.sse.addEventListener(type, function (message) {
_this.setState(function (prevState) {
var events = (saveAllEvents ? prevState.sseEvents : []).concat(message);
return {
sseEvents: events
};
});
onReceiveMessageHandler && onReceiveMessageHandler(message, _assertThisInitialized(_this));
}, false);
});
_this.sse.onopen = function (e) {
debugLog("log", "---> SSE Open");
onReceiveMessageHandler && onReceiveMessageHandler(e, _assertThisInitialized(_this));
}; // 连接异常时会触发 error 事件并自动重连
_this.sse.onerror = function (e) {
var target = e.target;
var readyState = target.readyState;
if (EventSource.CLOSED === readyState) {
debugLog("log", "---> SSE Disconnected");
} else if (EventSource.CONNECTING === readyState) {
debugLog("log", "---> SSE Connecting...");
}
onReceiveMessageHandler && onReceiveMessageHandler(e, _assertThisInitialized(_this));
_this.onErrorEventHandler({
type: ErrorType.eventSourceError,
data: e
});
};
} else {
console.error("Your browser doesn't support SSE");
}
};
_this.uninstallEventSource = function () {
var debugEnable = _this.props.debugEnable;
if (_this.sse) {
try {
debugLog("log", "--> uninstallEventSource");
_this.sse.close();
} catch (e) {
debugLog("error", "--> uninstallEventSource [error]", e);
}
}
};
_this.onErrorEventHandler = function (errorInfo) {
try {
var type = errorInfo.type,
data = errorInfo.data;
if (type === ErrorType.eventSourceError) {} else {}
} catch (e) {
console.error(e);
}
};
return _this;
}
var _proto = WodaXLoginWithQrCode.prototype;
_proto.componentDidMount = function componentDidMount() {
this.updateQrCode();
};
_proto.componentWillUnmount = function componentWillUnmount() {
this.uninstallEventSource();
};
_proto.render = function render() {
var _this$props3 = this.props,
className = _this$props3.className,
style = _this$props3.style,
titleRender = _this$props3.titleRender,
qrCodeRender = _this$props3.qrCodeRender,
toolTipRender = _this$props3.toolTipRender,
additionLayerRender = _this$props3.additionLayerRender,
refreshQrCodeRender = _this$props3.refreshQrCodeRender,
sseMessageRender = _this$props3.sseMessageRender;
return React__default.createElement("div", {
className: className,
style: _extends({
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
flexDirection: 'column'
}, style)
}, titleRender(this), qrCodeRender(this), toolTipRender(this), additionLayerRender(this), refreshQrCodeRender(this), sseMessageRender(this));
}
/**
* 获取或更新二维码
*/
;
return WodaXLoginWithQrCode;
}(React.PureComponent);
/**
* 封装默认的渲染函数
* @private
*/
WodaXLoginWithQrCode.getEnumStateQrCodeLogin = function () {
return StateQrCodeLogin;
};
var _default = {
/**
* 最上部分标题渲染
* @param instance React Object
* @returns {*}
*/
titleRender: function titleRender(instance) {
var defaultOptions = WodaXLoginWithQrCode.defaultProps.options;
var options = instance.props.options;
var _defaultOptions$optio2 = _extends({}, defaultOptions, {}, options),
title = _defaultOptions$optio2.title,
titleStyle = _defaultOptions$optio2.titleStyle,
titleClassName = _defaultOptions$optio2.titleClassName,
appLogo = _defaultOptions$optio2.appLogo,
appLogoClassName = _defaultOptions$optio2.appLogoClassName,
appLogoStyle = _defaultOptions$optio2.appLogoStyle;
return React__default.createElement("div", {
className: titleClassName,
style: _extends({
padding: '4px'
}, titleStyle),
wodaxuiname: "TitleContainer"
}, React__default.createElement("span", null, title), appLogo !== "" ? React__default.createElement("div", {
className: appLogoClassName,
style: appLogoStyle,
wodaxuiname: "appLogoContainer"
}, React__default.createElement("img", {
src: appLogo,
alt: appLogo
})) : null);
},
/**
* 二维码显示渲染
* @param instance React Object
* @returns {*}
*/
qrCodeRender: function qrCodeRender(instance) {
var defaultOptions = WodaXLoginWithQrCode.defaultProps.options;
var options = instance.props.options;
var _defaultOptions$optio3 = _extends({}, defaultOptions, {}, options),
qrCodeContainerClassName = _defaultOptions$optio3.qrCodeContainerClassName,
qrCodeContainerStyle = _defaultOptions$optio3.qrCodeContainerStyle,
qrCodeContainerOpacity = _defaultOptions$optio3.qrCodeContainerOpacity,
qrCodeConfig = _defaultOptions$optio3.qrCodeConfig;
var _instance$state = instance.state,
qrcode = _instance$state.qrcode,
currentQrLoginState = _instance$state.currentQrLoginState;
var opacity = [StateQrCodeLogin.loginFailed, StateQrCodeLogin.loginSuccess, StateQrCodeLogin.scanComplete, StateQrCodeLogin.codeOutWork, StateQrCodeLogin.networkLost, StateQrCodeLogin.qrCodeGetting, StateQrCodeLogin.qrCodeGetFailed].includes(currentQrLoginState) ? qrCodeContainerOpacity["min"] : qrCodeContainerOpacity["max"];
return React__default.createElement("div", {
className: qrCodeContainerClassName,
style: _extends({
padding: '4px'
}, qrCodeContainerStyle, {
opacity: opacity
}),
wodaxuiname: "qrCodeContainer"
}, qrcode !== "" && React__default.createElement(QRCode, {
value: qrcode,
renderAs: qrCodeConfig.renderAs,
size: qrCodeConfig.size,
bgColor: qrCodeConfig.bgColor,
fgColor: qrCodeConfig.fgColor,
level: qrCodeConfig.level,
includeMargin: qrCodeConfig.includeMargin
}));
},
/**
* 提示信息显示渲染
* @param instance React Object
* @returns {*}
*/
toolTipRender: function toolTipRender(instance) {
var defaultOptions = WodaXLoginWithQrCode.defaultProps.options;
var options = instance.props.options;
var _defaultOptions$optio4 = _extends({}, defaultOptions, {}, options),
toolTipContainerClassName = _defaultOptions$optio4.toolTipContainerClassName,
toolTipContainerStyle = _defaultOptions$optio4.toolTipContainerStyle,
toolTipContainerProps = _defaultOptions$optio4.toolTipContainerProps;
var currentQrLoginState = instance.state.currentQrLoginState;
var uiMapRender = function uiMapRender() {
var uiMap = {}; // eslint-disable-next-line array-callback-return
Object.entries(StateQrCodeLogin).map(function (_ref3) {
var key = _ref3[0],
value = _ref3[1];
["Text", "ClassName", "Style"].forEach(function (attribute) {
if (_extends({}, defaultOptions, {}, options).hasOwnProperty("" + key + attribute)) {
var _extends2;
uiMap[key] = uiMap[key] || {};
uiMap[key] = _extends((_extends2 = {}, _extends2["" + attribute] = _extends({}, defaultOptions, {}, options)["" + key + attribute], _extends2), uiMap[key]);
}
});
});
var eleProps = uiMap[currentQrLoginState];
return eleProps ? React.createElement('div', _extends({
className: toolTipContainerClassName,
style: toolTipContainerStyle,
wodaxuiname: "toolTipContainer"
}, toolTipContainerProps), React__default.createElement("div", {
className: eleProps["ClassName"],
style: _extends({
padding: '4px'
}, eleProps["Style"])
}, React__default.createElement("span", null, eleProps["Text"]))) : null;
};
return uiMapRender();
},
/**
* 附加层处理,完全由外部绘制
* @param instance
* @returns {null}
*/
additionLayerRender: function additionLayerRender(instance) {
return null;
},
/**
* 刷新操作显示渲染
* @param instance React Object
* @returns {*}
*/
refreshQrCodeRender: function refreshQrCodeRender(instance) {
var defaultOptions = WodaXLoginWithQrCode.defaultProps.options;
var options = instance.props.options;
var _defaultOptions$optio5 = _extends({}, defaultOptions, {}, options),
refreshContainerShowEveryTime = _defaultOptions$optio5.refreshContainerShowEveryTime,
refreshContainerProps = _defaultOptions$optio5.refreshContainerProps,
refreshButtonCaption = _defaultOptions$optio5.refreshButtonCaption,
refreshButtonElement = _defaultOptions$optio5.refreshButtonElement,
refreshButtonProps = _defaultOptions$optio5.refreshButtonProps;
var currentQrLoginState = instance.state.currentQrLoginState;
var enableRenderElement = [// StateQrCodeLogin.ready,
StateQrCodeLogin.loginFailed, StateQrCodeLogin.codeOutWork, // StateQrCodeLogin.qrCodeGetting,
// StateQrCodeLogin.qrCodeGetSuccess,
StateQrCodeLogin.qrCodeGetFailed].indexOf(currentQrLoginState) > 0 || refreshContainerShowEveryTime;
return enableRenderElement && React.createElement("div", _extends({
wodaxuiname: "RefreshContainer"
}, refreshContainerProps), React.createElement(refreshButtonElement, _extends({
wodaxuiname: "RefreshButton",
onClick: function onClick() {
instance.updateQrCode();
}
}, refreshButtonProps), refreshButtonCaption));
},
/**
* 实时信息接收处理
* @param instance React Object
* @returns {null}
*/
sseMessageRender: function sseMessageRender(instance) {
var sseEvents = instance.state.sseEvents;
var defaultOptions = WodaXLoginWithQrCode.defaultProps.options;
var options = instance.props.options;
var _defaultOptions$optio6 = _extends({}, defaultOptions, {}, options),
showSSEMessage = _defaultOptions$optio6.showSSEMessage;
return instance.sse && sseEvents.length > 0 && showSSEMessage ? React__default.createElement("div", {
wodaxuiname: "sseMessageRender",
children: sseEvents.map(function (eventMsg) {
// TODO: 根据事件的数据,来处理
return React__default.createElement("p", null, eventMsg.data);
})
}) : null;
},
/**
* 获取二维码接口
* @param instance WodaXLoginWithQrCode 实例
* @returns {Promise<R>|Promise}
*/
fetchQrCodeHandler: function fetchQrCodeHandler(instance) {
return new Promise(function (resolve, reject) {
resolve({
code: 0,
data: "http://ops.woda.ink/wodax/umi/" + Date.now()
});
});
},
/**
* 接收SSE发过来的数据
* @param data SSE发送的数据
* @param instance WodaXLoginWithQrCode 实例
*/
onReceiveMessageHandler: function onReceiveMessageHandler(data, instance) {// debugLog(`log`, `onReceiveMessageHandler -->`, data);
}
};
WodaXLoginWithQrCode.propTypes = {
className: PropTypes.string,
Style: PropTypes.object,
// 是否开启日志调试
debugEnable: PropTypes.bool,
options:
/*#__PURE__*/
PropTypes.shape({
// 基础参数: {eventSource使用}
// 是否使用EventSource来重新获取最新QrCode
useEventSourceForFetchQrCode: PropTypes.bool,
// EventSource 的配置
clientEventSource:
/*#__PURE__*/
PropTypes.shape({
// EventSource 主要服务url
url: PropTypes.string,
// EventSource 附带参数
params: PropTypes.object,
// EventSource 可以处理的消息类型
messageTypes: PropTypes.array,
// withCredentials
withCredentials: PropTypes.bool,
// EventSource 是否保存所有接收到的事件
saveAllEvents: PropTypes.bool
}),
// 基础参数: {Title使用}
// 显示的Title内容
title: PropTypes.string,
titleStyle: PropTypes.object,
titleClassName: PropTypes.string,
// 基础参数: {AppLogo使用}
// 显示App的Logo
appLogo: PropTypes.string,
appLogoClassName: PropTypes.string,
appLogoStyle: PropTypes.object,
// 基础参数: {二维码配置}
// QrCode 二维码配置
// see: https://github.com/zpao/qrcode.react
qrCodeConfig:
/*#__PURE__*/
PropTypes.shape({
renderAs: PropTypes.string,
size: PropTypes.number,
bgColor: PropTypes.string,
fgColor: PropTypes.string,
level: PropTypes.string,
includeMargin: PropTypes.bool
}),
qrCodeContainerClassName: PropTypes.string,
qrCodeContainerStyle: PropTypes.object,
qrCodeContainerOpacity:
/*#__PURE__*/
PropTypes.shape({
min: PropTypes.number,
max: PropTypes.number
}),
// 基础参数: {提示信息}
toolTipContainerClassName: PropTypes.string,
toolTipContainerStyle: PropTypes.object,
toolTipContainerProps: PropTypes.object,
codeOutWorkText: PropTypes.string,
codeOutWorkClassName: PropTypes.string,
codeOutWorkStyle: PropTypes.object,
loginFailedText: PropTypes.string,
loginFailedClassName: PropTypes.string,
loginFailedStyle: PropTypes.object,
loginSuccessText: PropTypes.string,
loginSuccessClassName: PropTypes.string,
loginSuccessStyle: PropTypes.object,
qrCodeGetFailedText: PropTypes.string,
qrCodeGetFailedClassName: PropTypes.string,
qrCodeGetFailedStyle: PropTypes.object,
scanCompleteText: PropTypes.string,
scanCompleteClassName: PropTypes.string,
scanCompleteStyle: PropTypes.object,
// 基础参数: {刷新,重新获取二维码}
// 是否一直显示刷新区域
refreshContainerShowEveryTime: PropTypes.bool,
// 刷新最外层的div的Props
refreshContainerProps: PropTypes.object,
// 指定按钮的标题
refreshButtonCaption: PropTypes.string,
// 指定按钮的选择的元素
refreshButtonElement: PropTypes.string | PropTypes.element | PropTypes.elementType | PropTypes.func,
// 指定按钮的Props
refreshButtonProps: PropTypes.object,
// 基础参数: {实时信息接收处理}
// 是否默认显示sse回显信息
showSSEMessage: PropTypes.bool
}),
// 数据请求接口,可以覆盖
fetchQrCodeHandler: PropTypes.func.isRequired,
// 数据反馈接口。外接应用,可以自己处理所有来自服务器的消息
onReceiveMessageHandler: PropTypes.func,
// 渲染接口, 可以覆盖
titleRender: PropTypes.func.isRequired,
qrCodeRender: PropTypes.func.isRequired,
toolTipRender: PropTypes.func.isRequired,
additionLayerRender: PropTypes.func,
refreshQrCodeRender: PropTypes.func.isRequired,
sseMessageRender: PropTypes.func.isRequired
};
WodaXLoginWithQrCode.defaultProps = {
className: "wodax-login-with-qrcode",
Style: {},
// 是否开启日志调试
debugEnable: false,
// 可选项
options: {
// 基础参数: {eventSource使用}
// 是否使用EventSource来重新获取最新QrCode
useEventSourceForFetchQrCode: false,
clientEventSource: {
// EventSource 主要服务url
url: "https://stream.wikimedia.org/v2/stream/recentchange",
// EventSource 附带参数
params: {},
// EventSource 可以处理的消息类型
messageTypes: ["message"],
// withCredentials
withCredentials: false,
// EventSource 是否保存所有
saveAllEvents: false
},
// 基础参数: {Title使用}
title: "\u6253\u5F00App\uFF0C\u626B\u7801\u767B\u5F55",
titleClassName: "qr-login-title",
appLogo: "",
// QrCode 二维码配置
qrCodeConfig: {
renderAs: "canvas",
size: 128,
bgColor: "#FFFFFF",
fgColor: "#000000",
level: "L",
includeMargin: false
},
qrCodeContainerOpacity: {
min: 0.01,
max: 1
},
// 提示信息
toolTipContainerClassName: "qr-login-tooltip",
toolTipContainerStyle: {
padding: '4px',
position: 'absolute'
},
codeOutWorkText: "\u4E8C\u7EF4\u7801\u5DF2\u5931\u6548",
loginFailedText: "\u767B\u5F55\u5931\u8D25",
loginSuccessText: "\u767B\u5F55\u6210\u529F",
qrCodeGetFailedText: "\u83B7\u53D6\u4E8C\u7EF4\u7801\u5931\u8D25",
scanCompleteText: "\u626B\u63CF\u6210\u529F! \u8BF7\u5728\u624B\u673A\u4E0A\u786E\u8BA4\u767B\u5F55",
// 基础参数: {刷新区域,重新获取二维码}
// 是否一直显示刷新区域
refreshContainerShowEveryTime: false,
refreshContainerProps: {
style: {
padding: '4px',
position: 'absolute',
marginTop: '40px'
}
},
// 点击刷新
refreshButtonCaption: "\u8BF7\u70B9\u51FB\u5237\u65B0",
refreshButtonElement: "button",
refreshButtonProps: {
style: {
padding: '4px'
}
},
// 基础参数: {实时信息接收处理}
// 是否默认显示sse回显信息
showSSEMessage: false
},
// 数据请求接口,可以覆盖
fetchQrCodeHandler: _default.fetchQrCodeHandler,
// 数据反馈接口。外接应用,可以自己处理所有来自服务器的消息
onReceiveMessageHandler: _default.onReceiveMessageHandler,
// 渲染接口, 可以覆盖,重新写
titleRender: _default.titleRender,
qrCodeRender: _default.qrCodeRender,
toolTipRender: _default.toolTipRender,
additionLayerRender: _default.additionLayerRender,
refreshQrCodeRender: _default.refreshQrCodeRender,
sseMessageRender: _default.sseMessageRender
};
module.exports = WodaXLoginWithQrCode;
//# sourceMappingURL=index.cjs.js.map