@blazes/captcha 1.0.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api.d.ts +12 -0
- package/dist/captcha.d.ts +38 -0
- package/dist/draw.d.ts +5 -0
- package/dist/image-url.d.ts +7 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/lang.d.ts +51 -0
- package/dist/style.css +1 -0
- package/dist/template.d.ts +5 -0
- package/dist/test.d.ts +1 -0
- package/dist/type.d.ts +35 -0
- package/dist/utils.d.ts +17 -0
- package/package.json +47 -0
package/dist/api.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { IGetCaptcha, ICaptcha, IPostValidate } from "./type";
|
|
2
|
+
interface ApiInstanceConfig {
|
|
3
|
+
baseUrl: string;
|
|
4
|
+
}
|
|
5
|
+
export declare class ApiInstance {
|
|
6
|
+
private config;
|
|
7
|
+
constructor(config: ApiInstanceConfig);
|
|
8
|
+
private request;
|
|
9
|
+
getCaptcha(params: IGetCaptcha): Promise<ICaptcha>;
|
|
10
|
+
postValidate(token: string, params: IPostValidate): Promise<null>;
|
|
11
|
+
}
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { ICaptchaConfig } from "./type";
|
|
2
|
+
import "./assets/style/index.less";
|
|
3
|
+
export declare class Captcha {
|
|
4
|
+
private root;
|
|
5
|
+
private refs;
|
|
6
|
+
private token;
|
|
7
|
+
private eventNames;
|
|
8
|
+
private config;
|
|
9
|
+
private resolve;
|
|
10
|
+
private apiInstance;
|
|
11
|
+
constructor(config: ICaptchaConfig);
|
|
12
|
+
private setConfig;
|
|
13
|
+
resetConfig(config: Partial<ICaptchaConfig>): void;
|
|
14
|
+
private initEventNames;
|
|
15
|
+
private initRoot;
|
|
16
|
+
show(): Promise<string>;
|
|
17
|
+
private render;
|
|
18
|
+
private queryRef;
|
|
19
|
+
close(): void;
|
|
20
|
+
private retry;
|
|
21
|
+
private handleHeader;
|
|
22
|
+
private handleBody;
|
|
23
|
+
private drawBackground;
|
|
24
|
+
private addRefresh;
|
|
25
|
+
reset(): void;
|
|
26
|
+
private clearCanvas;
|
|
27
|
+
private handleBar;
|
|
28
|
+
private getClientX;
|
|
29
|
+
private verifyFail;
|
|
30
|
+
private verifySuccess;
|
|
31
|
+
private moveBar;
|
|
32
|
+
private fallbackBar;
|
|
33
|
+
private getChangeProperty;
|
|
34
|
+
private loopBar;
|
|
35
|
+
}
|
|
36
|
+
export interface Captcha {
|
|
37
|
+
new (config: ICaptchaConfig): Captcha;
|
|
38
|
+
}
|
package/dist/draw.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare const CloseImage: string;
|
|
2
|
+
export declare const ErrorImage: string;
|
|
3
|
+
export declare const WaitingImage: string;
|
|
4
|
+
export declare const LogoImage: string;
|
|
5
|
+
export declare const RefreshImage: string;
|
|
6
|
+
export declare const RetryImage: string;
|
|
7
|
+
export declare const LoadingImage: string;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { AppId, InRecord, Version } from "./type";
|
|
2
|
+
import { Captcha } from "./captcha";
|
|
3
|
+
declare global {
|
|
4
|
+
interface Window {
|
|
5
|
+
yh_captcha: {
|
|
6
|
+
Captcha: Captcha;
|
|
7
|
+
AppId: InRecord<typeof AppId>;
|
|
8
|
+
Version: InRecord<typeof Version>;
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export { Captcha, AppId, Version };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.yh_captcha=t():e.yh_captcha=t()}(window,(function(){return function(e){var t={};function s(a){if(t[a])return t[a].exports;var n=t[a]={i:a,l:!1,exports:{}};return e[a].call(n.exports,n,n.exports,s),n.l=!0,n.exports}return s.m=e,s.c=t,s.d=function(e,t,a){s.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:a})},s.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},s.t=function(e,t){if(1&t&&(e=s(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var a=Object.create(null);if(s.r(a),Object.defineProperty(a,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var n in e)s.d(a,n,function(t){return e[t]}.bind(null,n));return a},s.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return s.d(t,"a",t),t},s.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},s.p="",s(s.s=2)}([function(e,t,s){"use strict";var a,n,r;Object.defineProperty(t,"__esModule",{value:!0}),function(e){e.WEBVIEW="WebView",e.ACCOUNT="Account"}(a||(a={})),function(e){e.OPEN_URL="openUrl",e.CLOSE_WEBVIEW="closeWebView",e.GET_TOKEN="getToken"}(n||(n={})),function(e){e.SDK="sdk",e.UNITY="unity"}(r||(r={})),t.isAndriod=function(){return!!navigator.userAgent.match(/Android/i)},t.isInWebview=function(){return!!navigator.userAgent.match("YHSDK")},t.isIos=function(){return!!navigator.userAgent.match(/iPhone|iPad|iPod|Mac OS/i)&&"ontouchend"in document}},function(e,t,s){},function(e,t,s){"use strict";s.r(t),s.d(t,"Captcha",(function(){return v})),s.d(t,"AppId",(function(){return n})),s.d(t,"Version",(function(){return a}));const a={V1:"v1"},n={NINJA3:"ninja3"};var r=s(0);class c{constructor(e){this.config=e}request(e,t){return new Promise((s,a)=>{const{method:n,body:r}=t,c=new XMLHttpRequest;c.open(n.toLocaleUpperCase(),`${this.config.baseUrl}${e}`,!0),c.setRequestHeader("Content-type","application/json; charset=utf-8"),c.onreadystatechange=function(){if(4!==c.readyState)return;200!==c.status&&a("请求错误");const e=JSON.parse(c.responseText),{code:t,msg:n="",data:r}=e;0===t?s(r):a(n)},c.onerror=function(){a("网络错误")},c.ontimeout=function(){a("请求超时")},c.send(r?JSON.stringify(r):"")})}getCaptcha(e){return this.request(`/apis/v1/apps/${e.appId}/versions/${e.version}/captchas`,{method:"get"})}postValidate(e,t){return this.request(`/apis/v1/tokens/${e}/validate`,{method:"post",body:t})}}devicePixelRatio;function o(e,t){let s;const a=()=>{const t=Math.ceil(Math.random()*e);return t===e?t-1:t};return function(){let e=a();for(;e===s||t&&t(e);)e=a();return s=e,e}}o(250,e=>e<60),o(100,e=>e<50);function i(e){return+getComputedStyle(e).left.match(/\d+/)[0]}function d(e,t){let s;const a=new Promise(e=>s=e),n=new Image;return n.onload=()=>{null==t||t(n),s(n)},n.src=e,a}s(1);const l="https://resource.captcha.svc.pandadagames.com/puzzle-captcha/images/",h=l+"refresh.png";let p,u;!function(e){e.HANT="hant",e.HANS="hans",e.JA="ja",e.EN="en",e.KO="ko"}(p||(p={})),function(e){e.DRAG="drag",e.LOADING="loading",e.SUCCESS="success",e.FAIL="fail",e.RETRY="retry"}(u||(u={}));const g={[p.HANS]:{[u.DRAG]:"拖动左侧滑块将图片还原",[u.LOADING]:"加载中... ",[u.SUCCESS]:"验证成功",[u.FAIL]:"加载失败,",[u.RETRY]:"请点击重试!"},[p.HANT]:{[u.DRAG]:"拖動左側滑塊將圖片還原",[u.LOADING]:"加載中... ",[u.SUCCESS]:"驗證成功",[u.FAIL]:"加載失敗,",[u.RETRY]:"請點擊重試!"},[p.JA]:{[u.DRAG]:"矢印を右にスライドしてください",[u.LOADING]:"ロード中... ",[u.SUCCESS]:"認証成功",[u.FAIL]:"ロードに失敗、",[u.RETRY]:"再度お試してください"},[p.KO]:{[u.DRAG]:"왼쪽 이미지를 끌어 그림을 복원해 주세요.",[u.LOADING]:"로드 중... ",[u.SUCCESS]:"인증 성공",[u.FAIL]:"로드 실패,",[u.RETRY]:"재시도해 주세요!"},[p.EN]:{[u.DRAG]:"Slide from left to right to complete the image",[u.LOADING]:"Uploading",[u.SUCCESS]:"Verification Successful",[u.FAIL]:"Failed to load,",[u.RETRY]:"please tap to retry!"}},f=e=>`\n <div class="dx-captcha-mask"></div>\n <div class="dx-captcha-wrap">\n ${(e=>`\n <div class="dx-captcha-header">\n <img src=https://resource.captcha.svc.pandadagames.com/puzzle-captcha/images/close.png />\n </div>\n <div class="dx-captcha-body">\n <canvas></canvas>\n <img class="dx-captcha-body-slider" draggable="false" />\n <img class="dx-captcha-body-refresh" src=${h} width="16px" height="16px" />\n <img class="dx-captcha-body-logo" src=https://resource.captcha.svc.pandadagames.com/puzzle-captcha/images/logo.png width="50px" />\n <div class="dx-captcha-body-loading display-none">\n <div>\n <img class="dx-captcha-body-loading-img" src=https://resource.captcha.svc.pandadagames.com/puzzle-captcha/images/loading.gif />\n <div class="dx-captcha-body-loading-text">${g[e][u.LOADING]}</div>\n </div>\n </div>\n </div>\n <div class="dx-captcha-bar">\n <div class="dx-captcha-bar-slider"></div>\n <div class="dx-captcha-bar-progress"></div>\n <span class="dx-captcha-bar-text">\n ${g[e][u.DRAG]}\n </span>\n </div>\n`)(e)}\n </div>\n`;class v{constructor(e){this.setConfig(e),this.apiInstance=new c({baseUrl:e.baseUrl}),this.initEventNames()}setConfig(e){if(!Object.values(p).includes(e.lang))throw new Error(`传入的lang ${e.lang} 不正确`);this.config=Object.assign({},e)}resetConfig(e){this.config=Object.assign(this.config,e)}initEventNames(){Object(r.isAndriod)()||Object(r.isIos)()?this.eventNames={down:"touchstart",up:"touchend",move:"touchmove"}:this.eventNames={down:"mousedown",up:"mouseup",move:"mousemove"}}initRoot(){const e=document.createElement("div");return e.classList.add("dx-captcha-root"),document.body.appendChild(e),e}show(){this.root||(this.root=this.initRoot());const e=new Promise(e=>this.resolve=e);return this.render(),e}render(){this.root.innerHTML=f(this.config.lang),this.queryRef(),this.handleHeader(),this.handleBody().then(e=>{this.token=e,this.handleBar()})}queryRef(){const e=e=>this.root.querySelector(e),t=e(".dx-captcha-wrap"),s=e(".dx-captcha-header img"),a=e("canvas"),n=e(".dx-captcha-bar"),r=e(".dx-captcha-bar-slider"),c=e(".dx-captcha-body-slider"),o=e(".dx-captcha-body-refresh"),i=e(".dx-captcha-body-logo"),d=e(".dx-captcha-bar-progress"),l=e(".dx-captcha-bar-text"),h=e(".dx-captcha-body-loading");this.refs={wrapper:t,close:s,canvas:a,fragment:c,bar:n,slider:r,progress:d,infoText:l,refresh:o,logo:i,loading:h}}close(){const e=this.refs.wrapper;e.style.top="0",e.style.opacity="0",setTimeout(()=>{this.root.innerHTML=""},300)}retry(){var e;this.refs.wrapper.innerHTML=(e=this.config.lang,`\n <div class="dx-captcha-retry">\n <img class="dx-captcha-retry-img" src=https://resource.captcha.svc.pandadagames.com/puzzle-captcha/images/retry.jpg />\n <div>${g[e][u.FAIL]}<a class="dx-captcha-retry-link">${g[e][u.RETRY]}</a></div>\n </div>\n`);this.refs.wrapper.querySelector(".dx-captcha-retry-link").addEventListener("click",()=>{this.render()})}handleHeader(){this.refs.close.addEventListener("click",()=>{this.close()})}handleBody(){return this.addRefresh(),this.drawBackground()}drawBackground(){const{refs:e,apiInstance:t,config:s}=this,{canvas:a,loading:n,fragment:r}=e;a.width=300*devicePixelRatio,a.height=150*devicePixelRatio;const c=a.getContext("2d");let o;const i=new Promise(e=>o=e);return n.classList.remove("display-none"),t.getCaptcha({appId:s.appId,version:s.version}).then(e=>{let{y:t,token:s,bgUrl:i,fgUrl:l}=e;d(i,e=>{n.classList.add("display-none"),c.drawImage(e,0,0,a.width,a.height),r.src=l,r.style.top=t+"px",o(s)})}).catch(()=>{this.retry()}),i}addRefresh(){const e=this.refs.refresh;e.src=h,e.addEventListener("click",()=>{this.reset()})}reset(){this.clearCanvas(),this.drawBackground().then(e=>{this.token=e});const{slider:e,progress:t}=this.refs;this.loopBar(e=>{e.style.transitionDuration="0s"}),e.style.backgroundImage="url(https://resource.captcha.svc.pandadagames.com/puzzle-captcha/images/waiting.png)",t.classList.remove("error"),t.classList.add("success")}clearCanvas(){const e=this.refs.canvas;e.getContext("2d").clearRect(0,0,e.width,e.height)}handleBar(){const{down:e,move:t,up:s}=this.eventNames,{bar:a,fragment:n,slider:r,progress:c}=this.refs,o=a.getBoundingClientRect().width-r.getBoundingClientRect().width;let d,l;const h={value:!1},p=e=>{e.preventDefault();const t=this.getClientX(e)-d+l;t>o||t<0||this.moveBar(t)},u=()=>{document.body.removeEventListener(t,p),document.body.removeEventListener(s,u);const e=i(n);this.apiInstance.postValidate(this.token,{x:e}).then(()=>{this.verifySuccess()}).catch(()=>{this.verifyFail(h)})};r.addEventListener(e,e=>{h.value||(d=this.getClientX(e),l=i(n),c.classList.add("success"),document.body.addEventListener(t,p),document.body.addEventListener(s,u))})}getClientX(e){return e.clientX||e.touches[0].clientX}verifyFail(e){e.value=!0;const{slider:t,progress:s}=this.refs;t.style.backgroundImage="url(https://resource.captcha.svc.pandadagames.com/puzzle-captcha/images/error.png)",s.classList.remove("success"),s.classList.add("error"),this.fallbackBar(),setTimeout(()=>{this.reset(),e.value=!1},500)}verifySuccess(){const{refs:e,token:t,config:s}=this,a=e.bar;var n;a.innerHTML=(n=this.config.lang,`\n <span class="dx-captcha-bar-text">\n ${g[n][u.SUCCESS]}\n </span>\n`),a.classList.add("success"),setTimeout(()=>{var e;this.close(),null===(e=s.success)||void 0===e||e.call(s,t),this.resolve(t)})}moveBar(e){this.loopBar(t=>{t.style[this.getChangeProperty(t)]=e+"px"})}fallbackBar(){this.loopBar(e=>{e.style.transitionDuration="0.5s",e.style[this.getChangeProperty(e)]="0"})}getChangeProperty(e){return e.classList.contains("dx-captcha-bar-progress")?"width":"left"}loopBar(e){const{fragment:t,slider:s,progress:a}=this.refs;[t,s,a].forEach(t=>e(t))}}}])}));
|
|
2
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["webpack://yh_captcha/webpack/universalModuleDefinition","webpack://yh_captcha/webpack/bootstrap","webpack://yh_captcha/./node_modules/@blazes/webview-sdk/dist/env.js","webpack://yh_captcha/./src/type.ts","webpack://yh_captcha/./src/api.ts","webpack://yh_captcha/./src/draw.ts","webpack://yh_captcha/./src/utils.ts","webpack://yh_captcha/./src/image-url.ts","webpack://yh_captcha/./src/lang.ts","webpack://yh_captcha/./src/template.ts","webpack://yh_captcha/./src/captcha.ts"],"names":["root","factory","exports","module","define","amd","window","installedModules","__webpack_require__","moduleId","i","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","prototype","hasOwnProperty","p","s","e","WEBVIEW","ACCOUNT","OPEN_URL","CLOSE_WEBVIEW","GET_TOKEN","SDK","UNITY","isAndriod","navigator","userAgent","match","isInWebview","isIos","document","Version","V1","AppId","NINJA3","ApiInstance","constructor","config","this","request","url","Promise","resolve","reject","method","body","xhr","XMLHttpRequest","open","toLocaleUpperCase","baseUrl","setRequestHeader","onreadystatechange","readyState","status","data","JSON","parse","responseText","code","msg","respData","onerror","ontimeout","send","stringify","getCaptcha","params","appId","version","postValidate","token","devicePixelRatio","random","total","test","latest","calRandom","num","Math","ceil","result","BACK_WIDTH","BACK_HEIGHT","getLeft","el","getComputedStyle","left","loadImage","img","callback","resolved","promise","imgEl","Image","onload","src","host","RefreshImage","Language","Translate","resources","HANS","DRAG","LOADING","SUCCESS","FAIL","RETRY","HANT","JA","KO","EN","defaultTemplate","lang","wrapTemplate","Captcha","setConfig","apiInstance","initEventNames","values","includes","Error","assign","resetConfig","eventNames","down","up","move","initRoot","createElement","classList","add","appendChild","show","render","innerHTML","queryRef","handleHeader","handleBody","then","handleBar","query","selector","querySelector","wrapper","close","canvas","bar","slider","fragment","refresh","logo","progress","infoText","loading","refs","style","top","opacity","setTimeout","retry","addEventListener","addRefresh","drawBackground","width","height","ctx","getContext","remove","y","bgUrl","fgUrl","drawImage","catch","reset","clearCanvas","loopBar","transitionDuration","backgroundImage","clearRect","maxLeft","getBoundingClientRect","originX","curOffset","fallbacking","moveBar","event","preventDefault","offset","getClientX","upMouse","removeEventListener","x","verifySuccess","verifyFail","clientX","touches","fallbackBar","FALLBACK_DRUATION","success","getChangeProperty","contains","forEach"],"mappings":"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","file":"index.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"yh_captcha\"] = factory();\n\telse\n\t\troot[\"yh_captcha\"] = factory();\n})(window, function() {\nreturn "," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 2);\n","\"use strict\";Object.defineProperty(exports,\"__esModule\",{value:!0});var e,n,t;!function(e){e.WEBVIEW=\"WebView\",e.ACCOUNT=\"Account\"}(e||(e={})),function(e){e.OPEN_URL=\"openUrl\",e.CLOSE_WEBVIEW=\"closeWebView\",e.GET_TOKEN=\"getToken\"}(n||(n={})),function(e){e.SDK=\"sdk\",e.UNITY=\"unity\"}(t||(t={})),exports.isAndriod=function(){return!!navigator.userAgent.match(/Android/i)},exports.isInWebview=function(){return!!navigator.userAgent.match(\"YHSDK\")},exports.isIos=function(){return!!navigator.userAgent.match(/iPhone|iPad|iPod|Mac OS/i)&&\"ontouchend\"in document};\n//# sourceMappingURL=env.js.map\n","import { Language } from \"./lang\";\n\nexport const Version = {\n V1: \"v1\",\n} as const;\nexport const AppId = {\n NINJA3: \"ninja3\",\n} as const;\nexport type InRecord<T> = Record<keyof T, T[keyof T]>;\ntype ValueOf<T> = T[keyof T];\n\nexport interface IPostValidate {\n x: number;\n}\n\nexport interface IGetCaptcha {\n appId: string;\n version: string;\n}\n\nexport interface ICaptcha {\n token: string;\n bgUrl: string;\n fgUrl: string;\n y: number;\n}\n\nexport interface ICaptchaConfig {\n appId: ValueOf<typeof AppId>;\n success?: (token: string) => void;\n baseUrl: string;\n version: ValueOf<typeof Version>;\n lang: Language;\n}\n\nexport interface IResponse<T> {\n code: number;\n msg: string;\n data: T;\n}\n","import {\n IGetCaptcha,\n ICaptcha,\n IPostValidate,\n IResponse,\n} from \"./type\";\n\ninterface IRequestConfig {\n method: \"get\" | \"post\";\n body?: Record<string, any>;\n}\n\ninterface ApiInstanceConfig {\n baseUrl: string;\n}\n\nexport class ApiInstance {\n private config: ApiInstanceConfig;\n constructor(config: ApiInstanceConfig) {\n this.config = config;\n }\n\n private request<T>(url: string, config: IRequestConfig) {\n return new Promise<T>((resolve, reject) => {\n const { method, body } = config;\n const xhr = new XMLHttpRequest();\n\n xhr.open(\n method.toLocaleUpperCase(),\n `${this.config.baseUrl}${url}`,\n true\n );\n xhr.setRequestHeader(\"Content-type\", \"application/json; charset=utf-8\");\n\n xhr.onreadystatechange = function () {\n if (xhr.readyState !== 4) {\n return;\n }\n if (xhr.status !== 200) {\n reject(\"请求错误\");\n }\n const data = JSON.parse(xhr.responseText) as IResponse<T>;\n const { code, msg = \"\", data: respData } = data;\n if (code === 0) {\n resolve(respData);\n } else {\n reject(msg);\n }\n };\n xhr.onerror = function handleError() {\n reject(\"网络错误\");\n };\n xhr.ontimeout = function handleTimeout() {\n reject(\"请求超时\");\n };\n\n xhr.send(body ? JSON.stringify(body) : \"\");\n });\n }\n\n getCaptcha(params: IGetCaptcha): Promise<ICaptcha> {\n return this.request(\n `/apis/v1/apps/${params.appId}/versions/${params.version}/captchas`,\n {\n method: \"get\",\n }\n );\n }\n\n postValidate(token: string, params: IPostValidate): Promise<null> {\n return this.request(`/apis/v1/tokens/${token}/validate`, {\n method: \"post\",\n body: params,\n });\n }\n}\n","const SMALLER_WIDTH = 4;\nexport const IMG_SIZE = 50 * devicePixelRatio;\n\nexport function triangleDraw(\n ctx: CanvasRenderingContext2D,\n x: number,\n y: number,\n size: \"small\" | \"normal\" = \"normal\"\n) {\n const sideLength = 44 * devicePixelRatio;\n ctx.beginPath();\n if (size === \"normal\") {\n ctx.moveTo(x, y);\n ctx.lineTo(x + sideLength, y);\n ctx.lineTo(x + sideLength, y + sideLength);\n } else {\n ctx.moveTo(x + SMALLER_WIDTH * 2.5, y + SMALLER_WIDTH );\n ctx.lineTo(x + sideLength - SMALLER_WIDTH , y + SMALLER_WIDTH );\n ctx.lineTo(x + sideLength - SMALLER_WIDTH , y + sideLength - SMALLER_WIDTH * 2.5);\n }\n ctx.closePath();\n\n return { left: 3, top: 3 };\n}\n","import { IMG_SIZE, triangleDraw } from \"./draw\";\n\nexport function random(total: number, test?: (result: number) => boolean) {\n let latest: number;\n\n const calRandom = () => {\n const num = Math.ceil(Math.random() * total);\n return num === total ? num - 1 : num;\n };\n return function () {\n let result = calRandom();\n while (result === latest || (test && test(result))) {\n result = calRandom();\n }\n latest = result;\n\n return result;\n };\n}\n\nexport const BACK_WIDTH = 300;\nexport const BACK_HEIGHT = 150;\n\nexport const leftRandom = random(BACK_WIDTH - 50, (result) => result < 60);\nexport const topRandom = random(BACK_HEIGHT - 50, (result) => result < 50);\n\nexport function getLeft(el: HTMLElement) {\n return +getComputedStyle(el).left.match(/\\d+/)![0];\n}\n\nexport function loadImage(\n img: any,\n callback?: (img: HTMLImageElement) => void\n) {\n let resolved: (img: HTMLImageElement) => void;\n const promise = new Promise<HTMLImageElement>((r) => (resolved = r));\n const imgEl = new Image();\n imgEl.onload = () => {\n callback?.(imgEl);\n resolved(imgEl);\n };\n imgEl.src = img;\n\n return promise;\n}\n\nexport async function addBorder(\n canvas: HTMLCanvasElement,\n x: number,\n y: number,\n options: {\n shadowColor: string;\n fillStyle: string;\n reFillStyle?: string;\n }\n) {\n const ctx = canvas.getContext(\"2d\");\n const { shadowColor, fillStyle, reFillStyle } = options;\n triangleDraw(ctx, x, y);\n ctx.globalCompositeOperation = \"destination-in\";\n ctx.fill();\n\n const borderCanvas = canvas.cloneNode() as HTMLCanvasElement;\n const borderCtx = borderCanvas.getContext(\"2d\");\n triangleDraw(borderCtx, x, y);\n borderCtx.shadowBlur = 2;\n borderCtx.shadowColor = shadowColor;\n borderCtx.fillStyle = fillStyle;\n borderCtx.strokeStyle = shadowColor;\n borderCtx.fill();\n // borderCtx.lineWidth = 0.5;\n // borderCtx.stroke();\n\n triangleDraw(borderCtx, x, y, \"small\");\n borderCtx.shadowBlur = 0;\n borderCtx.globalCompositeOperation = \"destination-out\";\n borderCtx.fill();\n if (reFillStyle) {\n triangleDraw(borderCtx, x, y, \"small\");\n borderCtx.globalCompositeOperation = \"source-over\";\n borderCtx.fillStyle = reFillStyle;\n borderCtx.fill();\n }\n const url = await loadImage(canvasToPng(borderCanvas));\n ctx.globalCompositeOperation = \"source-over\";\n ctx.drawImage(url, 0, 0);\n\n return {\n left: x,\n top: y,\n };\n}\n\nexport function canvasToPng(canvas: HTMLCanvasElement) {\n return canvas.toDataURL(\"image/png\");\n}\n\nexport function coverCanvas(canvas: HTMLCanvasElement, x: number, y: number) {\n const ctx = canvas.getContext(\"2d\");\n const data = ctx.getImageData(x, y, IMG_SIZE, IMG_SIZE);\n canvas.width = IMG_SIZE;\n canvas.height = IMG_SIZE;\n ctx.putImageData(data, 0, 0);\n\n return canvas;\n}\n","const host =\n \"https://resource.captcha.svc.pandadagames.com/puzzle-captcha/images/\";\n\nexport const CloseImage = `${host}close.png`;\nexport const ErrorImage = `${host}error.png`;\nexport const WaitingImage = `${host}waiting.png`;\nexport const LogoImage = `${host}logo.png`;\nexport const RefreshImage = `${host}refresh.png`;\nexport const RetryImage = `${host}retry.jpg`;\nexport const LoadingImage = `${host}loading.gif`;\n","export enum Language {\n HANT = \"hant\",\n HANS = \"hans\",\n JA = \"ja\",\n EN = \"en\",\n KO = \"ko\",\n}\n\nexport enum Translate {\n DRAG = \"drag\",\n LOADING = \"loading\",\n SUCCESS = \"success\",\n FAIL = \"fail\",\n RETRY = \"retry\",\n}\n\nexport const resources = {\n [Language.HANS]: {\n [Translate.DRAG]: \"拖动左侧滑块将图片还原\",\n [Translate.LOADING]: \"加载中... \",\n [Translate.SUCCESS]: \"验证成功\",\n [Translate.FAIL]: \"加载失败,\",\n [Translate.RETRY]: \"请点击重试!\",\n },\n [Language.HANT]: {\n [Translate.DRAG]: \"拖動左側滑塊將圖片還原\",\n [Translate.LOADING]: \"加載中... \",\n [Translate.SUCCESS]: \"驗證成功\",\n [Translate.FAIL]: \"加載失敗,\",\n [Translate.RETRY]: \"請點擊重試!\",\n },\n [Language.JA]: {\n [Translate.DRAG]:\n \"矢印を右にスライドしてください\",\n [Translate.LOADING]: \"ロード中... \",\n [Translate.SUCCESS]: \"認証成功\",\n [Translate.FAIL]: \"ロードに失敗、\",\n [Translate.RETRY]: \"再度お試してください\",\n },\n [Language.KO]: {\n [Translate.DRAG]: \"왼쪽 이미지를 끌어 그림을 복원해 주세요.\",\n [Translate.LOADING]: \"로드 중... \",\n [Translate.SUCCESS]: \"인증 성공\",\n [Translate.FAIL]: \"로드 실패,\",\n [Translate.RETRY]: \"재시도해 주세요!\",\n },\n [Language.EN]: {\n [Translate.DRAG]: \"Slide from left to right to complete the image\",\n [Translate.LOADING]: \"Uploading\",\n [Translate.SUCCESS]: \"Verification Successful\",\n [Translate.FAIL]: \"Failed to load,\",\n [Translate.RETRY]: \"please tap to retry!\",\n },\n};\n","import {\n CloseImage,\n RefreshImage,\n LogoImage,\n LoadingImage,\n RetryImage,\n} from \"./image-url\";\nimport { Language, resources, Translate } from \"./lang\";\n\nexport const wrapTemplate = (lang: Language) => `\n <div class=\"dx-captcha-header\">\n <img src=${CloseImage} />\n </div>\n <div class=\"dx-captcha-body\">\n <canvas></canvas>\n <img class=\"dx-captcha-body-slider\" draggable=\"false\" />\n <img class=\"dx-captcha-body-refresh\" src=${RefreshImage} width=\"16px\" height=\"16px\" />\n <img class=\"dx-captcha-body-logo\" src=${LogoImage} width=\"50px\" />\n <div class=\"dx-captcha-body-loading display-none\">\n <div>\n <img class=\"dx-captcha-body-loading-img\" src=${LoadingImage} />\n <div class=\"dx-captcha-body-loading-text\">${\n resources[lang][Translate.LOADING]\n }</div>\n </div>\n </div>\n </div>\n <div class=\"dx-captcha-bar\">\n <div class=\"dx-captcha-bar-slider\"></div>\n <div class=\"dx-captcha-bar-progress\"></div>\n <span class=\"dx-captcha-bar-text\">\n ${resources[lang][Translate.DRAG]}\n </span>\n </div>\n`;\n\nexport const defaultTemplate = (lang: Language) => `\n <div class=\"dx-captcha-mask\"></div>\n <div class=\"dx-captcha-wrap\">\n ${wrapTemplate(lang)}\n </div>\n`;\n\nexport const successBarTemplate = (lang: Language) => `\n <span class=\"dx-captcha-bar-text\">\n ${resources[lang][Translate.SUCCESS]}\n </span>\n`;\n\nexport const retryTemplate = (lang: Language) => `\n <div class=\"dx-captcha-retry\">\n <img class=\"dx-captcha-retry-img\" src=${RetryImage} />\n <div>${\n resources[lang][Translate.FAIL]\n }<a class=\"dx-captcha-retry-link\">${\n resources[lang][Translate.RETRY]\n}</a></div>\n </div>\n`;\n","import { isAndriod, isIos } from \"@blazes/webview-sdk/dist/env\";\nimport { ApiInstance } from \"./api\";\nimport { ICaptchaConfig } from \"./type\";\nimport { getLeft, loadImage, BACK_WIDTH, BACK_HEIGHT } from \"./utils\";\nimport \"./assets/style/index.less\";\nimport { defaultTemplate, retryTemplate, successBarTemplate } from \"./template\";\nimport { RefreshImage, WaitingImage, ErrorImage } from \"./image-url\";\nimport { Language } from \"./lang\";\n\nconst FALLBACK_DRUATION = 0.5;\n\nexport class Captcha {\n private root: HTMLDivElement;\n private refs: {\n wrapper: HTMLDivElement;\n close: HTMLImageElement;\n canvas: HTMLCanvasElement;\n fragment: HTMLImageElement;\n refresh: HTMLImageElement;\n logo: HTMLImageElement;\n bar: HTMLDivElement;\n slider: HTMLDivElement;\n progress: HTMLDivElement;\n infoText: HTMLSpanElement;\n loading: HTMLElement;\n };\n private token: string;\n private eventNames: {\n down: string;\n up: string;\n move: string;\n };\n private config: ICaptchaConfig;\n private resolve: (token: string) => void;\n private apiInstance: ApiInstance;\n\n constructor(config: ICaptchaConfig) {\n this.setConfig(config);\n this.apiInstance = new ApiInstance({ baseUrl: config.baseUrl });\n this.initEventNames();\n }\n\n private setConfig(config: ICaptchaConfig) {\n if (!Object.values(Language).includes(config.lang)) {\n throw new Error(`传入的lang ${config.lang} 不正确`);\n }\n this.config = Object.assign({}, config);\n }\n\n resetConfig(config: Partial<ICaptchaConfig>) {\n this.config = Object.assign(this.config, config);\n }\n\n private initEventNames() {\n if (isAndriod() || isIos()) {\n this.eventNames = {\n down: \"touchstart\",\n up: \"touchend\",\n move: \"touchmove\",\n };\n } else {\n this.eventNames = {\n down: \"mousedown\",\n up: \"mouseup\",\n move: \"mousemove\",\n };\n }\n }\n\n private initRoot() {\n const root = document.createElement(\"div\");\n root.classList.add(\"dx-captcha-root\");\n document.body.appendChild(root);\n\n return root;\n }\n\n show() {\n if (!this.root) {\n this.root = this.initRoot();\n }\n const p = new Promise<string>((r) => (this.resolve = r));\n this.render();\n return p;\n }\n\n private render() {\n this.root.innerHTML = defaultTemplate(this.config.lang);\n this.queryRef();\n this.handleHeader();\n this.handleBody().then((token) => {\n this.token = token;\n this.handleBar();\n });\n }\n\n private queryRef() {\n const query = <T>(selector: string): T =>\n this.root.querySelector(selector) as unknown as T;\n const wrapper = query<HTMLDivElement>(\".dx-captcha-wrap\");\n const close = query<HTMLImageElement>(\".dx-captcha-header img\");\n const canvas = query<HTMLCanvasElement>(\"canvas\");\n const bar = query<HTMLDivElement>(\".dx-captcha-bar\");\n const slider = query<HTMLDivElement>(\".dx-captcha-bar-slider\");\n const fragment = query<HTMLImageElement>(\".dx-captcha-body-slider\");\n const refresh = query<HTMLImageElement>(\".dx-captcha-body-refresh\");\n const logo = query<HTMLImageElement>(\".dx-captcha-body-logo\");\n const progress = query<HTMLDivElement>(\".dx-captcha-bar-progress\");\n const infoText = query<HTMLSpanElement>(\".dx-captcha-bar-text\");\n const loading = query<HTMLSpanElement>(\".dx-captcha-body-loading\");\n\n this.refs = {\n wrapper,\n close,\n canvas,\n fragment,\n bar,\n slider,\n progress,\n infoText,\n refresh,\n logo,\n loading,\n };\n }\n\n close() {\n const wrapper = this.refs.wrapper;\n wrapper.style.top = \"0\";\n wrapper.style.opacity = \"0\";\n setTimeout(() => {\n this.root.innerHTML = \"\";\n }, 300);\n }\n\n private retry() {\n this.refs.wrapper.innerHTML = retryTemplate(this.config.lang);\n const retryLink = this.refs.wrapper.querySelector(\n \".dx-captcha-retry-link\"\n ) as HTMLLinkElement;\n retryLink.addEventListener(\"click\", () => {\n this.render();\n });\n }\n\n private handleHeader() {\n const closeEl = this.refs.close;\n closeEl.addEventListener(\"click\", () => {\n this.close();\n });\n }\n\n private handleBody() {\n this.addRefresh();\n return this.drawBackground();\n }\n\n private drawBackground() {\n const { refs, apiInstance, config } = this;\n const { canvas, loading, fragment } = refs;\n canvas.width = BACK_WIDTH * devicePixelRatio;\n canvas.height = BACK_HEIGHT * devicePixelRatio;\n const ctx = canvas.getContext(\"2d\");\n let resolved: (token: string) => void;\n const p = new Promise<string>((r) => (resolved = r));\n\n loading.classList.remove(\"display-none\");\n apiInstance\n .getCaptcha({ appId: config.appId, version: config.version })\n .then(({ y, token, bgUrl, fgUrl }) => {\n loadImage(bgUrl, (url) => {\n loading.classList.add(\"display-none\");\n ctx.drawImage(url, 0, 0, canvas.width, canvas.height);\n fragment.src = fgUrl;\n fragment.style.top = `${y}px`;\n\n resolved(token);\n });\n })\n .catch(() => {\n this.retry();\n });\n\n return p;\n }\n\n private addRefresh() {\n const refresh = this.refs.refresh;\n refresh.src = RefreshImage;\n refresh.addEventListener(\"click\", () => {\n this.reset();\n });\n }\n\n reset() {\n this.clearCanvas();\n this.drawBackground().then((token) => {\n this.token = token;\n });\n const { slider, progress } = this.refs;\n this.loopBar((el) => {\n el.style.transitionDuration = \"0s\";\n });\n slider.style.backgroundImage = `url(${WaitingImage})`;\n progress.classList.remove(\"error\");\n progress.classList.add(\"success\");\n }\n\n private clearCanvas() {\n const canvas = this.refs.canvas;\n const ctx = canvas.getContext(\"2d\");\n ctx.clearRect(0, 0, canvas.width, canvas.height);\n }\n\n private handleBar() {\n const { down, move, up } = this.eventNames;\n const { bar, fragment, slider, progress } = this.refs;\n const maxLeft =\n bar.getBoundingClientRect().width - slider.getBoundingClientRect().width;\n\n let originX: number, curOffset: number;\n const fallbacking = { value: false };\n const moveBar = (event: MouseEvent | TouchEvent) => {\n event.preventDefault();\n const offset = this.getClientX(event) - originX + curOffset;\n if (offset > maxLeft || offset < 0) {\n return;\n }\n this.moveBar(offset);\n };\n const upMouse = () => {\n document.body.removeEventListener(move, moveBar);\n document.body.removeEventListener(up, upMouse);\n const left = getLeft(fragment);\n this.apiInstance\n .postValidate(this.token, {\n x: left,\n })\n .then(() => {\n this.verifySuccess();\n })\n .catch(() => {\n this.verifyFail(fallbacking);\n });\n };\n slider.addEventListener(down, (event: MouseEvent | TouchEvent) => {\n if (fallbacking.value) {\n return;\n }\n originX = this.getClientX(event);\n curOffset = getLeft(fragment);\n progress.classList.add(\"success\");\n document.body.addEventListener(move, moveBar);\n document.body.addEventListener(up, upMouse);\n });\n }\n\n private getClientX(event: MouseEvent | TouchEvent) {\n return (\n (event as MouseEvent).clientX || (event as TouchEvent).touches[0].clientX\n );\n }\n\n private verifyFail(fallbacking: { value: boolean }) {\n fallbacking.value = true;\n const { slider, progress } = this.refs;\n slider.style.backgroundImage = `url(${ErrorImage})`;\n progress.classList.remove(\"success\");\n progress.classList.add(\"error\");\n this.fallbackBar();\n setTimeout(() => {\n this.reset();\n fallbacking.value = false;\n }, FALLBACK_DRUATION * 1000);\n }\n\n private verifySuccess() {\n const { refs, token, config } = this;\n const bar = refs.bar;\n bar.innerHTML = successBarTemplate(this.config.lang);\n bar.classList.add(\"success\");\n setTimeout(() => {\n this.close();\n config.success?.(token);\n this.resolve(token);\n });\n }\n\n private moveBar(offset: number) {\n this.loopBar((el) => {\n el.style[this.getChangeProperty(el)] = `${offset}px`;\n });\n }\n\n private fallbackBar() {\n this.loopBar((el) => {\n el.style.transitionDuration = `${FALLBACK_DRUATION}s`;\n el.style[this.getChangeProperty(el)] = \"0\";\n });\n }\n\n private getChangeProperty(el: HTMLElement) {\n return el.classList.contains(\"dx-captcha-bar-progress\") ? \"width\" : \"left\";\n }\n\n private loopBar(callback: (el: HTMLElement) => void) {\n const { fragment, slider, progress } = this.refs;\n [fragment, slider, progress].forEach((el) => callback(el));\n }\n}\n\nexport interface Captcha {\n new (config: ICaptchaConfig): Captcha;\n}\n"],"sourceRoot":""}
|
package/dist/lang.d.ts
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
export declare enum Language {
|
|
2
|
+
HANT = "hant",
|
|
3
|
+
HANS = "hans",
|
|
4
|
+
JA = "ja",
|
|
5
|
+
EN = "en",
|
|
6
|
+
KO = "ko"
|
|
7
|
+
}
|
|
8
|
+
export declare enum Translate {
|
|
9
|
+
DRAG = "drag",
|
|
10
|
+
LOADING = "loading",
|
|
11
|
+
SUCCESS = "success",
|
|
12
|
+
FAIL = "fail",
|
|
13
|
+
RETRY = "retry"
|
|
14
|
+
}
|
|
15
|
+
export declare const resources: {
|
|
16
|
+
hans: {
|
|
17
|
+
drag: string;
|
|
18
|
+
loading: string;
|
|
19
|
+
success: string;
|
|
20
|
+
fail: string;
|
|
21
|
+
retry: string;
|
|
22
|
+
};
|
|
23
|
+
hant: {
|
|
24
|
+
drag: string;
|
|
25
|
+
loading: string;
|
|
26
|
+
success: string;
|
|
27
|
+
fail: string;
|
|
28
|
+
retry: string;
|
|
29
|
+
};
|
|
30
|
+
ja: {
|
|
31
|
+
drag: string;
|
|
32
|
+
loading: string;
|
|
33
|
+
success: string;
|
|
34
|
+
fail: string;
|
|
35
|
+
retry: string;
|
|
36
|
+
};
|
|
37
|
+
ko: {
|
|
38
|
+
drag: string;
|
|
39
|
+
loading: string;
|
|
40
|
+
success: string;
|
|
41
|
+
fail: string;
|
|
42
|
+
retry: string;
|
|
43
|
+
};
|
|
44
|
+
en: {
|
|
45
|
+
drag: string;
|
|
46
|
+
loading: string;
|
|
47
|
+
success: string;
|
|
48
|
+
fail: string;
|
|
49
|
+
retry: string;
|
|
50
|
+
};
|
|
51
|
+
};
|
package/dist/style.css
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.dx-captcha-mask{background-color:#00000073;bottom:0;height:100%;left:0;position:fixed;right:0;top:0;z-index:1010}.dx-captcha-wrap{background:#fff;border-radius:4px;box-shadow:0 4px 12px #00000026;left:50%;padding:12px 20px;position:fixed;top:50%;transform:translate(-50%,-50%);transition:all .3s;z-index:1010}.dx-captcha-header{text-align:right}.dx-captcha-header img{cursor:pointer;height:14px;-webkit-user-select:none;-moz-user-select:none;user-select:none;width:14px}.dx-captcha-body{margin-top:4px;position:relative}.dx-captcha-body-slider{height:60px;left:10px;top:50%;transition-property:left;width:60px}.dx-captcha-body-refresh,.dx-captcha-body-slider{position:absolute;-webkit-user-select:none;-moz-user-select:none;user-select:none}.dx-captcha-body-refresh{cursor:pointer;left:275px;top:125px}.dx-captcha-body-logo{left:0;position:absolute;top:5px;-webkit-user-select:none;-moz-user-select:none;user-select:none}.dx-captcha-body canvas{height:150px;width:300px}.dx-captcha-body-loading{align-items:center;background:#fff;border:1px solid #e9e9e9;border-radius:4px;box-sizing:content-box;display:flex;flex-wrap:wrap;font-size:12px;height:146px;justify-content:center;left:0;margin-top:8px;position:absolute;text-align:center;top:0;width:298px}.dx-captcha-body-loading-img{width:24px}.dx-captcha-body-loading-text{margin-top:8px}.dx-captcha-bar{background:#f7f7f7;border:1px solid #d2d2d2;border-radius:4px;color:#999;font-size:14px;height:38px;line-height:38px;margin-top:8px;position:relative;text-align:center;touch-action:none}.dx-captcha-bar-slider{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHgAAABMCAYAAACmj3NpAAAGcklEQVR4Ae2c1ZPjyhXGvyMZhhfDzHCZwszMeQvTpdfMvxB8DXOewzxwaXl36MKULy14mHnMtvRlVKuukrvGcbbiqoxV5zfgdlef1lF/gra+agssXjkw+7ojHc73N6ve6zZqXjpX80UEIIgAU4ag7j1BiOlNAIB1rwQhEEAIEy9hW8Jqv08/ZNi/YJ94hu3kf4y34+x4k7+9rwD/U/6I1Av2HSua/O2xbRLf7SZ4TNzyYTc1sgW/H8AIIshLFs8ioGvjjamelYUTk7nq633fFwhRL6zUD4S9MyZBIUCCEibIcDDtg0RoD4LpN4xnGI96YUCTSyQPq18iEm+EFQBGnDBCIvmbfsP8o8KJRISIDry9X3ViMyzDiifE5CLh7kok3vQmlrBW/gjjovGO4/DGZM+F8rP63g6ggoDrmMF1GaZuun9+peMvV9j51yzvfXSNI5sl5mo+lYNNzq/xQnmbd65n6M4M0ZkZ4GuWTq/s6ZoKtEXw7/UPzp/r/EuWLx2c4UOrRSrtyQOldT5v/iEGIt+6dObc3t/Ve27nn6f8rr9MxURcFdmdG2Ribsjfu/2+Dq9/aPHEnsC855E1xgPlzo0M3dkB3rJy5oSzWfFeBxBfelEv4oHyle7ngQA2verrnI2SlwaA1/YmEQ+U65I9CFj3a2l0/inLzj9nGS8UZ3aA7twAHcQWhQRCgQXxQjGKOuYJSbxQCCNwLFEk/OeQREzRM5iEI3oPji0iAse4HPFDIQkHEMQZPYNjjn4OJhFPFBHAQWxRaB50kIgZikAAc4kWEcQNhQCojyptlmsVfCL7GPomT+B1T49irLjbtvJCxJ5kKXfOPom/bK9i16thtLCDd1wax6n8FtpVZQd1KA/kNhEl73n44JVHApHjMItWXp3ugoUlclv7wcqPXvBqdLtuQ5FPGpHb0w9Wbu/sxb9eenNDkT9kzuT29YOVt3YfNiK3/nKtfrCKrH6wiqx+sIqsfnBLRTaza/WDYyryh4zI6ge3t8j/bCLyicYi65OsAn1MVYpYqJbhoznZSgk/XZ/H77dXUCFb2L4xb2si8keuPIqJ4q76wTartSoe3NnAZDGH8cIOTuc24YFoxHBuA9c9eR53zT6Jz2Yn8aaLYyjSv/b2LRY559Xw6alJbPue+sFRMsVd+CAM214NM5USGvHN+UsoRgYxOCh+tb7QqvbNRQ7vyc9KpmEzVS7ih2uz6gdH2e9sKvo+GhBcyvepK7WmfetRP/h4IrVPXRKNeHfvUdi8x9S1oH0zghlz8PFouVqGzYvTnbj3+AvUD45yQ0cPjrlJ44Dg1R3deGZEdJsfPf9VeFcoUKfj4tvPfTneH7xvSfvm4gYz5mBSZdPjJvCHF9+AQ457IGbREiwAhwCFj78YB4EqCReAI4L/hmAy0+04SODa27da3GDS9Y+X3oy3dx/G/xt3bhABiYPmBydFcC0EZ0pL2rdA3GBmHUy+DgICgOoHt15c9YNVXPWDVVz1g1XcmPrBKq76wSpuYz9YCZaqxEDchn6wcs/skzEQt6EfrDxZLsRA3IZ+sPKuniOxENf4wYl6P1j56QtebRahBeuUgqUswWqHtl0fnNBHlfU8K5HCn19yo/rBiq4PVnQWrej6YEXXByvqB+v3RSv6fdGKfl+0on6won6won6wok+yFAJwuhMuSSDvEfFAydODQNAtCTpH01IWETy+U0E8UDLVHADimCTKzpFUYgQgfjuTQzxQflWYBwEcSXSMOJulWr+I8NfTOZxYK6G9UR4sb+CX+XkEmm55fr9TvWl25Ia+5AWC+MrEmorc5uJ+fn0Svu/jpkTPhSPCEdy6dAbXZZi66f75lY4/X2HX37K899E1jmyWmKv5VA42Ob/GC+Vt3rmeoTsztPc3yNcsnV65jpnU3h8k+IeAx1+b6llZODG5W3k9QQEAghABCAASKcOUGbEuePU1bAuD6UkAMWUgEh8p2/1EyhRCRML4q2XCD+Olcby1/fBd4+3b+Uf7tPMnAWmWf6RPO3/6gDTP37za9fb2HUd4Y7L3QvlZfW8HUAEQChyhOtj3ukMdzve3q7XXbVS9dN6j1Altb0wY1glIRnfWWFb2gIbx9sEhAH0g3FmJ1BO+GQRr0KzBpT1I0e3b4pr46IA3iY+Ia+rMQIuDMF5gC0PYB6fp245vnr8d3+26PCpu+YibHtmq+f0ARhDh35sXqn9Uq+ZoAAAAAElFTkSuQmCC);background-repeat:no-repeat;background-size:contain;border-radius:4px;box-shadow:0 0 3px #bcbcbc;cursor:move;height:38px;left:0;opacity:.7;position:absolute;transition-property:left;width:60px}.dx-captcha-bar-text{margin-left:22px;-webkit-user-select:none;-moz-user-select:none;user-select:none}.dx-captcha-bar-progress{bottom:0;left:0;position:absolute;top:0;transition-property:width}.dx-captcha-bar-progress.success{background:#d0fbee}.dx-captcha-bar-progress.error{background:#fa96a0}.dx-captcha-bar.success{background:#d4fff2;color:#01c7b5}.dx-captcha-bar.success .dx-captcha-bar-text{margin-left:0}.dx-captcha-retry{border:1px solid #e9e9e9;border-radius:4px;box-sizing:content-box;font-size:12px;height:186px;line-height:24px;margin-top:8px;overflow:hidden;text-align:center;width:100%}.dx-captcha-retry-img{margin:23px 60px 0;width:178px}.dx-captcha-retry a{color:#1f8efa;cursor:pointer}body{margin:0}.display-none{display:none}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { Language } from "./lang";
|
|
2
|
+
export declare const wrapTemplate: (lang: Language) => string;
|
|
3
|
+
export declare const defaultTemplate: (lang: Language) => string;
|
|
4
|
+
export declare const successBarTemplate: (lang: Language) => string;
|
|
5
|
+
export declare const retryTemplate: (lang: Language) => string;
|
package/dist/test.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import "./assets/style/index.less";
|
package/dist/type.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { Language } from "./lang";
|
|
2
|
+
export declare const Version: {
|
|
3
|
+
readonly V1: "v1";
|
|
4
|
+
};
|
|
5
|
+
export declare const AppId: {
|
|
6
|
+
readonly NINJA3: "ninja3";
|
|
7
|
+
};
|
|
8
|
+
export declare type InRecord<T> = Record<keyof T, T[keyof T]>;
|
|
9
|
+
declare type ValueOf<T> = T[keyof T];
|
|
10
|
+
export interface IPostValidate {
|
|
11
|
+
x: number;
|
|
12
|
+
}
|
|
13
|
+
export interface IGetCaptcha {
|
|
14
|
+
appId: string;
|
|
15
|
+
version: string;
|
|
16
|
+
}
|
|
17
|
+
export interface ICaptcha {
|
|
18
|
+
token: string;
|
|
19
|
+
bgUrl: string;
|
|
20
|
+
fgUrl: string;
|
|
21
|
+
y: number;
|
|
22
|
+
}
|
|
23
|
+
export interface ICaptchaConfig {
|
|
24
|
+
appId: ValueOf<typeof AppId>;
|
|
25
|
+
success?: (token: string) => void;
|
|
26
|
+
baseUrl: string;
|
|
27
|
+
version: ValueOf<typeof Version>;
|
|
28
|
+
lang: Language;
|
|
29
|
+
}
|
|
30
|
+
export interface IResponse<T> {
|
|
31
|
+
code: number;
|
|
32
|
+
msg: string;
|
|
33
|
+
data: T;
|
|
34
|
+
}
|
|
35
|
+
export {};
|
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export declare function random(total: number, test?: (result: number) => boolean): () => number;
|
|
2
|
+
export declare const BACK_WIDTH = 300;
|
|
3
|
+
export declare const BACK_HEIGHT = 150;
|
|
4
|
+
export declare const leftRandom: () => number;
|
|
5
|
+
export declare const topRandom: () => number;
|
|
6
|
+
export declare function getLeft(el: HTMLElement): number;
|
|
7
|
+
export declare function loadImage(img: any, callback?: (img: HTMLImageElement) => void): Promise<HTMLImageElement>;
|
|
8
|
+
export declare function addBorder(canvas: HTMLCanvasElement, x: number, y: number, options: {
|
|
9
|
+
shadowColor: string;
|
|
10
|
+
fillStyle: string;
|
|
11
|
+
reFillStyle?: string;
|
|
12
|
+
}): Promise<{
|
|
13
|
+
left: number;
|
|
14
|
+
top: number;
|
|
15
|
+
}>;
|
|
16
|
+
export declare function canvasToPng(canvas: HTMLCanvasElement): string;
|
|
17
|
+
export declare function coverCanvas(canvas: HTMLCanvasElement, x: number, y: number): HTMLCanvasElement;
|
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@blazes/captcha",
|
|
3
|
+
"version": "1.0.18",
|
|
4
|
+
"description": "滑动验证块",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist"
|
|
9
|
+
],
|
|
10
|
+
"publishConfig": {
|
|
11
|
+
"access": "public"
|
|
12
|
+
},
|
|
13
|
+
"scripts": {
|
|
14
|
+
"serve": "webpack-dev-server --config build/webpack.config.dev.js",
|
|
15
|
+
"build": "webpack --config build/webpack.config.prod.js && tsc --emitDeclarationOnly"
|
|
16
|
+
},
|
|
17
|
+
"author": "",
|
|
18
|
+
"license": "ISC",
|
|
19
|
+
"dependencies": {
|
|
20
|
+
"@blazes/webview-sdk": "^1.0.37"
|
|
21
|
+
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"@babel/core": "^7.17.9",
|
|
24
|
+
"@babel/preset-env": "^7.16.11",
|
|
25
|
+
"@babel/preset-typescript": "^7.16.7",
|
|
26
|
+
"autoprefixer": "^9.8.0",
|
|
27
|
+
"babel-loader": "^8.2.5",
|
|
28
|
+
"postcss-loader": "^3.0.0",
|
|
29
|
+
"ts-loader": "^6.2.2",
|
|
30
|
+
"typescript": "^4.6.4",
|
|
31
|
+
"url-loader": "^4.1.1",
|
|
32
|
+
"clean-webpack-plugin": "^3.0.0",
|
|
33
|
+
"copy-webpack-plugin": "^6.0.4",
|
|
34
|
+
"css-loader": "^3.5.3",
|
|
35
|
+
"file-loader": "^4.2.0",
|
|
36
|
+
"html-webpack-plugin": "^3.2.0",
|
|
37
|
+
"less": "^3.0.4",
|
|
38
|
+
"less-loader": "^5.0.0",
|
|
39
|
+
"less-plugin-npm-import": "^2.1.0",
|
|
40
|
+
"mini-css-extract-plugin": "^0.9.0",
|
|
41
|
+
"optimize-css-assets-webpack-plugin": "^6.0.0",
|
|
42
|
+
"webpack": "^4.0.0",
|
|
43
|
+
"webpack-cli": "^3.3.10",
|
|
44
|
+
"webpack-dev-server": "^3.11.0",
|
|
45
|
+
"webpack-merge": "^4.2.2"
|
|
46
|
+
}
|
|
47
|
+
}
|