MutliQRCode

PC端和移动端都可用的二维码识别

  1. // ==UserScript==
  2. // @name MutliQRCode
  3. // @namespace https://greasyfork.org/zh-CN/users/1073349
  4. // @version 0.5.4
  5. // @description PC端和移动端都可用的二维码识别
  6. // @author 4ehex
  7. // @grant GM_setValue
  8. // @grant GM_getValue
  9. // @grant GM_xmlhttpRequest
  10. // @match *://*/*
  11. // @icon data:image/svg+xml;base64,PHN2ZyBjbGFzcz0iaWNvbiIgc3R5bGU9IndpZHRoOiAxZW07aGVpZ2h0OiAxZW07dmVydGljYWwtYWxpZ246IG1pZGRsZTtmaWxsOiBjdXJyZW50Q29sb3I7b3ZlcmZsb3c6IGhpZGRlbjsiIHZpZXdCb3g9IjAgMCAxMDI0IDEwMjQiIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBwLWlkPSI3NjA1Ij48cGF0aCBkPSJNMTg2LjAyNjY2NyAwaDY1MS45NDY2NjZRMTAyNCAwIDEwMjQgMTg2LjAyNjY2N3Y2NTEuOTQ2NjY2UTEwMjQgMTAyNCA4MzcuOTczMzMzIDEwMjRIMTg2LjAyNjY2N1EwIDEwMjQgMCA4MzcuOTczMzMzVjE4Ni4wMjY2NjdRMCAwIDE4Ni4wMjY2NjcgMHoiIGZpbGw9IiMzNjg5RjUiIHAtaWQ9Ijc2MDYiPjwvcGF0aD48cGF0aCBkPSJNMjEzLjMzMzMzMyAzMDQuNjRBOTAuODggOTAuODggMCAwIDEgMzA0LjIxMzMzMyAyMTMuMzMzMzMzaDkwLjg4djQyLjY2NjY2N0gzMDYuMzQ2NjY3YTQ1LjY1MzMzMyA0NS42NTMzMzMgMCAwIDAtNDYuNTA2NjY3IDQ4LjY0djkxLjczMzMzM0gyMTMuMzMzMzMzek0zOTYuOCA4MTAuNjY2NjY3SDMwNi4zNDY2NjdhOTAuNDUzMzMzIDkwLjQ1MzMzMyAwIDAgMS05MC44OC05MS4zMDY2Njd2LTkxLjczMzMzM2g0Ni41MDY2NjZ2OTEuNzMzMzMzQTQ1LjY1MzMzMyA0NS42NTMzMzMgMCAwIDAgMzA4LjA1MzMzMyA3NjhoOTAuODhhMjk4LjY2NjY2NyAyOTguNjY2NjY3IDAgMCAwLTIuMTMzMzMzIDQyLjY2NjY2N3pNODEwLjY2NjY2NyA3MTkuMzZBOTAuNDUzMzMzIDkwLjQ1MzMzMyAwIDAgMSA3MTcuNjUzMzMzIDgxMC42NjY2NjdINjI3LjJ2LTQ2LjkzMzMzNGg5MC40NTMzMzNhNDUuNjUzMzMzIDQ1LjY1MzMzMyAwIDAgMCA0Ni41MDY2NjctNDYuNTA2NjY2di05MS4zMDY2NjdIODEwLjY2NjY2N3pNMjEzLjMzMzMzMyA0ODcuNjhoNTk1LjJ2NDYuOTMzMzMzSDIxMy4zMzMzMzN6TTgxMC42NjY2NjcgMzk2LjM3MzMzM2gtNDguNjRWMzA0LjY0YTQ1LjY1MzMzMyA0NS42NTMzMzMgMCAwIDAtNDYuMDgtNDYuNTA2NjY3aC05MC44OFYyMTMuMzMzMzMzaDkwLjg4YTkwLjg4IDkwLjg4IDAgMCAxIDkwLjg4IDkxLjMwNjY2N3oiIGZpbGw9IiNGRkZGRkYiIHAtaWQ9Ijc2MDciPjwvcGF0aD48L3N2Zz4=
  12. // @require https://update.greasyfork.org/scripts/469053/1207999/jsQR.js
  13. // @grant unsafeWindow
  14. // @license GPL
  15. // ==/UserScript==
  16.  
  17. (function() {
  18. 'use strict';
  19.  
  20. //全局变量 被选中的图片src
  21. var g_img_src = null;
  22. var g_is_moblie_env = isPhone();
  23. var g_cors_proxy = ['https://api.allorigins.win/get?url=', 'https://corsproxy.io/?', 'GM_xmlhttpRequest'];
  24. var g_usr_diy_cors = GM_getValue('usr_diy_cors', '');
  25. var g_cur_use_cors = GM_getValue('cur_use_cors', g_cors_proxy[0]);
  26.  
  27. //适配移动端 很多移动端浏览器并没有实现油猴接口
  28. //添加'识别二维码'按钮样式
  29. let btn_style = document.createElement('style');
  30. btn_style.type = 'text/css';
  31. if (!g_is_moblie_env){
  32. btn_style.innerText = `.idtfy_div{width:5.5vw;height:2.1vh;font-size:1vh;color:#000000;background:#F8F8FF;border-radius:1.5vh;border:0.12vh solid #f2cac9;line-height:2vh;text-align:center;vertical-align:middle;z-index:99999999;display:none;position:absolute;top:20;left:20;cursor:pointer;box-shadow:0.13vh 0.13vh 0.1vh #888888;}`;
  33. //GM_addStyle(`.idtfy_div{width:5.5vw;height:2.1vh;font-size:1vh;color:#000000;background:#F8F8FF;border-radius:1.5vh;border:0.12vh solid #f2cac9;line-height:2vh;text-align:center;vertical-align:middle;z-index:99999999;display:none;position:absolute;top:20;left:20;cursor:pointer;box-shadow:0.13vh 0.13vh 0.1vh #888888;}`);
  34. }
  35. else{
  36. btn_style.innerText = `.idtfy_div{width:25vw;height:3vh;font-size:1.6vh;color:#000000;background:#F8F8FF;border-radius:1.5vh;border:0.14vw solid #f2cac9;line-height:3vh;text-align:center;vertical-align:middle;z-index:99999999;display:none;position:absolute;top:20;left:20;cursor:pointer;box-shadow:0.15vw 0.15vw 0.13vw #888888;}`;
  37. }
  38. document.head.appendChild(btn_style);
  39.  
  40. //添加'识别二维码'按钮
  41. var identify_div = document.createElement('div');
  42. identify_div.id = 'identify_div';
  43. identify_div.className = 'idtfy_div';//👇添加一个图标
  44. identify_div.innerHTML = `<svg class="icon" style="width:1.3vh;height:1.3vh;vertical-align:middle;fill:currentColor;overflow:hidden" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3325"><path d="M613.888 715.264h-41.984C448.512 715.264 348.16 614.912 348.16 491.52s99.84-223.232 223.232-223.232h41.984c123.392 0 223.232 99.84 223.232 223.232 0.512 123.392-99.328 223.744-222.72 223.744z" fill="#CAD3FF" opacity=".2" p-id="3326"></path><path d="M873.984 940.032h-152.576c-14.336 0-25.6-11.264-25.6-25.6s11.264-25.6 25.6-25.6h147.456v-147.456c0-14.336 11.264-25.6 25.6-25.6s25.6 11.264 25.6 25.6v152.576c0 25.088-20.48 46.08-46.08 46.08zM894.464 311.296c-14.336 0-25.6-11.264-25.6-25.6v-148.48h-147.456c-14.336 0-25.6-11.264-25.6-25.6s11.264-25.6 25.6-25.6h152.576c25.6 0 46.08 20.48 46.08 46.08v153.6c0 13.824-11.264 25.6-25.6 25.6z m-20.48-174.08zM131.072 311.296c-14.336 0-25.6-11.264-25.6-25.6v-153.6c0-25.6 20.48-46.08 46.08-46.08h152.576c14.336 0 25.6 11.264 25.6 25.6s-11.264 25.6-25.6 25.6H156.672v148.48c0 13.824-11.776 25.6-25.6 25.6zM304.128 940.032H151.552c-25.6 0-46.08-20.48-46.08-46.08v-152.576c0-14.336 11.264-25.6 25.6-25.6s25.6 11.264 25.6 25.6v147.456h147.456c14.336 0 25.6 11.264 25.6 25.6s-11.264 25.6-25.6 25.6zM726.528 537.6H297.472c-14.336 0-25.6-11.264-25.6-25.6s11.264-25.6 25.6-25.6h429.056c14.336 0 25.6 11.264 25.6 25.6s-11.776 25.6-25.6 25.6z" fill="#4E63DD" p-id="3327"></path></svg> 识别二维码`;
  45. identify_div.onclick = OnClickedIdentifyBtn;
  46. document.body.appendChild(identify_div);
  47.  
  48. //添加精简后的'notie.js' 一款纯js实现的消息弹窗
  49. var notie=function(){function E(a,b,c){document.activeElement.blur(),D++,setTimeout(function(){D--},1e3*e+10),1==D&&(A?(clearTimeout(B),clearTimeout(C),G(function(){F(a,b,c)})):F(a,b,c))}function F(b,c,d){A=!0;var f=0;switch(f="undefined"==typeof d?3e3:1>d?1e3:1e3*d,b){case 1:v.style.backgroundColor=g,v.onclick=function(){};break;case 2:v.style.backgroundColor=h,v.onclick=w;break;case 3:v.style.backgroundColor=i,v.onclick=w;break;case 4:v.style.backgroundColor=j,v.onclick=w}y.innerHTML=c,v.style.top="-10000px",v.style.display="table",v.style.top="-"+v.offsetHeight-5+"px",B=setTimeout(function(){a&&(v.style.boxShadow="0px 0px 10px 0px rgba(0,0,0,0.5)"),v.style.MozTransition="all "+e+"s ease",v.style.WebkitTransition="all "+e+"s ease",v.style.transition="all "+e+"s ease",v.style.top=0,C=setTimeout(function(){G(function(){})},f)},20)}function G(b){v.style.top="-"+v.offsetHeight-5+"px",setTimeout(function(){a&&(v.style.boxShadow=""),v.style.MozTransition="",v.style.WebkitTransition="",v.style.transition="",v.style.top="-10000px",A=!1,b&&b()},1e3*e+10)}var v,w,x,y,A,B,C,D,a=!0,b="18px",c="24px",d=600,e=.3,g="#57BF57",h="#E3B771",i="#E1715B",j="#4D82D6",k="#FFF",l="notie-alert-outer",m="notie-alert-inner",n="notie-alert-text",o=function(a){a.style.fontSize=window.innerWidth<=d?b:c},p=500,q=function(a,b,c){var d;return function(){var e=this,f=arguments,g=function(){d=null,c||a.apply(e,f)},h=c&&!d;clearTimeout(d),d=setTimeout(g,b),h&&a.apply(e,f)}};return window.addEventListener("keydown",function(a){var b=13==a.which||13==a.keyCode,c=27==a.which||27==a.keyCode;A&&(b||c)&&(clearTimeout(B),clearTimeout(C),G())}),"undefined"==typeof Element.prototype.addEventListener&&(Element.prototype.addEventListener=Window.prototype.addEventListener=function(a,b){return a="on"+a,this.attachEvent(a,b)}),v=document.createElement("div"),v.id=l,v.style.position="fixed",v.style.top="0",v.style.left="0",v.style.zIndex="999999999",v.style.height="auto",v.style.width="100%",v.style.display="none",v.style.textAlign="center",v.style.cursor="default",v.style.MozTransition="",v.style.WebkitTransition="",v.style.transition="",v.style.cursor="pointer",w=function(){clearTimeout(B),clearTimeout(C),G()},x=document.createElement("div"),x.id=m,x.style.padding="20px",x.style.display="table-cell",x.style.verticalAlign="middle",v.appendChild(x),y=document.createElement("span"),y.id=n,y.style.color=k,y.style.fontSize=window.innerWidth<=d?b:c,window.addEventListener("resize",q(o.bind(null,y),p),!0),x.appendChild(y),document.body.appendChild(v),A=!1,D=0,{alert:E,alert_hide:G}}();
  50. //👆以上混淆纯粹为了压缩体积 原作者代码: https://github.com/jaredreich/notie
  51.  
  52. if (!g_is_moblie_env){
  53. //电脑端 右键弹出 双击隐藏
  54. window.onmousedown = function(e) {
  55. if (e.button == 2) {//右键
  56. var clickedElement = e.target;
  57. if (clickedElement.id == 'identify_div'){
  58. SelectCorsProxy();
  59. document.getElementById("identify_div").style.display = 'none';
  60. }
  61. else if ((g_img_src = GetQRSrc(clickedElement)) != null){
  62. document.getElementById("identify_div").style.top = (e.pageY + 10) + "px";
  63. document.getElementById("identify_div").style.left = (e.pageX) + "px";
  64. document.getElementById("identify_div").style.display = 'block';
  65. }
  66. else{
  67. document.getElementById("identify_div").style.display = 'none';
  68. }
  69. }
  70. };
  71.  
  72. window.ondblclick = function(e) {//双击隐藏按钮
  73. document.getElementById("identify_div").style.display = 'none';
  74. };
  75. }
  76. else{
  77. //移动端 监听长按事件
  78. let time_out = 0, touch_time = 800;
  79. window.addEventListener("touchstart", function(e){
  80. time_out = setTimeout(function(){
  81. var touchedElement = e.target;
  82. if (touchedElement.id == 'identify_div'){
  83. //长按识别按钮 弹出设置跨域代理服务器的设置窗口
  84. SelectCorsProxy();
  85. document.getElementById("identify_div").style.display = 'none';
  86. }
  87. else if ((g_img_src = GetQRSrc(touchedElement)) != null) {
  88. document.getElementById("identify_div").style.top = (e.touches[0].pageY - 50) + "px";
  89. document.getElementById("identify_div").style.left = (e.touches[0].pageX + 20) + "px";
  90. document.getElementById("identify_div").style.display = 'block';
  91. }
  92. }, touch_time);//touch_time毫秒后弹出识别按钮
  93.  
  94. //触碰其他地方则隐藏按钮
  95. if (e.target.id != 'identify_div'){
  96. g_img_src = null;
  97. document.getElementById("identify_div").style.display = 'none';
  98. }
  99. });
  100. window.addEventListener("touchmove", function(e){
  101. // 如果触摸未达到 touch_time ms且开始移动,则清除计时器
  102. clearTimeout(time_out);
  103. time_out = 0;
  104. });
  105. window.addEventListener("touchend", function(e){
  106. // 如果触摸未达到 touch_time ms且离开屏幕,则清除计时器
  107. clearTimeout(time_out);
  108. time_out = 0;
  109. });
  110. }
  111.  
  112. //设置/选择跨域代理服务器
  113. function SelectCorsProxy(){
  114. let select_html = `<select id="cors_select" style="width:200px; margin: 0px 5px;">[options_]</select><button id="sys_cors_btn">选用</button>`,
  115. options_html, usr_input_html = `<input id="usr_cors_input" placeholder="输入自定义代理网址" style="width:200px; margin: 0px 5px;" type="text" value="${g_usr_diy_cors}"><button id="usr_cors_btn">选用</button>`;
  116. for (let i = 0, len = g_cors_proxy.length; i < len; i++){
  117. options_html += `<option>${g_cors_proxy[i]}</option>`;
  118. }
  119. select_html = select_html.replace('[options_]', options_html);
  120. let setting_html = `<div>` + select_html + `<br>`+ usr_input_html + `<br><a id="cors_close_btn" href="javascript:void(0);">关闭</a></div>`;
  121. notie.alert(1, '选择一个跨域代理服务器<div style="color:blue">当前代理:' + g_cur_use_cors + '</div>' + setting_html, 60);
  122. setTimeout(()=>{
  123. document.getElementById("sys_cors_btn").onclick = function(){
  124. let obj = document.getElementById('cors_select');
  125. let text = obj.options[obj.selectedIndex].text; // 选中文本
  126. GM_setValue('cur_use_cors', text);
  127. g_cur_use_cors = text;
  128. notie.alert_hide();
  129. };
  130. document.getElementById("usr_cors_btn").onclick = function(){
  131. let obj = document.getElementById('usr_cors_input');
  132. let text = obj.value;
  133. GM_setValue('usr_diy_cors', text);
  134. g_usr_diy_cors = text;
  135. GM_setValue('cur_use_cors', text);
  136. g_cur_use_cors = text;
  137. notie.alert_hide();
  138. };
  139. document.getElementById("cors_close_btn").onclick = function(){notie.alert_hide();};
  140. }, 500);
  141. }
  142.  
  143. //通过UA判断是否是移动端
  144. function isPhone() {
  145. var info = navigator.userAgent;
  146. var isPhone = /mobile/i.test(info);
  147. return isPhone;
  148. }
  149.  
  150. //从传入的元素中获取IMG元素的src 若没有则返回null
  151. function GetQRSrc(ele){
  152. let ret_src = null;
  153. let ele_tag_name = ele.tagName.toLowerCase();//'IMG' 'svg' 'CANVAS'
  154.  
  155. if (ele_tag_name == 'img'){
  156. if (ele.src != null) ret_src = ele.src;
  157. }
  158. else if(ele_tag_name == 'svg'){
  159. ret_src = svg2b64(ele);
  160. }
  161. else if (ele_tag_name == 'canvas'){
  162. ret_src = ele.toDataURL();
  163. }
  164. else{
  165. //获取同胞元素 判断完同胞元素还需要判断子元素 因为可能获取到不是选择的图片
  166. for (let i = 0, sibling = ele.nextElementSibling;i < 6 && sibling != null; sibling = sibling.nextElementSibling, i++){
  167. if (sibling.tagName == 'IMG' && sibling.src != null){
  168. ret_src = sibling.src;
  169. break;
  170. }
  171. }
  172.  
  173. //遍历子元素看看是否有图片
  174. var childs = ele.childNodes;
  175. if (childs.length >= 6) return ret_src;
  176. for(var i = childs.length - 1; i >= 0; i--) {
  177. if (childs[i].tagName == 'IMG' && childs[i].src != null){
  178. ret_src = childs[i].src;
  179. break;
  180. }
  181. }
  182. }
  183.  
  184. return ret_src;
  185. }
  186.  
  187. //将图片URL转为jsqr需要的数据
  188. function Img2CanvasData(img_url){
  189. return new Promise((resolve, reject) => {
  190. const canvas = document.createElement("canvas");
  191. const ctx = canvas.getContext("2d");
  192. canvas.width = 500;
  193. canvas.height = 500;
  194. const img = new Image();
  195. //img.crossOrigin = '';
  196. img.onerror = () => {
  197. notie.alert(3, 'Image Err!', 4);
  198. };
  199. img.onload = () => {
  200. try{
  201. ctx.drawImage(img, 0, 0,300,300);
  202. let data = ctx.getImageData(0, 0, 300, 300).data;
  203. resolve(data);
  204. }
  205. catch(e){
  206. reject(e);
  207. }
  208. };
  209. img.src = img_url;
  210. });
  211. }
  212.  
  213. //cb_ok\cb_failed识别成功\失败时的回调函数
  214. function IdentifyQRCode(data, cb_ok, cb_failed){
  215. Img2CanvasData(data).then( res=>{
  216. const code = jsQR(res, 300, 300, {
  217. inversionAttempts: "dontInvert",
  218. });
  219. if (code) cb_ok(code.data, data); else cb_failed('IdentifyError', data);
  220. }).catch(err=>{
  221. cb_failed(err.name, data);
  222. });
  223. }
  224.  
  225. //'识别二维码'按钮事件
  226. function OnClickedIdentifyBtn(){
  227. if ((typeof jsQR != 'function')){
  228. notie.alert(2, '外部JS脚本未加载成功!', 3);
  229. return;
  230. }
  231.  
  232. if (g_img_src == null){
  233. notie.alert(2, '未选中任何图片', 2);
  234. }
  235. else {
  236. IdentifyQRCode(g_img_src, callback_ok, function(msg, url_){
  237. if (msg == 'IdentifyError'){
  238. notie.alert(3, '识别失败!', 3);
  239. }
  240. else if (msg == 'SecurityError'){
  241. if (g_cur_use_cors == 'GM_xmlhttpRequest'){//使用GM_xmlhttpRequest
  242. SyncXmlHttpRequest(url_, 'GET').then(data=>{
  243. if (data != null){
  244. IdentifyQRCode(data, callback_ok, function(){
  245. setTimeout(()=>{
  246. notie.alert(3, '识别失败!', 3);
  247. }, 500);
  248. });
  249. }
  250. else{
  251. notie.alert(3, '图片数据为空!', 3);
  252. }
  253. }).catch(err=>{
  254. notie.alert(3, 'SyncXmlHttpRequest Err: ' + err, 6);
  255. });
  256. }
  257. else{//使用跨域代理服务器
  258. if (g_cur_use_cors == '' || !isMaybeURL(g_cur_use_cors)) {
  259. notie.alert(2, '代理服务器不是一个正确的网址', 3);
  260. return;
  261. }
  262. notie.alert(4, '等待跨域代理服务器返回图片数据<div>⋘ 𝑃𝑙𝑒𝑎𝑠𝑒 𝑤𝑎𝑖𝑡... ⋙</div>', 20);
  263. let cors_proxy = g_cur_use_cors + encodeURIComponent(url_);
  264. fetchImage(cors_proxy).then((img_src)=>{
  265. if (img_src != null){
  266. IdentifyQRCode(img_src, callback_ok, function(){
  267. setTimeout(()=>{
  268. notie.alert(3, '识别失败!', 3);
  269. }, 500);//不等待500ms这个提示框会弹不出来,不知道为啥
  270. });
  271. }
  272. else{
  273. notie.alert(3, '图片数据为空!', 3);
  274. }
  275. });
  276. }
  277. }
  278. else{
  279. notie.alert(3, '未知错误!', 3);
  280. }
  281. });
  282. }
  283. document.getElementById("identify_div").style.display = 'none';
  284. }
  285.  
  286. //'复制'按钮单击事件
  287. function OnClickedCopyBtn(){
  288. //GM_setClipboard(document.getElementById("notie_all_text").innerText);
  289. navigator.clipboard.writeText(document.getElementById("notie_all_text").innerText);
  290. notie.alert(1, '复制成功!', 2);
  291. }
  292.  
  293. //判字符串是否可能为URL
  294. function isMaybeURL(str) {
  295. let is_maybe = false;
  296. if ((str.indexOf('://') != -1) ||
  297. (str.substr(0, 3) == 'www') ||
  298. (str.indexOf('.com') != -1 || str.indexOf('.cn') != -1 || str.indexOf('.org') != -1 || str.indexOf('.net') != -1) ||
  299. (str.indexOf('.') != -1 && str.indexOf('/') != -1)) is_maybe = true;
  300. return is_maybe;
  301. }
  302.  
  303. //fetch获取图片
  304. async function fetchImage(get_url) {
  305. try {
  306. const response = await fetch(get_url, {mode: "cors"});
  307. if (!response.ok) {
  308. throw new Error("Network response was not OK");
  309. }
  310. let img_data = null,
  311. data_type = response.headers.get("content-type"), data;
  312. if (data_type == "application/json"){
  313. data = await response.json();
  314. if (data.contents.length != 0) {
  315. img_data = data.contents;
  316. }
  317. }
  318. else if (data_type.indexOf('image') != -1){
  319. data = await response.blob();
  320. img_data = URL.createObjectURL(data);
  321. }
  322. return img_data;
  323.  
  324. } catch (error) {
  325. console.error("[Debug] There has been a problem with fetch operation:" + error);
  326. notie.alert(3, 'There has been a problem with fetch operation:' + error, 3);
  327. return null;
  328. }
  329. }
  330.  
  331. //以同步方式发送跨域请求
  332. function SyncXmlHttpRequest(request_url, method_type) {
  333. return new Promise((resolve, reject) => {
  334. GM_xmlhttpRequest({
  335. method: method_type,
  336. url: request_url,
  337. responseType: "blob",
  338. onload: function(response) {
  339. if (response.status != 200){
  340. return reject("Response Not 200 OK!");
  341. }
  342.  
  343. if (typeof response.response == 'undefined') return reject('你的油猴不支持blob返回值');
  344.  
  345. let data = response.response, img_data;
  346. if (data.length != 0){
  347. //img_data = b64EncodeUnicode(data);
  348. //console.log(img_data);
  349. //return resolve('data:image/png;base64,' + img_data);
  350.  
  351. img_data = URL.createObjectURL(data);
  352. return resolve(img_data);
  353. }
  354. return reject('response data is empty!');
  355.  
  356. },
  357. onerror: function(err) {
  358. return reject(err);
  359. }
  360. });
  361. });
  362. }
  363.  
  364. function callback_ok(text, url_){
  365. let display_text = text, ope_html = '<div><a id="notie_copy_btn" href="javascript:void(0);">复制</a>[placeholder_]<a id="notie_close_btn" style="margin-left: 20px" href="javascript:void(0);">关闭</a></div>';
  366. if (g_is_moblie_env && (text.length >= 40)){//如果是移动端 且识别内容过长 则隐藏一部分内容
  367. display_text = text.substr(0, 35) + '...';
  368. }
  369. if (isMaybeURL(text)){
  370. let jump_url = text;
  371. if (jump_url.indexOf('://') == -1) jump_url = 'https://' + jump_url;
  372. ope_html = ope_html.replace("[placeholder_]", '<a id="goto_btn" href="' + jump_url + '" target="_blank" style="margin-left: 20px">转到</a>');
  373. }
  374. else{
  375. ope_html = ope_html.replace("[placeholder_]", '<a id="notie_search_btn" href="https://www.baidu.com/s?wd=' + encodeURIComponent(text) + '" target="_blank" style="margin-left: 20px">搜索</a>');
  376. }
  377. setTimeout(()=>{
  378. notie.alert(1, '<a id="notie_all_text" style="display: none;">'+ text +'</a>识别到以下文本:<br><div style="word-wrap:break-word;">' + display_text + '</div>' + ope_html, 20);
  379. setTimeout(()=>{
  380. document.getElementById("notie_copy_btn").onclick = OnClickedCopyBtn;
  381. document.getElementById("notie_close_btn").onclick = function(){notie.alert_hide();};
  382. }, 500);
  383. }, 300);
  384.  
  385. }
  386.  
  387. //svg转base64
  388. function svg2b64(svg_ele) {
  389. const s = new XMLSerializer().serializeToString(svg_ele);
  390. const ImgBase64 = `data:image/svg+xml;base64,${window.btoa(s)}`;
  391. return ImgBase64;
  392. }
  393.  
  394. function b64EncodeUnicode(str) {
  395. // first we use encodeURIComponent to get percent-encoded Unicode,
  396. // then we convert the percent encodings into raw bytes which
  397. // can be fed into btoa.
  398. return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function toSolidBytes(match, p1) {return String.fromCharCode('0x' + p1);}));
  399. }
  400. })();