dsh-mobile-web 0.1.2 → 0.1.4
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/LICENSE-APACHE +202 -202
- package/NOTICE +26 -26
- package/README.md +128 -45
- package/assets/apple-touch-icon.png +0 -0
- package/assets/icon-192.png +0 -0
- package/assets/icon-512.png +0 -0
- package/assets/icon.svg +3 -11
- package/assets/mobile.bundle.js +1259 -326
- package/assets/theme.css +3492 -3439
- package/client.js +468 -141
- package/mobile-src/UPSTREAM.md +58 -50
- package/package.json +3 -2
- package/src/host/assets.js +9 -9
- package/src/host/cleanup.js +380 -0
- package/src/host/config.js +6 -0
- package/src/host/core.js +445 -18
- package/src/host/devices.js +226 -226
- package/src/host/http.js +8 -8
- package/src/host/pages.js +514 -514
- package/src/host/rpc/index.js +32 -32
- package/src/host/rpc/push.js +58 -58
- package/src/host/rpc/settings.js +88 -88
- package/src/host/rpc/subagent.js +27 -27
- package/src/host/state.js +30 -30
package/client.js
CHANGED
|
@@ -14,111 +14,268 @@ window.__ModuleLoader__.load({
|
|
|
14
14
|
const h = React.createElement
|
|
15
15
|
const { useState, useEffect, useCallback, useRef } = React
|
|
16
16
|
|
|
17
|
+
|
|
18
|
+
// ── QR 生成(qrcode-generator 2.0.4,MIT,Copyright (c) 2009 Kazuhiko Arase)──
|
|
19
|
+
// 无构建步骤的手写 client.js 不能 require npm 包;这里内联一个 MIT 的极简
|
|
20
|
+
// byte-mode 编码器(约 21KB,esbuild 压缩),在客户端直接算矩阵并绘制 SVG。
|
|
21
|
+
var __qrGen=(()=>{var or=(L,T)=>()=>{try{return T||L((T={exports:{}}).exports,T),T.exports}catch(N){throw T=0,N}};var vr=or((W,V)=>{var $=(function(){var L=function(x,w){var g=236,l=17,n=x,s=N[w],t=null,r=0,h=null,i=[],v={},_=function(a,f){r=n*4+17,t=(function(e){for(var u=new Array(e),o=0;o<e;o+=1){u[o]=new Array(e);for(var d=0;d<e;d+=1)u[o][d]=null}return u})(r),B(0,0),B(r-7,0),B(0,r-7),E(),C(),m(a,f),n>=7&&O(a),h==null&&(h=ir(n,s,i)),U(h,f)},B=function(a,f){for(var e=-1;e<=7;e+=1)if(!(a+e<=-1||r<=a+e))for(var u=-1;u<=7;u+=1)f+u<=-1||r<=f+u||(0<=e&&e<=6&&(u==0||u==6)||0<=u&&u<=6&&(e==0||e==6)||2<=e&&e<=4&&2<=u&&u<=4?t[a+e][f+u]=!0:t[a+e][f+u]=!1)},y=function(){for(var a=0,f=0,e=0;e<8;e+=1){_(!0,e);var u=P.getLostPoint(v);(e==0||a>u)&&(a=u,f=e)}return f},C=function(){for(var a=8;a<r-8;a+=1)t[a][6]==null&&(t[a][6]=a%2==0);for(var f=8;f<r-8;f+=1)t[6][f]==null&&(t[6][f]=f%2==0)},E=function(){for(var a=P.getPatternPosition(n),f=0;f<a.length;f+=1)for(var e=0;e<a.length;e+=1){var u=a[f],o=a[e];if(t[u][o]==null)for(var d=-2;d<=2;d+=1)for(var c=-2;c<=2;c+=1)d==-2||d==2||c==-2||c==2||d==0&&c==0?t[u+d][o+c]=!0:t[u+d][o+c]=!1}},O=function(a){for(var f=P.getBCHTypeNumber(n),e=0;e<18;e+=1){var u=!a&&(f>>e&1)==1;t[Math.floor(e/3)][e%3+r-8-3]=u}for(var e=0;e<18;e+=1){var u=!a&&(f>>e&1)==1;t[e%3+r-8-3][Math.floor(e/3)]=u}},m=function(a,f){for(var e=s<<3|f,u=P.getBCHTypeInfo(e),o=0;o<15;o+=1){var d=!a&&(u>>o&1)==1;o<6?t[o][8]=d:o<8?t[o+1][8]=d:t[r-15+o][8]=d}for(var o=0;o<15;o+=1){var d=!a&&(u>>o&1)==1;o<8?t[8][r-o-1]=d:o<9?t[8][15-o-1+1]=d:t[8][15-o-1]=d}t[r-8][8]=!a},U=function(a,f){for(var e=-1,u=r-1,o=7,d=0,c=P.getMaskFunction(f),p=r-1;p>0;p-=2)for(p==6&&(p-=1);;){for(var b=0;b<2;b+=1)if(t[u][p-b]==null){var D=!1;d<a.length&&(D=(a[d]>>>o&1)==1);var A=c(u,p-b);A&&(D=!D),t[u][p-b]=D,o-=1,o==-1&&(d+=1,o=7)}if(u+=e,u<0||r<=u){u-=e,e=-e;break}}},H=function(a,f){for(var e=0,u=0,o=0,d=new Array(f.length),c=new Array(f.length),p=0;p<f.length;p+=1){var b=f[p].dataCount,D=f[p].totalCount-b;u=Math.max(u,b),o=Math.max(o,D),d[p]=new Array(b);for(var A=0;A<d[p].length;A+=1)d[p][A]=255&a.getBuffer()[A+e];e+=b;var R=P.getErrorCorrectPolynomial(D),I=K(d[p],R.getLength()-1),S=I.mod(R);c[p]=new Array(R.getLength()-1);for(var A=0;A<c[p].length;A+=1){var X=A+S.getLength()-c[p].length;c[p][A]=X>=0?S.getAt(X):0}}for(var Z=0,A=0;A<f.length;A+=1)Z+=f[A].totalCount;for(var J=new Array(Z),Q=0,A=0;A<u;A+=1)for(var p=0;p<f.length;p+=1)A<d[p].length&&(J[Q]=d[p][A],Q+=1);for(var A=0;A<o;A+=1)for(var p=0;p<f.length;p+=1)A<c[p].length&&(J[Q]=c[p][A],Q+=1);return J},ir=function(a,f,e){for(var u=Y.getRSBlocks(a,f),o=G(),d=0;d<e.length;d+=1){var c=e[d];o.put(c.getMode(),4),o.put(c.getLength(),P.getLengthInBits(c.getMode(),a)),c.write(o)}for(var p=0,d=0;d<u.length;d+=1)p+=u[d].dataCount;if(o.getLengthInBits()>p*8)throw"code length overflow. ("+o.getLengthInBits()+">"+p*8+")";for(o.getLengthInBits()+4<=p*8&&o.put(0,4);o.getLengthInBits()%8!=0;)o.putBit(!1);for(;!(o.getLengthInBits()>=p*8||(o.put(g,8),o.getLengthInBits()>=p*8));)o.put(l,8);return H(o,u)};v.addData=function(a,f){f=f||"Byte";var e=null;switch(f){case"Numeric":e=q(a);break;case"Alphanumeric":e=z(a);break;case"Byte":e=rr(a);break;case"Kanji":e=tr(a);break;default:throw"mode:"+f}i.push(e),h=null},v.isDark=function(a,f){if(a<0||r<=a||f<0||r<=f)throw a+","+f;return t[a][f]},v.getModuleCount=function(){return r},v.make=function(){if(n<1){for(var a=1;a<40;a++){for(var f=Y.getRSBlocks(a,s),e=G(),u=0;u<i.length;u++){var o=i[u];e.put(o.getMode(),4),e.put(o.getLength(),P.getLengthInBits(o.getMode(),a)),o.write(e)}for(var d=0,u=0;u<f.length;u++)d+=f[u].dataCount;if(e.getLengthInBits()<=d*8)break}n=a}_(!1,y())},v.createTableTag=function(a,f){a=a||2,f=typeof f=="undefined"?a*4:f;var e="";e+='<table style="',e+=" border-width: 0px; border-style: none;",e+=" border-collapse: collapse;",e+=" padding: 0px; margin: "+f+"px;",e+='">',e+="<tbody>";for(var u=0;u<v.getModuleCount();u+=1){e+="<tr>";for(var o=0;o<v.getModuleCount();o+=1)e+='<td style="',e+=" border-width: 0px; border-style: none;",e+=" border-collapse: collapse;",e+=" padding: 0px; margin: 0px;",e+=" width: "+a+"px;",e+=" height: "+a+"px;",e+=" background-color: ",e+=v.isDark(u,o)?"#000000":"#ffffff",e+=";",e+='"/>';e+="</tr>"}return e+="</tbody>",e+="</table>",e},v.createSvgTag=function(a,f,e,u){var o={};typeof arguments[0]=="object"&&(o=arguments[0],a=o.cellSize,f=o.margin,e=o.alt,u=o.title),a=a||2,f=typeof f=="undefined"?a*4:f,e=typeof e=="string"?{text:e}:e||{},e.text=e.text||null,e.id=e.text?e.id||"qrcode-description":null,u=typeof u=="string"?{text:u}:u||{},u.text=u.text||null,u.id=u.text?u.id||"qrcode-title":null;var d=v.getModuleCount()*a+f*2,c,p,b,D,A="",R;for(R="l"+a+",0 0,"+a+" -"+a+",0 0,-"+a+"z ",A+='<svg version="1.1" xmlns="http://www.w3.org/2000/svg"',A+=o.scalable?"":' width="'+d+'px" height="'+d+'px"',A+=' viewBox="0 0 '+d+" "+d+'" ',A+=' preserveAspectRatio="xMinYMin meet"',A+=u.text||e.text?' role="img" aria-labelledby="'+F([u.id,e.id].join(" ").trim())+'"':"",A+=">",A+=u.text?'<title id="'+F(u.id)+'">'+F(u.text)+"</title>":"",A+=e.text?'<description id="'+F(e.id)+'">'+F(e.text)+"</description>":"",A+='<rect width="100%" height="100%" fill="white" cx="0" cy="0"/>',A+='<path d="',b=0;b<v.getModuleCount();b+=1)for(D=b*a+f,c=0;c<v.getModuleCount();c+=1)v.isDark(b,c)&&(p=c*a+f,A+="M"+p+","+D+R);return A+='" stroke="transparent" fill="black"/>',A+="</svg>",A},v.createDataURL=function(a,f){a=a||2,f=typeof f=="undefined"?a*4:f;var e=v.getModuleCount()*a+f*2,u=f,o=e-f;return fr(e,e,function(d,c){if(u<=d&&d<o&&u<=c&&c<o){var p=Math.floor((d-u)/a),b=Math.floor((c-u)/a);return v.isDark(b,p)?0:1}else return 1})},v.createImgTag=function(a,f,e){a=a||2,f=typeof f=="undefined"?a*4:f;var u=v.getModuleCount()*a+f*2,o="";return o+="<img",o+=' src="',o+=v.createDataURL(a,f),o+='"',o+=' width="',o+=u,o+='"',o+=' height="',o+=u,o+='"',e&&(o+=' alt="',o+=F(e),o+='"'),o+="/>",o};var F=function(a){for(var f="",e=0;e<a.length;e+=1){var u=a.charAt(e);switch(u){case"<":f+="<";break;case">":f+=">";break;case"&":f+="&";break;case'"':f+=""";break;default:f+=u;break}}return f},ur=function(a){var f=1;a=typeof a=="undefined"?f*2:a;var e=v.getModuleCount()*f+a*2,u=a,o=e-a,d,c,p,b,D,A={"\u2588\u2588":"\u2588","\u2588 ":"\u2580"," \u2588":"\u2584"," ":" "},R={"\u2588\u2588":"\u2580","\u2588 ":"\u2580"," \u2588":" "," ":" "},I="";for(d=0;d<e;d+=2){for(p=Math.floor((d-u)/f),b=Math.floor((d+1-u)/f),c=0;c<e;c+=1)D="\u2588",u<=c&&c<o&&u<=d&&d<o&&v.isDark(p,Math.floor((c-u)/f))&&(D=" "),u<=c&&c<o&&u<=d+1&&d+1<o&&v.isDark(b,Math.floor((c-u)/f))?D+=" ":D+="\u2588",I+=a<1&&d+1>=o?R[D]:A[D];I+=`
|
|
22
|
+
`}return e%2&&a>0?I.substring(0,I.length-e-1)+Array(e+1).join("\u2580"):I.substring(0,I.length-1)};return v.createASCII=function(a,f){if(a=a||1,a<2)return ur(f);a-=1,f=typeof f=="undefined"?a*2:f;var e=v.getModuleCount()*a+f*2,u=f,o=e-f,d,c,p,b,D=Array(a+1).join("\u2588\u2588"),A=Array(a+1).join(" "),R="",I="";for(d=0;d<e;d+=1){for(p=Math.floor((d-u)/a),I="",c=0;c<e;c+=1)b=1,u<=c&&c<o&&u<=d&&d<o&&v.isDark(p,Math.floor((c-u)/a))&&(b=0),I+=b?D:A;for(p=0;p<a;p+=1)R+=I+`
|
|
23
|
+
`}return R.substring(0,R.length-1)},v.renderTo2dContext=function(a,f){f=f||2;for(var e=v.getModuleCount(),u=0;u<e;u++)for(var o=0;o<e;o++)a.fillStyle=v.isDark(u,o)?"black":"white",a.fillRect(o*f,u*f,f,f)},v};L.stringToBytesFuncs={default:function(x){for(var w=[],g=0;g<x.length;g+=1){var l=x.charCodeAt(g);w.push(l&255)}return w}},L.stringToBytes=L.stringToBytesFuncs.default,L.createStringToBytes=function(x,w){var g=(function(){for(var n=nr(x),s=function(){var C=n.read();if(C==-1)throw"eof";return C},t=0,r={};;){var h=n.read();if(h==-1)break;var i=s(),v=s(),_=s(),B=String.fromCharCode(h<<8|i),y=v<<8|_;r[B]=y,t+=1}if(t!=w)throw t+" != "+w;return r})(),l=63;return function(n){for(var s=[],t=0;t<n.length;t+=1){var r=n.charCodeAt(t);if(r<128)s.push(r);else{var h=g[n.charAt(t)];typeof h=="number"?(h&255)==h?s.push(h):(s.push(h>>>8),s.push(h&255)):s.push(l)}}return s}};var T={MODE_NUMBER:1,MODE_ALPHA_NUM:2,MODE_8BIT_BYTE:4,MODE_KANJI:8},N={L:1,M:0,Q:3,H:2},k={PATTERN000:0,PATTERN001:1,PATTERN010:2,PATTERN011:3,PATTERN100:4,PATTERN101:5,PATTERN110:6,PATTERN111:7},P=(function(){var x=[[],[6,18],[6,22],[6,26],[6,30],[6,34],[6,22,38],[6,24,42],[6,26,46],[6,28,50],[6,30,54],[6,32,58],[6,34,62],[6,26,46,66],[6,26,48,70],[6,26,50,74],[6,30,54,78],[6,30,56,82],[6,30,58,86],[6,34,62,90],[6,28,50,72,94],[6,26,50,74,98],[6,30,54,78,102],[6,28,54,80,106],[6,32,58,84,110],[6,30,58,86,114],[6,34,62,90,118],[6,26,50,74,98,122],[6,30,54,78,102,126],[6,26,52,78,104,130],[6,30,56,82,108,134],[6,34,60,86,112,138],[6,30,58,86,114,142],[6,34,62,90,118,146],[6,30,54,78,102,126,150],[6,24,50,76,102,128,154],[6,28,54,80,106,132,158],[6,32,58,84,110,136,162],[6,26,54,82,110,138,166],[6,30,58,86,114,142,170]],w=1335,g=7973,l=21522,n={},s=function(t){for(var r=0;t!=0;)r+=1,t>>>=1;return r};return n.getBCHTypeInfo=function(t){for(var r=t<<10;s(r)-s(w)>=0;)r^=w<<s(r)-s(w);return(t<<10|r)^l},n.getBCHTypeNumber=function(t){for(var r=t<<12;s(r)-s(g)>=0;)r^=g<<s(r)-s(g);return t<<12|r},n.getPatternPosition=function(t){return x[t-1]},n.getMaskFunction=function(t){switch(t){case k.PATTERN000:return function(r,h){return(r+h)%2==0};case k.PATTERN001:return function(r,h){return r%2==0};case k.PATTERN010:return function(r,h){return h%3==0};case k.PATTERN011:return function(r,h){return(r+h)%3==0};case k.PATTERN100:return function(r,h){return(Math.floor(r/2)+Math.floor(h/3))%2==0};case k.PATTERN101:return function(r,h){return r*h%2+r*h%3==0};case k.PATTERN110:return function(r,h){return(r*h%2+r*h%3)%2==0};case k.PATTERN111:return function(r,h){return(r*h%3+(r+h)%2)%2==0};default:throw"bad maskPattern:"+t}},n.getErrorCorrectPolynomial=function(t){for(var r=K([1],0),h=0;h<t;h+=1)r=r.multiply(K([1,M.gexp(h)],0));return r},n.getLengthInBits=function(t,r){if(1<=r&&r<10)switch(t){case T.MODE_NUMBER:return 10;case T.MODE_ALPHA_NUM:return 9;case T.MODE_8BIT_BYTE:return 8;case T.MODE_KANJI:return 8;default:throw"mode:"+t}else if(r<27)switch(t){case T.MODE_NUMBER:return 12;case T.MODE_ALPHA_NUM:return 11;case T.MODE_8BIT_BYTE:return 16;case T.MODE_KANJI:return 10;default:throw"mode:"+t}else if(r<41)switch(t){case T.MODE_NUMBER:return 14;case T.MODE_ALPHA_NUM:return 13;case T.MODE_8BIT_BYTE:return 16;case T.MODE_KANJI:return 12;default:throw"mode:"+t}else throw"type:"+r},n.getLostPoint=function(t){for(var r=t.getModuleCount(),h=0,i=0;i<r;i+=1)for(var v=0;v<r;v+=1){for(var _=0,B=t.isDark(i,v),y=-1;y<=1;y+=1)if(!(i+y<0||r<=i+y))for(var C=-1;C<=1;C+=1)v+C<0||r<=v+C||y==0&&C==0||B==t.isDark(i+y,v+C)&&(_+=1);_>5&&(h+=3+_-5)}for(var i=0;i<r-1;i+=1)for(var v=0;v<r-1;v+=1){var E=0;t.isDark(i,v)&&(E+=1),t.isDark(i+1,v)&&(E+=1),t.isDark(i,v+1)&&(E+=1),t.isDark(i+1,v+1)&&(E+=1),(E==0||E==4)&&(h+=3)}for(var i=0;i<r;i+=1)for(var v=0;v<r-6;v+=1)t.isDark(i,v)&&!t.isDark(i,v+1)&&t.isDark(i,v+2)&&t.isDark(i,v+3)&&t.isDark(i,v+4)&&!t.isDark(i,v+5)&&t.isDark(i,v+6)&&(h+=40);for(var v=0;v<r;v+=1)for(var i=0;i<r-6;i+=1)t.isDark(i,v)&&!t.isDark(i+1,v)&&t.isDark(i+2,v)&&t.isDark(i+3,v)&&t.isDark(i+4,v)&&!t.isDark(i+5,v)&&t.isDark(i+6,v)&&(h+=40);for(var O=0,v=0;v<r;v+=1)for(var i=0;i<r;i+=1)t.isDark(i,v)&&(O+=1);var m=Math.abs(100*O/r/r-50)/5;return h+=m*10,h},n})(),M=(function(){for(var x=new Array(256),w=new Array(256),g=0;g<8;g+=1)x[g]=1<<g;for(var g=8;g<256;g+=1)x[g]=x[g-4]^x[g-5]^x[g-6]^x[g-8];for(var g=0;g<255;g+=1)w[x[g]]=g;var l={};return l.glog=function(n){if(n<1)throw"glog("+n+")";return w[n]},l.gexp=function(n){for(;n<0;)n+=255;for(;n>=256;)n-=255;return x[n]},l})();function K(x,w){if(typeof x.length=="undefined")throw x.length+"/"+w;var g=(function(){for(var n=0;n<x.length&&x[n]==0;)n+=1;for(var s=new Array(x.length-n+w),t=0;t<x.length-n;t+=1)s[t]=x[t+n];return s})(),l={};return l.getAt=function(n){return g[n]},l.getLength=function(){return g.length},l.multiply=function(n){for(var s=new Array(l.getLength()+n.getLength()-1),t=0;t<l.getLength();t+=1)for(var r=0;r<n.getLength();r+=1)s[t+r]^=M.gexp(M.glog(l.getAt(t))+M.glog(n.getAt(r)));return K(s,0)},l.mod=function(n){if(l.getLength()-n.getLength()<0)return l;for(var s=M.glog(l.getAt(0))-M.glog(n.getAt(0)),t=new Array(l.getLength()),r=0;r<l.getLength();r+=1)t[r]=l.getAt(r);for(var r=0;r<n.getLength();r+=1)t[r]^=M.gexp(M.glog(n.getAt(r))+s);return K(t,0).mod(n)},l}var Y=(function(){var x=[[1,26,19],[1,26,16],[1,26,13],[1,26,9],[1,44,34],[1,44,28],[1,44,22],[1,44,16],[1,70,55],[1,70,44],[2,35,17],[2,35,13],[1,100,80],[2,50,32],[2,50,24],[4,25,9],[1,134,108],[2,67,43],[2,33,15,2,34,16],[2,33,11,2,34,12],[2,86,68],[4,43,27],[4,43,19],[4,43,15],[2,98,78],[4,49,31],[2,32,14,4,33,15],[4,39,13,1,40,14],[2,121,97],[2,60,38,2,61,39],[4,40,18,2,41,19],[4,40,14,2,41,15],[2,146,116],[3,58,36,2,59,37],[4,36,16,4,37,17],[4,36,12,4,37,13],[2,86,68,2,87,69],[4,69,43,1,70,44],[6,43,19,2,44,20],[6,43,15,2,44,16],[4,101,81],[1,80,50,4,81,51],[4,50,22,4,51,23],[3,36,12,8,37,13],[2,116,92,2,117,93],[6,58,36,2,59,37],[4,46,20,6,47,21],[7,42,14,4,43,15],[4,133,107],[8,59,37,1,60,38],[8,44,20,4,45,21],[12,33,11,4,34,12],[3,145,115,1,146,116],[4,64,40,5,65,41],[11,36,16,5,37,17],[11,36,12,5,37,13],[5,109,87,1,110,88],[5,65,41,5,66,42],[5,54,24,7,55,25],[11,36,12,7,37,13],[5,122,98,1,123,99],[7,73,45,3,74,46],[15,43,19,2,44,20],[3,45,15,13,46,16],[1,135,107,5,136,108],[10,74,46,1,75,47],[1,50,22,15,51,23],[2,42,14,17,43,15],[5,150,120,1,151,121],[9,69,43,4,70,44],[17,50,22,1,51,23],[2,42,14,19,43,15],[3,141,113,4,142,114],[3,70,44,11,71,45],[17,47,21,4,48,22],[9,39,13,16,40,14],[3,135,107,5,136,108],[3,67,41,13,68,42],[15,54,24,5,55,25],[15,43,15,10,44,16],[4,144,116,4,145,117],[17,68,42],[17,50,22,6,51,23],[19,46,16,6,47,17],[2,139,111,7,140,112],[17,74,46],[7,54,24,16,55,25],[34,37,13],[4,151,121,5,152,122],[4,75,47,14,76,48],[11,54,24,14,55,25],[16,45,15,14,46,16],[6,147,117,4,148,118],[6,73,45,14,74,46],[11,54,24,16,55,25],[30,46,16,2,47,17],[8,132,106,4,133,107],[8,75,47,13,76,48],[7,54,24,22,55,25],[22,45,15,13,46,16],[10,142,114,2,143,115],[19,74,46,4,75,47],[28,50,22,6,51,23],[33,46,16,4,47,17],[8,152,122,4,153,123],[22,73,45,3,74,46],[8,53,23,26,54,24],[12,45,15,28,46,16],[3,147,117,10,148,118],[3,73,45,23,74,46],[4,54,24,31,55,25],[11,45,15,31,46,16],[7,146,116,7,147,117],[21,73,45,7,74,46],[1,53,23,37,54,24],[19,45,15,26,46,16],[5,145,115,10,146,116],[19,75,47,10,76,48],[15,54,24,25,55,25],[23,45,15,25,46,16],[13,145,115,3,146,116],[2,74,46,29,75,47],[42,54,24,1,55,25],[23,45,15,28,46,16],[17,145,115],[10,74,46,23,75,47],[10,54,24,35,55,25],[19,45,15,35,46,16],[17,145,115,1,146,116],[14,74,46,21,75,47],[29,54,24,19,55,25],[11,45,15,46,46,16],[13,145,115,6,146,116],[14,74,46,23,75,47],[44,54,24,7,55,25],[59,46,16,1,47,17],[12,151,121,7,152,122],[12,75,47,26,76,48],[39,54,24,14,55,25],[22,45,15,41,46,16],[6,151,121,14,152,122],[6,75,47,34,76,48],[46,54,24,10,55,25],[2,45,15,64,46,16],[17,152,122,4,153,123],[29,74,46,14,75,47],[49,54,24,10,55,25],[24,45,15,46,46,16],[4,152,122,18,153,123],[13,74,46,32,75,47],[48,54,24,14,55,25],[42,45,15,32,46,16],[20,147,117,4,148,118],[40,75,47,7,76,48],[43,54,24,22,55,25],[10,45,15,67,46,16],[19,148,118,6,149,119],[18,75,47,31,76,48],[34,54,24,34,55,25],[20,45,15,61,46,16]],w=function(n,s){var t={};return t.totalCount=n,t.dataCount=s,t},g={},l=function(n,s){switch(s){case N.L:return x[(n-1)*4+0];case N.M:return x[(n-1)*4+1];case N.Q:return x[(n-1)*4+2];case N.H:return x[(n-1)*4+3];default:return}};return g.getRSBlocks=function(n,s){var t=l(n,s);if(typeof t=="undefined")throw"bad rs block @ typeNumber:"+n+"/errorCorrectionLevel:"+s;for(var r=t.length/3,h=[],i=0;i<r;i+=1)for(var v=t[i*3+0],_=t[i*3+1],B=t[i*3+2],y=0;y<v;y+=1)h.push(w(_,B));return h},g})(),G=function(){var x=[],w=0,g={};return g.getBuffer=function(){return x},g.getAt=function(l){var n=Math.floor(l/8);return(x[n]>>>7-l%8&1)==1},g.put=function(l,n){for(var s=0;s<n;s+=1)g.putBit((l>>>n-s-1&1)==1)},g.getLengthInBits=function(){return w},g.putBit=function(l){var n=Math.floor(w/8);x.length<=n&&x.push(0),l&&(x[n]|=128>>>w%8),w+=1},g},q=function(x){var w=T.MODE_NUMBER,g=x,l={};l.getMode=function(){return w},l.getLength=function(t){return g.length},l.write=function(t){for(var r=g,h=0;h+2<r.length;)t.put(n(r.substring(h,h+3)),10),h+=3;h<r.length&&(r.length-h==1?t.put(n(r.substring(h,h+1)),4):r.length-h==2&&t.put(n(r.substring(h,h+2)),7))};var n=function(t){for(var r=0,h=0;h<t.length;h+=1)r=r*10+s(t.charAt(h));return r},s=function(t){if("0"<=t&&t<="9")return t.charCodeAt(0)-48;throw"illegal char :"+t};return l},z=function(x){var w=T.MODE_ALPHA_NUM,g=x,l={};l.getMode=function(){return w},l.getLength=function(s){return g.length},l.write=function(s){for(var t=g,r=0;r+1<t.length;)s.put(n(t.charAt(r))*45+n(t.charAt(r+1)),11),r+=2;r<t.length&&s.put(n(t.charAt(r)),6)};var n=function(s){if("0"<=s&&s<="9")return s.charCodeAt(0)-48;if("A"<=s&&s<="Z")return s.charCodeAt(0)-65+10;switch(s){case" ":return 36;case"$":return 37;case"%":return 38;case"*":return 39;case"+":return 40;case"-":return 41;case".":return 42;case"/":return 43;case":":return 44;default:throw"illegal char :"+s}};return l},rr=function(x){var w=T.MODE_8BIT_BYTE,g=x,l=L.stringToBytes(x),n={};return n.getMode=function(){return w},n.getLength=function(s){return l.length},n.write=function(s){for(var t=0;t<l.length;t+=1)s.put(l[t],8)},n},tr=function(x){var w=T.MODE_KANJI,g=x,l=L.stringToBytesFuncs.SJIS;if(!l)throw"sjis not supported.";(function(t,r){var h=l(t);if(h.length!=2||(h[0]<<8|h[1])!=r)throw"sjis not supported."})("\u53CB",38726);var n=l(x),s={};return s.getMode=function(){return w},s.getLength=function(t){return~~(n.length/2)},s.write=function(t){for(var r=n,h=0;h+1<r.length;){var i=(255&r[h])<<8|255&r[h+1];if(33088<=i&&i<=40956)i-=33088;else if(57408<=i&&i<=60351)i-=49472;else throw"illegal char at "+(h+1)+"/"+i;i=(i>>>8&255)*192+(i&255),t.put(i,13),h+=2}if(h<r.length)throw"illegal char at "+(h+1)},s},j=function(){var x=[],w={};return w.writeByte=function(g){x.push(g&255)},w.writeShort=function(g){w.writeByte(g),w.writeByte(g>>>8)},w.writeBytes=function(g,l,n){l=l||0,n=n||g.length;for(var s=0;s<n;s+=1)w.writeByte(g[s+l])},w.writeString=function(g){for(var l=0;l<g.length;l+=1)w.writeByte(g.charCodeAt(l))},w.toByteArray=function(){return x},w.toString=function(){var g="";g+="[";for(var l=0;l<x.length;l+=1)l>0&&(g+=","),g+=x[l];return g+="]",g},w},er=function(){var x=0,w=0,g=0,l="",n={},s=function(r){l+=String.fromCharCode(t(r&63))},t=function(r){if(!(r<0)){if(r<26)return 65+r;if(r<52)return 97+(r-26);if(r<62)return 48+(r-52);if(r==62)return 43;if(r==63)return 47}throw"n:"+r};return n.writeByte=function(r){for(x=x<<8|r&255,w+=8,g+=1;w>=6;)s(x>>>w-6),w-=6},n.flush=function(){if(w>0&&(s(x<<6-w),x=0,w=0),g%3!=0)for(var r=3-g%3,h=0;h<r;h+=1)l+="="},n.toString=function(){return l},n},nr=function(x){var w=x,g=0,l=0,n=0,s={};s.read=function(){for(;n<8;){if(g>=w.length){if(n==0)return-1;throw"unexpected end of file./"+n}var r=w.charAt(g);if(g+=1,r=="=")return n=0,-1;if(r.match(/^\s$/))continue;l=l<<6|t(r.charCodeAt(0)),n+=6}var h=l>>>n-8&255;return n-=8,h};var t=function(r){if(65<=r&&r<=90)return r-65;if(97<=r&&r<=122)return r-97+26;if(48<=r&&r<=57)return r-48+52;if(r==43)return 62;if(r==47)return 63;throw"c:"+r};return s},ar=function(x,w){var g=x,l=w,n=new Array(x*w),s={};s.setPixel=function(i,v,_){n[v*g+i]=_},s.write=function(i){i.writeString("GIF87a"),i.writeShort(g),i.writeShort(l),i.writeByte(128),i.writeByte(0),i.writeByte(0),i.writeByte(0),i.writeByte(0),i.writeByte(0),i.writeByte(255),i.writeByte(255),i.writeByte(255),i.writeString(","),i.writeShort(0),i.writeShort(0),i.writeShort(g),i.writeShort(l),i.writeByte(0);var v=2,_=r(v);i.writeByte(v);for(var B=0;_.length-B>255;)i.writeByte(255),i.writeBytes(_,B,255),B+=255;i.writeByte(_.length-B),i.writeBytes(_,B,_.length-B),i.writeByte(0),i.writeString(";")};var t=function(i){var v=i,_=0,B=0,y={};return y.write=function(C,E){if(C>>>E)throw"length over";for(;_+E>=8;)v.writeByte(255&(C<<_|B)),E-=8-_,C>>>=8-_,B=0,_=0;B=C<<_|B,_=_+E},y.flush=function(){_>0&&v.writeByte(B)},y},r=function(i){for(var v=1<<i,_=(1<<i)+1,B=i+1,y=h(),C=0;C<v;C+=1)y.add(String.fromCharCode(C));y.add(String.fromCharCode(v)),y.add(String.fromCharCode(_));var E=j(),O=t(E);O.write(v,B);var m=0,U=String.fromCharCode(n[m]);for(m+=1;m<n.length;){var H=String.fromCharCode(n[m]);m+=1,y.contains(U+H)?U=U+H:(O.write(y.indexOf(U),B),y.size()<4095&&(y.size()==1<<B&&(B+=1),y.add(U+H)),U=H)}return O.write(y.indexOf(U),B),O.write(_,B),O.flush(),E.toByteArray()},h=function(){var i={},v=0,_={};return _.add=function(B){if(_.contains(B))throw"dup key:"+B;i[B]=v,v+=1},_.size=function(){return v},_.indexOf=function(B){return i[B]},_.contains=function(B){return typeof i[B]!="undefined"},_};return s},fr=function(x,w,g){for(var l=ar(x,w),n=0;n<w;n+=1)for(var s=0;s<x;s+=1)l.setPixel(s,n,g(s,n));var t=j();l.write(t);for(var r=er(),h=t.toByteArray(),i=0;i<h.length;i+=1)r.writeByte(h[i]);return r.flush(),"data:image/gif;base64,"+r};return L})();(function(){$.stringToBytesFuncs["UTF-8"]=function(L){function T(N){for(var k=[],P=0;P<N.length;P++){var M=N.charCodeAt(P);M<128?k.push(M):M<2048?k.push(192|M>>6,128|M&63):M<55296||M>=57344?k.push(224|M>>12,128|M>>6&63,128|M&63):(P++,M=65536+((M&1023)<<10|N.charCodeAt(P)&1023),k.push(240|M>>18,128|M>>12&63,128|M>>6&63,128|M&63))}return k}return T(L)}})();(function(L){typeof define=="function"&&define.amd?define([],L):typeof W=="object"&&(V.exports=L())})(function(){return $})});return vr();})();
|
|
24
|
+
|
|
25
|
+
|
|
17
26
|
const CSS = `
|
|
18
27
|
.dm-wrap { display: flex; flex-direction: column; gap: 16px; padding: 4px 2px; }
|
|
19
28
|
.dm-card {
|
|
20
|
-
border: 1px solid var(--dsw-alias-border-l1
|
|
21
|
-
background: var(--dsw-alias-bg-layer-1
|
|
29
|
+
border: 1px solid var(--dsw-alias-border-l1);
|
|
30
|
+
background: var(--dsw-alias-bg-layer-1);
|
|
22
31
|
border-radius: 16px; padding: 18px;
|
|
23
32
|
animation: dm-in .34s cubic-bezier(.2,.75,.25,1) both;
|
|
24
33
|
}
|
|
25
34
|
.dm-card:nth-child(2) { animation-delay: .06s; }
|
|
26
35
|
.dm-card:nth-child(3) { animation-delay: .12s; }
|
|
27
|
-
.dm-title { margin: 0; font-size: 14px; font-weight: 600; color: var(--dsw-alias-label-primary
|
|
28
|
-
.dm-sub { margin: 6px 0 0; font-size: 12.5px; line-height: 18px; color: var(--dsw-alias-label-secondary
|
|
36
|
+
.dm-title { margin: 0; font-size: 14px; font-weight: 600; color: var(--dsw-alias-label-primary); }
|
|
37
|
+
.dm-sub { margin: 6px 0 0; font-size: 12.5px; line-height: 18px; color: var(--dsw-alias-label-secondary); }
|
|
29
38
|
.dm-urlRow { display: flex; align-items: center; gap: 8px; margin-top: 10px; }
|
|
30
39
|
.dm-url {
|
|
31
40
|
flex: 1; min-width: 0; font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
32
|
-
font-size: 12.5px; color:
|
|
41
|
+
font-size: 12.5px; color: var(--dsw-alias-label-primary); word-break: break-all;
|
|
33
42
|
}
|
|
34
43
|
.dm-btn {
|
|
35
44
|
display: inline-flex; align-items: center; justify-content: center; gap: 7px;
|
|
36
|
-
border: 1px solid
|
|
45
|
+
border: 1px solid var(--dsw-alias-label-primary); border-radius: 10px; padding: 9px 16px;
|
|
37
46
|
font-size: 13px; font-weight: 600; cursor: pointer;
|
|
38
|
-
background:
|
|
47
|
+
background: var(--dsw-alias-label-primary); color: var(--dsw-alias-bg-layer-1);
|
|
39
48
|
transition: background-color .16s ease, transform .09s ease, box-shadow .16s ease, opacity .16s ease;
|
|
40
49
|
}
|
|
41
|
-
.dm-btn:hover { background:
|
|
50
|
+
.dm-btn:hover { background: var(--dsw-alias-label-primary); border-color: var(--dsw-alias-label-primary); box-shadow: 0 4px 14px var(--dsw-alias-bg-layer-1); }
|
|
42
51
|
.dm-btn:active { transform: scale(.97); }
|
|
43
|
-
.dm-btn:focus-visible { outline: 2px solid
|
|
52
|
+
.dm-btn:focus-visible { outline: 2px solid var(--dsw-alias-label-primary); outline-offset: 2px; }
|
|
44
53
|
.dm-btn[disabled] { opacity: .6; cursor: default; transform: none; box-shadow: none; }
|
|
45
54
|
.dm-ghost {
|
|
46
55
|
display: inline-flex; align-items: center; justify-content: center; gap: 7px;
|
|
47
|
-
border: 1px solid var(--dsw-alias-border-l2
|
|
56
|
+
border: 1px solid var(--dsw-alias-border-l2); border-radius: 10px;
|
|
48
57
|
padding: 9px 16px; font-size: 13px; font-weight: 500; cursor: pointer;
|
|
49
|
-
background: transparent; color: var(--dsw-alias-label-primary
|
|
58
|
+
background: transparent; color: var(--dsw-alias-label-primary);
|
|
50
59
|
transition: background-color .16s ease, border-color .16s ease, transform .09s ease;
|
|
51
60
|
}
|
|
52
|
-
.dm-ghost:hover { background:
|
|
61
|
+
.dm-ghost:hover { background: var(--dsw-alias-bg-layer-1); }
|
|
53
62
|
.dm-ghost:active { transform: scale(.97); }
|
|
54
|
-
.dm-ghost:focus-visible { outline: 2px solid
|
|
63
|
+
.dm-ghost:focus-visible { outline: 2px solid var(--dsw-alias-label-primary); outline-offset: 2px; }
|
|
55
64
|
.dm-danger {
|
|
56
65
|
display: inline-flex; align-items: center; justify-content: center;
|
|
57
|
-
border: 1px solid
|
|
58
|
-
font-size: 12.5px; font-weight: 500; cursor: pointer; background: transparent; color:
|
|
66
|
+
border: 1px solid var(--dsw-alias-state-error-primary); border-radius: 10px; padding: 7px 12px;
|
|
67
|
+
font-size: 12.5px; font-weight: 500; cursor: pointer; background: transparent; color: var(--dsw-alias-state-error-primary);
|
|
59
68
|
transition: background-color .16s ease, color .16s ease, transform .09s ease;
|
|
60
69
|
}
|
|
61
|
-
.dm-danger:hover { background:
|
|
70
|
+
.dm-danger:hover { background: var(--dsw-alias-bg-layer-1); }
|
|
62
71
|
.dm-danger:active { transform: scale(.96); }
|
|
63
|
-
.dm-danger[data-confirm="true"] { background:
|
|
72
|
+
.dm-danger[data-confirm="true"] { background: var(--dsw-alias-state-error-primary); color: var(--dsw-alias-bg-layer-1); }
|
|
64
73
|
.dm-copy {
|
|
65
|
-
flex: none; border: 1px solid var(--dsw-alias-border-l2
|
|
66
|
-
color: var(--dsw-alias-label-secondary
|
|
74
|
+
flex: none; border: 1px solid var(--dsw-alias-border-l2); background: transparent;
|
|
75
|
+
color: var(--dsw-alias-label-secondary); border-radius: 8px; padding: 5px 10px;
|
|
67
76
|
font-size: 11.5px; cursor: pointer; transition: background-color .15s, color .15s, transform .09s;
|
|
68
77
|
}
|
|
69
|
-
.dm-copy:hover { background:
|
|
78
|
+
.dm-copy:hover { background: var(--dsw-alias-bg-layer-1); }
|
|
70
79
|
.dm-copy:active { transform: scale(.95); }
|
|
71
|
-
.dm-copy[data-copied="true"] { border-color:
|
|
80
|
+
.dm-copy[data-copied="true"] { border-color: var(--dsw-alias-label-primary); color: var(--dsw-alias-label-primary); }
|
|
72
81
|
.dm-code {
|
|
73
|
-
margin:
|
|
82
|
+
margin: 8px 0 2px; text-align: center;
|
|
74
83
|
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
75
|
-
font-size:
|
|
84
|
+
font-size: 30px; font-weight: 700; letter-spacing: 6px; color: var(--dsw-alias-label-primary);
|
|
76
85
|
animation: dm-pop .4s cubic-bezier(.2,.8,.25,1.1) both;
|
|
77
86
|
}
|
|
78
87
|
.dm-codeExpired { opacity: .45; text-decoration: line-through; }
|
|
79
|
-
.dm-count { text-align: center; font-size: 12px; color: var(--dsw-alias-label-secondary
|
|
80
|
-
.dm-count b { color:
|
|
88
|
+
.dm-count { text-align: center; font-size: 12px; color: var(--dsw-alias-label-secondary); }
|
|
89
|
+
.dm-count b { color: var(--dsw-alias-label-primary); font-weight: 600; font-variant-numeric: tabular-nums; }
|
|
81
90
|
.dm-row {
|
|
82
91
|
display: flex; align-items: center; justify-content: space-between; gap: 12px;
|
|
83
|
-
padding: 11px 0; border-top: 1px solid var(--dsw-alias-border-l1
|
|
92
|
+
padding: 11px 0; border-top: 1px solid var(--dsw-alias-border-l1);
|
|
84
93
|
animation: dm-in .28s ease both;
|
|
85
94
|
}
|
|
86
95
|
.dm-row:first-of-type { border-top: 0; }
|
|
87
|
-
.dm-name { font-size: 13.5px; font-weight: 500; color: var(--dsw-alias-label-primary
|
|
88
|
-
.dm-detail { font-size: 12px; color: var(--dsw-alias-label-secondary
|
|
89
|
-
.dm-muted { color: var(--dsw-alias-label-secondary
|
|
90
|
-
.dm-err { color: var(--dsw-alias-state-error-primary
|
|
91
|
-
.dm-domain { margin-top: 14px; padding-top: 12px; border-top: 1px dashed var(--dsw-alias-border-l2
|
|
96
|
+
.dm-name { font-size: 13.5px; font-weight: 500; color: var(--dsw-alias-label-primary); }
|
|
97
|
+
.dm-detail { font-size: 12px; color: var(--dsw-alias-label-secondary); margin-top: 2px; }
|
|
98
|
+
.dm-muted { color: var(--dsw-alias-label-secondary); font-size: 13px; }
|
|
99
|
+
.dm-err { color: var(--dsw-alias-state-error-primary); font-size: 12.5px; margin-top: 10px; }
|
|
100
|
+
.dm-domain { margin-top: 14px; padding-top: 12px; border-top: 1px dashed var(--dsw-alias-border-l2); }
|
|
92
101
|
.dm-domainHead { display: flex; align-items: baseline; gap: 8px; margin-bottom: 8px; }
|
|
93
|
-
.dm-domainLabel { font-size: 12.5px; font-weight: 600; color: var(--dsw-alias-label-primary
|
|
94
|
-
.dm-domainHint { font-size: 11.5px; color: var(--dsw-alias-label-secondary
|
|
102
|
+
.dm-domainLabel { font-size: 12.5px; font-weight: 600; color: var(--dsw-alias-label-primary); }
|
|
103
|
+
.dm-domainHint { font-size: 11.5px; color: var(--dsw-alias-label-secondary); }
|
|
95
104
|
.dm-input {
|
|
96
105
|
flex: 1; min-width: 0; height: 34px; padding: 0 10px; border-radius: 8px;
|
|
97
|
-
border: 1px solid var(--dsw-alias-border-l2
|
|
98
|
-
color: var(--dsw-alias-label-primary
|
|
106
|
+
border: 1px solid var(--dsw-alias-border-l2); background: transparent;
|
|
107
|
+
color: var(--dsw-alias-label-primary); font-size: 12.5px;
|
|
99
108
|
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
100
109
|
}
|
|
101
|
-
.dm-input::placeholder { color: var(--dsw-alias-label-secondary
|
|
102
|
-
.dm-input:focus { outline: none; border-color:
|
|
110
|
+
.dm-input::placeholder { color: var(--dsw-alias-label-secondary); }
|
|
111
|
+
.dm-input:focus { outline: none; border-color: var(--dsw-alias-label-primary); box-shadow: 0 0 0 2px var(--dsw-alias-bg-layer-1); }
|
|
103
112
|
.dm-btnSm { padding: 8px 14px; font-size: 12.5px; }
|
|
104
113
|
.dm-actions { display: flex; align-items: center; justify-content: center; gap: 10px; margin-top: 12px; }
|
|
105
114
|
.dm-spin {
|
|
106
|
-
width: 14px; height: 14px; border: 2px solid
|
|
107
|
-
border-top-color:
|
|
115
|
+
width: 14px; height: 14px; border: 2px solid var(--dsw-alias-bg-layer-1);
|
|
116
|
+
border-top-color: var(--dsw-alias-bg-layer-1); border-radius: 50%;
|
|
108
117
|
animation: dm-rot .8s linear infinite;
|
|
109
118
|
}
|
|
110
119
|
.dm-spinGhost {
|
|
111
|
-
width: 14px; height: 14px; border: 2px solid
|
|
112
|
-
border-top-color:
|
|
120
|
+
width: 14px; height: 14px; border: 2px solid var(--dsw-alias-bg-layer-1);
|
|
121
|
+
border-top-color: var(--dsw-alias-label-primary); border-radius: 50%;
|
|
113
122
|
animation: dm-rot .8s linear infinite;
|
|
114
123
|
}
|
|
115
|
-
.dm-live { display: inline-flex; align-items: center; gap: 6px; font-size: 11.5px; color: var(--dsw-alias-label-secondary
|
|
116
|
-
.dm-liveDot { width: 7px; height: 7px; border-radius: 50%; background:
|
|
117
|
-
.dm-liveDotOff { background:
|
|
124
|
+
.dm-live { display: inline-flex; align-items: center; gap: 6px; font-size: 11.5px; color: var(--dsw-alias-label-secondary); }
|
|
125
|
+
.dm-liveDot { width: 7px; height: 7px; border-radius: 50%; background: var(--dsw-alias-label-primary); box-shadow: 0 0 0 0 var(--dsw-alias-bg-layer-1); animation: dm-pulse 2s infinite; }
|
|
126
|
+
.dm-liveDotOff { background: var(--dsw-alias-label-secondary); animation: none; }
|
|
127
|
+
/* ── 连接二维码:单码 + 地址切换器(与设置卡片同一套 token/圆角/间距)── */
|
|
128
|
+
.dm-cardHead { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
|
|
129
|
+
/* 二维码卡:主视觉只有一张码、一行地址、一行提示、两条折叠备用路径 */
|
|
130
|
+
/* 引导式两步:① 选择网络(radio 列表) ② 扫码连接(140–150px 小码) */
|
|
131
|
+
/* 连接向导:只用 DSH 主题 token(无自定义配色 / 阴影 / 装饰) */
|
|
132
|
+
.dm-help {
|
|
133
|
+
border: 0; background: transparent; padding: 0;
|
|
134
|
+
color: var(--dsw-alias-label-secondary);
|
|
135
|
+
font-size: 12px; line-height: 1; cursor: help;
|
|
136
|
+
}
|
|
137
|
+
.dm-page { margin-top: 8px; }
|
|
138
|
+
.dm-stepText { margin: 0 0 6px; font-size: 11.5px; line-height: 16px; color: var(--dsw-alias-label-secondary); }
|
|
139
|
+
.dm-pageTitle { margin: 0 0 8px; font-size: 13px; font-weight: 600; line-height: 19px; color: var(--dsw-alias-label-primary); }
|
|
140
|
+
.dm-netList { list-style: none; margin: 0; padding: 0; }
|
|
141
|
+
.dm-netItem + .dm-netItem { border-top: 1px solid var(--dsw-alias-border-l1); }
|
|
142
|
+
.dm-netRow {
|
|
143
|
+
/* 网格列:radio | 固定宽标签列 | 地址(1fr) | 右侧动作,保证各行左右都对齐 */
|
|
144
|
+
display: grid; grid-template-columns: auto 4.6em minmax(0, 1fr) auto;
|
|
145
|
+
align-items: center; column-gap: 8px;
|
|
146
|
+
padding: 8px 2px; cursor: pointer;
|
|
147
|
+
font-size: 12.5px; line-height: 18px; color: var(--dsw-alias-label-primary);
|
|
148
|
+
}
|
|
149
|
+
.dm-netRowUnset { color: var(--dsw-alias-label-secondary); }
|
|
150
|
+
.dm-netRadio { flex: none; margin: 0; }
|
|
151
|
+
/* 标签列固定宽度:局域网(3 字)与公网(2 字)必须让地址列从同一 x 开始 */
|
|
152
|
+
.dm-netLabel { flex: none; width: 4.6em; white-space: nowrap; font-weight: 500; }
|
|
153
|
+
/* 地址用 DSH 默认字体(不设 font-family,继承面板),只降字号与颜色 */
|
|
154
|
+
.dm-netAddr {
|
|
155
|
+
flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
|
156
|
+
font-family: inherit; /* <code> 自带 monospace,必须显式 inherit 才与 DSH 字体一致 */
|
|
157
|
+
font-size: 11.5px; color: var(--dsw-alias-label-secondary);
|
|
158
|
+
}
|
|
159
|
+
/* 公网域名区:放在最上方(先设域名,再出码) */
|
|
160
|
+
.dm-domainBlock { margin: 0 0 4px; padding-bottom: 6px; border-bottom: 1px solid var(--dsw-alias-border-l1); }
|
|
161
|
+
.dm-domainHead {
|
|
162
|
+
display: grid; grid-template-columns: auto 4.6em minmax(0, 1fr) auto;
|
|
163
|
+
align-items: center; column-gap: 8px; min-height: 30px;
|
|
164
|
+
padding: 0 2px; /* 与地址行同内边距,动作列严格对齐 */
|
|
165
|
+
}
|
|
166
|
+
.dm-domainLabel { flex: none; width: 4.6em; white-space: nowrap; font-size: 12.5px; font-weight: 500; color: var(--dsw-alias-label-primary); }
|
|
167
|
+
.dm-domainValue {
|
|
168
|
+
flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
|
169
|
+
font-size: 11.5px; color: var(--dsw-alias-label-secondary);
|
|
170
|
+
}
|
|
171
|
+
.dm-domainValueUnset { color: var(--dsw-alias-label-tertiary); }
|
|
172
|
+
.dm-netUnsetText { flex: 1; min-width: 0; font-size: 11.5px; color: var(--dsw-alias-label-secondary); }
|
|
173
|
+
.dm-rowAction {
|
|
174
|
+
justify-self: end; flex: none; border: 0; background: transparent; padding: 0 2px;
|
|
175
|
+
color: var(--dsw-alias-label-secondary); font-size: 12px; cursor: pointer;
|
|
176
|
+
}
|
|
177
|
+
.dm-rowAction:hover { color: var(--dsw-alias-label-primary); }
|
|
178
|
+
.dm-domainPad { width: 13px; }
|
|
179
|
+
.dm-netEdit, .dm-netOpen {
|
|
180
|
+
flex: none; border: 0; background: transparent; padding: 0 2px;
|
|
181
|
+
color: var(--dsw-alias-label-secondary); font-size: 12px; cursor: pointer;
|
|
182
|
+
}
|
|
183
|
+
.dm-netEdit { text-decoration: underline; justify-self: end; }
|
|
184
|
+
.dm-netOpen { justify-self: end; }
|
|
185
|
+
.dm-remoteForm { margin-top: 8px; padding-top: 8px; border-top: 1px solid var(--dsw-alias-border-l1); }
|
|
186
|
+
.dm-remoteHint { margin: 0 0 6px; font-size: 11.5px; line-height: 16px; color: var(--dsw-alias-label-secondary); }
|
|
187
|
+
.dm-remoteRow { display: flex; align-items: center; gap: 8px; }
|
|
188
|
+
.dm-input {
|
|
189
|
+
flex: 1; min-width: 0; height: 32px; padding: 0 10px; border-radius: 8px;
|
|
190
|
+
border: 1px solid var(--dsw-alias-border-l2); background: transparent;
|
|
191
|
+
color: var(--dsw-alias-label-primary); font-size: 12.5px;
|
|
192
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
193
|
+
}
|
|
194
|
+
.dm-input:focus { outline: none; border-color: var(--dsw-alias-border-l2); }
|
|
195
|
+
.dm-stepBtn {
|
|
196
|
+
display: inline-flex; align-items: center; justify-content: center; gap: 6px;
|
|
197
|
+
padding: 7px 14px; border: 1px solid var(--dsw-alias-border-l2); border-radius: 8px;
|
|
198
|
+
background: transparent; color: var(--dsw-alias-label-primary);
|
|
199
|
+
font-size: 12.5px; font-weight: 500; line-height: 18px; cursor: pointer;
|
|
200
|
+
}
|
|
201
|
+
.dm-stepBtn:hover { background: var(--dsw-alias-bg-layer-1); }
|
|
202
|
+
.dm-stepBtn:disabled { opacity: 0.55; cursor: default; }
|
|
203
|
+
.dm-stepBtnPrimary { font-weight: 600; }
|
|
204
|
+
.dm-pageActions { display: flex; align-items: center; gap: 8px; margin-top: 12px; }
|
|
205
|
+
.dm-pageTools { display: flex; align-items: center; gap: 12px; margin-top: 6px; }
|
|
206
|
+
.dm-toolBtn {
|
|
207
|
+
display: inline-flex; align-items: center; gap: 4px;
|
|
208
|
+
border: 0; background: transparent; padding: 0;
|
|
209
|
+
color: var(--dsw-alias-label-secondary); font-size: 11.5px; line-height: 16px; cursor: pointer;
|
|
210
|
+
}
|
|
211
|
+
.dm-toolGlyph { display: inline-flex; align-items: center; justify-content: center; }
|
|
212
|
+
.dm-qrCard {
|
|
213
|
+
display: inline-grid; place-items: center; padding: 8px;
|
|
214
|
+
border-radius: 10px; border: 1px solid var(--dsw-alias-border-l1);
|
|
215
|
+
/* 二维码白底是扫码必需(黑白对比),不属于面板配色 */
|
|
216
|
+
background: #ffffff;
|
|
217
|
+
}
|
|
218
|
+
.dm-qrCard svg { display: block; }
|
|
219
|
+
.dm-scanHint { margin: 8px 0 0; font-size: 12px; line-height: 17px; color: var(--dsw-alias-label-secondary); }
|
|
220
|
+
.dm-summaryLine { margin: 0; font-size: 12.5px; line-height: 18px; color: var(--dsw-alias-label-secondary); }
|
|
221
|
+
.dm-devicesOneLine { margin: 10px 2px 0; font-size: 12px; line-height: 18px; color: var(--dsw-alias-label-secondary); }
|
|
222
|
+
.dm-cardTight { padding: 12px 16px; }
|
|
223
|
+
.dm-collapse { margin-top: 14px; border-top: 1px dashed var(--dsw-alias-border-l2); padding-top: 10px; }
|
|
224
|
+
.dm-collapseHead { display: flex; align-items: center; justify-content: space-between; width: 100%; padding: 4px 0; border: 0; background: transparent; cursor: pointer; color: var(--dsw-alias-label-secondary); font-size: 12.5px; font-weight: 500; }
|
|
225
|
+
.dm-collapseCaret { font-size: 12px; }
|
|
226
|
+
.dm-collapseBody { padding-top: 10px; }
|
|
118
227
|
@keyframes dm-in { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
|
|
119
228
|
@keyframes dm-pop { 0% { opacity: 0; transform: scale(.86); } 62% { transform: scale(1.05); } 100% { opacity: 1; transform: scale(1); } }
|
|
120
229
|
@keyframes dm-rot { to { transform: rotate(360deg); } }
|
|
121
|
-
|
|
230
|
+
/* ── 定稿(A · 极简留白):大字级对比 + 留白分组,全部 DSH token ── */
|
|
231
|
+
.dm-connectCard { position: relative; border: 0; background: transparent; padding: 24px 24px 16px; }
|
|
232
|
+
.dm-connectHead { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; margin-bottom: 20px; }
|
|
233
|
+
.dm-headRight { flex: none; display: inline-flex; align-items: center; gap: 8px; }
|
|
234
|
+
.dm-pageTitle { margin: 0; font-size: 16px; font-weight: 600; letter-spacing: -0.2px; line-height: 22px; color: var(--dsw-alias-label-primary); }
|
|
235
|
+
.dm-stepTag { flex: none; padding-top: 2px; font-size: 11px; line-height: 16px; color: var(--dsw-alias-label-tertiary); font-variant-numeric: tabular-nums; }
|
|
236
|
+
.dm-page.dm-inner { padding: 0; background: transparent; border: 0; animation: dm-page-in 160ms ease both; }
|
|
237
|
+
@keyframes dm-page-in {
|
|
238
|
+
from { opacity: 0; transform: translateY(6px); }
|
|
239
|
+
to { opacity: 1; transform: translateY(0); }
|
|
240
|
+
}
|
|
241
|
+
@media (prefers-reduced-motion: reduce) { .dm-page.dm-inner { animation: none; } }
|
|
242
|
+
.dm-netList { margin: 0; }
|
|
243
|
+
/* 不给行加左右 margin:否则第一行与后续行起点差 6px,标签/地址会错位;hairline 用内缩伪元素实现 */
|
|
244
|
+
.dm-netItem + .dm-netItem { border-top: 1px solid var(--dsw-alias-border-l1); margin: 0; }
|
|
245
|
+
.dm-netRow { min-height: 44px; padding: 0 2px; } /* 行内基础 padding 由上方 grid 规则统一 */
|
|
246
|
+
.dm-qrStage { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
|
|
247
|
+
.dm-qrWrap { flex: 1; display: flex; justify-content: center; padding: 4px 0; }
|
|
248
|
+
.dm-qrCard { padding: 8px; border-radius: 12px; border: 1px solid var(--dsw-alias-border-l1); background: #ffffff; }
|
|
249
|
+
.dm-scanHint { text-align: center; margin: 8px 0 0; }
|
|
250
|
+
.dm-pageTools { justify-content: center; margin-top: 10px; }
|
|
251
|
+
.dm-pageActions { margin-top: 20px; }
|
|
252
|
+
.dm-navRow { display: flex; justify-content: flex-end; margin-top: 16px; }
|
|
253
|
+
.dm-arrow {
|
|
254
|
+
flex: none; display: inline-flex; flex-direction: column; align-items: center; justify-content: center;
|
|
255
|
+
gap: 2px; min-width: 48px; min-height: 56px; padding: 6px;
|
|
256
|
+
border: 0; background: transparent; cursor: pointer;
|
|
257
|
+
color: var(--dsw-alias-label-tertiary);
|
|
258
|
+
transition: color 120ms ease;
|
|
259
|
+
}
|
|
260
|
+
.dm-arrow:hover, .dm-arrow:active, .dm-arrow:focus-visible { color: var(--dsw-alias-label-primary); }
|
|
261
|
+
.dm-arrow:disabled { opacity: 0.4; cursor: default; }
|
|
262
|
+
.dm-arrowGlyph { font-size: 20px; line-height: 20px; }
|
|
263
|
+
.dm-arrowLabel { font-size: 12px; line-height: 16px; color: var(--dsw-alias-label-tertiary); }
|
|
264
|
+
.dm-arrow:hover .dm-arrowLabel, .dm-arrow:active .dm-arrowLabel { color: var(--dsw-alias-label-primary); }
|
|
265
|
+
@media (prefers-reduced-motion: reduce) { .dm-arrow { transition: none; } }
|
|
266
|
+
.dm-stepBtn { height: 36px; padding: 0 16px; border-radius: 8px; }
|
|
267
|
+
.dm-stepBtnPrimary {
|
|
268
|
+
border-color: transparent;
|
|
269
|
+
background: var(--dsw-alias-button-primary-fill);
|
|
270
|
+
color: var(--dsw-alias-label-primary-foreground);
|
|
271
|
+
font-weight: 600;
|
|
272
|
+
}
|
|
273
|
+
.dm-stepBtnPrimary:hover { background: var(--dsw-alias-button-primary-hover); }
|
|
274
|
+
.dm-stepBtnGhost { border-color: transparent; background: transparent; padding: 0 8px; font-weight: 400; }
|
|
275
|
+
.dm-stepBtnGhost:hover { background: var(--dsw-alias-interactive-bg-hover); }
|
|
276
|
+
.dm-summaryLine { margin-top: 2px; }
|
|
277
|
+
.dm-devicesOneLine { margin: 4px 2px 0; }
|
|
278
|
+
@keyframes dm-pulse { 0% { box-shadow: 0 0 0 0 var(--dsw-alias-bg-layer-1); } 70% { box-shadow: 0 0 0 6px var(--dsw-alias-bg-layer-1); } 100% { box-shadow: 0 0 0 0 var(--dsw-alias-bg-layer-1); } }
|
|
122
279
|
@media (prefers-reduced-motion: reduce) {
|
|
123
280
|
.dm-card, .dm-row, .dm-code { animation: none !important; }
|
|
124
281
|
.dm-btn, .dm-ghost, .dm-danger, .dm-copy { transition: none !important; }
|
|
@@ -222,6 +379,52 @@ window.__ModuleLoader__.load({
|
|
|
222
379
|
* 有些机器上会多出 VPN / 虚拟网卡的公网段 IPv4(例如 2.0.1.1/24),
|
|
223
380
|
* 那不是手机能用来直连的入口,混进来就会显示成三条地址。
|
|
224
381
|
*/
|
|
382
|
+
/**
|
|
383
|
+
* 扫码即配对的链接:手机打开 /m/ 后自动用 ?code= 完成配对(与手输 6 位码
|
|
384
|
+
* 等价),不需要再手动确认。
|
|
385
|
+
* @param base - 地址(含协议/端口,不含尾斜杠)
|
|
386
|
+
* @param code - 6 位配对码
|
|
387
|
+
*/
|
|
388
|
+
function qrUrl(base, code) {
|
|
389
|
+
const origin = String(base || '').replace(/\/+$/, '')
|
|
390
|
+
return origin + '/m/?code=' + encodeURIComponent(String(code))
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
/**
|
|
394
|
+
* 把文本生成二维码 SVG 字符串(quiet zone 4 个模块)。
|
|
395
|
+
* @param text - 要编码的 URL
|
|
396
|
+
* @param size - 渲染边长(px)
|
|
397
|
+
*/
|
|
398
|
+
function qrSvg(text, size, quietZone) {
|
|
399
|
+
let qr = null
|
|
400
|
+
for (let v = 1; v <= 40; v += 1) {
|
|
401
|
+
try {
|
|
402
|
+
const candidate = __qrGen(v, 'M')
|
|
403
|
+
candidate.addData(text)
|
|
404
|
+
candidate.make()
|
|
405
|
+
qr = candidate
|
|
406
|
+
break
|
|
407
|
+
} catch (e) { /* 容量不够就换下一个版本 */ }
|
|
408
|
+
}
|
|
409
|
+
if (!qr) return ''
|
|
410
|
+
const n = qr.getModuleCount()
|
|
411
|
+
// 二维码右下角要叠两个小图标按钮:留 8 个模块的静区,图标只压在静区上,
|
|
412
|
+
// 不遮挡任何数据模块(不牺牲可扫性)。
|
|
413
|
+
const quiet = quietZone === undefined ? 4 : quietZone
|
|
414
|
+
const total = n + quiet * 2
|
|
415
|
+
let path = ''
|
|
416
|
+
for (let r = 0; r < n; r += 1) {
|
|
417
|
+
for (let c = 0; c < n; c += 1) {
|
|
418
|
+
if (!qr.isDark(r, c)) continue
|
|
419
|
+
path += 'M' + (c + quiet) + ' ' + (r + quiet) + 'h1v1h-1z'
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
return '<svg xmlns="http://www.w3.org/2000/svg" width="' + size + '" height="' + size +
|
|
423
|
+
'" viewBox="0 0 ' + total + ' ' + total + '" shape-rendering="crispEdges" role="img" aria-label="连接二维码">' +
|
|
424
|
+
'<rect width="' + total + '" height="' + total + '" fill="#fff"></rect>' +
|
|
425
|
+
'<path d="' + path + '" fill="#000"></path></svg>'
|
|
426
|
+
}
|
|
427
|
+
|
|
225
428
|
function lanOnly(urls) {
|
|
226
429
|
const isPrivate = (host) =>
|
|
227
430
|
host.startsWith('10.') || host.startsWith('192.168.') || /^172\.(1[6-9]|2\d|3[01])\./.test(host)
|
|
@@ -263,10 +466,15 @@ window.__ModuleLoader__.load({
|
|
|
263
466
|
const [err, setErr] = useState('')
|
|
264
467
|
const [copied, setCopied] = useState('')
|
|
265
468
|
const [confirmRevoke, setConfirmRevoke] = useState('')
|
|
266
|
-
const [now, setNow] = useState(() => Date.now())
|
|
267
469
|
const [domainDraft, setDomainDraft] = useState('')
|
|
268
470
|
const [domainBusy, setDomainBusy] = useState(false)
|
|
269
471
|
const [domainErr, setDomainErr] = useState('')
|
|
472
|
+
// 连接二维码:当前选中的地址 + 切换面板 + 「远程连接(可选)」折叠区
|
|
473
|
+
const [selectedBase, setSelectedBase] = useState('')
|
|
474
|
+
const [wizardStep, setWizardStep] = useState(1) // 1 / 2 / 0=完成后的摘要态
|
|
475
|
+
const [remoteOpen, setRemoteOpen] = useState(false)
|
|
476
|
+
// 手动重画二维码用:固定配对码下重画不改变内容,但保留入口以防宿主轮换码。
|
|
477
|
+
const [qrVersion, setQrVersion] = useState(0)
|
|
270
478
|
const domainEdited = useRef(false)
|
|
271
479
|
const confirmTimer = useRef()
|
|
272
480
|
const copyTimer = useRef()
|
|
@@ -291,12 +499,6 @@ window.__ModuleLoader__.load({
|
|
|
291
499
|
return () => clearInterval(t)
|
|
292
500
|
}, [refresh])
|
|
293
501
|
|
|
294
|
-
// 倒计时 tick
|
|
295
|
-
useEffect(() => {
|
|
296
|
-
const t = setInterval(() => setNow(Date.now()), 1000)
|
|
297
|
-
return () => clearInterval(t)
|
|
298
|
-
}, [])
|
|
299
|
-
|
|
300
502
|
useEffect(() => () => {
|
|
301
503
|
clearTimeout(confirmTimer.current)
|
|
302
504
|
clearTimeout(copyTimer.current)
|
|
@@ -346,6 +548,7 @@ window.__ModuleLoader__.load({
|
|
|
346
548
|
.then((j) => {
|
|
347
549
|
if (j && j.ok) {
|
|
348
550
|
domainEdited.current = false
|
|
551
|
+
setRemoteOpen(false)
|
|
349
552
|
refresh()
|
|
350
553
|
} else {
|
|
351
554
|
setDomainErr((j && j.error) || '保存失败')
|
|
@@ -370,47 +573,116 @@ window.__ModuleLoader__.load({
|
|
|
370
573
|
|
|
371
574
|
const addrs = (status && status.addresses) || { lan: [], publicBase: null }
|
|
372
575
|
const devices = (status && status.devices) || []
|
|
373
|
-
const
|
|
576
|
+
const lanBases = lanOnly(addrs.lan)
|
|
577
|
+
const publicBase = addrs.publicBase || ''
|
|
578
|
+
const urls = [...lanBases, ...(publicBase ? [publicBase] : [])]
|
|
374
579
|
// 「清除」只在用户自己填过域名时出现;没填时 publicBase 来自 profile 配置,
|
|
375
580
|
// 清掉只会回到配置值,按钮会误导。
|
|
376
581
|
const hasDomainOverride = addrs.publicBaseCustom === true
|
|
377
|
-
|
|
378
|
-
const
|
|
582
|
+
// 二维码内部仍用 6 位配对码拼 ?code=,但它不再作为 UI 概念出现。
|
|
583
|
+
const pairingCode = code ? String(code.code || '') : ''
|
|
584
|
+
const candidates = [...lanBases, ...(publicBase ? [publicBase] : [])]
|
|
585
|
+
// 默认选中规则(用户口径):配了公网地址 → 默认公网(在家在外都能连);
|
|
586
|
+
// 没配 → 默认第一个局域网地址。用户手动切换后保持其选择。
|
|
587
|
+
const defaultBase = publicBase !== '' ? publicBase : (lanBases[0] || '')
|
|
588
|
+
const activeBase = candidates.indexOf(selectedBase) >= 0 ? selectedBase : defaultBase
|
|
589
|
+
const isPublicSelected = activeBase !== '' && activeBase === publicBase
|
|
590
|
+
const qrText = pairingCode && activeBase ? qrUrl(activeBase, pairingCode) : ''
|
|
591
|
+
const displayAddr = (base) => String(base || '').replace(/^https?:\/\//, '').replace(/\/+$/, '')
|
|
592
|
+
const selectedReason = publicBase !== '' ? '已配置公网地址,默认选公网' : '未配置公网地址,默认选第一个局域网地址'
|
|
379
593
|
|
|
380
|
-
|
|
381
|
-
|
|
594
|
+
// 全部解释性文字都收进标题旁的 (?):正文只留步骤标题与最必要的一行。
|
|
595
|
+
// 所有解释都收在这里;正文只保留步骤必要的两行字。
|
|
596
|
+
const HELP_TEXT = [
|
|
597
|
+
'扫码即连:手机扫码后自动配对,无需输入配对码。',
|
|
598
|
+
'扫不开 / 没反应:多半是手机与电脑不在同一网络(例如电脑有线、手机用流量),把手机接到同一 Wi-Fi,或选择「公网」。',
|
|
599
|
+
'公网地址需要一条反向代理 / 隧道(frp、Cloudflare Tunnel、Tailscale 均可)。',
|
|
600
|
+
].join(' ')
|
|
382
601
|
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
602
|
+
// 分页导航箭头:左=上一步,右=下一步/完成;热区 ≥40×40,视觉 20px。
|
|
603
|
+
const navArrow = (direction, label, glyph, onClick, disabled) => h('button', {
|
|
604
|
+
type: 'button',
|
|
605
|
+
className: 'dm-arrow dm-arrow-' + direction,
|
|
606
|
+
'aria-label': label,
|
|
607
|
+
title: label,
|
|
608
|
+
disabled: disabled === true,
|
|
609
|
+
onClick: onClick,
|
|
610
|
+
},
|
|
611
|
+
h('span', { className: 'dm-arrowGlyph' }, glyph),
|
|
612
|
+
h('span', { className: 'dm-arrowLabel' }, label),
|
|
613
|
+
)
|
|
614
|
+
|
|
615
|
+
const regenerate = () => {
|
|
616
|
+
setQrVersion((v) => v + 1)
|
|
617
|
+
issue()
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
const copyGlyph = copied === qrText
|
|
621
|
+
? h('span', { className: 'dm-toolGlyph' }, '✓')
|
|
622
|
+
: h('span', {
|
|
623
|
+
className: 'dm-toolGlyph',
|
|
624
|
+
dangerouslySetInnerHTML: {
|
|
625
|
+
__html: '<svg width="12" height="12" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linejoin="round"><rect x="5.5" y="5.5" width="8" height="8" rx="1.6"></rect><path d="M10.5 3.5H3.9A1.4 1.4 0 0 0 2.5 4.9v6.6"></path></svg>',
|
|
626
|
+
},
|
|
627
|
+
})
|
|
628
|
+
|
|
629
|
+
// ── 第 1 页:选择网络(原生 radio,不用自绘圆圈/填色)──
|
|
630
|
+
const netOptions = lanBases.map((base) => ({ base: base, kind: 'lan', configured: true }))
|
|
631
|
+
netOptions.push({ base: publicBase, kind: 'public', configured: publicBase !== '' })
|
|
632
|
+
|
|
633
|
+
const netNodes = netOptions.map((option) => {
|
|
634
|
+
const active = option.configured && option.base === activeBase
|
|
635
|
+
const label = option.kind === 'public' ? '公网' : '局域网'
|
|
636
|
+
return h('li', { key: option.kind + ':' + option.base, className: 'dm-netItem' },
|
|
637
|
+
h('label', { className: 'dm-netRow' + (option.configured ? '' : ' dm-netRowUnset') },
|
|
638
|
+
h('input', {
|
|
639
|
+
type: 'radio',
|
|
640
|
+
name: 'dm-connect-net',
|
|
641
|
+
className: 'dm-netRadio',
|
|
642
|
+
checked: active,
|
|
643
|
+
disabled: !option.configured,
|
|
644
|
+
'data-kind': option.kind,
|
|
645
|
+
'data-base': option.base,
|
|
646
|
+
onChange: () => {
|
|
647
|
+
if (!option.configured) { setRemoteOpen(true); return }
|
|
648
|
+
setSelectedBase(option.base)
|
|
649
|
+
setRemoteOpen(false)
|
|
650
|
+
},
|
|
651
|
+
}),
|
|
652
|
+
h('span', { className: 'dm-netLabel' }, label),
|
|
653
|
+
option.configured
|
|
654
|
+
? h('code', { className: 'dm-netAddr' }, displayAddr(option.base))
|
|
655
|
+
: h('span', { className: 'dm-netUnsetText' }, '未配置'),
|
|
656
|
+
option.configured && option.kind === 'lan'
|
|
657
|
+
? h('button', {
|
|
658
|
+
type: 'button',
|
|
659
|
+
className: 'dm-rowAction',
|
|
660
|
+
'aria-label': '复制局域网链接',
|
|
661
|
+
title: '复制局域网链接',
|
|
662
|
+
onClick: (event) => {
|
|
663
|
+
event.preventDefault()
|
|
664
|
+
onCopy(option.base + '/m/' + (pairingCode ? '?code=' + encodeURIComponent(pairingCode) : ''))
|
|
665
|
+
},
|
|
666
|
+
}, '复制')
|
|
667
|
+
: option.kind === 'public' && option.configured
|
|
668
|
+
? h('button', {
|
|
397
669
|
type: 'button',
|
|
398
|
-
className: 'dm-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
),
|
|
413
|
-
h('div', { className: 'dm-
|
|
670
|
+
className: 'dm-rowAction dm-netEdit',
|
|
671
|
+
onClick: (event) => { event.preventDefault(); setRemoteOpen(true) },
|
|
672
|
+
}, '修改')
|
|
673
|
+
: h('button', {
|
|
674
|
+
type: 'button',
|
|
675
|
+
className: 'dm-netOpen',
|
|
676
|
+
onClick: (event) => { event.preventDefault(); setRemoteOpen(true) },
|
|
677
|
+
}, '›'),
|
|
678
|
+
),
|
|
679
|
+
)
|
|
680
|
+
})
|
|
681
|
+
|
|
682
|
+
const remoteFormNode = remoteOpen
|
|
683
|
+
? h('div', { className: 'dm-remoteForm' },
|
|
684
|
+
h('p', { className: 'dm-remoteHint' }, '公网域名(可选,不在同一局域网时使用)'),
|
|
685
|
+
h('div', { className: 'dm-remoteRow' },
|
|
414
686
|
h('input', {
|
|
415
687
|
className: 'dm-input',
|
|
416
688
|
value: domainDraft,
|
|
@@ -429,72 +701,127 @@ window.__ModuleLoader__.load({
|
|
|
429
701
|
}),
|
|
430
702
|
h('button', {
|
|
431
703
|
type: 'button',
|
|
432
|
-
className: 'dm-
|
|
704
|
+
className: 'dm-stepBtn',
|
|
433
705
|
disabled: domainBusy,
|
|
434
706
|
onClick: () => saveDomain(domainDraft.trim()),
|
|
435
707
|
}, domainBusy ? '保存中…' : '保存'),
|
|
436
708
|
addrs.publicBaseCustom
|
|
437
|
-
? h('button', {
|
|
438
|
-
type: 'button',
|
|
439
|
-
className: 'dm-ghost dm-btnSm',
|
|
440
|
-
disabled: domainBusy,
|
|
441
|
-
onClick: clearDomain,
|
|
442
|
-
}, '清除')
|
|
709
|
+
? h('button', { type: 'button', className: 'dm-stepBtn', disabled: domainBusy, onClick: clearDomain }, '清除')
|
|
443
710
|
: null,
|
|
444
711
|
),
|
|
445
712
|
domainErr ? h('p', { className: 'dm-err' }, domainErr) : null,
|
|
446
|
-
)
|
|
713
|
+
)
|
|
714
|
+
: null
|
|
715
|
+
|
|
716
|
+
// 单页布局(用户要求取消分页):先设公网域名 → 选连接地址 → 二维码
|
|
717
|
+
const domainBlockNode = h('div', { className: 'dm-domainBlock' },
|
|
718
|
+
h('div', { className: 'dm-domainHead' },
|
|
719
|
+
h('span', { className: 'dm-domainPad', 'aria-hidden': 'true' }),
|
|
720
|
+
h('span', { className: 'dm-domainLabel' }, '公网域名'),
|
|
721
|
+
publicBase
|
|
722
|
+
? h('span', { className: 'dm-domainValue' }, displayAddr(publicBase))
|
|
723
|
+
: h('span', { className: 'dm-domainValue dm-domainValueUnset' }, '未配置'),
|
|
724
|
+
h('button', {
|
|
725
|
+
type: 'button',
|
|
726
|
+
className: 'dm-netEdit',
|
|
727
|
+
onClick: (event) => { event.preventDefault(); setRemoteOpen((open) => !open) },
|
|
728
|
+
}, remoteOpen || publicBase === '' ? '收起' : '修改'),
|
|
447
729
|
),
|
|
730
|
+
remoteOpen || publicBase === '' ? remoteFormNode : null,
|
|
731
|
+
)
|
|
732
|
+
|
|
733
|
+
const qrCardNode = h('div', { className: 'dm-qrCard', 'data-qr-url': qrText },
|
|
734
|
+
h('div', { dangerouslySetInnerHTML: { __html: qrSvg(qrText, 124) } }),
|
|
735
|
+
)
|
|
448
736
|
|
|
449
|
-
|
|
450
|
-
h('div', { className: 'dm-
|
|
451
|
-
h('p', { className: 'dm-
|
|
452
|
-
h('
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
h('div', { className: 'dm-code' + (expired ? ' dm-codeExpired' : '') }, code.code),
|
|
456
|
-
h('p', { className: 'dm-count' },
|
|
457
|
-
isFixed
|
|
458
|
-
? '固定配对码 · 长期有效'
|
|
459
|
-
: expired
|
|
460
|
-
? '配对码已过期,请重新生成'
|
|
461
|
-
: h('span', null, '剩余 ', h('b', null, remaining(code.expiresAt, now))),
|
|
462
|
-
),
|
|
463
|
-
h('div', { className: 'dm-actions' },
|
|
464
|
-
h('button', { type: 'button', className: 'dm-ghost', onClick: issue, disabled: issuing },
|
|
465
|
-
issuing ? h('span', { className: 'dm-spinGhost' }) : null,
|
|
466
|
-
issuing ? '生成中…' : '重新生成'),
|
|
467
|
-
),
|
|
468
|
-
)
|
|
469
|
-
: h('div', { className: 'dm-actions' },
|
|
470
|
-
h('button', { type: 'button', className: 'dm-btn', onClick: issue, disabled: issuing },
|
|
471
|
-
issuing ? h('span', { className: 'dm-spin' }) : null,
|
|
472
|
-
issuing ? '生成中…' : '生成配对码'),
|
|
473
|
-
),
|
|
474
|
-
err ? h('p', { className: 'dm-err' }, err) : null,
|
|
737
|
+
const connectNode = h('div', { key: 'connect-page', className: 'dm-page dm-inner' },
|
|
738
|
+
h('div', { className: 'dm-connectHead' },
|
|
739
|
+
h('p', { className: 'dm-pageTitle' }, '连接手机'),
|
|
740
|
+
h('span', { className: 'dm-headRight' },
|
|
741
|
+
h('span', { className: 'dm-help', role: 'note', tabIndex: 0, title: HELP_TEXT, 'aria-label': HELP_TEXT }, '?'),
|
|
742
|
+
),
|
|
475
743
|
),
|
|
744
|
+
domainBlockNode,
|
|
745
|
+
h('ul', { className: 'dm-netList' }, netNodes),
|
|
746
|
+
h('div', { className: 'dm-qrStage' },
|
|
747
|
+
h('div', { className: 'dm-qrWrap' },
|
|
748
|
+
pairingCode && activeBase
|
|
749
|
+
? qrCardNode
|
|
750
|
+
: h('p', { className: 'dm-muted' }, activeBase ? '正在生成二维码…' : '先设置公网域名,或连接局域网后自动生成二维码'),
|
|
751
|
+
),
|
|
752
|
+
),
|
|
753
|
+
h('p', { className: 'dm-scanHint' }, '扫码后自动配对,无需输入配对码'),
|
|
754
|
+
h('div', { className: 'dm-pageTools' },
|
|
755
|
+
h('button', {
|
|
756
|
+
type: 'button',
|
|
757
|
+
className: 'dm-toolBtn',
|
|
758
|
+
'aria-label': '复制链接',
|
|
759
|
+
title: '复制链接',
|
|
760
|
+
onClick: () => onCopy(qrText),
|
|
761
|
+
}, copyGlyph, h('span', null, copied === qrText ? '已复制' : '复制链接')),
|
|
762
|
+
h('button', {
|
|
763
|
+
type: 'button',
|
|
764
|
+
className: 'dm-toolBtn',
|
|
765
|
+
'aria-label': '刷新二维码',
|
|
766
|
+
title: '刷新二维码',
|
|
767
|
+
onClick: regenerate,
|
|
768
|
+
}, '刷新'),
|
|
769
|
+
),
|
|
770
|
+
)
|
|
476
771
|
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
772
|
+
const wizardNode = connectNode
|
|
773
|
+
|
|
774
|
+
const errNode = err ? h('p', { className: 'dm-err' }, err) : null
|
|
775
|
+
|
|
776
|
+
const deviceRowNodes = devices.map((d, i) => {
|
|
777
|
+
const desc = describeDevice(d)
|
|
778
|
+
return h('div', { key: d.deviceId, className: 'dm-row', style: { animationDelay: (i * 40) + 'ms' } },
|
|
779
|
+
h('div', null,
|
|
780
|
+
h('div', { className: 'dm-name', title: d.userAgent || '' }, desc.title),
|
|
781
|
+
h('div', { className: 'dm-detail' }, desc.detail),
|
|
782
|
+
),
|
|
783
|
+
h('button', {
|
|
784
|
+
type: 'button',
|
|
785
|
+
className: 'dm-danger',
|
|
786
|
+
'data-confirm': confirmRevoke === d.deviceId ? 'true' : 'false',
|
|
787
|
+
onClick: () => revoke(d.deviceId),
|
|
788
|
+
}, confirmRevoke === d.deviceId ? '确认撤销?' : '撤销'),
|
|
789
|
+
)
|
|
790
|
+
})
|
|
791
|
+
|
|
792
|
+
const devicesNode = devices.length === 0
|
|
793
|
+
? h('p', { className: 'dm-devicesOneLine' }, '已配对设备 · 暂无')
|
|
794
|
+
: h('div', { className: 'dm-card dm-cardTight' },
|
|
795
|
+
h('p', { className: 'dm-title' }, '已配对设备(' + devices.length + ')'),
|
|
796
|
+
deviceRowNodes,
|
|
797
|
+
)
|
|
798
|
+
|
|
799
|
+
useEffect(() => {
|
|
800
|
+
// 配置变化(新增/清除公网域名、网卡增减)时回到默认选择;
|
|
801
|
+
// 同一批候选里用户切换过的选择保持不动。
|
|
802
|
+
setSelectedBase((current) => (candidates.indexOf(current) >= 0 ? current : defaultBase))
|
|
803
|
+
}, [publicBase, lanBases.join('|')])
|
|
804
|
+
|
|
805
|
+
useEffect(() => {
|
|
806
|
+
// 公网域名刚配置好('' → 非空):自动选中公网并出码,符合「保存后自动出码」。
|
|
807
|
+
if (publicBase !== '') setSelectedBase(publicBase)
|
|
808
|
+
}, [publicBase])
|
|
809
|
+
|
|
810
|
+
useEffect(() => {
|
|
811
|
+
// 二维码内部依赖 ?code=:状态里没有码时静默取一次;配对码不再作为
|
|
812
|
+
// UI 概念出现(宿主默认是固定码,取一次即可长期有效)。
|
|
813
|
+
if (!code && !issuing) issue()
|
|
814
|
+
}, [code, issuing])
|
|
815
|
+
|
|
816
|
+
return h('div', { className: 'dm-wrap' },
|
|
817
|
+
h('style', { dangerouslySetInnerHTML: { __html: CSS } }),
|
|
818
|
+
|
|
819
|
+
// ── 连接二维码(主路径:单码 + 地址切换;备用:配对码 / 远程连接 折叠)──
|
|
820
|
+
h('div', { className: 'dm-card dm-connectCard', 'data-qr-card': '1' },
|
|
821
|
+
wizardNode,
|
|
822
|
+
errNode,
|
|
497
823
|
),
|
|
824
|
+
devicesNode,
|
|
498
825
|
)
|
|
499
826
|
}
|
|
500
827
|
|