YEuHCH^$3xdItTNS!#X^%Li+UM(NTXjKl#z_BVE)pNu7#wz*KkakN-x+FMzgfdUT2OJWNK6v
z)G)pxlSf3EzcVL_cZuX4nC$;Z{0E>o_OD>Eb2!Oo2CGeEgoX(i8))wro%j%hdUhy_ifLH`Oi
z=Emw*`P#y3f)G`^qg~vts9~q!%s&UiHEo+c@XK+
z|BlY|N!MC3Px?Mf_Gdep_w7OW0sm#RyrvlyaS>cgnbv7&l29)nY;snp*=%(#V6rjl
zp<}bROHnb=_UI&>;O}by@*qA6s->fD3BnZ38oBDNOf`^|%l!wq@F$iB=BA7}`+OMv
zoX?%Wgf}?GriKIn0Z0K-bFEkii1{ncCM=O#%DE44GfPiR8)xfPXExe1a7`?a;W7|Dy+ep53;o`TQzTTf6c8-L{)L9>+
z;gIkxb>Y-Awt7!J*3{q#)iM8!TaG>M7afCOgLvmMA_5IOV&2
zkZpnfGE9fOj_5D+2q88`#Y9e5m#-_h^BgS!xrOgJC=2|*_QpYY;s=@O-v0Rh0~gR<
z51_JT2t>y%LEKC4__C?PjO|Huek+$zQ)G47LJP5wclWy4k7O4unzkI>0zzUeBWh;0
z!1!;rBNk77r+v&>6OhvwZmBO$1Et=XCT8vMNtHq;*==-h2^C)0NkMGWeP3DUU*T4m
z&Y!RQE!@1+A8r^pWlFHP6nwnM&Qyt)u7m#5=O{lrf4KzCGIcE1l*0}R3P8N}Ildxy
zk_CE$Sn^iJ^XYjNuN`{o0Wn($>o18QMJzK@iZK5HU>SCyFVRzXn+e0o7}!Co@rj8Za}kYT7XJlZ8oF6oE*Ws&AHkFi`Acrc;EYRjUyblnlcnwNEphQ^Guc`g6!9M*
z-6v~M)!X>w)rUIv+pfPp!X;}&y$Ox_S5BTSHVg_3EVm-`pU=uQFOg10l-JRIiy?2;
zQONQ=@k%0|hKuC5iqu5S#8v;A2)1*f1%2AY*M8IfWC%r*MOZ@=G`<1K=uIcXfkirr
zD2eWAUm7#CrBnXYy~~hH_c9qWu7}N45Uws$uC-M#*bmM6>pYs`Sz!&!s#9qcrKqf!
z)hCMK+NQ4dc<<+Sw}Uu;gC~1I<3{$6PCeRQU#JZalFVSrP2#MMP7k#)bpm)
zI_e4z1U$Xb=FA++{nD!1blBb$E6RYPDASo3Ccmun^r;dySmdJI(Vd1e*z}}*$yM69
z92swAIqdwgse^*_TmKfTr>h`C-8hjnP^_S4jVgI4B(G?BhoaWtQ8R%hG=Dmql&B
zu)Kq-+R~CgH7DR(r(BmKA}&=oG$j3J3LJ_)4Q8AAYqLu|mGwtL(MvnHf75el0zkw-
z0|Bi&?BQ*zB*|($k0_d_|^cyrsJVxG&C9etgj+FCSK?V?R|nV#Ab`<6Z`D
zFFf2wW97SRI~{14yPHdK_InXbJ8L2X>sf{7VYPCYK@U4SXkTt8GFDt9G&RMR{7ZhZ
zc4^%1fb9o6{gCl*yBmG>XP-@?JjB-j!kJKBc%pyL@5ZN5PGc@{h03zS
zzoKcsVrAS%Z-xBCD!gi$S3pNfUhqtk?6o&**}>N{)oal(d7<{1;!Uy{RVyj`rtFe6
zNMslwZ{I;Dd22V_iRLT({pv2rGK=C$&lvNs)D3gRlkD#_rUhGC!V~PD%nX$5YWdfW
z!W{c*Gfzc~)5(Vwv_KK*Q>^n33?KWdU#BNa)si@)k`cPQD$#>eW-1Fexm;~9ebtMk
z5tF#69u@e&BM<0rAKupiNO!vQB%kD@^LCiYylSpxUe&L(JNE~&W;t+0dQNX3iP;b0A9S|y{KH8+nN5I+ZTv=sUzGaBsoE=!_q?=&XfmPV^`!BD;mDuX{r*NzE1jd5Tv
z%e?bNjY^3Z6KQ7MzF-GScSpRwIRiF#eqB!wOt1t=N~&8La57CQi)fES;D$p=080QsoBP(`ZQkMv
zV}rGucR_CkRdO;hVk)}lJS|~g$(H8s&I$Si013bq*LzelQ6*`1!W4w`51?Xu6SaJu
ze@5*WRMTS1h&a^Ds{U5;VDO7)^EKuikJ<;_igrvncn5DyH`zH*^VjxP0R0RiGrLlc
z+5q;Wq#4>^O&Ya;x}DPo8F9be65fSnf)yE>Y=GT$=**>oXwTV^QVlK)6DQ9=i4eo8
zVB#E|0fPnVJ-IujJDR~ZR?2PQqZ1zf{AH`-nMac+!>Y)euopZ6E>aLLIn;r}x6|&!
zrzTjp=~(Y(5Z7mq6{QDq&%2(fhMF!|SpAsA`Rlq$VnN^9
z*DHmPAn5DfHo?!1L{yO;;#_BrI{tLf{2n!LADa2&qDgD8rBL1ioQoY&=W#n4|Ew8#
z@}6`z@8BN*!{}W9%Z~1VnFHpmZ@icd+E~4%otgR=Iib`AK5TW4%X4{V|&AeK3^Cn<(Cd5TZ*=j
z)i!eD>joy&HZ$^u-V*rf$DsnVH%t7;RJ0gStcxjj1T@cx01xtw+B4|T6xdAU|4
zNphz)VXC3%dASm;{HyS1x*COibQcCk&onYvSSxn!um}QLVU7SH+df~ba$~L2ak*A7
zns!t(EsNm?gzzYcqG-{bUidF0dd4JsyKTuap(RG66tLQ?#R`>>(q+6kzKAVTiPqm3
z^ryVh+a#p6erWcPHeeEl&2x&s!jDrBG(q0T9y)=5WK=A`Hx@ps+w45}Z8>pux}KPp
zng6)C47dzw=VnsMZu=cyD*GPokn%_`uG{i&d-5}hF?;Y>ddLbiaFexkck_F+_k;+a
zRcEWB@f;ar=dPh#X{k|WYyuJ;zp(bB4=3E`E~>Rsw9U9c
z<`M}t(?r^NP0Kbv3S%s>H|T}P>5wDLDxBhevUxPRk64{Zev;ZuBSd*fxZakbW*(j(
z$_XYO9jgsqbUq;4+soKmkF$&ROAV->4gYIxiB)+$W!s`TBMxu?Bg(9>kO-ILb;$0K
zO}`s1S;}NgvCr;Z%IrzDG;_fIGqe;Rx;Uqxyu$u2n(ndF$UcH1o1+eiU%Vrm#PbfG
zBuzc#%KA6VKo0l041`O6fQsG-I}5Xuj#U=6WmF5UmwRN^23MVu^B&FwrR$xNN)J`}
zxLO^NI5!_p7Pv2m%UWfvak*dIRzM@%xIyxNo69%@4s)~$^uCps_*M4-!2OF2)
zPVpxuPcMeD?G{Ih^12~!9PT#Pv-sct)JVHO_AZUJ?lFFnTQu`7JZ0{#sF~VHlU0p9
z#AMq^axjCZJp7+-ymI^PR2S1(kxi<*A+ti28HyD@xup-TFU8
zZ?T@)^}LFOzG^(bUA8v&7YOch(&c&b$M|y-S{J7=J6^+|*QJm6%2sqksymNb8ti_?
zK4_I(Fk2ECHl?OukwWwEdeZR^FvrhDj+Q1&YrlKej^DzR^q;hW=@04dxqBbn5OD2v
z$hc$DDirg;wzr^DcvnyqQk>kHI{@DTJBg9c2NYww(iA&nNvJuWqnFt2Q5YQ9locH~
zS3rK{+(nDh_5C^YLKkw@CF3Kf3n%Yf1Act-)^8gZM2n`^Byi0pGx!InTqh0V=`Y?v
zvZ#kGT1NBokb-}znmI$~+287pa07=Mg1YAj#f|E8oWdte(mwbd2OE;#n}kd`t(hKX
zE&*3r^TDvF^!8!(MT`knorS<5K}B3eUS`&>^?2!czn%oT79U&YNUc`^Sb98>;f;b
zV4NWzTd^b3XR44zv*^Kl{Wd{ob>sFK6^t?)>a2+2(c0TPYY30mJkr_8sO=@Q%Zd#4
zkdSi=ScUTY9$}kHCBMF@{CssIOaBDgB%n@!&
zcGsmD!vB1tC>%S&sRZ(E={)Uc;Vs1y_U=Xfuz(%@-e3n!m}k~gn1j^+Z{sHIRoV;V
zJ;NA{xwGCJ)dF;uz8;Vmqvql&>8_=to}Wo!-VkTEu>0{qhhYGZfo|$u4Q4ynzSOYl
zWmLPI!cfv-76rp>^QaCwv*C6zuU4;!OCufpO_|d?kHBLcf93MfI{VBSIunA0~obV;>x43az_jdOer#~i3;)!!4GwB9wfBP
ztjvIF0j$|>?^L;@o8R5XVZ}4xT#t8q8QasvB*{I~&V2~^zl|jtP~vv%OxQyrnez}x
z$5^YTkwiNlJDx&7O-+Opswc%3XEsFqcP`cy=sIlfnGb#vT`XtDZb|<#$5|?{68YKw
zz-|81hq8jfV2q1&j6CBd=Y)Jaut|f{VMhVCx!Kpn-@AlzimaWPM}pI*2U9_{^xi5{
z?oB9BQnr38&cU@OdDcN4Wz2OeT+N>&cG#{UdMdTPP{`QpHE@Vzz|*m6MHRiDvCoQo
zmsskM)MS@~4q{nXa!0`U2Tp0Z6s9cc2D(yE%W?s9V;$de#~>c5?BRIk7{E@jrBDq8
zcr5E?%Ga&bV{5R}i)k4s*JmvA3KK~#)M*Ll-}t&Z#T`yBX)v@Na@B=5e&N_x=;)iI
zwj5EYN`XneUH;ypCd`bmLC}%{_QMZThs_s~_K@c~{^u8EW1ym*#)RI44B=LI)b&4z
zLlm)^t1A@M2y~LwsRx(F$kB!;%!2H!YrYQhN~6wxi}}c0yt&ypQeS}KEh6W`DiAzU
zHp?&zF;a*#?Y%}QDXR8#2$)yscI8tj_>LE71O_k8?bu@iLK=IDkK!Fv^Yp7b+U|hV_SD
z5tW!sB6JLHa_D(tb)|NfbxHKi2EG)pE&w
zk|VQ7FTmsY6m2~I=Xgk~hCnq-^>%I9x&Y;-9u9U7b2Vcvm%`bW);$-ic_qk~9-(IA
zDAZBWrk71$01|ZKlu>It7Ox;yiPbf|ejei4=Zeg3{JQFEoH`{!%%oC#U_8#&KB~;Gx|AQN2wn&nS6hg&{(P9X
zIZ}n{r?SLNWtn42>3qpE5SRBviR8sksP%pCc(QpSMZncYV<`{2cj>7m_V4P7Gcmc{
z&HIh7pg8tn|BrDM+P$el*3nafUP-4bJ_*L<1*KBz$4HgOJ+?I_F~Y8}7lz?`cb$yo
zLPiy-|FgrfONTST1lc=WyVYOS$V7@n7N$8Wd%syQ5*
z=IxQ?pIDzk6_`I)^i_T^8OC5tlcQXw9JX+AeeJDI)u=~#(~m;bi&IqXZgL=zJS>=+tTj>Yh6ctS@^bAMlX}+d{v{f$vHm+$AHj#EI2Mq@BNhL?-TY
znz7xMfCIbK(@cOzX@mYBX|`aKxXc?IGj5OWx^G*qgCSh`3JJSmz$-6GWT=f&Ciyjs8me>;Nx^_A*s$8?x~l8!oU
zTm?}LSDteaDV%1F`^gy+QfU$I6?Mi#u5eG-ZmG_5$)8eLR`(2jy|OF)x{
zj*m0@2Ap5_p<~v18h}%hi;LkU=1Q>w8k-HYeJ-aIv05O%p&8~!laynq?zibnaFVee
z@LMfCw~`DuHE2^l*f*%I2evW8=1+C%>h2d_CRXs$Z%mFJJnPzeARZ$xY?FrGj|zCB
zm-b7$4HssQ^f(j^S>$%LZ2a>qcEz)QQ3dycxfln!yVSag7)$zAxf>-7TrWTjGPYJG
zXj{@wlj0Dz!rGpZOQ*J;P^z!fELcL`1$
znbDya)cu+Af=lZq$4>T0I-3p4@bY+GmMzcimY-|9bH7zYpG7e4mlX+`-nop9AhvsT
zs@tJ2@N$uFkJE~k)v^a&i0(c#to>l5m|KO2&{H$ubA4I8*r(Tkyreh@(zyKf0+F6j
zbXl?Ka1VSpz?nZ{k53S0;Q7sVI@Clwk}IM##MixaMwEyDW$7Q_XZ~D+tSBPqW}Qx|
z6gjPNJLexMQr19c#yUQML^Qb@?Mm%*bN$>S&0Et(u7I|`6ETXKdWfl+NZU=LtrbuY
z_XGx06Ef;n3&)7;Crn``hB=)%2oZ3^Okmsrfboij#Cp%9UR{F6`wCK*lh<)ud|1>%
zjZ;BOwJXOCp_b5{!U$0bJ)(1p^1H>47L{yW)JQ{ObU$rQ!i5Wl|0Il#J#bY~h}K@5
z2Bs&9#ltAd8y8%p)bG^6`o0*k1eoV1PDnT%rJ45RwuHyc>}~mQlbZNStT>
zVMCH4l9w?jp=WJg;#EvmRXy>s>=}B^zd9@Z&R;660)0LLeowYyWL7ZjMQptp5UV_m
zV!bAK!_Zy*po6wd!m0NUz;m>%e+tt3@09J!|23Im?dWxusl#J@mi@Us%hI~$tb|Y2
z>89h{*?%!#-GAZ9^F|Ez^Y@`(@D7UXCl@qL*ri2&Rge9>CKh8n$ATDPmPN({8b%FB
z@lSul)@Upu%As*7FIWZ)1+)dTfQ_zzH
z($SG%B(ffqu^uzd-X2zE3<|bC$x8k+g1atQL3Ml
zf8N#no+7(R{c6>MG}-*w%-5u8)o9eg
zGjt@l%ur~X6x(igq5bb$|8B17wOaMEPsT{__H4YRcDgTis)-1#-3R`BBPZ2*!IZT>Al>3}ka&{Doodaic
zpM*lzBa?lE@GJ1fBy;*VWtJs>g!kVVDx`?EWt~9loyKxR@?1(OHdiO9xzIN_=Z1u
zn_vE#u_il}UJ6^NKhhc+mUBC
z>MIX@P|tzwA_+`lfamXmp;4IkUW_N`0@d&MHL_5qlis$p=LReNfU*&<5(|jydx|}j
zHoAocoZ?EbX=HCPj>zS(zd>!}iL{CJXfzlSI?^THXrpjTTdF9q*5%eiBiJZI2;zbR
zSHMreMJGknje)A|8kov#owjB6yc86e1*MAR-3cs4s8Hen{3Nw~4|6pm4T0Fqft725AbYZKm!-Zs&BcfHHIK^iJ7d;_#UW1;@yz^pm3M*427iJg
z-%)*Ji+Z=yEFg2)n8zJ}3b9L{K$6f4g^AT__n`Af*}Gh+0hhIUILaXMi|1a0VHpxD
z1u(~5xe|MNBU=XhH-AKk#-6_8psVag@{JbsKDEuemrG9OTMFz8Zrl~F5YQ9LW(GkK++8MOaZNOW;Ga^PV
z$C9uLuK|B{DvVfhDHR#^Zm!)9AM2NTW#=xx{Pg!g2}H}(zt3`le50Ls3e
z@e4-|j&%dvODV)L?jsj2TR;ZnBN|Tj2tZY6lJT2-dPyX<}FDJs8BjB!2xfQD*gv9F%0$!`fi+xz4saqDS
zf6O~%g)Q*n4$~A2J=QZ_8G-F(3ga`cVFzlF6~&A);L
zUdB5{b&yme`J@?VPSNC~Z%;5tA=q&)n44;e1T@Z@RI(OYrT8PRc#914*qb0s-*}|=
z&_70o2|C;B$C07%blefRWG#-_&|_dE7ts%}a{lp-#1*|^)iYeXcbzdpt{UFk4|Oyc
zlzGLvD;0gfculzSh+bizYxk8n&=9t`juOh)EV^dq{=4YyVDr66=efxTqI?KWZoK(Q
z@I||CtvD9U*r3K}M2tGlrjaV2kb7C~tzlq>S5ehjON!sQ!CH!e#4z|5vr9tyS)PSA
zI_&bc_jXis(eb%~v%4u_NKo<{-H_UXE7#V0c^Ik+t_LkJo{5v7sd|pEoL~0HLb>UO
z1IFKD!?BL4x*5nUTF2!|%ms_&rlWGnWng!C$JTI3E7#?m#^xeK0k1eM0gq%mL#COA
z>DjED1;B5w#*NYegIT*})l{o^7VpP<%2IsiaE~h=8qJvvS`wi`=ssM>C01DtLX#o$
z(pYjO=~vzSLFM$wSZhh#u|8cPl%Tt*jsCu%_p3R*7Cni0d4##w
zY`t=98Zvarn0BcmFGx>&2Ct;OAaaeyq%eFRb24xU$)r{{<9v=}NrFdDtk>yr4Y{;$z}FA@1Q-x
z42Wj{%IvBhw?Kb9Y;*qlSiicaM%bd*?7E)xwY_1Hk>}Twr%-o0iL2BU7+u;xu*{KE
z_Sa8Go%8;{P$vvAbxc!xf5@hFY%?c={y{|Ndc=vjxh{JeX0v1XfRoHhdPlbs)%Nzs`L91LZNcKr5+{^`Czix8{VoLP8-;Jdy)>Qv2uijNCx$lNu(;P*%heob0*8Z;zH
zH^D_C)R_F#(&`_H17{{lbspDl?q=_<|9m|fFo{f+6ZDq-qg$Wv&a}FoiXhYSEie0S
zfwA@_|
ziLb+-|_N5|Y~z2SOJ5|xZ>QqnegiWr;6cAxlXztvYC68DEomqqNc{EtP^c5HJh@!OhXY~W=
ziafSrKxmC_0zti&D`iBy>%HzA9z#PLZ88*;Ri2>3-3i=L8<`6yooY^C>lUi`kKS7^}=wfUH4(cn10lIALl;EY|HCu)U>4#k@>o6*IH!&8e0
z<`NagQ}HfFt48NDAIVF!9$`7E6kB{*swwSXnAQ!2@gS~U`vpsHi3xnyir%dR*+5X#>Unai?lSB*8`EGVQoT(@B{m1O03*Rmn@G`QsdrT`XDds!Z
zB%J0K{CD~p1P{UfbMAjS$u}Qd%Ry8LrBCA06@_#sP@RDS2XcHl{3(#s!(kh8pT8q5
zB^zg6@Xx?Z{X3re@+A1fTlD?^+?0@5!DX~%{1>Wj7$dF6@@Ix^l;Y>*?06mvb`xXO
z7>zl(R(l58`b)kSywI`)D=5DeSw1_H$htL)_anlp!>)2|jbj?C_N=SR9|e^%h3c+M
zB&A5yH$49loSf)+k_s`ZC%xs&Z=n(0*j7{Oft;-Du{rIU8B#YBSYK*DU=7uQritlj
z$l6-u3u^--%r|tNhx-2js1~(IO7)p$9UbDc
zNG(0`+-p3-^_Dw~f4(4Z<)5A0G1(r2us)BI>bi&)!M$wjW~u5!fv7075?qt*_qyTH
zKf|p|k~n{kbivKT13ju*n6J~ly3DB?`2DrX^w@>Y&g6f+{Q4w+)3xyCP@2U`bbLuD
z?7Cyrj;bR!N*6B7S(u@Dmz(Eg@A?!xsXxNjmzC>zqa_2RAt?e-{iumthJJYKB|oCH
zr|!M;15#f5q2AZsuPtQ+Hk1J15AwsI*NlAkE?_mXJK%r1ivKSQ{QvP%F^JFnqVQ8Z
zDw$SjzSNUr))a4Y@vybbw#qDRGsEPQWcKl6+HkAMf`|Ei@;>QNyy%6=$qq-+CxbDqeeCV^p6!Y_s$8YzX5N=b*(Y
zDTNa9g+uGYGVm_aqtvD1&&q(m;yFg-M}Zy7r;iJ->u&NVodkyMA<|DmKRGp3ozkt?
z=D=>`eihIUR0~4)qb(0a^>Z!=pVq-&t7MhahkfrZNxW~g?MA-Tzi9Bd4UAlp;jQzk
z+AA+K(qbrnVn;qsP2ZjlTha~bk&dW31Of*uQq{=C=*f4#B$
z*H!kq(J(YF-b&`%W!ZAB_n$EC8%;{@vX?d~Qj8Idr=vA~Ua}#S9KDF|auS8Gix+ov
z40TV(>dlfl#$YF8j`J*F^=!eBI|GYnwe5c5RT^c%8^tuMAA6EFoK=
z=_f2#vogNZHF21w4A}N^`Si{gGiYcTo=*3(=5UT&41MT3Oqp@$Pq@ui;0ZndZIGY5
z_&c2a`bcc=*U}yRNop+r2at-6qnV8?7;g{{+>BUU@bg8hGTqAp1D1wq(wR`;s*|nd
zB@lXFelwKwBQdN@#Xc+O*I_MkOuJacjy1YUXF3H-I;Vzn2hQ2^X3@tiV3}3LNYkez
zv2?AK0IK3g&*0Zw5Wux>KBrK_{KQzWbVAkD)F9nY!TP!ZUr{
zf3Ozf-q%kj>FiP_HWi}NiYvz2!TFD)>1Y-qF5A
zz(55X<(--*jwS6svZ2&K1*aW_04zJ{DA|iA{I=?VrYP|vw0cEAuO*A%Zw?YCVG3$X
zCvRcgwcRq~fP
z9+GBeMkX0oOr?3>#}z_2rs#Ue?4fptl{AD~uuCFHp8~7GTqcGD4dQSr2dRbEJ>zD%
z`E9wjUCD!a&H5lcS-x|od0yDAGM0JQ^ln3i1T*8B3QxDaULUo!YTPfddYJlHtugY7
z4W+*e226=W>Q?7)7y`z+Yq?oeEitp;xNeft$ppeU#l;F-dNTAG9#gt
z(c{+@@`tD74pdeMqBlZ2y>#DsZ
zg+QD$OBmEV$`0L_<|%_<(<(5i99pCbr1f4(1u*Gme+N47VA&BIvNgIyjH}hFoHg4<
zAFriVOMyYXP(Y-pe>_!0qi84>M=W9zeslse}MaJ~-@2I`9{76vD^nq$1{+Crp
z{{#?%yh&1kp{8C+4O8hRG$m59_e5Ug2wa1EB!B?S!GTJGeGkxIPT>VLF=Hz~|Hg1AB2n=XA=MJZzFT5a!
z+w&c&@&!)tGO4LjH0XN;hCd1O5Io_0D7|dcu}YXXYg_u8ve7-E_?BQ%;Jum?E)Zg@
z`*xEEGGk8gInJ2*fDEs9zive>-Z6
zBl0~bl;GH(Y|N&g{`j_|091dNn(!g+?oi+GQ6EO*5Q}qTT2v0|!yU|qv{p0>!tJ3c
z+ZP)psfoKDD>PWk^Dik}_mcRC^qISFu1_<2=&AJ{^pu~|v98lBe*AT-#B!X{UCtI0=X02TQ+R;HSSc~^2k>1
zA=-WPN%(o;I;zvPmiqV~;L2nQ;{wIwKd1cL#PrAi0k{Oo&&2QAzR&7u&fpzN2&R!-MIpAbVJBovi9fZq_528%6sx?KcaNZwrgzy;G}FU@n&B9uFoh
zoGHY=VtRABi}@iIWBkq;3wnb>82rn~O
zEREZ6-jxRlF8iBK6g1`Vp+`_@LPKN#E->zSh;ULC|WZo!7wnaiC5=QB3bYv)`d8
zjyqnpM{nWH_=MZ>GUS*f1btXA`Z4xjmWB?W$&?zwE;Ns8
zJ*pi->I#uMHiIi+^-p{0ePbz~>)yko^KJa4S@3+{L8_WZgDb)}D^fZki{pykH=Xo~LPR%;DL9)twZcQ=2mef13ep0M-D^RR2``qhgWPls2w$vg
ztZDLHrLjGAa)NE_C|Ar;>HcQ(_axjBZ3w3ll#@4&OO2l~lF4H*I^j07py_IDf(qck
zKWP}b6&`k%Y=nenMJz|c);Q(1BS2WaE{!`}vJKY;VxNu(KJXCBrkkc8Y%3Q;gfd>a
zweMkg$!RT$bVU-dd~(p+bjiOW8bG|1jSME{W(fK9sIy<2f8oM;k@O=kyOV=$VNm@P
z(^)3^QEIMI7rn{l%k&xA9?uWP_9%P7KCh%4bk7Vdy<6{1p@;2pnPsNgGU!{%z-x+1{EWN
zf9e_&VF}yfGC<|`aGR-$Ez<~-C%Vyz5QbrtQAdyvy(I=wqxT*L
zqX(mm-or3Sv_!NhV?+<4Mvoxcb3O0zuRC`4w7a
z4nw}-_{?uiuJiG;^l@*EZGcqjOT-w2lb&*7F{R>c%H@0bR(TrPdpa*rWfK-Q%EK}@
zE=GPa$0vCVrkgIec!BO}Zy8?Z1aAa9J}ENE7IP@Xa-{kev8Ek6pBHUX1knGFEAt^8
zgq+n`2O8=nG0|o%v0$*qK5u+2xf(ez0n`FFWt?w=I1WSIoUp2N@HLuPdpSfDvgv;_IDpkY1-A@gvbfwlXX
zA$>g+k0bm*Owzv4+o9t#b92st3aX
zWqsV^TyZcO5p^dyh-q-%vhnD4J{W0aimL3sIq43^7f?RQaJ9W7%L?O7kFQ5ZK}q0u
z7j-is_)r+tK<#)i85q_g%sv2h53reWzW+MLbITlKIX`2}moR9zFR{bURBqzW=GHfA
zq?%K0F!w%M&{_HL7yotUq?`A#o#TJ8yv|xPD+pBDehNPfZ9aVu!B2&DF+l@Hy&t
zr{yOQ5;O6J@0T7gY{21}1F2xWkT#xrOR0EHmJ(YOJd<2;w_gek1UHBbUzP^S8o5$i
zYOQczSK}cD`84Lc|K3CBysXeSkep5tRmTdWw<+O1M
z8b{WanCg#YQAm9|f6CE%;8d0TJt*5d{=WWv6TLnLs&_9vGYKlbk;NBTuJ9wfmR(Xd%);XS#eh1`XWM{709T5mHw6Fak$8R6hyKT7u+jfMP13
z?_@&XW@mfjFj?~qyW7g4al`6od%?_&DsPORp
zC{W@adKF$`<@9}ph*n>WDt*iH+~S1k8oCntOg2xBSjoqFytnW)$?!~X-;zKu5{mEd
zPH(!U1Nrvu!AxSidyUF~w?d&5r(nssM1EYwoC;J#l^t(8QxN#UV%
z3uUDnTmp0(r8$lM1g;EH@2|^3n4jPNuH0a={X9Y#pk?A*>3Qb;OO>g9ztyDddqTpd
zC#U--k(xc~nxF5aIJhEu5!NcZEv^oYE!+U-RDTXvtUG9WdML1w#w`gYMmtey{@Ov$
z!^5i}x2`j-31k$sRfRo|A25c*-v)$tD-{6N#H~m7&Ob|>h2CrK^%Hz|WV
z6@|0@$!$4ICApp&r2i1VZ0jecf5=*cbOXH71`+d(d*;7_e=cRn@jU<9StQ!O6f`At
zK)Al#sV=#b*B
z9h?glGG5oM*ML}ND6MxM{BdP`Ws3<`nrXB`$vG-GjBXJ2oldF_0&Gw=rNj+qn(ZMK
z2cAzkTQT>P4L+Ub(vI_R=4KzyZLwu$*z3tPa$1E#9`TQ>w8P2*&F^LnRlLJ?02HX6
z>dRO)hsCtILf;e=W4!8?KJfy@n$^?nN|ly~cCDKCS2!$Ahi$W!@0Qfg99h&o*XM>aKAfl&gDI<)(^~R-3E0C1ADPv=a)lldbFD%SjOei^YZ%5>
z-ZWK;Y&Q}&5zIoc#4Hor7^(dL#-hbZ$#)swrife
zksdu!c#&nkRee)zV>~5N_>xg%?+r+TNd&!2mBo%V5)mSJ{KQNKhYR-1!A)_GK1v6E
zfj8is3>+m_c8LR;-4XyscKMhVeS2X8At4<>viy_zYPnwPvurb-nI4{u&;Cr1<^scW
z80rPWF)i#bqD8MO^L0yBjLF&ZJQoB$Jnt|9!Va)5{8l8!HR?LQ)r{
zKfPq%2fdJcu{r{_!NT#Tmb8K?tJWV-ZrPG)%HLL`PfJZTQ{RUib~&}Qux!f`96~yP
z2{q2J^Y5)oZ!%WCI3HRxrmwP0Ol!}xJupC0LdbYYnAB1(m&zW{PSk`rX<9`5Vqas>
zH4J%kDmou+auEwy0@61g?#|oW!b(Y)rRdS3P;Kr2{Z;B=Dc_85FMs5Ep)9h+8G;UJ
z3Xg5c@%PkGRN&yqi8yS|ANBYjjL~URo_sf5JT*%1ZyGevzmLM-$UhqD{tWqENnjgP
zj;{QL5Y}7OQ8KFQ7WL_4yJ86i8#m?MdO?g>A
z=3B4$MUBRsOJDmwKDBH*w_klI+ngU}dzoh{-Z?1M5+n~27NC3EN;u4wCwG^eS9S5G
zU(cUr(5$cV_`W>BF5bMpF?**wjYBOxB9Wyk^`mTe#eI+X8!Kzi}==dx$5Zn|T~3
zRBr)Wn4K)P>2lLDNt0dza${G3Q|11oQ14FGgbHvVh*c1ovY;Nze`&}nq{ur69F20~
znNdP;U1WJ42XwqQEWuGTB5{9LBmg%a{~wKvH8Cf@ppscT>veIR84gYX$?Np_AK440
z#z+|wNB!)Unu~qA$NS(Y{M#`nucG{buOp1Hy}3!oQwlnW#i@HxfmRLoZyG$LJjh35
zv@=_*40Kezlb=cV|Bm|F{RCD-98Goq7VO}LZ?FM7toI4W*&_@B#a1hk5AWnxn6A==
z+S_lwW1dndmG_~G6cAvyoR(qRJ@^JyFfVkR8Ndf-%4xX;hyYlvR*yH(J
zQ_qZgUE%_BnDx4=d|_5lEfjpO&LersYTa7tYRS{8eyqG+WoiS7RIs#}_BAc7oMJ=Y
zl51VtpQ;#0`WB&5+CB;Nbl5+*feu*pIh&j3{ZfM*(b=(eWiaC`D|CW|$Irgi;oHne
zQ)MGf6>%YrkNUU}^gF`^cexT6riXeJlLV$0_5b~mlf!h*2t6AB05x@pmPC*x)*Nd;
z^xAk2X*>3HP*kcJtMZ=4u(o&Fn`URdzP*C>23t{UyQSORn9G|zn&$wsZton61Pe*i
zgwo!%K_~N2@yUy}l)H!zNlx+ETKhF?lcw?!6}VhYN#wGdb}_Jv<@D6(*ladNK_L|Q
z@-oJ#(vL0J2VM?Z3Sf1r?R;wLB46twjB&{Ls626PK}&D%xucJ-`u=fqpF+rqT!GyN
zKfbw=gS7jb{bpREeDn`HV6OiQsG{Hlq{up>HVpYzv{;+ph@%}Xt!k}ujcwHJ9Ow^}
z^QClKHO*>@c^S8N^Y-z}T{_<=s=vL8-I2IF#Yo_in)L{<8?av_<_K7#@H6;3G@?^L
zXS%2D(E=my_R<{J-c1(CRk*l7E>m9y`)qa(gQ<$Jw(1q$23u9_ZI#HHz2}^=M%{Hv
z8`Z=ID{?0sB}c{H&pDPIx$)ChyRAJrt+z<(oY!CN!_Yp4>bP(lmtwB=q-d2iz#S`(w42I+8Zs97QPb{paBO$D
z-dT7~j7Mc4s;skhdv+oBCW&I^2D6mA1HoZQ4_sYL{1mlMYdbbU1bp20v3;uN%8fhE
z*>vRc44Ykgml;9!Mg!OTHhQ~@lBZtUN&Br#_i8BYI}x{BRTR@LT5!;nz!PyBifgpT
zC6n)mE%qO{`pvTp;`zJwYWpk?kUZ`RHi5C#!y&H}%}6hByj1{+LVUA7x3hQpUqk^K
z_+!1D0crCh0lL3)kkEj+hC_j0+@}w%+{#)bO87135B(P`E0pLK4R_S+O-Lxm&q_iBr1n6IAi6PgbBG27ftCiz~*;oC8?
z5ch@mRyNtjQGjQHmzf!mH^_iT3#Z5v#H2II?E%~yzYAMsdXIR4
zd`?g$hS#g_K3?P{`sR=;)_qY{cA9*lA7)*8EkSy)pBd<%WP)=X_qM+U~}RAUp#clGJj4e3iC6V?NmyH*oiP
zKf}$$`%?$X^Q?)}kN>oZ)(u#st9EsM*f@PkEqP|=+=g(DP8{gYgN?ssEY{4aNH1;v
z&OP{y<(=;-U0bcDBh8HarYc7tp|3_{d(Xw7MBd^%XmKok&*D8}nTdp%z?=?0)V~Z5
zNAl_mgq^d$BtO_-HMsgpYaMW~Jm0lD<q6F|L!)lrO}I*rZxT`LMezZPcF(fiB5z3Se*
z?XdFbjXDb`&3EMxrtp@4j5v(J(B)2J#~8!XEmYo9WLNbLO}t|5c0$NG`1@wfliDK872P6(AFeEKTwT-sSpRRFrp
zxB5|iFPEQEf0$m2S(e5*e!F=P&F*&Jkm&WBKVbAbH*qoWQ;P(iA4ufa?Tl3>
z{E_j2)l{lRf&WaT`3=*!lY5l<@FG`xTT$-W^K@`;ovE2dMHklzSakNJ
zQuu14E<3@Z@Uzc!)SeZ>6Z{n|&nDs%*!i`$cE?>n-227H2a)UBcMp>zE^i<`uoQd>
zJNnd+_}^^LK;m=1`pT(o;2x>zMH8Ol1bnW=T*K^bQ`cn;&mSz$s&@39d>oK`2goZJ
zNL}CS`51EotE1a6idirO^if{5=45SiLP}q-uS0UzzQ+D>8Uuzu$S`P>?IYID_vdes
z0Pr!@;U!mjqt_;*Q-hkpJpsCG&F*C$k0^-yV-s}jlFZa`uN`LdmUvzO;PBy%+5L?H
zMha3OL*wBH+z)vTrf0?T!nVjB15>et0XV}Qk~GGUFR@3S>PLwq;*e{;+>>gY1TmMT
zCK%5%&?Zg>kGCcDZ5vhdjYRf^MzX@KG0%6K?l(bq!qE)X7
z=vF`7j;690QOI~?f0N5np@2hTqTX|;!7`S*OB?9{t5Xz88aC#m6PW{Evlr7nMyY`M
zeI8g(zJOcdUz$l&NwKn`a7i=gAFN94Rv(H@NULPk^W49Ns(l`&PdkEAZ7~s+E!TcI
bU%wH%))kmr!m{4`zjX%rcSOhX*Ytk@0*mj(
literal 0
HcmV?d00001
diff --git a/java-mall-app-shop-admin/store/modules/user.js b/java-mall-app-shop-admin/store/modules/user.js
index 9d7ea34..8448c64 100644
--- a/java-mall-app-shop-admin/store/modules/user.js
+++ b/java-mall-app-shop-admin/store/modules/user.js
@@ -1,20 +1,25 @@
-import { GetLogin, GetAccountLogin } from '../../api/login';
-import { OutLogin, GetAccountDashboard } from '../../api/user';
-import { GetAuditStatus, GetAuditInfo } from '../../api/audit';
+import { GetAuditInfo, GetAuditStatus } from "../../api/audit";
+import { GetAccountLogin, GetLogin } from "../../api/login";
+import { OutLogin } from "../../api/user";
+import $Socket from "../../utils/socket";
+import Vue from "vue";
// import $cookies from '../../utils/vue-cookies'
const defaultState = () => {
return {
- userInfo: uni.getStorageSync('userInfo') || {},
- uid: uni.getStorageSync('uid') || '',
- ukey: uni.getStorageSync('ukey') || '',
- auditStatusInfo: uni.getStorageSync('auditStatusInfo') || {
+ userInfo: uni.getStorageSync("userInfo") || {},
+ uid: uni.getStorageSync("uid") || "",
+ ukey: uni.getStorageSync("ukey") || "",
+ auditStatusInfo: uni.getStorageSync("auditStatusInfo") || {
approval_invalid_col: [],
approval_status: -4,
- approval_remark: '',
+ approval_remark: "",
id: 0,
},
- approvalStatus: uni.getStorageSync('approvalStatus'),
+ approvalStatus: uni.getStorageSync("approvalStatus"),
+ socket: {},
+ getMsg: {},
+ imWeidu: {},
};
};
@@ -28,16 +33,45 @@ const mutations = {
state.auditStatusInfo = auditStatusInfo;
},
LOGIN_OUT(state) {
- state.userInfo = '';
- state.uid = '';
- state.ukey = '';
+ state.userInfo = "";
+ state.uid = "";
+ state.ukey = "";
state.auditStatusInfo = {
approval_invalid_col: [],
approval_status: -4,
- approval_remark: '',
+ approval_remark: "",
id: 0,
};
- state.approvalStatus = '';
+ state.approvalStatus = "";
+ state.socket = {};
+ state.getMsg = {};
+ state.imWeidu = {};
+ },
+ CONNECT_SOCKET(state, { socket }) {
+ state.socket = socket;
+ },
+ GET_IM_MSG(state, { msg }) {
+ state.getMsg = msg;
+ var im = {};
+ let _imWeiDu = uni.getStorageSync("imWeiDu");
+ if (_imWeiDu) {
+ im = _imWeiDu;
+ }
+
+ if (!im[msg.id]) {
+ im[msg.id] = { weidu: 0 };
+ }
+ im[msg.id].weidu += 1;
+ im.userId = state.userInfo.user_id;
+ state.imWeidu = im;
+ uni.setStorageSync("imWeiDu", im);
+ },
+ REMOVE_IM_KEY(state, imId) {
+ Vue.delete(state.imWeidu, imId);
+ let imWeiDu = uni.getStorageSync("imWeiDu");
+ if (!imWeiDu && !imWeiDu[imId]) return;
+ delete imWeiDu[imId];
+ uni.setStorageSync("imWeiDu", imWeiDu);
},
};
@@ -46,9 +80,9 @@ const actions = {
const res = await GetAccountLogin(params);
if (res && res.status == 200) {
- let mobile = '';
+ let mobile = "";
- let isContain = res.data.user_mobile.indexOf('86');
+ let isContain = res.data.user_mobile.indexOf("86");
if (isContain != -1 && res.data.user_mobile.length > 11) {
mobile = res.data.user_mobile.slice(2);
@@ -58,23 +92,23 @@ const actions = {
const userInfo = res.data;
- await dispatch('checkAccountIsPass', {
+ await dispatch("checkAccountIsPass", {
mobile: mobile,
userInfo: userInfo,
});
- uni.setStorageSync('uid', res.data.user_id);
- uni.setStorageSync('ukey', res.data.key);
- uni.setStorageSync('userInfo', res.data);
+ uni.setStorageSync("uid", res.data.user_id);
+ uni.setStorageSync("ukey", res.data.key);
+ uni.setStorageSync("userInfo", res.data);
}
},
async GetLogin({ dispatch }, params) {
const res = await GetLogin(params);
if (res && res.status == 200) {
- let mobile = '';
+ let mobile = "";
- let isContain = res.data.user_mobile.indexOf('86');
+ let isContain = res.data.user_mobile.indexOf("86");
if (isContain != -1 && res.data.user_mobile.length > 11) {
mobile = res.data.user_mobile.slice(2);
@@ -84,39 +118,66 @@ const actions = {
const userInfo = res.data;
- uni.setStorageSync('uid', res.data.user_id);
- uni.setStorageSync('ukey', res.data.key);
- uni.setStorageSync('userInfo', res.data);
+ uni.setStorageSync("uid", res.data.user_id);
+ uni.setStorageSync("ukey", res.data.key);
+ uni.setStorageSync("userInfo", res.data);
- await dispatch('checkAccountIsPass', {
+ await dispatch("checkAccountIsPass", {
mobile: mobile,
userInfo: userInfo,
});
+
+ await dispatch("connectSocket", res.data);
}
},
- LoginOut({ commit }) {
+ async LoginOut({ commit }, isTokenExpires) {
+ if (isTokenExpires) {
+ let result = await OutLogin();
+
+ if (result && result.status == 200) {
+ uni.removeStorageSync("ukey");
+ uni.removeStorageSync("uid");
+ uni.removeStorageSync("accountDashboard");
+ uni.removeStorageSync("approvalStatus");
+ uni.removeStorageSync("auditInfo");
+ uni.removeStorageSync("auditId");
+ uni.removeStorageSync("contractDownloadUrl");
+ uni.removeStorageSync("pdfjs.history");
+ uni.removeStorageSync("userInfo");
+
+ commit("LOGIN_OUT");
+
+ setTimeout(() => {
+ uni.redirectTo({
+ url: "/pages/login/login",
+ });
+ }, 100);
+ }
+ return;
+ }
+
uni.showModal({
- title: '退出登录',
+ title: "退出登录",
content: `您是否要退出登录?`,
success: async (res) => {
if (res.confirm) {
let res = await OutLogin();
if (res && res.status == 200) {
- uni.removeStorageSync('ukey');
- uni.removeStorageSync('uid');
- uni.removeStorageSync('accountDashboard');
- uni.removeStorageSync('approvalStatus');
- uni.removeStorageSync('auditInfo');
- uni.removeStorageSync('auditId');
- uni.removeStorageSync('contractDownloadUrl');
- uni.removeStorageSync('pdfjs.history');
- uni.removeStorageSync('userInfo');
+ uni.removeStorageSync("ukey");
+ uni.removeStorageSync("uid");
+ uni.removeStorageSync("accountDashboard");
+ uni.removeStorageSync("approvalStatus");
+ uni.removeStorageSync("auditInfo");
+ uni.removeStorageSync("auditId");
+ uni.removeStorageSync("contractDownloadUrl");
+ uni.removeStorageSync("pdfjs.history");
+ uni.removeStorageSync("userInfo");
- commit('LOGIN_OUT');
+ commit("LOGIN_OUT");
setTimeout(() => {
uni.redirectTo({
- url: '/pages/index/index',
+ url: "/pages/login/login",
});
}, 100);
}
@@ -129,14 +190,20 @@ const actions = {
let res = await GetAuditStatus({ mobile: mobile });
if (res && res.status == 200) {
const auditStatusInfo = res.data;
- commit('GET_LOGIN', { userInfo, auditStatusInfo });
+ commit("GET_LOGIN", { userInfo, auditStatusInfo });
+ const lastIM = uni.getStorageSync("imWeiDu");
+ if (lastIM) {
+ if (lastIM.userId != userInfo.user_id) {
+ uni.removeStorageSync("imWeiDu");
+ }
+ }
let { approval_status, signed_status, store_status } = res.data;
//2-未通过;3-待审核;4-未申请过;5-已提交审核;'
if ([2, 3, 4, 5].includes(approval_status)) {
uni.navigateTo({
- url: '/pages/audit/checkAudit',
+ url: "/pages/audit/checkAudit",
});
return;
}
@@ -147,7 +214,7 @@ const actions = {
// 5 - 已过期(签署截止日到期后触发)7 - 已拒签(签署方拒绝签署)',
if (signed_status != 2) {
uni.navigateTo({
- url: '/pages/audit/checkAudit',
+ url: "/pages/audit/checkAudit",
});
return;
}
@@ -157,19 +224,43 @@ const actions = {
let result = await GetAuditInfo({ mobile: mobile });
uni.setStorageSync(
- 'contractDownloadUrl',
+ "contractDownloadUrl",
result.data.contract_download_url
);
- uni.setStorageSync('auditId', result.data.id);
- uni.setStorageSync('auditInfo', result.data);
+ uni.setStorageSync("auditId", result.data.id);
+ uni.setStorageSync("auditInfo", result.data);
uni.switchTab({
- url: '/pages/order/order',
+ url: "/pages/order/order",
});
return;
}
}
},
+ connectSocket({ commit }, userInfo) {
+ if (!userInfo) return;
+ var socket = new $Socket({
+ url: userInfo.im.node_site_url,
+ maxInterValCount: 5,
+ interValTime: 20000,
+ onClose: (res) => {
+ console.log("sockrt关闭");
+ },
+ onOpen: (res) => {
+ console.log("sockrt连接成功");
+ },
+ onMsg: (res) => {
+ console.log("onMsg", res);
+ if (res) {
+ let msg = JSON.parse(res.data);
+ commit("GET_IM_MSG", { msg });
+ }
+ },
+ });
+ socket.connectserver(userInfo.im);
+
+ commit("CONNECT_SOCKET", { socket });
+ },
};
export default {
diff --git a/java-mall-app-shop-admin/utils/date.js b/java-mall-app-shop-admin/utils/date.js
index 84ffd7e..8906006 100644
--- a/java-mall-app-shop-admin/utils/date.js
+++ b/java-mall-app-shop-admin/utils/date.js
@@ -2,18 +2,58 @@
* @description 日期转换工具类
*/
+/**
+ * 2020-07-12T11:39:35.000+00:00 =》 2020-07-12 12:24:18
+ * 如果是当天的话 只显示时分秒
+ * @returns {string}
+ * @param date
+ */
+
+export function toDayTime(date) {
+ if (!date) return "";
+
+ // Convert input date to Date object
+ const inputDate = new Date(date);
+
+ // Get current date
+ const now = new Date();
+
+ // Check if the input date is today
+ const isToday =
+ inputDate.getDate() === now.getDate() &&
+ inputDate.getMonth() === now.getMonth() &&
+ inputDate.getFullYear() === now.getFullYear();
+
+ // Adjust for timezone offset (+8 hours)
+ const adjustedDate = new Date(+inputDate + 8 * 3600 * 1000);
+
+ if (isToday) {
+ // Return only time (HH:MM:SS)
+ return adjustedDate
+ .toISOString()
+ .split("T")[1]
+ .replace(/\.[\d]{3}Z/, "");
+ } else {
+ // Return full date and time (YYYY-MM-DD HH:MM:SS)
+ return adjustedDate
+ .toISOString()
+ .replace(/T/g, " ")
+ .replace(/\.[\d]{3}Z/, "");
+ }
+}
+
/**
* 2020-07-12T11:39:35.000+00:00 =》 2020-07-12 12:24:18
* @returns {string}
* @param date
*/
export function renderTime(date) {
- if (!date) return ''
- const dateee = new Date(date).toJSON()
+ if (!date) return "";
+ const dateee = new Date(date).toJSON();
return new Date(+new Date(dateee) + 8 * 3600 * 1000)
.toISOString()
- .replace(/T/g, ' ')
- .replace(/\.[\d]{3}Z/, '')
+ .replace(/T/g, " ")
+ .replace(/\.[\d]{3}Z/, "");
}
/**
@@ -23,54 +63,61 @@ export function renderTime(date) {
*/
export function timestampToTime(timestamp) {
if (timestamp) {
- let date = new Date(parseInt(timestamp))
- let Y = date.getFullYear() + '-'
+ let date = new Date(parseInt(timestamp));
+ let Y = date.getFullYear() + "-";
let M =
(date.getMonth() + 1 < 10
- ? '0' + (date.getMonth() + 1)
- : date.getMonth() + 1) + '-'
- let D = date.getDate() < 10 ? '0' + date.getDate() : date.getDate()
+ ? "0" + (date.getMonth() + 1)
+ : date.getMonth() + 1) + "-";
+ let D = date.getDate() < 10 ? "0" + date.getDate() : date.getDate();
let h =
- (date.getHours() < 10 ? '0' + date.getHours() : date.getHours()) + ':'
+ (date.getHours() < 10 ? "0" + date.getHours() : date.getHours()) + ":";
let m =
- (date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes()) +
- ':'
- let s = date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds()
- return Y + M + D + ' ' + h + m + s
+ (date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes()) +
+ ":";
+ let s =
+ date.getSeconds() < 10 ? "0" + date.getSeconds() : date.getSeconds();
+ return Y + M + D + " " + h + m + s;
} else {
- return ''
+ return "";
}
}
export function renderDate(date) {
- if (!date) return ''
+ if (!date) return "";
const fmt = "yyyy-MM-dd";
- return renderDefault(date, fmt)
+ return renderDefault(date, fmt);
}
export function renderDefault(data, fmt) {
if (data == null) {
- return null
+ return null;
}
const date = new Date(data);
const o = {
- "M+": date.getMonth() + 1, //月份
- "d+": date.getDate(), //日
- "h+": date.getHours(), //小时
- "m+": date.getMinutes(), //分
- "s+": date.getSeconds(), //秒
+ "M+": date.getMonth() + 1, //月份
+ "d+": date.getDate(), //日
+ "h+": date.getHours(), //小时
+ "m+": date.getMinutes(), //分
+ "s+": date.getSeconds(), //秒
"q+": Math.floor((date.getMonth() + 3) / 3), //季度
- "S": date.getMilliseconds() //毫秒
+ S: date.getMilliseconds(), //毫秒
};
if (/(y+)/.test(fmt)) {
- fmt = fmt.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length));
+ fmt = fmt.replace(
+ RegExp.$1,
+ (date.getFullYear() + "").substr(4 - RegExp.$1.length)
+ );
}
for (const k in o) {
if (new RegExp("(" + k + ")").test(fmt)) {
- fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
+ fmt = fmt.replace(
+ RegExp.$1,
+ RegExp.$1.length == 1 ? o[k] : ("00" + o[k]).substr(("" + o[k]).length)
+ );
}
}
return fmt;
@@ -83,16 +130,16 @@ export function renderDefault(data, fmt) {
*/
export function timeToYMD(time) {
if (time) {
- let date = new Date(time)
- let Y = date.getFullYear() + '-'
+ let date = new Date(time);
+ let Y = date.getFullYear() + "-";
let M =
(date.getMonth() + 1 < 10
- ? '0' + (date.getMonth() + 1)
- : date.getMonth() + 1) + '-'
- let D = date.getDate() < 10 ? '0' + date.getDate() : date.getDate()
- return Y + M + D
+ ? "0" + (date.getMonth() + 1)
+ : date.getMonth() + 1) + "-";
+ let D = date.getDate() < 10 ? "0" + date.getDate() : date.getDate();
+ return Y + M + D;
} else {
- return ''
+ return "";
}
}
diff --git a/java-mall-app-shop-admin/utils/http.js b/java-mall-app-shop-admin/utils/http.js
index de4c4c6..96a1967 100644
--- a/java-mall-app-shop-admin/utils/http.js
+++ b/java-mall-app-shop-admin/utils/http.js
@@ -1,6 +1,8 @@
import axios from 'axios';
import config from '../config/config';
import axiosAdapterUniapp from 'axios-adapter-uniapp';
+import $store from '../store/index';
+
const service = axios.create({
baseURL: config.baseApi, // url = base url + request url
headers: {
@@ -39,6 +41,7 @@ service.interceptors.response.use(
duration: 1000,
});
}
+
if (res.code == 30) {
uni.showToast({
title: `token已经过期需要重新登录`,
@@ -46,11 +49,7 @@ service.interceptors.response.use(
duration: 1000,
});
- uni.removeStorageSync('ukey');
-
- uni.redirectTo({
- url: '/pages/login/login',
- });
+ $store.dispatch('user/LoginOut', true);
return;
}
diff --git a/java-mall-app-shop-admin/utils/permission.js b/java-mall-app-shop-admin/utils/permission.js
new file mode 100644
index 0000000..b2cf16e
--- /dev/null
+++ b/java-mall-app-shop-admin/utils/permission.js
@@ -0,0 +1,542 @@
+//permission.js
+/**
+ * 本模块封装了Android、iOS的应用权限判断、打开应用权限设置界面、以及位置系统服务是否开启
+ */
+
+var isIos;
+var unPermission = []; //当前未获取到的权限
+// #ifdef APP-PLUS
+isIos = plus.os.name == "iOS";
+// #endif
+var viewShow = true;
+// 判断推送权限是否开启
+function judgeIosPermissionPush() {
+ var result = false;
+ var UIApplication = plus.ios.import("UIApplication");
+ var app = UIApplication.sharedApplication();
+ var enabledTypes = 0;
+ if (app.currentUserNotificationSettings) {
+ var settings = app.currentUserNotificationSettings();
+ enabledTypes = settings.plusGetAttribute("types");
+ console.log("enabledTypes1:" + enabledTypes);
+ if (enabledTypes == 0) {
+ console.log("推送权限没有开启");
+ unPermission.push("推送权限");
+ } else {
+ result = true;
+ console.log("已经开启推送功能!");
+ }
+ plus.ios.deleteObject(settings);
+ } else {
+ enabledTypes = app.enabledRemoteNotificationTypes();
+ if (enabledTypes == 0) {
+ console.log("推送权限没有开启!");
+ } else {
+ result = true;
+ console.log("已经开启推送功能!");
+ }
+ console.log("enabledTypes2:" + enabledTypes);
+ }
+ plus.ios.deleteObject(app);
+ plus.ios.deleteObject(UIApplication);
+ return result;
+}
+
+// 判断定位权限是否开启
+function judgeIosPermissionLocation() {
+ var result = false;
+ var cllocationManger = plus.ios.import("CLLocationManager");
+ var status = cllocationManger.authorizationStatus();
+ result = status != 2;
+ console.log("定位权限开启:" + result);
+ // 以下代码判断了手机设备的定位是否关闭,推荐另行使用方法 checkSystemEnableLocation
+ /* var enable = cllocationManger.locationServicesEnabled();
+ var status = cllocationManger.authorizationStatus();
+ console.log("enable:" + enable);
+ console.log("status:" + status);
+ if (enable && status != 2) {
+ result = true;
+ console.log("手机定位服务已开启且已授予定位权限");
+ } else {
+ console.log("手机系统的定位没有打开或未给予定位权限");
+ } */
+ plus.ios.deleteObject(cllocationManger);
+ return result;
+}
+
+// 判断麦克风权限是否开启
+function judgeIosPermissionRecord() {
+ var result = false;
+ var avaudiosession = plus.ios.import("AVAudioSession");
+ var avaudio = avaudiosession.sharedInstance();
+ var permissionStatus = avaudio.recordPermission();
+ console.log("permissionStatus:" + permissionStatus);
+ if (permissionStatus == 1684369017 || permissionStatus == 1970168948) {
+ console.log("麦克风权限没有开启");
+ unPermission.push("麦克风权限");
+ } else {
+ result = true;
+ console.log("麦克风权限已经开启");
+ }
+ plus.ios.deleteObject(avaudiosession);
+ return result;
+}
+
+// 判断相机权限是否开启
+function judgeIosPermissionCamera() {
+ var result = false;
+ var AVCaptureDevice = plus.ios.import("AVCaptureDevice");
+ var authStatus = AVCaptureDevice.authorizationStatusForMediaType("vide");
+ console.log("authStatus:" + authStatus);
+ if (authStatus == 3) {
+ result = true;
+ console.log("相机权限已经开启");
+ } else {
+ console.log("相机权限没有开启");
+ unPermission.push("相机权限");
+ }
+ plus.ios.deleteObject(AVCaptureDevice);
+ return result;
+}
+
+// 判断相册权限是否开启
+function judgeIosPermissionPhotoLibrary() {
+ var result = false;
+ var PHPhotoLibrary = plus.ios.import("PHPhotoLibrary");
+ var authStatus = PHPhotoLibrary.authorizationStatus();
+ console.log("authStatus:" + authStatus);
+ if (authStatus == 3) {
+ result = true;
+ console.log("相册权限已经开启");
+ } else {
+ console.log("相册权限没有开启");
+ unPermission.push("相册权限");
+ }
+ plus.ios.deleteObject(PHPhotoLibrary);
+ return result;
+}
+
+// 判断通讯录权限是否开启
+function judgeIosPermissionContact() {
+ var result = false;
+ var CNContactStore = plus.ios.import("CNContactStore");
+ var cnAuthStatus = CNContactStore.authorizationStatusForEntityType(0);
+ if (cnAuthStatus == 3) {
+ result = true;
+ console.log("通讯录权限已经开启");
+ } else {
+ console.log("通讯录权限没有开启");
+ unPermission.push("通讯录权限");
+ }
+ plus.ios.deleteObject(CNContactStore);
+ return result;
+}
+
+// 判断日历权限是否开启
+function judgeIosPermissionCalendar() {
+ var result = false;
+ var EKEventStore = plus.ios.import("EKEventStore");
+ var ekAuthStatus = EKEventStore.authorizationStatusForEntityType(0);
+ if (ekAuthStatus == 3) {
+ result = true;
+ console.log("日历权限已经开启");
+ } else {
+ console.log("日历权限没有开启");
+ unPermission.push("日历权限");
+ }
+ plus.ios.deleteObject(EKEventStore);
+ return result;
+}
+
+// 判断备忘录权限是否开启
+function judgeIosPermissionMemo() {
+ var result = false;
+ var EKEventStore = plus.ios.import("EKEventStore");
+ var ekAuthStatus = EKEventStore.authorizationStatusForEntityType(1);
+ if (ekAuthStatus == 3) {
+ result = true;
+ console.log("备忘录权限已经开启");
+ } else {
+ console.log("备忘录权限没有开启");
+ nPermission.push("备忘录权限");
+ }
+ plus.ios.deleteObject(EKEventStore);
+ return result;
+}
+//获取当前权限中文描述
+function getCurrentPermissionType(permissionId) {
+ console.log(permissionId);
+ switch (permissionId) {
+ case "android.permission.READ_EXTERNAL_STORAGE":
+ return "文件读取权限";
+ case "android.permission.WRITE_EXTERNAL_STORAGE":
+ return "文件写入权限";
+ case "android.permission.CAMERA":
+ return "相机权限";
+ case "android.permission.RECORD_AUDIO":
+ return "麦克风权限";
+ default:
+ return "其他权限";
+ }
+}
+// Android权限查询 -export
+function requestAndroidPermission(permissionID) {
+ console.log(permissionID.split(","));
+
+ return new Promise((resolve, reject) => {
+ plus.android.requestPermissions(
+ permissionID.split(","),
+ // [permissionID], // 理论上支持多个权限同时查询,但实际上本函数封装只处理了一个权限的情况。有需要的可自行扩展封装
+ function (resultObj) {
+ var result = 0;
+ for (var i = 0; i < resultObj.granted.length; i++) {
+ var grantedPermission = resultObj.granted[i];
+ console.log("已获取的权限:" + grantedPermission);
+ result = 1;
+ }
+ for (var i = 0; i < resultObj.deniedPresent.length; i++) {
+ var deniedPresentPermission = resultObj.deniedPresent[i];
+ console.log("拒绝本次申请的权限:" + deniedPresentPermission);
+ console.log("deniedPresentPermission", deniedPresentPermission);
+ let permissionName = getCurrentPermissionType(
+ deniedPresentPermission
+ );
+ console.log(permissionName);
+ unPermission.push(permissionName);
+ result = 0;
+ }
+ for (var i = 0; i < resultObj.deniedAlways.length; i++) {
+ var deniedAlwaysPermission = resultObj.deniedAlways[i];
+ console.log("永久拒绝申请的权限:" + deniedAlwaysPermission);
+ console.log("deniedPresentPermission", deniedAlwaysPermission);
+ let permissionName = getCurrentPermissionType(deniedAlwaysPermission);
+ unPermission.push(permissionName);
+ result = -1;
+ }
+ resolve(result);
+ // 若所需权限被拒绝,则打开APP设置界面,可以在APP设置界面打开相应权限
+ // if (result != 1) {
+ // gotoAppPermissionSetting()
+ // }
+ },
+ function (error) {
+ console.log("申请权限错误:" + error.code + " = " + error.message);
+ resolve({
+ code: error.code,
+ message: error.message,
+ });
+ }
+ );
+ });
+}
+
+// 使用一个方法,根据参数判断权限 -export
+function judgeIosPermission(permissionID) {
+ return new Promise((resolve, reject) => {
+ console.log(permissionID);
+ let result;
+ if (permissionID == "location") {
+ result = judgeIosPermissionLocation();
+ resolve(result);
+ } else if (permissionID == "camera") {
+ result = judgeIosPermissionCamera();
+ resolve(result);
+ } else if (permissionID == "photoLibrary") {
+ result = judgeIosPermissionPhotoLibrary();
+ resolve(result);
+ } else if (permissionID == "record") {
+ result = judgeIosPermissionRecord();
+ resolve(result);
+ } else if (permissionID == "push") {
+ result = judgeIosPermissionPush();
+ resolve(result);
+ } else if (permissionID == "contact") {
+ result = judgeIosPermissionContact();
+ resolve(result);
+ } else if (permissionID == "calendar") {
+ result = judgeIosPermissionCalendar();
+ resolve(result);
+ } else if (permissionID == "memo") {
+ result = judgeIosPermissionMemo();
+ resolve(result);
+ }
+ resolve(false);
+ });
+}
+
+// 跳转到**应用**的权限页面 -export
+export function gotoAppPermissionSetting() {
+ if (isIos) {
+ var UIApplication = plus.ios.import("UIApplication");
+ var application2 = UIApplication.sharedApplication();
+ var NSURL2 = plus.ios.import("NSURL");
+ // var setting2 = NSURL2.URLWithString("prefs:root=LOCATION_SERVICES");
+ var setting2 = NSURL2.URLWithString("app-settings:");
+ application2.openURL(setting2);
+
+ plus.ios.deleteObject(setting2);
+ plus.ios.deleteObject(NSURL2);
+ plus.ios.deleteObject(application2);
+ } else {
+ // console.log(plus.device.vendor);
+ var Intent = plus.android.importClass("android.content.Intent");
+ var Settings = plus.android.importClass("android.provider.Settings");
+ var Uri = plus.android.importClass("android.net.Uri");
+ var mainActivity = plus.android.runtimeMainActivity();
+ var intent = new Intent();
+ intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
+ var uri = Uri.fromParts("package", mainActivity.getPackageName(), null);
+ intent.setData(uri);
+ mainActivity.startActivity(intent);
+ }
+}
+
+// 检查系统的设备服务是否开启 -export
+// var checkSystemEnableLocation = async function () {
+export function checkSystemEnableLocation() {
+ if (isIos) {
+ var result = false;
+ var cllocationManger = plus.ios.import("CLLocationManager");
+ var result = cllocationManger.locationServicesEnabled();
+ console.log("系统定位开启:" + result);
+ plus.ios.deleteObject(cllocationManger);
+ return result;
+ } else {
+ var context = plus.android.importClass("android.content.Context");
+ var locationManager = plus.android.importClass(
+ "android.location.LocationManager"
+ );
+ var main = plus.android.runtimeMainActivity();
+ var mainSvr = main.getSystemService(context.LOCATION_SERVICE);
+ var result = mainSvr.isProviderEnabled(locationManager.GPS_PROVIDER);
+ console.log("系统定位开启:" + result);
+ return result;
+ }
+}
+
+let permissionMap = {
+ android: {
+ CAMERA_EXTERNAL_STORAGE: {
+ // 相机权限/相册读写权限
+ name: "android.permission.READ_EXTERNAL_STORAGE,android.permission.WRITE_EXTERNAL_STORAGE,android.permission.CAMERA",
+ title: "相机/相册权限说明",
+ content:
+ "便于您使用该功能上传您的照片/图片/视频及用于更换头像、发布产品/需求、下载、与客服沟通等场景中读取和写入相册和文件内容",
+ },
+ CAMERA: {
+ // 相机权限
+ name: "android.permission.CAMERA",
+ title: "相机权限说明",
+ content: "便于您使用该功能上传图片,用于与客服沟通等场景中发送拍摄图片",
+ },
+ EXTERNAL_STORAGE: {
+ //相册读写权限
+ name: "android.permission.READ_EXTERNAL_STORAGE,android.permission.WRITE_EXTERNAL_STORAGE",
+ title: "相册读写权限说明",
+ content:
+ "便于您使用该功能上传您的照片/图片/视频及用于更换头像、发布产品/需求、下载、与客服沟通等场景中读取和写入相册和文件内容",
+ },
+ CAMERA_EXTERNAL_STORAGE_RECORD_AUDIO: {
+ //视频录制和获取权限
+ name: "android.permission.READ_EXTERNAL_STORAGE,android.permission.WRITE_EXTERNAL_STORAGE,android.permission.CAMERA,android.permission.RECORD_AUDIO",
+ title: "相机/相册和麦克风权限说明",
+ content:
+ "便于您使用该功能获取并上传视频用于发布产品/需求过程中读取和写入视频文件内容",
+ },
+ },
+ ios: {},
+};
+
+let view = null;
+//华为要求每一个获取权限都要有对应的说明提示,否则无法上架
+function showViewDesc(permission) {
+ let plat = isIos ? "ios" : "android";
+ view = new plus.nativeObj.View("per-modal", {
+ top: "0px",
+ left: "0px",
+ width: "100%",
+ backgroundColor: "rgba(0,0,0,0.2)",
+ //opacity: '.9'
+ });
+ view.drawRect(
+ {
+ color: "#fff",
+ radius: "5px",
+ },
+ {
+ top: "30px",
+ left: "5%",
+ width: "90%",
+ height: "100px",
+ }
+ );
+ view.drawText(
+ permissionMap[plat][permission]["title"],
+ {
+ top: "40px",
+ left: "8%",
+ height: "30px",
+ },
+ {
+ align: "left",
+ color: "#000",
+ },
+ {
+ onClick: function (e) {
+ console.log(e);
+ },
+ }
+ );
+ view.drawText(
+ permissionMap[plat][permission]["content"],
+ {
+ top: "65px",
+ height: "60px",
+ left: "8%",
+ width: "84%",
+ },
+ {
+ whiteSpace: "normal",
+ size: "14px",
+ align: "left",
+ color: "#656563",
+ }
+ );
+ setTimeout(() => {
+ if (viewShow) view.show();
+ }, 200);
+}
+
+async function permissionIosCheck(permission) {
+ console.log("permissionIosCheck", permission);
+ let results = [];
+ if (permission == "CAMERA_EXTERNAL_STORAGE") {
+ results.push(await judgeIosPermission("camera"));
+ results.push(await judgeIosPermission("photoLibrary"));
+ } else if (permission == "CAMERA_EXTERNAL_STORAGE_RECORD_AUDIO") {
+ results.push(await judgeIosPermission("camera"));
+ results.push(await judgeIosPermission("photoLibrary"));
+ results.push(await judgeIosPermission("record"));
+ } else if (permission == "CAMERA") {
+ results.push(await judgeIosPermission("camera"));
+ } else if (permission == "RECORD") {
+ results.push(await judgeIosPermission("record"));
+ } else if (permission == "PHOTO_LIBRARY") {
+ results.push(await judgeIosPermission("photoLibrary"));
+ }
+ // 检查所有权限是否都已开启
+ let allPermissionsGranted = results.every((result) => result);
+ return allPermissionsGranted;
+}
+
+// 权限检查
+/**
+ *
+ * @param {*} permission // 要获取的权限 type:String
+ * @returns
+ */
+function premissionCheck(permission) {
+ console.log(permission);
+ console.log(isIos);
+ return new Promise(async (resolve, reject) => {
+ let plat = isIos ? "ios" : "android";
+ unPermission = [];
+ if (isIos) {
+ // ios
+
+ // const camera = judgeIosPermissionCamera();//判断ios是否给予摄像头权限
+ // //ios相册没权限,系统会自动弹出授权框
+ // //let photoLibrary = permission.judgeIosPermission("photoLibrary");//判断ios是否给予相册权限
+ // if(camera){
+ // resolve();
+ // }else{
+ // reject('需要开启相机使用权限');
+ // }
+ console.log("permission", permission);
+ if (permission) {
+ let result = await permissionIosCheck(permission);
+ if (result) {
+ resolve(1);
+ } else {
+ // reject('需要开启相机使用权限');
+ let str = unPermission.join(",");
+ uni.showModal({
+ title: "温馨提示",
+ content: `请注意:该功能需要获取${str}!`,
+ showCancel: true,
+ confirmText: "去设置",
+ success: function (res) {
+ if (res.confirm) {
+ gotoAppPermissionSetting();
+ } else if (res.cancel) {
+ return;
+ }
+ },
+ });
+ }
+ }
+ } else {
+ // android
+ console.log("android");
+ let permission_arr = permissionMap[plat][permission]["name"].split(",");
+ console.log(permission_arr);
+ let flag = true;
+ for (let i = 0; i < permission_arr.length; i++) {
+ let status = plus.navigator.checkPermission(permission_arr[i]);
+ if (status == "undetermined") {
+ flag = false;
+ }
+ }
+ console.log("flag", flag);
+ if (flag == false) {
+ // 未完全授权
+ console.log("未授权");
+ showViewDesc(permission);
+ requestAndroidPermission(permissionMap[plat][permission]["name"]).then(
+ (res) => {
+ viewShow = false;
+ setTimeout(() => {
+ viewShow = true;
+ }, 120);
+ console.log("值", res);
+
+ if (res == -1) {
+ let str = unPermission.join(",");
+ console.log(str);
+ uni.showModal({
+ title: "提示",
+ content: `操作权限已被拒绝,请手动前往设置${str}`,
+ confirmText: "立即设置",
+ success: (res) => {
+ if (res.confirm) {
+ gotoAppPermissionSetting();
+ }
+ view.close();
+ resolve(res);
+ },
+ fail() {
+ view.close();
+ resolve(res);
+ },
+ });
+ } else if (res == 1) {
+ view.close();
+ resolve(res);
+ } else {
+ view.close();
+ }
+ }
+ );
+ } else {
+ resolve(1);
+ }
+ }
+ });
+}
+module.exports = {
+ judgeIosPermission: judgeIosPermission,
+ requestAndroidPermission: requestAndroidPermission,
+ checkSystemEnableLocation: checkSystemEnableLocation,
+ gotoAppPermissionSetting: gotoAppPermissionSetting,
+ premissionCheck: premissionCheck,
+};
diff --git a/java-mall-app-shop-admin/vue.config.js b/java-mall-app-shop-admin/vue.config.js
index cef5c75..fdc7e9d 100644
--- a/java-mall-app-shop-admin/vue.config.js
+++ b/java-mall-app-shop-admin/vue.config.js
@@ -1,27 +1,31 @@
module.exports = {
devServer: {
- port:8080,
+ port: 8080,
proxy: {
- '/mobile': { // 匹配所有以 /mobile 开头的请求路径
- target: 'https://mall.gpxscs.cn/mobile', // 目标服务器
+ '/mobile': {
+ // 匹配所有以 /mobile 开头的请求路径
+ target: 'https://mall.gpxscs.cn', // 目标服务器
changeOrigin: true, // 是否改变请求源
pathRewrite: {
- "^/mobile": ""
- }
+ '^/mobile': '/mobile',
+ },
},
- '/api/admin': { // 匹配所有以 /api 开头的请求路径
- target: 'https://mall.gpxscs.cn/api/admin', // 目标服务器
+ '/api/admin': {
+ // 匹配所有以 /api 开头的请求路径
+ target: 'https://mall.gpxscs.cn', // 目标服务器
changeOrigin: true, // 是否改变请求源
pathRewrite: {
- "^/api/admin": ""
- }
+ '^/api/admin': '/api/admin',
+ },
},
- '/api/mobile': { // 匹配所有以 /api/mobile 开头的请求路径
- target: 'https://mall.gpxscs.cn/api/mobile', // 目标服务器
+ '/api/mobile': {
+ // 匹配所有以 /api/mobile 开头的请求路径
+ target: 'https://mall.gpxscs.cn', // 目标服务器
changeOrigin: true, // 是否改变请求源
+ logLevel: 'debug',
pathRewrite: {
- "^/api/mobile": ""
- }
+ '^/api/mobile': '/api/mobile',
+ },
},
// '/signed':{
// target:"https://mall.gpxscs.cn",
@@ -29,6 +33,6 @@ module.exports = {
// pathRewrite:{
// }
// },
- }
- }
-}
\ No newline at end of file
+ },
+ },
+};