From 486948ad6f409d74b80fc44d58e50dda14565d8b Mon Sep 17 00:00:00 2001 From: hole-thu Date: Wed, 2 Sep 2020 11:51:42 +0800 Subject: [PATCH] =?UTF-8?q?=E5=90=88=E5=B9=B6submodule?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitmodules | 4 - src/infrastructure | 1 - src/infrastructure/appicon/course_survey.png | Bin 0 -> 2058 bytes src/infrastructure/appicon/dropdown.png | Bin 0 -> 1832 bytes src/infrastructure/appicon/dropdown_rev.png | Bin 0 -> 1484 bytes src/infrastructure/appicon/hole.png | Bin 0 -> 2286 bytes src/infrastructure/appicon/homepage.png | Bin 0 -> 2339 bytes src/infrastructure/appicon/imasugu.png | Bin 0 -> 1893 bytes src/infrastructure/appicon/imasugu_rev.png | Bin 0 -> 1517 bytes src/infrastructure/appicon/score.png | Bin 0 -> 1960 bytes src/infrastructure/appicon/syllabus.png | Bin 0 -> 1476 bytes src/infrastructure/const.js | 2 + src/infrastructure/elevator.js | 47 ++ src/infrastructure/functions.js | 35 ++ src/infrastructure/global.css | 37 ++ src/infrastructure/widgets.css | 301 ++++++++++++ src/infrastructure/widgets.js | 472 +++++++++++++++++++ 17 files changed, 894 insertions(+), 5 deletions(-) delete mode 160000 src/infrastructure create mode 100644 src/infrastructure/appicon/course_survey.png create mode 100644 src/infrastructure/appicon/dropdown.png create mode 100644 src/infrastructure/appicon/dropdown_rev.png create mode 100644 src/infrastructure/appicon/hole.png create mode 100644 src/infrastructure/appicon/homepage.png create mode 100644 src/infrastructure/appicon/imasugu.png create mode 100644 src/infrastructure/appicon/imasugu_rev.png create mode 100644 src/infrastructure/appicon/score.png create mode 100644 src/infrastructure/appicon/syllabus.png create mode 100644 src/infrastructure/const.js create mode 100644 src/infrastructure/elevator.js create mode 100644 src/infrastructure/functions.js create mode 100644 src/infrastructure/global.css create mode 100644 src/infrastructure/widgets.css create mode 100644 src/infrastructure/widgets.js diff --git a/.gitmodules b/.gitmodules index 59e10ee..c8bff63 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,7 +1,3 @@ [submodule "src/react-lazyload"] path = src/react-lazyload url = https://github.com/xmcp/react-lazyload - -[submodule "src/infrastructure"] - path = src/infrastructure - url = https://github.com/thuhole/infrastructure diff --git a/src/infrastructure b/src/infrastructure deleted file mode 160000 index e3c39ff..0000000 --- a/src/infrastructure +++ /dev/null @@ -1 +0,0 @@ -Subproject commit e3c39ff4e3efaad45e16796d9eb511345d4cbcf4 diff --git a/src/infrastructure/appicon/course_survey.png b/src/infrastructure/appicon/course_survey.png new file mode 100644 index 0000000000000000000000000000000000000000..a2ea2e3b2c59174ec394f5207cb79bd6885b134f GIT binary patch literal 2058 zcmV+l2=(`gP)D)84VLEga#!bcW8743hOUJ+msNX9NeELczewU@(wdv-ZuivBX#RQ`uoP zlN;AExiXfG<+zL9%P{2M``y_g>|KU4Z_rtiL9#+V*-tgVw_)yzU~{0Wwe_XT@nox! z&5u`q90heBS}ccoy%5X;>w=xi~QyV}35ebEYpBn;V&Ml>QYcR4m5jmAE;l|rTH zDrVt$_bIJ;j_>?TW`veVIa*4Q|0@MY&E{E#r4-6XqOm0;JLDQsX8>CilCWdrCpbWg z9Zktwo-o(bdg!alv%=WDSD5?u3%#&WXkBSXi*-AA3N773h>#HivKOxmHnT1d1rLrn zq`ZH9`yxx(P*I6gfRY6yv!0+jk39n@_G(u~R31DO^m80XRPH|z(`SAWM*l8H&-Kz7 zGQx)JnH}re7g9JPZgwy^Rt1A|K$iJ{>vmB>Z4soUV<#MI;;|^-91(gRo~4wU=kDTf z8#W84To#qT?~3V5zX@B{h4-^2Cmp@8NvJ8sD&p*9I(IV~X_?mqon!A+7TDi7cQ{^ z@>C@w;59EOQlkkm1Fs2sebYBUuZQ>Oy+Fmb#q_!J0`izgZoROfYeH#V`wEegtJc|A z*H@IgWFdK_g3adsLlVMAV=Sn0_a1#0`j)N2{Ao}adw!N{*B(G#6xP4vG7}&N1Qh0> zBYeJe^0YKoW)SNjU8g$}Uo35E3Iy6vUQxZyz$!<@pIq78v??7xDXhnnqC9d-dJi({ zfR>Ci_8kz$-a%m=J;92m&tH_D_H4kjTa<5%aOez#MRUnZvPlPul=Cp93e80N@an1Zy!}SQQWeP ziARPNcl2{PW>gRgr&8gpDSopZDD+EY>WyFn3^JfD1huBa@g&$u0ae4|ww-Jk#h0?f z+;>n|;}gOzO*71dn%ddLypbXMgR{jvctj#o<4-jNce}H(CrRjwF$v`yM*g#ho(Fjl zE{V|mc7?-K9=%0nTj(3NaJV@BTX#sWk(LcTq)Nh}&ctF$!?)|w&?6$jjmlO!bW|7v zyJeB_&~c434<42c$gTS}pr>E?&%fmUv_!HY1AsQmP?3hOc!lUxwGh!JQjUs870&w+ zC%6)N2vNErz6|&En;`9|tegmo2Cu!8)f=*gbdatGsq9HKq-rT%RxQOc3!Irhu1V$t zR<3Gz*9dwq3*546mr6`h;sSL+u9)Bo*A2I4xCrn};VZ?TaVd72(E?aCsmVD2&8XX% zzHqVH;V94TnHgE2z;em}y>BZUSNZ3W3E~OL0Al;BK4;&WW9-0G)^^_q*Nb~4% zxd$9VNF0*swc~T~uCKWrhtQ6B{Kjw)YiXGW>qe>riQB=9?+0X??UHq#CLDd!7Woar zN~h0?>0d9%|L~1asaw5$OlqXNW$;XpyVenjJYOA1{3990rFStll|d99$v88T8HeLY z_1xc#QZmMrX8!r0VX^1#Naj?sh0^wQ>)%=#^o?Zxp>(AjN|(4pDPo?p{JE<=SyIJp z-#o&(#myT^ox{=C2g~I=SQ|=b8_QiIX6nZBTC;LyQ|@cG-v17rHKg(qWPZ3jSi2iM z^&2vYMXS4*OlESIX%Z%xp=Y?5c=tlSBY>FmF+esWZ65ir zW?KCvr7k?))eO&vIJ+v^((=MHUCsPPgnXA%N*86#ngu8vOaDnJbR(WL8mb$;8?u`| z#-3wTWN_wHI=dS3p80axXh_7pp09wQrKp%R!=Zk^HryFsGL}+e#Y}zxiU-iuqC=hW okMQ5Cw1@VtaL4Y*|6I@i1J)Zm?X46Al>h($07*qoM6N<$g1N2LbN~PV literal 0 HcmV?d00001 diff --git a/src/infrastructure/appicon/dropdown.png b/src/infrastructure/appicon/dropdown.png new file mode 100644 index 0000000000000000000000000000000000000000..0ac094a8bbb2fd1db8a1fccac47c41c9c9b94cd1 GIT binary patch literal 1832 zcmV+@2iN$CP)&BzsH#zfi zeef*&_};zu&CHpzeCNy=b>zqq<;LN|hc)F928;sVft=laupQY;5d#%=y7jk?X0csXGx) z)!W;v{FRunIbx<#Qd0K#ZTw?$a`K*rhK3l9)2;N-z`%e8-wDcSYHAA0&d#p&cs!qT zEx4g&EL^zoB*IEwSZ*cmb2}|hN=n)-3-9p>tIlHMIUEyC(3K8^@o5S4e;n)U>(ffL zw6ugSSg@eSEelGF&=WA!F-qtk3Zn&Z>v~M|V!<6QNJvO%<3w&wQu2K=GWqdG&!r;R zNM&VZRYBHG$h=FL^rXnMwFlr*vfTpV<}k)&H771!yts`*;4%kVYb&vdGZjFvjSVcm z4-O70@S|KjF^1=D5c45=sjI8Yp~k_~G%hagc|#ny{Twaf=8PN3!v*-B5@;cn=UOP^ zVd!8`hv8L7NXVsq`}Wa89yL5XtTt`h^e_hh0md-l=lc5k2newlFA8jJZ4JrH%xsu9 zZ(bMB4rMzh1I9WyCoL_lW!J7C&aU zO^ggTR;*aDbGmf^UL2+Z5)PaDfMaVgMnZbS!ouF5=V^U7V)F(61g?Vdk#reDK!(%x zMMXs$#6#XGY|c4%kjkwL0~F9{M`haD+USLkWX_*uWo2^}Qlo~&f{Vk$!!Iz;K_1JT z3DlDRq2Me-NnQ(-Kpn9rKP2h3K{8zPZduxq@K=EmRH6cx+Au%8m6eql;sHy_v(_5t z!V}Dp>5vc=wS!zD3B?0Cm8+_%qA~uvlzAGiuDcXScPn7BfT5Xg79br5#RHa~0#O+M z&8@%{eCQDHR1*b!Az=LBPESTgMio+Y56}#>1VA&-63ngNv13P=`}E_JA*imdPGB|k zg#aXchs}f(hi$ajpM(^|u82izsxYbSYH)N)qYUS|NcbJoaHq6Yx&({mzBDukOO<=R0UgepC!>C=-a2#pa%|bL6#o=pl$(6>&#!z=5qT5PJ zN(z`QqA2lq0E|jaxr#8P{3T!np-7+y$bL2;tR<-bZyNH!&~4<3Zk^e^&YCsrqR}3WXbLn~LWUY!M*|C-he6}Lzl5|8hopb}tcqjWB;3pdfpRL~MwZ@Fv3Wc|J0 zox(QVHSPzwu=*F?9Vi<||4Er=`Zhltq+aN9bb=i~-6g9@3p z+`Q9UOf|TCB^wSg#B6>M%oL6OV2|MlTyEUK-oP1?G3 zYcwz$CtM;pv=VDNX3UuJp452XI%LpESg!mxpY&?xz8#@RWkB<{0^~Y3`GW_GRTzfaC?!5usA6#R^psQBhQ~@0plAlT0#`$;9XV`<-z7 z%_Nf=cr%lnbH49A-+qGT=H{RjT3T9?d@gBdXb2h`8-w27-lgN?5 z!3A)R|D9rOUpk$x(%$;|`k<+)sR9|P`E<;y90AdH6tBu=vnNpUGs@D29?)&y`@kR= zV9%fIeYd~A|H0PQ)`&PVl8Ysf(7~>*t{V`h+m3-5Pz2Lp3QU3tL#}Y?r)c|x{N&{1 zNyy)7BogHkh?EZw4sJt8hbK_zk}idi8OdZa z`>|-?EIJ>7gf?>Ea7;+M{)a`b*SZMK1U28*1Fa#BZ6|^2Qcp1fvoJ*B^EQXq{)k7!fg(9ON;EHQ!XJuxAkvX4ia`IDP_3i z3A2O(I7eXK;VvbXOT+|IzvFz)_d5O0ln2hNMrc8}y=Lx|zH^~!CqJLhf8EyB7Oh1E z14ehUFm5TzOIaT?wXC;+7DwQ$=YsWd7g+SBMn*<wV`CnO}o`Z#sS{ja#hA)ay6;}AmibETwTN*D!MD;`Fvr$8)1V$~w)41W;cp*}4 zK-UEe=phQxO|BHzy5J$;p7G)!3POY(S!@t;yZ2(HIOHPtnE9t^Nav$cEPt`^fC`Zo zVE6}(q=LgyOO+6;Qi-cxhvF>^u6neTGoh7(KWovv4K$zSM>x@1ZlQWl*zD==(m5W}b4NbL+Jn!7{Ld7+R|agraY( z(9E9Gn?NI3T={}eGlZ^2;Mv%;Q?Qg(;pwv1Q^u4|`%{w$Gfi!9nG{z(@8i^s)G|B1 zd>oU0YLipO9-?XQaXMgCP!=18^f|KVIi=d=K2H4yMuk$zUddGy8}*J)!1wkvzX*QU mCu>L8vqF2VAte`jp8o^FK2zSWdWkRq0000uw~;Q0;$vlsnDoNqpGD% z3buSUBBb8k(d--@UjjSG2W}m(d}?>SGntt+76b~#Ty-N9XpuSW8qz~*k|I%3MI!;1PS-cgJ}vxm zcIR!MJ;;AP7&tyHT_+uuO-?p#nn?q~A(|!sZm?|g%#JOVk9}sOzWc=!z)E%KkD3;_ zUQsGTKm^ECV0>BS&!Y(r>^J@|3Z&$<48s?(EZ^TZ);|K0@J||&9Cxwmz(ewdGl7Qr z5w3#adyrAwKUGV}q5OX0)?W#8Za+p9rL8kLAbNlktkOpFvmvDkHcm zx<~+!0JsY@*UeIs@Q4hbEMFIhCM^CN!@Rc_?%6&2gAVNe-MZR22!0O1DM;ZYsQ8>x zK%+DhRmfB+%v0WfH&8d1#nRM`d#Z5P?pei5%g2ou7FrM-rAOn*GNmfM4u%0e0B$-~ zrou=hX}SV#w%oqEIfAA&edaw9ao43|W9(Y(1R1K`@GYGE7*!+(SV9KqNfk=nXQKW;sds#|?EYcyZj*e-S zsDQ{77|BxM+#*yULuG|3sNiI&Zyb0f;^(n6rXR($-Q&~OX_(}Cd1(;zAYv@|XgY z`5;3BJ_<|)ov*;BOG_Jfwna(jG={v>Y3FOfjrU<~&0-LOBiOx*vv(OdS3ah-%&MqX8jxR__I}TGehR!ED6BCJrc~24mV`Bwzs#jot+b(+YPr~G<4n1 zE*IC!wdc`zju*SIJ1PBTtqQIyWvBo*B~(`I0P#CjxCdko{0XMv-`Ob=JeIg2aTI7s zcYH{_-CD2{*` z?;IXX$CgYb!2{>X;3~K-!r14s_=BxAy|qgoIn%ONfV}P9)V15#z_*?$;Q+2>l*xRjl82_ca(I+ zET7I4Kts$hqZWys(VpFLpo`vRq2oQa!0X$($2G2=!^tbw{=kqPKPVjK2Cb zVJJue~Bs zu~(!kPhr;stZQMS@F+@uJOp`zfzF1W#xEy26GS(4FNQ3SM$9J0-e#h|A6%=C<(${A z6d?&tgpUOkp&g@z)V@?iccC%|&%OW$|GEa+x<#n(4nyfak-l(5q(2@M=*l+*x|+#- zR7_$)KGv!~lw1h@UMp#Rt&P}mE46?4A~HP^7)K+T@EKN|7=zXGQ3+ii%^fv{3(y;! z2%Q`cn$?Mp7P!sVirkz(1>GNEm#YUtPTmQW`Kag=_lcBsoQECf^anmJ7zn&ty}v#~ z$Ny%s>nU(=5t-%`8xt=NhK^e*g7WM`HO{J!=@-_tB9VXSXi}Y#xl)WHDgq1r61`Xq zFP;cN!4VM(j|wm;b54H{Ru7cCx28{S*AA~++Pb}!B;suOn116k;J4ie*nyOKT6lwr z*?t3w7`9IIQ&qF|bHWew3u}LYr>)~9!klSzbP=;@n>VKY&BWN#O3b}2 zKE0>qE3Mnwzlt>ji?nWUBNh_g8tEp?WbC)PH3@9o0z6s&0k|}xrRKvTfB*mh07*qo IM6N<$g1ehK!TL~WX+MIlv+C=Dg01gD`4rr0KkAqHb8U@%}X{)T(*Jf5?<_PO`7jghr< z&Nuj5Yp=ccIr}<0ckOa|dU}@k^!7L>j-POzJb2t=;{3LWvsMR)(a)vD^(egz|Iz%>*oT}EE4TC+o6pZwPk`zc~zaNs4U|LuNf51FivApYRqz5pKN_p5piF)vpl{p%M`Wc?g~Q_y2wJ#1Fc= zyO%kqPJHvdxDkxOFJauYFkVXXv=&mkpy+}MxhIrwjH?#GCECWc-D^%OK?9n%9Xe{ipJOoqDK#5LZ-@RYDjKGL~LP9qO?g}Z8Fbfk^7Zn zyi!vDZDR_&f;Q(6bVM)}&@Kgp8KQeLcyfFgYS)JdUfBeH{Z<5PHX>Ntg<$w*4dNDe!Uvz^KO1NLqh5M zDtc2`kX#w9YXRbf;CT_X5GAN;Bbf`)>b(H->Jaol7+FqdT%WC3A53nW1(u?5>>%`S zSHOJr9*M2x{4NC)1f$j@(Yg|#4F!lJ))gznSS*OqC|$b1Q`o=ThWo}+hhb_#GOylXP|KZu`2|PP<1<%fn;@O3B zm>a(g|DQXMoqr2uI8EXJW$BVw39&^^0XYTa@*1^(xg+8>o@-_GIQ z<=Z#+fDqRVJ|%E%K&o{%&qc`PdlBm3Gj5gmv-0-~C5DeNW2=yO_s=R1Yp zuM6>Kp0;m;5XhCz z0xU9v(f_otb4`kU+YKJy*N8Y2`K}B*8bMGZh%*FPf}ji$XdeN|D!2%sxDq6+VfY?J zNJ=O`uI#1o1u|u^_zK?6#||~Hb!CZtI}O@RlG}-l-w8DQh)4_gbiglT_(mvv_;kS| zxla+Y^JQ;W`BcfbSPvB7cL-kqNf>3Cl=$QR23}ib@bMoQJqbB+Rbyc&lbhzv&6~2w zd8tZ?MX>Q2p{hhw=5W&lR~G#7Oq$G=nP*M*;VlwT{ZWDlum#C^z*CDzJD?cOmv+Rv zbjih<*CKRn0j^I{6mMVGC!tL1GA^=6y@C#CK~{CTmKqOjDpW0^lLAEtT>2vtA|nEL zIni#JsAa6TtB7%3sc?g*vpELd%kbF|Ry|2wzlvT-^hq_xa;hUJfM>s)bDng$t@Dlx z3+a#)P=chuPyi32n72A_M~?QAckNZ9K4h}y)Xg*ivvbU|w4O}o@?0Xhm*SI|)!J_= z2TWnR+ol1P3kxD_`AG%vh!O|nEQr2wrly|k_kG@|9Oo-?dC*y03yhpcu~$8pSn~Pk zCI5v$S1vp!Abwti@r`wXB3w?uAwL_R9RImvA3OJQ=ial|S$pkuHsbK%!@@ic9Xd3AW$fR-Un(dlkRLg6#OC<%<2J{R9Wz`D z3kwx^F5&vYH;m@#99md{*WU3K>M_9Fmt-OI~s@qq&e z3?Qb$#P|)7bLR;O2@Y7W3W*-iojX@Kd-iM%lBt7(gCDG0x9(PaeEjdrmoM)?N%{az z>+bH}3n0TN%Uy48Z~y%Ke3oPC3>-arRBYL@MS$W$?C`Otr)Mt!XjiOQaks9nuJrly z=c(`CzmG+H^XAQ)q^_>6{FIcG1_00yjGLR=D1bKtoGXQEE=;Qca3k>#Bwh+i)kv9m?HBj%-E;2j?36QbZ?9A;J>I>07mY;c0YHrskdaXr7nkh4d-oc; z#Jsc<0wDF=eMUwG0aS7)TrfO5{K3!X(H^0YG%J6DLlHsHi9}eEgS>kB=50bQdpPEb8g$ zvE8$04;PZSBa4ve2^}3BLZi{d`T68#ZjHhh_%A!Z6C1vwiz^f$t@2Ebt{8 zQVONV&zm<-5BhasVPSv3TwEq=C!Wb6Q#&U9%GO4?#b}5fKqZM&Q;pfEVSY5VU z9dxk9xC5DGJDKh&PM!lWDK7xH4*(i~9|WkamoHzYJ|wGMKs8fHw{PEej*X42$3i+# zsYgfr3RiSyJ3)wY?#MhyJ(A04UUqhNg{(iQSD}Re)YsRCoIZV;N4fYM00t#DHa3dd z+S&{pE;_K#2O$m0WU>mJ3y$0+I|U_?5HjBL8IuEO3U;jl_5HXGpsjyI`#SQ-{v1ml zKYn=#>GgVV*y{}}s>6bPq!S)rw`kF#sO02i$E2hrv2o)@v3c`mIeLAuTrMxc?zJeH z8oO7rbV&OBrAwC#{=ycvHY<$ZgzmoHy_y=>XCHu$<8*4l@&VG#FfL<6D{ zaSBn3_#6Gsmg^?~GJw$H`F*r;IL(bgwrKSef%u@OS&Fu{Hrpppo+PYYyS52C)Zkdw zqAV(eX&xBC{SZQf-D|*>7ANMv0IM;wFa*}_V_=C}vSdjpPgh#~L<7r5l+a#VT3Q_7 z@vEz$D>fDD?LFb=&2O-$II<|iJ_ivJ%V zp&^)%&-k11cY}a&f;vESHAplFV^SKKP(wooCJ-EE+X;djqg8*_+-53^X%?_F7*hvv zKtX9%FI~E{1&MSJWIq^T2N8tY3`A>CP>?TY&?)~XGZ{dZ3WBx8{1}e|=}&?{TPj%w z0-z`Xpckz>262}0{b>PU4uTfk+S+RO;>C;gFeHK)Kq-_g1LsWuP$Kj+HgwhW0x*?> zUP2HkM?7ZBW`Zzwg%Ty{#or?f7cQ)!K}{O~OAutj=&I{s?YC&{EC~bj_oKbHV(y$? z0OrFA#Yzy+ggwreIQU96=FXx z6%PH8CxpzOS+tNqY*3;5wJ>TZC}`R=B+;fTxA~F&GUq&B&g0RO-{0Tg+I5}oN1mOj zM@ix0eSF{NdG71E@9Vzr=NKa+BZiLA(b1hJF+M(SnwXdf86F-E^Z9&XgM)+q=h)a- zDBhd!d}K}Fe!*buM*v1mFlO}i^%*c`%+AglGcz;(C%ze8uh&24|B%?#FgF|;8uC9k zHa3XUTU%T2ZEtUX1Y`o2@xNt#eLZS&a?&74MdYv~9y>k3lPxVR88Gw?Pz-beeSi=6 z2j~Z!Kn-96!6!%rqz_GE$EaFBSFf(FMq=ZyfnHz$a05NSLqU(c^9ZS5;E|WabB7|a zGvFegT#Ww!3;}jA?RRB9|*}Nj8F3b)W@Mcz(vc;%XIr! zG%g$Wz*tjDOUpMYDJdUXES8JFyK!-G$pr-kS1`XC^V~v)q4^E-pQ0voVFo3DfrIQ6K+VCr=_JO<>%)g<0jlx$K2eUQB_rCz$33OE-q374@ny9o8g70 z2L=WVrG~Z zV7)1r7dR=5F2$lmEbaq5aR2WR(v$n8lM*iS-vn$MG3Cw}%q{h?-Ng`wva4Ty9o?ei$wYRrZ zAEuyLKs8fHm6eszXfBmfURn2lg%_eFokDn`0MPYjt$6wS14!I&Y-~K!+uO@lZXASw zU&(cKbw*oT+sATx78NgJ2@+8}B{Kp~p4cp7RXJ0oTss&-q;&z(H%hhapdnDPWDU>C z%6b-?-V`q=5ZZ8qB_ zbiNv`4Lh~_fKTG>*1mVi*e>5FNGph(Wp`DTbGM9o%q1+Z6%`ecsPX6QcKbDKaz{L& zj43!^q#fyd1EfEfdCF_*?%4H>gr+VwjLw{>&>C#Aebx)|P+n)KUhlB#+?*ld-f(H3cZ_gAk zI%p(BS0cvjVq7Odf!aPVX#fp8>(M7@x3h;e$r2OX4f?vW7)BtcI|RZT)TZpo=VN*hRT8*fraN_1p12=Y5Nn1)F4Z4qVrzCZ;O*h?twreywC`VP!z8>f%kz6z)9X0n2P@b19+^< Tf-zC100000NkvXXu0mjfgXgtH literal 0 HcmV?d00001 diff --git a/src/infrastructure/appicon/score.png b/src/infrastructure/appicon/score.png new file mode 100644 index 0000000000000000000000000000000000000000..105a4c1f059eaa3c0bdae1df659d7ca19df879c9 GIT binary patch literal 1960 zcmV;Z2UqxsP)ML8C#_q6sj~T z$|A-T5sY96g&?AsXswnCxB(@~QUXed1O-8M6)a^fJG7-(Ta=bAQ(D@xJnwt|KIZkO z8n;Q#%%8u!d+xdS-FrVFfBsQ?P$ekRuR{K(k8I@MeANF!hCQgsCtR1r-_uhWoIFr{ z=HY?rnAC^WagRKpjZN;aK9`iB4(rxcNpLI@?=x!QI)1g3zfwz)y&n3YI&$rDb9?o1 zyPj4#lwNi{v;dj_jetvV{#S=q9kAkR9@=mogHSW>H`4Yfr0#CaexDpkusyEgxJOwz0V zu-(YnibdeY;YsRycw-bG1PHJ{uRgDT%)Kd*)VhEkUPF%?e5zfGs4yZ$dj;2Z_;=7I zeJ>T-EnM;vOfty)9$l457^m9-T>v+;+t+?-?rKE&Fb&GMQ3IOsxT+ z9N>u|>f57-Ywt{WR(pSHy7ob*j!HlD-XmaWr2F|jb`57O5)atsyl$+M_AXN)n*DBG zY8G&B1OXtEm0^6t$N^#i?NBXOf`ge)P|fyOH+VK$-{zWoxmO~lEXI&n3$u*x?(3tb z!9B4eVYVzc_xTA-9%n4V9n}qR8*aUuBy^C-1yKS0Mk2gEQD4F`l%B>#Pa_FN3c``U z!8)2gMxPxMMefeaF}M2(Y)trRX?pQ0vgJ~BqOm78L(=J zxwYmjBZ6D&H`i05*xMoX`%PZ`Xu0c=Dv{J;q^{s|7ah8BrTN1PqqK}$c| z^*5*J^QEq9i5w8!&_EK=n5{uP*R@AC<>|LFjO9gp?TcI$))mj#G+bcPnxCO0AGRaL zYOp%Wp<@Vp*VoMF$*Lm}!`~)#Oqd`N>4@9M!aV7d_Lw^3biRFo7cB_K=Y8Hf#K|vFt`&DXeOp$U=$)_ImmEtyL0|PGxa4W?k8J;JTMrsSV0T%xz)@aQ|kjgqLA9OPrEOz;i#YvQD6ry6k;hgM*IVJ4l3)Afq1BW^gaX zE&zF9NrgXzXnN<%lcjVLOSK_arHSTZ#qvT4&%n>HV_>9wmao%W)h*Opo%AJ^XI z3j7kOnyfzbyGt3@D*kh(7|UA8TH+ha1R(BBFoxCdhf!?5H;y%*u;~|>`feCrKAfJe ze*$E(LAklP?;7i`3$;WJ!0u^+Nebr2hg!{vdsee<7>am%700Yvgcz?F&R939BKM4C zcY|LoQAM3dgTr00d$m=B{URhvv5}Udj+vWf5+vhQfHA z8VV>+hFmfXwp#aSWv<(fI3% zB-Bs|7m2i!dO|Fc>VSplHfgZvqN^k!Hiitnua`0!UfCukC91C__t&PvT=-hj{p!ni zbXC%HgA72gO*GsQ?U?>|L(w2iR7DJq0s(2Bixx8?p11Ki)3-(d@9&6+#&f3see};> u#Z`%%j*DA9wc1N+`4J<Pk zXKedJb!=z4+3BLKic&2W1A^cdB?zG{kU$bh3W2bPfPg?7WmDZl6%tLca+q+|Y&Q)V# zw$;xvYs^|^jg6QdTf>=S-D1|1o6RbmgRHdFxcgVN4r-mjnXgudD2lX9q0zCdLJbS} z{paS^r3}`2E|r-J3Ye;L~rCy9*VvlQ5)TBLZfZlA{J{43JtlOhq$U!Q;zt*{fzn3l9)F`CKX`K zOlQ`F199H)=g_(PO(?4xps=*ToNx$3%jcsnZauhzS%LPFOb}0 z&RT#YE&|;v7ot#hN^s;fwWD&+ZozGfS<537DVH9>mNjxachVCT2K|N=$Ws*|ujM-O z-+Kog%ND@BGiufXXm2~WQSEvgdCi<7UkyX_a`Z$m1^FOfQUS3MavNW??~F#nicqN6 zg+aX~5@kylpqq!(zJ2yNKzqr?7&ag3%@I(ChY3#Nw%w1UR6zgMa5)DYoWRC$ZDlB$ zUI;IT2lvZ4@E<`czz4`VFcXHRV5T+S z>>w53@C?d1Fco&UM_fn8?_%N}FwTGI>c2B8*7{v;42|3YpAzu;hsE4JR~LL-P|ySn4*7+M^c*F= zPfkJN`3pF3N`|9n($U%73mV0hRrosbB)<6ZI4aByA`(Fp5P;3;g4N*^_jHwA&cx}g zD`cLH2I4=4(~ zb_Z_v^decIfIPoIBpnIs;zH(B0KGVofAv!$zWF%`2W83llM5kdbPRJYfJ%)rysWMs zhMHO&KX)EFQzeE+$3zayxqyMmdJhaeFS)~~Q(@&tLJoWS2SgH5xlRPL3IdIY-jwQ| z8W9bpR)>U)v!dzHaPv})PdkJ9mR9k6-!=#W+`b{vh}309Tq;oEH@yKF%3OST`~)g3 zO~P42Tf3M$lA0#UlbRLTknLj&pz@;%P^i>6dEp{bG8IV6&OvQ+3r2WUDBRQ;PngHviY#2>)j`e6GxP`oTwd=(bAUP`WjkH{JQv39P6#KI8}z2MMkN{8^U#v!z9a&i ze3CEBXhdfm06Cu8BRmhRyQi#A^WQSf_dsih-0t%5rZUDi42m-hCLA1;$duI09oMA- zipxy#wU%bsxk}#%59hESgZ|*a>%V_|6oFdHRcQ3aBN72!eYOyNdDTT-sR{L0TLtQx zT7rTAU#Y1E8bkSo5@Xdf($DgN0ajkqz|_UYk2MCPfp64ssDcDdk-?}hDKqW+-BiQ$ e91;Ql7ybq>6>2rmMmD(s0000A461 literal 0 HcmV?d00001 diff --git a/src/infrastructure/const.js b/src/infrastructure/const.js new file mode 100644 index 0000000..b8bc1b1 --- /dev/null +++ b/src/infrastructure/const.js @@ -0,0 +1,2 @@ +// export const THUHOLE_API_ROOT='//localhost:5001/'; +export const THUHOLE_API_ROOT = 'https://thuhole.com/' diff --git a/src/infrastructure/elevator.js b/src/infrastructure/elevator.js new file mode 100644 index 0000000..0ee93a4 --- /dev/null +++ b/src/infrastructure/elevator.js @@ -0,0 +1,47 @@ +const DUMP_VER='dump_v1'; + +function dump() { + return JSON.stringify({ + _dump_ver: DUMP_VER, + token: localStorage['TOKEN']||null, + hole_config: localStorage['hole_config']||null, + }); +} +function load(s) { + console.log('elevator: loading',s); + let obj=JSON.parse(s); + if(obj._dump_ver!==DUMP_VER) { + console.error('elevator: loading version mismatch, current',DUMP_VER,'param',obj._dump_ver); + return; + } + if(localStorage['TOKEN']===undefined && obj.token) { + console.log('replace token'); + localStorage['TOKEN']=obj.token; + } + if(localStorage['hole_config']===undefined && obj.hole_config) { + console.log('replace hole config'); + localStorage['hole_config']=obj.hole_config; + } +} + +export function elevate() { + // load + // '?foo=fo&bar=ba' -> [["foo","fo"],["bar","ba"]] + let params=window.location.search.substr(1).split('&').map((kv)=>kv.split('=')); + params.forEach((kv)=>{ + if(kv.length===2 && kv[0]==='_elevator_data') { + load(decodeURIComponent(kv[1])); + let url=new URL(window.location.href); + url.search=''; + window.history.replaceState('','',url.href); + } + }); + + // dump + if(window.location.protocol==='http:' && window.location.hostname==='pkuhelper.pku.edu.cn') { + let url=new URL(window.location.href); + url.protocol='https:'; + url.search='?_elevator_data='+encodeURIComponent(dump()); + window.location.replace(url.href); + } +} \ No newline at end of file diff --git a/src/infrastructure/functions.js b/src/infrastructure/functions.js new file mode 100644 index 0000000..842ddaa --- /dev/null +++ b/src/infrastructure/functions.js @@ -0,0 +1,35 @@ +export function get_json(res) { + if(!res.ok) throw Error(`网络错误 ${res.status} ${res.statusText}`); + return ( + res + .text() + .then((t)=>{ + try { + return JSON.parse(t); + } catch(e) { + console.error('json parse error'); + console.trace(e); + console.log(t); + throw new SyntaxError('JSON Parse Error '+t.substr(0,50)); + } + }) + ); +} + +export function listen_darkmode(override) { // override: true/false/undefined + function update_color_scheme() { + if(override===undefined ? window.matchMedia('(prefers-color-scheme: dark)').matches : override) + document.body.classList.add('root-dark-mode'); + else + document.body.classList.remove('root-dark-mode'); + } + + update_color_scheme(); + window.matchMedia('(prefers-color-scheme: dark)').addListener(()=>{ + update_color_scheme(); + }); +} + +export function API_VERSION_PARAM() { + return '&PKUHelperAPI=3.0&jsapiver='+encodeURIComponent((process.env.REACT_APP_BUILD_INFO||'null')+'-'+(Math.floor(+new Date()/7200000)*2)); +} \ No newline at end of file diff --git a/src/infrastructure/global.css b/src/infrastructure/global.css new file mode 100644 index 0000000..6be140f --- /dev/null +++ b/src/infrastructure/global.css @@ -0,0 +1,37 @@ +:root { + --foreground-dark: hsl(0,0%,93%); +} + +body { + margin: 0; + padding: 0; + overflow-x: hidden; + text-size-adjust: 100%; +} + +body, textarea, pre { + font-family: 'Segoe UI', '微软雅黑', 'Microsoft YaHei', sans-serif; +} + +* { + box-sizing: border-box; + word-wrap: break-word; + -webkit-overflow-scrolling: touch; +} + +p, pre { + margin: 0; +} + +a { + text-decoration: none; + cursor: pointer; +} + +pre { + white-space: pre-line; +} + +code { + font-family: Consolas, Courier, monospace; +} \ No newline at end of file diff --git a/src/infrastructure/widgets.css b/src/infrastructure/widgets.css new file mode 100644 index 0000000..b439cca --- /dev/null +++ b/src/infrastructure/widgets.css @@ -0,0 +1,301 @@ +.centered-line { + overflow: hidden; + text-align: center; +} + +.centered-line::before, +.centered-line::after { + background-color: #000; + content: ""; + display: inline-block; + height: 1px; + position: relative; + vertical-align: middle; + width: 50%; +} + +.root-dark-mode .centered-line { + color: var(--foreground-dark); +} +.root-dark-mode .centered-line::before, .root-dark-mode .centered-line::after { + background-color: var(--foreground-dark); +} + +.centered-line::before { + right: 1em; + margin-left: -50%; +} + +.centered-line::after { + left: 1em; + margin-right: -50%; +} + +.title-line { + color: #fff; + margin-top: 1em; +} +.title-line::before, +.title-line::after { + background-color: #fff; + box-shadow: 0 1px 1px #000; +} + +.root-dark-mode .title-line { + color: var(--foreground-dark); +} +.root-dark-mode .title-line::before, .root-dark-mode .title-line::after { + background-color: var(--foreground-dark); +} + +.app-switcher { + display: flex; + height: 2em; + text-align: center; + margin: 0 .1em; + user-select: none; +} +.app-switcher-desc { + margin: 0 .5em; + flex: 1 1 0; + opacity: .5; + height: 2em; + line-height: 2rem; + font-size: .8em; +} + +.root-dark-mode .app-switcher-desc { + color: var(--foreground-dark); +} + +@media screen and (max-width: 570px) { + .app-switcher-desc { + flex: 1 1 0; + display: none; + } + .app-switcher-item { + flex: 1 1 0 !important; + padding: 0 !important; + } + .app-switcher-dropdown-title { + padding-left: 0 !important; + padding-right: 0 !important; + text-align: center !important; + } + .app-switcher-dropdown-item { + margin-left: -2em !important; + margin-right: 0 !important; + } +} + +.app-switcher a:hover { /* reset underline from /hole style */ + border-bottom: unset; + margin-bottom: unset; +} + +.app-switcher-desc a { + color: unset; +} + +.app-switcher-left { + text-align: right; +} +.app-switcher-right { + text-align: left; +} +.app-switcher-item { + flex: 0 0 auto; + border-radius: 3px; + height: 1.6em; + line-height: 1.6em; + margin: .2em .1em; + padding: 0 .45em; +} +a.app-switcher-item, .app-switcher-item a { + transition: unset; /* override ant design */ + color: black; +} +.app-switcher-item img { + width: 1.2rem; + height: 1.2rem; + position: relative; + top: .2rem; + vertical-align: unset; /* override ant design */ +} +.app-switcher-item span:not(:empty) { + margin-left: .2rem; +} +.app-switcher-logo-hover { + margin-left: -1.2rem; +} + +.app-switcher-item:hover { + background-color: black; + color: white !important; +} +.app-switcher-item:hover a { + color: white !important; +} +.app-switcher-item-current { + background-color: rgba(0,0,0,.4); + text-shadow: 0 0 5px rgba(0,0,0,.5); + color: white !important; +} +.app-switcher-item-current a { + color: white !important; +} + +.root-dark-mode .app-switcher-item, .root-dark-mode .app-switcher-dropdown-title a { + color: var(--foreground-dark); +} +.root-dark-mode .app-switcher-item:hover, .root-dark-mode .app-switcher-item-current, .root-dark-mode .app-switcher-dropdown-title:hover a { + background-color: #555; + color: var(--foreground-dark); +} + +.app-switcher-item:hover .app-switcher-logo-normal, .app-switcher-item-current .app-switcher-logo-normal { + opacity: 0; +} +.app-switcher-item:not(.app-switcher-item-current):not(:hover) .app-switcher-logo-hover { + opacity: 0; +} + +.root-dark-mode .app-switcher-logo-normal { + opacity: 0 !important; +} +.root-dark-mode .app-switcher-logo-hover { + opacity: 1 !important; +} + +.app-switcher-dropdown { + padding: 0; + text-align: left; +} + +.app-switcher-dropdown:not(:hover) { + max-height: 1.6rem; + overflow: hidden; +} + +.app-switcher-dropdown-item { + background-color: hsla(0,0%,35%,.9); + padding: .125em .25em; + margin-left: -.75em; + margin-right: -.75em; + position: relative; + z-index: 10; + cursor: pointer; +} +.app-switcher-dropdown-item:hover { + background-color: rgba(0,0,0,.9); +} +.app-switcher-dropdown-item:nth-child(2) { + border-top-left-radius: 3px; + border-top-right-radius: 3px; +} +.app-switcher-dropdown-item:last-child { + border-bottom-left-radius: 3px; + border-bottom-right-radius: 3px; +} + +.app-switcher-dropdown-title { + padding-bottom: .2em; + padding-left: .5em; + padding-right: .25em; +} +.app-switcher-dropdown-title a { + cursor: unset; +} + +.thuhole-login-popup { + font-size: 1rem; + background-color: #f7f7f7; + color: black; + position: fixed; + left: 50%; + top: 50%; + width: 320px; + z-index: 114515; + transform: translateX(-50%) translateY(-50%); + border-radius: 5px; +} +.thuhole-login-popup a { + color: #00c; +} +.thuhole-login-popup p { + margin: .75em 0; + text-align: center; +} +/* override ant design */ +.thuhole-login-popup input, .thuhole-login-popup button { + font-size: .85em; + vertical-align: middle; +} +.thuhole-login-popup input:not([type="checkbox"]) { + width: 8rem; + border-radius: 5px; + border: 1px solid black; + outline: none; + margin: 0; + padding: 0 .5em; + line-height: 2em; +} +.thuhole-login-popup button { + width: 6rem; + color: black; + background-color: rgba(235,235,235,.5); + border-radius: 5px; + text-align: center; + border: 1px solid black; + line-height: 2em; + margin: 0 .5rem; +} +.thuhole-login-popup button:hover { + background-color: rgba(255,255,255,.7); +} +.thuhole-login-popup button:disabled { + background-color: rgba(128,128,128,.5); +} +.thuhole-login-type { + display: inline-block; + width: 6rem; + margin: 0 .5rem; +} +.thuhole-login-popup-shadow { + opacity: .5; + background-color: black; + position: fixed; + left: 0; + top: 0; + height: 100%; + width: 100%; + z-index: 114514; +} + +.thuhole-login-popup label.perm-item { + font-size: .8em; + vertical-align: .1rem; + margin-left: .5rem; +} + +.aux-margin { + width: calc(100% - 2 * 50px); + margin: 0 50px; +} +@media screen and (max-width: 1300px) { + .aux-margin { + width: calc(100% - 2 * 10px); + margin: 0 10px; + } +} + +.title { + font-size: 1.5em; + height: 4rem; + padding-top: 1rem; + text-align: center; +} + +.time-str { + color: #999999; +} \ No newline at end of file diff --git a/src/infrastructure/widgets.js b/src/infrastructure/widgets.js new file mode 100644 index 0000000..2ca90fc --- /dev/null +++ b/src/infrastructure/widgets.js @@ -0,0 +1,472 @@ +import React, {Component, PureComponent} from 'react'; +import ReactDOM from 'react-dom'; + +import TimeAgo from 'react-timeago'; +import chineseStrings from 'react-timeago/lib/language-strings/zh-CN'; +import buildFormatter from 'react-timeago/lib/formatters/buildFormatter'; + +import './global.css'; +import './widgets.css'; + +import appicon_hole from './appicon/hole.png'; +import appicon_imasugu from './appicon/imasugu.png'; +import appicon_imasugu_rev from './appicon/imasugu_rev.png'; +import appicon_syllabus from './appicon/syllabus.png'; +import appicon_score from './appicon/score.png'; +import appicon_course_survey from './appicon/course_survey.png'; +import appicon_dropdown from './appicon/dropdown.png'; +import appicon_dropdown_rev from './appicon/dropdown_rev.png'; +import appicon_homepage from './appicon/homepage.png'; +import {THUHOLE_API_ROOT} from './const'; +import {get_json, API_VERSION_PARAM} from './functions'; + +import { + GoogleReCaptchaProvider, + GoogleReCaptcha +} from 'react-google-recaptcha-v3'; + +const LOGIN_POPUP_ANCHOR_ID='pkuhelper_login_popup_anchor'; + +function pad2(x) { + return x<10 ? '0'+x : ''+x; +} +export function format_time(time) { + return `${time.getMonth()+1}-${pad2(time.getDate())} ${time.getHours()}:${pad2(time.getMinutes())}:${pad2(time.getSeconds())}`; +} +const chinese_format=buildFormatter(chineseStrings); +export function Time(props) { + const time=new Date(props.stamp*1000); + return ( + + +   + {!props.short ? format_time(time) : null} + + ); +} + +export function TitleLine(props) { + return ( +

+ {props.text} +

+ ) +} + +export function GlobalTitle(props) { + return ( +
+
+

{props.text}

+
+
+ ); +} + +const FALLBACK_APPS={ + // id, text, url, icon_normal, icon_hover, new_tab + bar: [ + ['hole', '树洞', '/hole', appicon_hole, null, false], + ['imasugu', '教室', '/spare_classroom', appicon_imasugu, appicon_imasugu_rev, false], + ['syllabus', '课表', '/syllabus', appicon_syllabus, null, false], + ['score', '成绩', '/my_score', appicon_score, null, false], + ], + dropdown: [ + ['course_survey', '课程测评', 'https://courses.pinzhixiaoyuan.com/', appicon_course_survey, null, true], + ['homepage', '客户端', '/', appicon_homepage, null, true], + ], + fix: {}, +}; +// const SWITCHER_DATA_VER='switcher_2'; +// const SWITCHER_DATA_URL=THUHOLE_API_ROOT+'web_static/appswitcher_items.json'; + +// export class AppSwitcher extends Component { +// constructor(props) { +// super(props); +// this.state={ +// apps: this.get_apps_from_localstorage(), +// } +// } +// +// get_apps_from_localstorage() { +// let ret=FALLBACK_APPS; +// if(localStorage['APPSWITCHER_ITEMS']) +// try { +// let content=JSON.parse(localStorage['APPSWITCHER_ITEMS'])[SWITCHER_DATA_VER]; +// if(!content || !content.bar) +// throw new Error('content is empty'); +// +// ret=content; +// } catch(e) { +// console.error('load appswitcher items from localstorage failed'); +// console.trace(e); +// } +// +// return ret; +// } +// +// check_fix() { +// if(this.state.apps && this.state.apps.fix && this.state.apps.fix[this.props.appid]) +// setTimeout(()=>{ +// window.HOTFIX_CONTEXT={ +// build_info: process.env.REACT_APP_BUILD_INFO || '---', +// build_env: process.env.NODE_ENV, +// }; +// eval(this.state.apps.fix[this.props.appid]); +// },1); // make it async so failures won't be critical +// } +// +// componentDidMount() { +// this.check_fix(); +// setTimeout(()=>{ +// fetch(SWITCHER_DATA_URL) +// .then((res)=>{ +// if(!res.ok) throw Error(`网络错误 ${res.status} ${res.statusText}`); +// return res.text(); +// }) +// .then((txt)=>{ +// if(txt!==localStorage['APPSWITCHER_ITEMS']) { +// console.log('loaded new appswitcher items',txt); +// localStorage['APPSWITCHER_ITEMS']=txt; +// +// this.setState({ +// apps: this.get_apps_from_localstorage(), +// }); +// } else { +// console.log('appswitcher items unchanged'); +// } +// }) +// .catch((e)=>{ +// console.error('loading appswitcher items failed'); +// console.trace(e); +// }); +// },500); +// } +// +// componentDidUpdate(prevProps, prevState) { +// if(this.state.apps!==prevState.apps) +// this.check_fix(); +// } +// +// render() { +// let cur_id=this.props.appid; +// +// function app_elem([id,title,url,icon_normal,icon_hover,new_tab],no_class=false,ref=null) { +// return ( +// +// {!!icon_normal && [ +// , +// +// ]} +// {title} +// +// ); +// } +// +// let dropdown_cur_app=null; +// this.state.apps.dropdown.forEach((app)=>{ +// if(app[0]===cur_id) +// dropdown_cur_app=app; +// }); +// +// //console.log(JSON.stringify(this.state.apps)); +// +// return ( +//
+// PKUHelper +// {this.state.apps.bar.map((app)=> +// app_elem(app) +// )} +// {!!this.state.apps.dropdown.length && +//
+//

+// {!!dropdown_cur_app ? +// app_elem((()=>{ +// let [id,title,_url,icon_normal,icon_hover,_new_tab]=dropdown_cur_app; +// return [id,title+'▾',null,icon_normal,icon_hover,false]; +// })(),true) : +// app_elem(['-placeholder-elem','更多▾',null,appicon_dropdown,appicon_dropdown_rev,false],true) +// } +//

+// {this.state.apps.dropdown.map((app)=>{ +// let ref=React.createRef(); +// return ( +//

{ +// if(!e.target.closest('a') && ref.current) +// ref.current.click(); +// }}> +// {app_elem(app,true,ref)} +//

+// ); +// })} +//
+// } +// 网页版 +//
+// ); +// } +// } + +class LoginPopupSelf extends Component { + constructor(props) { + super(props); + this.state={ + loading_status: 'idle', + recaptcha_verified: false + // excluded_scopes: [], + }; + this.username_ref=React.createRef(); + this.password_ref=React.createRef(); + this.input_token_ref=React.createRef(); + + this.popup_anchor=document.getElementById(LOGIN_POPUP_ANCHOR_ID); + if(!this.popup_anchor) { + this.popup_anchor=document.createElement('div'); + this.popup_anchor.id=LOGIN_POPUP_ANCHOR_ID; + document.body.appendChild(this.popup_anchor); + } + } + + do_sendcode(type) { + if(!this.state.recaptcha_verified) { + alert("reCAPTCHA风控系统正在评估您的浏览器安全状态,请稍后重试。") + return + } + if(this.state.loading_status==='loading') + return; + + this.setState({ + loading_status: 'loading', + },()=>{ + fetch( + THUHOLE_API_ROOT+'api_xmcp/login/send_code' + +'?user='+encodeURIComponent(this.username_ref.current.value) + +'&code_type='+encodeURIComponent(type) + +"&recaptcha_token="+localStorage["recaptcha"] + +API_VERSION_PARAM(), { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + excluded_scopes: [], + }), + } + ) + .then(get_json) + .then((json)=>{ + console.log(json); + if(!json.success) + throw new Error(JSON.stringify(json)); + + alert(json.msg); + this.setState({ + loading_status: 'done', + }); + }) + .catch((e)=>{ + console.error(e); + alert('发送失败\n'+e); + this.setState({ + loading_status: 'done', + }); + }); + + }); + } + + do_login(set_token) { + if(this.state.loading_status==='loading') + return; + + this.setState({ + loading_status: 'loading', + },()=>{ + fetch( + THUHOLE_API_ROOT+'api_xmcp/login/login' + +'?user='+encodeURIComponent(this.username_ref.current.value) + +'&valid_code='+encodeURIComponent(this.password_ref.current.value) + +API_VERSION_PARAM(), { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + excluded_scopes: [], + }), + } + ) + .then(get_json) + .then((json)=>{ + if(json.code!==0) { + if(json.msg) throw new Error(json.msg); + throw new Error(JSON.stringify(json)); + } + + set_token(json.user_token); + alert(`登录成功`); + this.setState({ + loading_status: 'done', + }); + this.props.on_close(); + }) + .catch((e)=>{ + console.error(e); + alert('登录失败\n'+e); + this.setState({ + loading_status: 'done', + }); + }); + }); + } + + do_input_token(set_token) { + if(this.state.loading_status==='loading') + return; + + let token=this.input_token_ref.current.value; + this.setState({ + loading_status: 'loading', + },()=>{ + fetch(THUHOLE_API_ROOT+'api_xmcp/hole/system_msg?user_token='+encodeURIComponent(token)+API_VERSION_PARAM()) + .then((res)=>res.json()) + .then((json)=>{ + if(json.error) + throw new Error(json.error); + if(json.result.length===0) + throw new Error('result check failed'); + this.setState({ + loading_status: 'done', + }); + set_token(token); + this.props.on_close(); + }) + .catch((e)=>{ + alert('Token检验失败\n'+e); + this.setState({ + loading_status: 'done', + }); + console.error(e); + }); + }); + } + + // perm_alert() { + // alert('如果你不需要 PKU Helper 的某项功能,可以取消相应权限。\n其中【状态信息】包括你的网费、校园卡余额等。\n该设置应用到你的【所有】设备,取消后如需再次启用相应功能需要重新登录。'); + // } + + render() { + // let PERM_SCOPES=[ + // ['score','成绩查询'], + // ['syllabus','课表查询'], + // ['my_info','状态信息'], + // ]; + + return ReactDOM.createPortal( + + { + this.setState({ + recaptcha_verified: true, + }); + localStorage["recaptcha"] = token + }} /> +
+
+
+

+ 接收验证码来登录 T大树洞 +

+

+ + + {/*this.do_sendcode('sms')}>*/} + {/*  短信 */} + {/**/} + {/*/*/} + this.do_sendcode('mail')}> +  发送邮件  + + +

+

+ + +

+
+

+ 从其他设备导入登录状态 +

+

+ + +

+
+

+ This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply. +

+

+ +

+
+
+ , + this.popup_anchor, + ); + } +} + +export class LoginPopup extends Component { + constructor(props) { + super(props); + this.state={ + popup_show: false, + }; + this.on_popup_bound=this.on_popup.bind(this); + this.on_close_bound=this.on_close.bind(this); + } + + on_popup() { + this.setState({ + popup_show: true, + }); + } + on_close() { + this.setState({ + popup_show: false, + }); + } + + render() { + return ( + <> + {this.props.children(this.on_popup_bound)} + {this.state.popup_show && + + } + + ); + } +} \ No newline at end of file