From 522f529c6adcabf8619e8ed1969d9ed18d961be9 Mon Sep 17 00:00:00 2001 From: Certificate System Date: Thu, 13 Aug 2026 19:12:52 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E7=B3=BB=E7=BB=9F=E7=95=8C?= =?UTF-8?q?=E9=9D=A2=E5=B9=B6=E6=8E=A5=E5=85=A5=E6=AD=A3=E5=BC=8F=E5=93=81?= =?UTF-8?q?=E7=89=8C=E6=A0=87=E8=AF=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/app/api/routes/admin_logs.py | 4 +- backend/app/schemas/log.py | 8 + backend/app/services/pdf.py | 6 +- backend/tests/test_admin_logs.py | 8 + frontend/index.html | 1 + frontend/public/brand/huiyu-logo.png | Bin 0 -> 42435 bytes .../src/components/PublicServiceHeader.vue | 98 ++++++ frontend/src/design.css | 202 ++++++++--- frontend/src/views/AdminCertificates.vue | 81 +++-- frontend/src/views/AdminHome.vue | 89 +++-- frontend/src/views/AdminLearners.vue | 39 ++- frontend/src/views/AdminLogin.vue | 84 ++++- frontend/src/views/AdminProjects.vue | 31 +- frontend/src/views/AdminShell.vue | 254 +++++++++++--- frontend/src/views/CertificateQuery.vue | 321 ++++++++++++++---- frontend/src/views/CertificateView.vue | 119 +++++-- frontend/src/views/VerifyView.vue | 60 +++- 17 files changed, 1092 insertions(+), 313 deletions(-) create mode 100644 backend/tests/test_admin_logs.py create mode 100644 frontend/public/brand/huiyu-logo.png create mode 100644 frontend/src/components/PublicServiceHeader.vue diff --git a/backend/app/api/routes/admin_logs.py b/backend/app/api/routes/admin_logs.py index e263e03..6a35acc 100644 --- a/backend/app/api/routes/admin_logs.py +++ b/backend/app/api/routes/admin_logs.py @@ -7,13 +7,13 @@ from app.api.deps import require_roles from app.core.paths import data_path from app.db.session import get_db from app.models import AdminUser, OperationLog -from app.schemas.log import OperationLogOut +from app.schemas.log import OperationLogPage from app.services.logs import HIGH_RISK_LOG_RETENTION_DAYS, LOG_RETENTION_DAYS, cleanup_expired_logs, format_log router = APIRouter() -@router.get("", response_model=list[OperationLogOut]) +@router.get("", response_model=OperationLogPage) def list_logs( action: str | None = Query(default=None), object_type: str | None = Query(default=None), diff --git a/backend/app/schemas/log.py b/backend/app/schemas/log.py index 5862ec8..e4e2ac3 100644 --- a/backend/app/schemas/log.py +++ b/backend/app/schemas/log.py @@ -19,3 +19,11 @@ class OperationLogOut(BaseModel): summary: str | None = None model_config = {"from_attributes": True} + + +class OperationLogPage(BaseModel): + items: list[OperationLogOut] + total: int + page: int + page_size: int + total_pages: int diff --git a/backend/app/services/pdf.py b/backend/app/services/pdf.py index 9546848..eba0799 100644 --- a/backend/app/services/pdf.py +++ b/backend/app/services/pdf.py @@ -208,7 +208,7 @@ def render_practice_camp_certificate_image(certificate: Certificate, learner: Le (end_month, 1058), ]: draw.text( - (x * x_scale, 648 * y_scale), + (x * x_scale, 658 * y_scale), value, fill="#202020", font=font(41, "song", False, text_scale), @@ -217,7 +217,7 @@ def render_practice_camp_certificate_image(certificate: Certificate, learner: Le issue_date_text = f"{issue_year}年{issue_month}月{issue_day}日" issue_date_font = font(36, "song", False, text_scale) - issue_date_position = (568 * x_scale, 1140 * y_scale) + issue_date_position = (568 * x_scale, 1149 * y_scale) draw.rectangle( ( 442 * x_scale, @@ -362,7 +362,7 @@ def draw_issue_date_numbers( y_scale: float, ) -> None: text_font = font(13, "song", False, scale) - y = 682 * y_scale + y = 685 * y_scale for value, x in [(issue_year, 500), (issue_month, 535), (issue_day, 566)]: draw.text((x * x_scale, y), value, fill="#111111", font=text_font, anchor="mm") diff --git a/backend/tests/test_admin_logs.py b/backend/tests/test_admin_logs.py new file mode 100644 index 0000000..95b097c --- /dev/null +++ b/backend/tests/test_admin_logs.py @@ -0,0 +1,8 @@ +from app.api.routes.admin_logs import router +from app.schemas.log import OperationLogPage + + +def test_operation_log_list_uses_paginated_response_model(): + list_route = next(route for route in router.routes if route.path == "") + + assert list_route.response_model is OperationLogPage diff --git a/frontend/index.html b/frontend/index.html index 5ca5b8f..165c160 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -3,6 +3,7 @@ + 培训结业证书管理与查询系统 diff --git a/frontend/public/brand/huiyu-logo.png b/frontend/public/brand/huiyu-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..6a1d0ba05ac2a83f62fd13f87b1e014179f23fbd GIT binary patch literal 42435 zcma(3Wn5HWxIPZkt#nFDNjFF+4FVFOqfPjREfPe_aKm&gw+SL3L z0pWARGZ{%u&)K~UFJB`a_x*O;eb=GZCKog$1{4gwglRQeHASxkGJSm(H7r>qeJOU) zjs!ZqURMHNltZ%KAR-nOF-A447jwOAUp{kis668MtoGI%nGpra42$k%rQ5!Em+^kA zYeiWKPE!n{($S^=6aW4^>Q8>dGrRRu#_hE-T0A&i+&HV}T{8q^Z_UWwzC!>XySSB6 zZa9JN5dMjb2?_ppUEKJl|NmWTL4l87rFHjhlwn8`S`(px zx8J!cEUhJA#Ne)_WpMBI>w26eK1N8(l#_knyQB>8m_U6Y&1&b4bNj=tDX3TYnzd!6 z{@uo?}7Iq^amA>&GH2+6>lYym_HH^HT43e&;BZg(|=;W2pUcefF1IWn-R^?;&kzX9r!IDd`#L#%wO4+aPM=-1@L_&bSp9*M<`k0C!NngTBew^FN2vzk;Y0m$ zldp}@BEt?;)hLV2Sa`mCd8NHLcKY@rYCdrkzScTuI3(U>P^2mpgWRaV&n1 zKOfIJuuyq~)wUd}(eIQH+D5QK*5}eTL%q8Fy?~5bZbA_E?lkshqF$B!Zqt*SO+I*E z%|KauX5gf!vQ^<~S=Ny@uGuA$#%4;Egb9jxns0g=r@>1hb4UEI5o>NlNS;SPMRuID zR$~{V*ah^}ygr21t~}68mkG)pWzi$CX^T0R8_r_AdF{`yicKr~Zjz8Xq1MymqYZo` zZ%d)~eMk~i_6R*%kcHHPcZNP;dl{D_O=ul+?frH zlM1aJ3tU^5I)XizSv614^SRFjl<%@uD8axt$hj&nx zUR}}Cc`tH(LQn_FZFynV39pIYarrA_L<`lS<3WxX-`R-b7Htvz={iHaXVDVyWEIqp zTD8Ax2xlbycZ`(@wbV0h)T?unoXqh@o?#;}ex;UetkU#1NJLf{d1i%zl1v&Z7v0N5 zKJcB_`WD1en9xMK10RqMR50^6TG#oc;bv#Y$rCNQA3FST)T)~#M1hQ<`qMXP%Y{>x za6b6JH@5r89xNmr4=paIH>k!8n6j!fVZF20y&uI5Jx*V|o5M^N;&X_i7wdoN_xAHT5AePF~ZS zg`hMaC+XRD8hcQ@vxbOw(5N|Dh0^wygLl|Va07ztju6NSF}atu?rS~B`DYja*LJvN zUdW2h{%E^R-G#DAlnzq>M|Pkq9!#+?pN!(}_w$rzt56nshIZOQ`67Z{s*|89b0)8> z=8O9E3sF!dgq-C2tHsnr9+NFG$Lk%GMOCYB&O8Y741upP9Q@@C5I(JdMG)dh>Xpre zltoG4b_cTLB*7v+M3b77JXI#u4o1p;(4ez7T0!(!^pe0=RW_JbFD9aLxfpxxtKYG@ zOz9KoZT&g(>sHc8YK2sPCK=U1O8}+%EcAh+vozZNGY#jisU`7m`)RTHMGXyW8H0lL zUa{lU>>-e6Glho-hsdSRHSXmh*VW&(Eo$zC3xu?x_&291Pwgzl^^s6dsWJN_++yoU z_T=w7?#1U*Oh+2r(6xTnT-1tm78gd9I4BeB5M6A8C}au?D{>EH-*qEI+84xg(f1>! zKCt=xImUvR1UuGUY}WdmtQtu=tG0VIteyrabfWhd?5TPaBE4Y!DDwk*-9_NP%Y&+Z z*Ad2=@>-Bk@|P~un|+_>muR|QwAA@*Y$MIsQ$fA+Qy9u4**q1u>^}6#U!(Q&IwYp_ z=)HuveasI8jAvIpS9sq!{S20 z;^nD_$NJIkuUN}%0f_z{l$VuJOWH(D%`12o(w0GZX)7jh@kB{p?#mbWnT12DH|_K8 zd$@VKVZwZezK!hfzF_slH(BX?-m6&c)o-yMbnr82QpzK zj=)cZiKDF7v8;S=R@toEu^KbYD!s#?t7TKvb{E;TXGr3@NIA;p*Se7v0bFKR;(AE? zu|X>C0a-43e5=e=@=Qhyx_W5RCY{pNQT)#ZbmQ)JDlbgqd_(qVtSyxE%#+!qbsFh@ zlKoQo1-PC$PH_bFD$ZkXbWUmggYd5$M+rt0(5j-um4tBnG|=U~P<{a*2j?z5eqV=% zd;>=%pZ%y3U}2q|^9}S4cC@@6EMB-&jpsmX>9vz!cCv~!_o(Skwt1%NipszugRhP` zhk&-XDsan<=0$f!ju9QUHp`+ZRELf-BM>JrKahT**Igtg!d<%}&vs4T*UeW{ee9Rh zkH&9v{X3t|>kWLj(Wu2rxktDy(H8Fe{8?K40lRn`LWnK<^5|z!q+Et|X?K!9v-<>c zACmH?tFuy?53z$KJi?2=$`rU`-nYO+Io6BB-r9MR!Oz|;s$;TG$9^h$E7efSwY)}u z!p+)H{OxSj-hYii5H!yq^%z9~e-GOCI@-0aJ*~SPyeti+wER0_Ih-xx&jsKO3QqiZ zf;xWr2Ff0NpXU2RqRhaNm3aSlmW8?{wkewf15fqgo(dAoNYP2&2|H z)d1`WcUu>uG)8|LH#?S^cm4^Xkd{e$WOpG={OFQ zuxp;id(^G5d-JwuTk^epPYm`4dBc$w>F7?L+#9{6raYSpqDjy!NaRB*yx? z)Ea`~{RmA{O1xv8(Lmd%U}+yKqUbuaIml;S<&U{`WkDRQHjG{pu}?{p^1;$ylGG`8 z>gjP)cu!hw$TjGo;T4=RzZ?KPGO#~jzh}-@sKQxRM@_l+%n0&8<_qkDcF)ha-JB;9 zPO_3Sh0Z-0&$T}ny&XlI3%gxHN_on3+)CZdpvveshx%AFSdi~M4SGuDcv!~p>luau`G~$u7HeAb5V8;J?QMMb8hb+k zxGwq9*Ic;_t6HBlI2z(4Aad?tMQqE723-Z0d@1X6VGdV}P3nlMCOO`D9{Dn7koayp z&hYU`2n4wjqqiItad^1$!08C;Q(m`T&;02?;2To^%EPf-wYwnOv$74;Lrx&MYxyFl$kC zSoV#Zr33mG71b!`vYvH)LvWa=ZQ|m(sAMDHfnq z3yVM02*ebk{v0Go`Pxt=xb*G*!3{sLkl6Di=+z)vR4%~hU*ry!*X&2)M3`9RESP=* zD$f-;;e9Wpj_X!sq)5B5oloKR?N8dav?QK7V7dhhH?UBR?qz4EV3OaTfEv$NQ+XS( zcv%swdZ)5U2<+NcN$X`_&a^n$G`2Y30X07Iv{n$5*2RCGG znJ!Lh*MvQdmZjY~wmg}Aq?n2b(H7uKYAOc zUi-ZNR!-E!0o>=G2s|opqbNv#;QAo~iC|bWsQNk9qX3S9oys>}&B#HD5J+?O_Gk2g zY*=;rNa5j{{!>S=u5i@^ zR(?rjE0s^|C!p#~`h3BmZ+I=|6r;pt!hma$LyUPV3R2$SxV627)_ucA{TbTWhZ$H+ zvIVeE;es$)XLc(6-Qc?B3>a&5-}TN6T%$ zM+m2{gu>l;`n%6ZTqo|GN9+&CMqL7n&mFX{4>ERc5=Bor@0CXT;pV+9p;?TzN~p3p z%m*MIgwKIqrf`ewJ$Bg!9qsmNm+6(CS=2`}H;@zjFxwLOnqDUxKOK)m+~;{Pf;n$n zvEDT(_*Z=&P~5`cGhyPoj-1knTe)u`H(rZUciC8}zIy1zb8&$X=pFX*@hY7;G2ah@ zY3UadvU=KRUy{??0v*>AqA7-#oXTZevG!|8N-|}`MtGS6O4N{aWFezh$wqRaGE)&!<8sE> zua7ng{~dXzv04-dV}{{p^u|keXHRHoe=7t|Y==_=GHRA2)c;K5-nP_rwe4w`gY@u@7w0iNQ5D3BX>|o@&7u+w9KZKdvH{M$fqWL@SuCR)Jg1-JBZgW{S zNTrTeEwNg?H@0@V^>sZbb%wNFVAq>5Xn4|tu(feN%=QVT{ZNPFPp^AO=VCXe&i3Wy zHeeLDZiYo2YP||-fO>Vl`YOJx5barz$a|E3=s$^8eS?Q_25Z>nO zU~nTje=RptcwBnUL=vqlcn6PF`34;U7mY{fEGwPbX(I!^2nlLRPO^P(vFmqZ$KPnh z1~oQl1GF{|^XK4d%;)Mj94de+luG;a*$NUvd-KqZb#YqZPR{pLi%CU2gAwC_tNfIP> zbVn)22b*dRfmOm3yLt^IfbE?GxX-}#Eo3#fJX_d!3k@y+D0_LCTTz|y;TFo2=S2_W zk?4Q$Q|5&Lx?YFhc4h^xAmv9_HVrMNSF;(Hr*Vk$hn60@XurVy(4^Tv8C?Y= z3?m}fuGzcjE9hh9vcb0;DF5TAWO2@uOm{y_Tn@#~PfLu9GSpLct|cgApvmZfJ(U-7 zQu=;Wn*FnQ`pHb~0o+%pf^FL0FgzD1tpWUa>yLuPU@(rw(Vg`&?)BZHKRIMY(^+{8 zKU;CeL;%fu;N!w&&}tD0EE84h^w^Q?1IO`BDVd`>txWv5hV|MAUPEgrvsLWM=7beL zz|&hXA>0Fc)l#QjEXZ*0Ws`7HXzqI2 z=lbOW64HyLP=M*#Eo}cI0iqs>*E&#qNEWiWR;lT|Kv?*;o(OqW+>M|WH}Bk9m_gs6 zHFp|=K+5b4hsD#A!6@E$!j9wSUbCPiLg1wY=UUeEFKUllcaVzc>^PJ(-Hr-WCi)4c zhtALY#V?0@uLPhA)rc9;1%INcnEG?`vU+++Osu$vSUDag`FD!ZU(e(9#L!u}Xk)he z>N7pbls#VriB?)YN$g>)m%oP4h0W`f1v9-1z6>!1Q9z*hmu)$*Jz*YU$@}H_s ziLM66CaUcf8drV8gL^@QSpP=@D6)R`P>M>$W!Y>Kh ztjeZDo(&`1B*~6-)EofoKm8ZY{+(jnl#ZcoH$dyPIacN~H<1IG@Lxb@PrAIVJYet3 z_PEBWFuvF{`?qV>{U9_{)j&g?>c<$Wu{^#w`sP;gkG?q*u^{V+#O^Zs0^*4BbaLe> z*WzFpS{d2F%^L};atV@}+L;X>b$+h_T3U$2E)R18>I3Ko)-6R6mimW}Uhi7!)K|UA zs5ydOyhA7MeN(s-$g$0kph4U){!_%bv$*hMweYKL#)*Uu-glmVfFz`Zi(jy{c^)Ff z*9OCJ{t1I#GtyKDR7$4zvPiElK4x6fSYoD&84bW@jYN1CH%xY&0Z}75xR2SHNNLrT zdPks9$6^?{JxcdV4hw-2=p)#A&%Vh?T7~wV!1I%glbIetI%U-US;Z2xp0{5vW7AG7 zdFns-SVNU42o4yh_lkK#0wBv{rY=coewkxuQ`M{dYx{R@{%dL89$ zC>8M)_autd2U%mH4U)cL8f^xZmEN|yt4{_U6`dRU%6T{}Kqs$a2raJkT$1Sk;%Zid zLX8g!{uOIXxY9@RdinCOq)vFllZ%#5U@QR~+(7GA#oDZr0DC($9cRq1y3i26r_|vT2vvhVU2&uff$gbot zVi~nQbvBT@?M-sb*xZ3i8ux(xYZ5&k;c}#bMEt`C@Iw3A4<7kN!eAwhZf%hC&D>mC z*Z-9OUuG?Y9bd{Q!B14iaqI*;d9UazRtHZqqX5o!0(oBnl-wcyxn~(9T92-F&yhJ6 zt6tZ)P35Dg#Hoq$Lk{}A+!uKkb0xx=QZX^&!d_f>v5Q>{$-DTR&ZN1I!%bGoDFBAD z)4)v*0`8X@6OTj7U|Sf2FO)qe z2yVG*2In7uX1k;VN;{Zb_P>Q`5TKa3LF=^Bv1SL1us9T?bDEMPC{ z!oH7%WiU}RgsM4C27H%;15vQY>tK&#uDaesIHOnN94I^&RlO9xo#$gP z6C=j;)uVG#xaT(O8#*647&+(#ZhvlGd=U2Xi~8!s>Q8DBQC7N`xE9!4wAb~HeZhNN z+`QM(7H}IRhEU|5wbbOw!f7ZvacdM-IqTqpXOF7OdNpW!+!0!-st*@}B%HtYvs=wK z13xi%z(p#rC;nGcJocC-+~foTz&V}U)A|XN??X7F_%J$Sx_yD4C;@v;+b}i~#RdFJ|jJM}aBCy6Ig3AUxcAmeISDWsq_5sy8asQ80lB$%#6vsQ*g6GSvq6u8y`JtY++-u)3Um+ zr7g#BRBCTEPu@tqgN&j>l;9^oohVhz&W3^xGB7|Klbpov^oC1 zk4a^8+K9`i7<+RLM3cOisWiv7S%Vtz2iYEa_8vWtT;sVzUtl9yHe(dN_5z`puy@lp z9hO}l|CVm6slCZq_;>KmW6n1oEglLkspMvc1|}eub@OXZM}gJ{-@^HCNKt^?JBJGa zhpl;GEkI}mV$szHVI$Dt9N2cp!xM83yMNh zx>V~Gn(jYdN85;I_U#f?;ZkxNi$VCjRYDkDKiz0qpJ|l@oq2eTCii6?$l|Jsp-69X zTyWCpeVbwJbFnK^zX7|K#{|{|9A&=Oncm_bI{jV9_K2Ac;Y&42)9az1aW2n3M(`=Y z*e~Xr)6$&O)zyTz{XfNzM8oC)QR&e;P16+vPTaS^pYgYQtOfSCL%lPJ&dZ$g@V9o_ zf9AgwteV*8gn6$Fl=SVPB7d8Qvg)>sk{9sJPaI zRHN9t!sOXBM(%gcs~l|;DZN)?n)8)z2MyZj`)2hz5lS!j`G(3NV<2s z%6r*9%q_2~u3xwIuz6<^uoM!?yjh1c{qpR}#0>FIMQFcQ#(sL+k}KHqsMHoTBDKvh zeZ_ZNs8q-l6SmQ~t#zJNe0*}$F-`h6_N|L6Y!kkLmOTZNdt<8lJg_~;xp#kuO~jtNF)-o zpd_7AbT+%90+cpt*EKdzlC)5vPG=u@^_}>BzHPwwM}DYFPMwb+n7}@H;GSE>v~N@+ zzhtHt*eH4CI$x>qWYJ`k7+4=sx7NpykiLaj$OTbXSD_IuIS2rw$a{kSD15XjgnR;g z|Iq+-J_;+{QG;dAunqpcqJ}f_!;}Z6_bVNru+r1x57Y!Fk%m%lV7+{tqi*H@zfmGw zV5fG&axM^5qs5idK#W4n|IRsQEo0#Imi=D0*7!#Bj0y-)$)RO4IYMiw`(;y3t-5IV zhN8^E!=m+>4-2YCB2aD%Fpq4@m&43}2p`qE5=9D7{8jt5qfqB^a!Mk{Bix8592e~Xh8(|n^BA<^1lcYII7?A?&~9ktr164v@h)0KY`{XOX>;&ghS9$ zPc7S{%+**3=mdp>m*i|{>0L8{Dlp@kwA~&9Utmbok`81Cdz|AQv9MAt%Z!?;a1}=32{#Ss8>{vXzcZf$E@JwFJ*XEMv?RpIFMRhs0SB#Q zVR_(AJ$H#pntE4my@4ReJzkr6_Wi-fpVWZM_fTV2TCS_K+IIM(u%U@@Dgei0=3MFZ zE^Y*L!+Wd-GE&bgwWjMn^FBS!SoIZ<1aN;FS*jy(k*-z7@y)-uv%C4?SQ1?Siwy8T zcC$Ip$bGrdHI5KC7&3l$t;7ek34WxuE!@ zz6^QF^}$cMre8#Eu}R||BPP6;X#mFG%b>GQMZ#&grVPq00TTbRNs;TYA;pxWx8l4RO6Hbgup{9p6a~E{7 zd+BiWoWh6-*+bwX4Zou|`v}qG?fbLg2}ukEz1HZ&R<>tiv7-+c3m^yfH(o!f|1=Du zbKftpCHHlTK8vlN&N^X2`J~DJuF$qa8=f=4ucW>kb-2jzV&ASfj(V-qx5g2)gAx%e zB|ZRC<4G~2^i>cEx{96?;Ci#J5(DK;Q3vj{`MCLoJuuE{Hr_+X)h+Tj5yyz&3Fnt{ z%eC8t(+Y*<|0JBcB+v$~rs3Wmx{H@4(aFDslbV#_y)9ricBS;s)##{tu#xC3@I72i zaDG)x$M0p8*8>kY-)Dn>Gx5-s@)f+VWjmX=p(7Pli*bFU6#q_)ur&1O3LbA#{}*q9 zfuL0kc-q{xbxAiA^`-))+qU+R>Q0+hVs(2AjqPEbK=Y~Jw$!_^R((KD;``9-bQyHM z?^?`wMk3LD{6V7~e1?}W_YvR9MWkM9xLQyB9+OUpL-I01Yd%(}^nFJpBB%$%x>VjP@4R&r& z1;%+(GHXntf573+G_b)bWTS5}TYRx|0Lqnu$1t)rip|?X9mA zjDdk*(L>$DE^YIjp($gM+Kms_{?U?~lX*_Ka+|o*Xdz*A?R2$eeR(x|;Gsl{DfzW- zUJuN(IZP!{G5jF|S7Q$GxfZpwpjgywZ2~-eZXg8_K9~^F?SS}UGA9R(gdkunuBO@h z?-2;P0YY9(A+HExO_q|`$E%B{rsPD1+ISQKnPk|Gs<)0ld_h~erysl9lYglBkdk95 zH#3kRf%@E>0oq+sw@Y=agL~pW08V(9ZT3Say@REFoKi8$Gw{uOXW{U@y;v+>1vEJ* zfctp{Vp`C|#pRIKb)#@wKMB_R@ml9f-B8qe3ZZ9|00{uPb4L# z#JuYMwUjfX7eJ|27_;8npGi+{H9)$uIe$H5Qo4|nRbwu(YCZlh-JH8NXcZcu#qtab zg(lX0yyb2Z@WGFdH7ylA77@YKq)OQy3ZkolTzb*qR6gnve^j6rxKG#;6QSkh= zL3fdd4=NV!q*SBiPiZ(9v&KeHvKf%)6qrje0^3Kg8ZzO2`3Fw61Y!gM1iBRX^9;|7 zD;&&9$7Qp8NG`-m8>|1;Qhp58o&*n0Sr4irGHS3k<%Sn@vFszWW0nNt#W@UE624U2jTK^X^F>fAy|lQ^9I5ORpGdjp1EsBf-?q`PdL^b`CMGnV?do0gVl&y<;3RZ z&4v8DN}mH3`0H2=qznmi7G(CC3I2S-pD4eu%f|%!UAW{;$-lGM@>DE-Q6Pa^eKLX0 zzN1C3r4~&Um&zvt>N)aCrvH;=f|@dm-p&P6Gy9XO{H`}ST-$@Zo(Fm)bzl~Srpy?7 z00a0aQLD6fMh4yL3NS;H*8%ck0i!+7(agw{m(hUTZm;d98NIhB-;`swwdU)i({ z663vRXGYjxJhAk`!^Sk7K>*Lh6Q);5qpmfPUgj*rVGXDqLr--5h2<{7zA6A!uqQEe zMg!Sw|4)t?O;PZcX&>lWkYh4G0FU*!zhh=kY0cx(=D!rP&_!J&R}b{}ev00Ra){HQ z`{nTqy=1tFvGwBC#28E)j^{&{$Gp?buJ^%s9&G0`0pavyAA&Lk7&@?nT>k;~w1*%K zH02SFiRxovmM6_|wmtg3wIr*lzH!+oBP{foj5>w4mDOYTa$)8iJhG$xasG`6wunbg z{2)>xavwJDW}|}LlR%yjH7zOx&;`EX>uSI0=hap9>;v6N98}1-w?vIyG0%kCcv|0? zmlK1pbSQda4my4@QMAaYZX_F!jF2Q$Zc8w-V}{#jayI3;?#V^Poru?~V0=(EiI~~r z8?kKmqr4eDvRMO0{y>CD+wUa4+yQyEC5aIFZS|wQKdWDhD9E3q%pDLcdPb=*h|sma zV1G3BuEfFO9KZylC*=UD`6o z3sMBSVp)TBy9QB9!D1c+ucMYP*wwIUS?qE28{musx?=elIirHEk|QEK_;p=#pZX+x zLWe5=l5PaNAao9F)9)|gP6nQrU`&1E<9|j5{s>4fA2qPwdGz$ql-eljexw#KLiT15 z5Kqc^%0vi=M((Q-o6Yo7@Fl6Z|LxE4PDY#TQU6~CPvQuG8YtV_AsukS=C-sC93Lb+ zfgM%L$ogdAj`WiowaTCA^JMcFfGkB|>S+0pB&*^K-o%2>8j#ArOu%iFnh$r=hRs=;kupjHH300*Dyf)2>s|V9?o!Jb_%IA86Q(gu z!=_}HxwJL>p_=?e{Fg^a2wL!gjv%%qlf0$pqQJ+UOnE*7#)l67f09e$;SIMU{wCnU z>cPuowJ0K0)4*PE(n5tr8j#2p;N)(g&yX2_->^AGjM7s`Y$Z6vw>5a|;WZ`g7YIy~ z>h>Os59#awL0`(K+x{;Qoo_PWS2))Bq~jt`_%N`PjN^-&CP`S-!TZ;nbFHbZ!JL;C z;{WSunBAt9|3UC~LwpG>BC=36QRb{?d1{k{*Pdy^z!ah(|6(p-k;Df~jar^XzQqmE zXFuZc-t%UkhThOy@ZB}8?a_ zMX?PN^H<&u5?Fti1U-6OGaYO9qrJm1^;A5h zlHp`Rxb=I3@N6ifvD0qYs;oSVk1{1el-KuW&oogY)FWlZfG(P*7F}@z9nD85R#I#NlRNdf(MGRmP zz(w{_<8&D_z#}~1aN&^<#>(+Ob}fTbv#}dH zzz%|UHF-3Vi9eiXel>%!t-Y#~93a7ZR>&--o3IQp_|^ipm{sB04O?6H<7uDUbABS> zfsV|nsKJ3&81dN-61^Iu5(g{(=`EjQ_~EN~6h-;s!=>*mtKr97PgVWhO=Siofx!<@ zOyi9L2p5a7KW)4z`waIl{0g;`ps#y+b@s#D?-rDsYF>#4MHd*1_N_ z0C|@|8p!|~D3%l7h8pEk9&%s@pQEWn+WJbvLZ$FieSKiL>dX|jRj&pej4bqk*Znn= zzN6jxhv!dEt|ZC3RPwwMs?l~v#tYgbu%}{Jjg+z@8%i^sUXWvmV+6v)+fom^UJv!$ zdGb6DzJmrx1j&T>p%X+E?(jtuRy40DEd&?Y_QIC9shqBys%9|5L-s?DM1@? zKN$9`yBMBmz8J|iLMH1G#||1Y3<_g1T(moG75;b~NCzkH70yxvRrv7fc|bt1q5vT) znoVoFO(k1|l(G@%vXKV%P8`Y3KBwRg5tDJ5Y3<=B_K^-N3P38A>5bdH;>3FI$}R{_ z0KH>QM0@jF#E?K930{c!21ZTy!Cqk7lAS5nHwFCUq#}1bt~hOAzNPPA!UVqxc(~xF zUEqo2aVc16HvoLz5_q7S0RkVZdk>t*sJ@Ym{73!O)eLS@7oQe0ekF9kQ%TB|Sa~p7 z0mmDK|K_$o^vYxsmqi7hs5zH{T$1fBm!zips%PTb)ery-`cvvZFQ}&{6b@Q%{rPNY z4-i42|1}Zij}EBqSZTIA(Qq0sf$0n%+P3&fRQI{4K@w=xo=-DEG+j(mH_!j^15ZVAtrOU;yH zZs~l4_+>nvrw2!Bi$?ZCxKDo`j?MK{hkA)h`{k{(^2-EeWE+ocdUD|XF)OA77{wVB z%+hO>|JyHuOwkj^Ghc;MM>BW@MsfJw`P_}-jOt(*z78axAEj%N1R_OrvvZ=x3+!2gyMdVfKwtG z%N2odW{pKR^`8hmBrvA~=0!?g?<@)OJ(-xAOX$F?V48zx+u9Y45ENiA^@zVjL<2M0 zW|W*il{|ITfAcePd&b(1XVW@1ja=_DR!zpD#+>-^ZoYn2(3%~t@t1Mb4f z`Ja1Mr}}7`0tj#)!}TIjc%_66&prR6%FYk?s77yWy=U*v!sVh{j?A_(2gr0+Sujpi z><8b{HM$sQctq8+Fp0NIWBxxG6emC5#*_fX+THr6Ju_PxG7rYIC+B<- zh<{+__RHRdl=t$Qd@9Dy>1jXYuQau1AGdo14F73|^cx#CNjqw+k1_PT;_Aszi8I~1 zh#%bS5AIM81|bW0Woi!*FV21Ueb`^J0D~T#l@z{X$_zIj7#QcaOlvo)F)*=Al34Zh z_8N2l7X0U1+eJqFsqu6GtB8o=mKFw>27DJV75rzb?PBYITOYD5gNEjW488Zqw~FNW zq%`~GhhU>3ERQtuzm=BBZPSbJgCcqM%YXcRORM^(xJ6ke1#(fKhrfkD<@ z(QXT-E3YpwuAIB_)*d7~yIF9gpUK$ogzR1m0*JM*Z-^kJitUZ0?^ zpdrL6+Mi9b?=!HThwLX25V_#bLQ^n2ie1v6vG{Gc^IKF)kHm!PsCx!qT@J|BfuXU# zzo#xjGDDl;uP3>-EeHphwEiSIa>(y^;ttNOb5DnUVE0kS4TX}=f-*hs8yBV4weNE@ zT^ZZl5#nk+rDB^pMZYhOEuRBZL?be;3G3+ z=Rnb3IY{2e4Ne60WXI@5QCmOP z_SVkdxL*N^?yav!lJkU}h4*QX5+%MVu_*bob_OH{scRXlsp|e1@+rPIqM%0nD6nc{AeH8Hmw(Oo5wA!G$)6 z3CK__QU#8u&`Vx*Gl+U-Zd?@2?44Csr6i$q=tL*19CAMZ5;IC4#( zKxofSHu2PCBasG`G+Di1Et_A2S0I=zrKxeXB{sp&rcf~y@G<_lt2|Mwq;~5I{v&Ak z4Nz$3uFyw80lKjl1D4E=e|xOa`Jyp3wfize1k8N5n1pj3xATwl-)e*jv9y7ss&P(w@H49VY1 zj(-`?#M5P*9sdSlb;=l>drfqEC*vy-h*O0Csg_Okirq!~cS2?H28an;C>p(UIHJBJ$d_JD#|e6R91j;O*lx!$jf( zf0db-);m@1@?+#&e%5M+jc`!!z2uD9V#a&lB9mb;KIytfh`upSiHA>k4EUAhA?8+Q zaR%Zd2ug&sU79TIN*S-0@qZv`K1e#MK=j`T&BB;xaI(M@V(NSj5A(wQrUKClDnVDF z66>W!@mGg4l;%^)?J0^18QtJ&?sqvE(&Q|nIwl$}EBlKRk=m)hzdejY-!J~*V=Sf4 zUEW!S^i;ADb$OG;gEk5=)#V_gw1jsU6ZeH@IBUT>CyIj+hEDmmOVP;cOCQ`A(((x6 z&%KT<)<53e=O;IAme;7k`3RI4`GU=6m&rUE>A)&hFCTGcUXT@w7{0Lh(Rqu6&mz0X zj}^=t%VG^h?LgM2=ng1tJ1}fU-zu%6Xz*Sa6ILS7_s{XjA#R1p8}Cke_2#(wtXov@so&z3v-iPXAg4kBg1} zR-LuWZbV1BHg&Gbcw%+x6{mmhB)l?j8EafAlnZ2w=d#q)`E#SqqE~sT@1R(AT<{LT z;&u8ZI`at&e8wU|)RVI_Qr$SaU&97dfH^U%k!63w_Q}!sh>Qt;BCbAE6g>`ksgL6e zA3|HfLDv17naAbrTNHnmnln~N6ki5Ix8A_Fg9+vD^T_pAD(8ejQOeKP7uk zO8IwBIvBBYsSm$F;)=NLFg0|GFpRZa zZ^25yQ0FK|3J|rRJa2(6(ffLL-@mcSRj+t(0%oS=nJ|)y=1C{Zq`?b?PCE;-9qW;6 zW-=`=%vfBmKN4D7W|(*T;2|$Cnd%KC>&LFlT%A1xZ##pvMoyXj`p}4h`AohA|2&>y zg=fLWYT038h%ZsvqcB6$#?XG{ai^79Ir0rWn=NU+P*uL7=w0p$Fjo^bF%GK!E}F@O zR3?pRKlZcS2fsY7Ys%c(GC}2BN9$(n@s0n5z~w@7#&1%^FEC9vQ;Oi5mzo`061C{c zhRtk4$xHY8=VUxzX+n5{kzA(zM>E)*ptC_~pa^>o1HQOknlx#yFekBV>8eM1X^MvB z&h2%j{#$2(e*AYpZxg zdm871Sn($@v;z%#%MaDRh9%oi{cW6k6~N`tV_>?!yyG-*ag>%@>JpQTHNpuBgk=i{ zjV;l@W}(CM(Is@2fE=h*bT_Qo1{r^55rOeb=abPJTPc zJSQD8))`pdA6f@Kvy8%O_|mtCp`hG3zOQnjU=?CGjIw@xe42!wF=iT1x`^?9oe1kj zq0F!5ktl6UA+@x&TEs!JR|m1}Yn?ZtVOd1cdN(aPXIpN_KPDNEUJz@`XKog07fci# zoUu(TrG1@Xfw6DSvD#4$Ha2gFkNtwX=GcGC3{G{@TjEZ z^IJ-0Jb zeXR3lLx!#u@=lC$no_={jgO~FCY!4xw*F$Sw)qqSrfTp_mAl?fx0=jX%V-PtS|avg zVa4f@+?&b%x&gU?m|FoQsg{D z1@%Upq>QR8K7gYG^^Mw*>Pn-_#l+<`I;V6|c{OZFev?1?NJCLgP}MFZYR_yIX#Aed>pvP%PB(GT<+R z2J%EJBo9rmLv`T8Jrfb=6?kV=Y*BDukKzil5Gqyc!4+px)I|YH7w!?5J997*r5JYL z=+Vfy{;Q6ZTrvGQ>zBVtn9!og;*-?T4#fofCnnU}ral}iXFUdM&Y{EDZC;9<;{k3W zp9hh6Kzs#hDwuYQOP>!vFY)fg?oE?lI`&0DtZ$}c%gBGaNJZg2MrHlt_1ljqB8VnV z3rm|u6ZJ&JOB!ze?W`WVBGY*iY6)W({p#;GecNzKb!(OW4pt-aCBG~9cCR9S{DXgz zEyVSwqh(mNxcndTUpTEUNV0ua(x$7$MiYI14|c;>Z@77R*eYcvyEFOOM!bW+%(hsZ zI`~x>b);f&=hGs;2lF?8us1WTq^@$f;ICMaUg2tO_o@@e89ZjWMpzF(ZTsw$$0~$< z9ThIhkjIEGo0_K*E|BvJiMjYl4Ymxm(DWqej}HvPJn2=RFm7OD5%GvyFwH&_qAHvF z#`x}Ce_(El75Gm#Qe(D)fROB((wKb*u@qaK(7CrwUnE3-gQBY!>!r&Vg2$x!nP#x2 z{e`z`!q@lfzQnri=3z0f+nH@cUH@iH<#!(`?oShXsn~7KQ%vYO!T241-YnVI0--1` zjc^?&_Nl$2U^TozV6J!L#-v2U_fffsk*xsU7W4gb+=F4~ubbPOZy|GEE+lR;N|F_Q zeLAEk4rw_aQ?2vRi(%>p9=v=bKV{LPU?rlDsM%$*wn))wov8l)hT;RU??aTuYQR$S z=bjA;mRQu)QY!OEyD#lg?w5A63tPKp1luJ`Z9~r{Xa^eg-aNPPaC$D1JF{Gi(c||^ zRsEw)m4BR=`0uF9AH#$Wt&wLYEe1@+u|sAMx&sp1cVSDC!pTxz@!*_oAvkd-kpzfY(60Qm~|9wv2X`G@$d-;lX_@@euQuH_LgE7r~25a z5*S_`GzhPhBD6n)d0}AhU=kp`d|bHb6M&)>!N4?DT-NvYZ&SQSOqBJj?SXCo>V5zH z_6uLHm=KTdOwz=}$~1~JTL{Nzq(CH z4tX-GFGYUi;=tJB&4Ihr`P}6tf)KajH2+udR=K}pslXqkY>ReRKLP8_dCvZ!PUq8) zm>M_0y6`}{P~VPXqR+*8HA@~mhL3s1jwe&cvHl3s5lLiRelYJX^&&|tZOzAy)Bu8N z{liIb$SRFdiF2WB>6e4$?~~^ogvdW3(k^m?hbp0raq{{X30{A+5_n_Yp|Btaq@quj z{rsL=S(1}?oSGlPyZ;saaGSlL&O7-@mrUY2gjK}i-FwnUi-eaAFo|Qb9|&$LgOF!x z%ftK@1I4>1S8BwQ_YlSxqO4YEi2}P+_jS^_R9TmaQH)n9hohRM!#laM*tH(*V5;Lc zaBv9+{B-!U%TJtqKX201S}}7w#AA=NMaITTEWMttRK=Wn-p)gApZZT+8+wiIDN1#E zMM6I#+|79%^4IY9g(~xc`P^r&{Lr2CYgJf^?=}F{QLxZw$S9yg=Uq&E2{(h4WgHJB?5u{<0~gkC)B%sWClT6s^VCM$~( zEz&lz!DZBwyG}F4BicbJE{RRm-tLro)}l{*lrDwJCBL*%JTHFwm-MF~smW1}O>vfA z`FKs35f6ja%YLP~C5y1=Ye9hYM_>8J$oIh{(X|i9#!T7u)>ZDl62ez}6|+)yGW}Kq zdHlEzJ^gvtgZ^9tuO}?bjq#r1{d4gt%p0gg-8mAU6h}>%Z8m+YjE;)o!)v9c2j8+b z93}#q6n5?nyWneg;~(q){Qsyr3$Li!@9op6w1A{Ek|H^DigXT02uOE#4IoH^(hU;Q z9YdFd)F9p6-O|kO@O;;L*Lweg)A!l;wXf^5i)|d1j_CdtS%3P6YBtp~*|Bu5Qi(VF zfaayimM~N?MXmc^B|M-papz(-g867mYNKpOlfyz&jM6ze4+2COsz={6c^+Y5621}Z z8a@7$LWP1c=1=t9GW99_^(?HqZ-Y*zF%uY897tN%*G2ALv63EgAuP7_9x7y*xUg>* zYwTW&&7Kx!tqzH^qHs`mgedJXxi0>ar)tr7Sz?_^0%$4pi5I8un!jMi#;!t$*71(# zE<{6K2V`%(?r8g``#3*dK;Qtd4fKcV6kF4k4LOTh4d;z3{-<{DWPi8Zss@#v z**2FXuT*jYy`W+b)q(<#G_ToH?=fpYXUG7xNWhvmblJ3!cgavrO zw7P(;{^MVfa$8+`?D*hOQ&fft4fGt^glZ=1?T4q{mMg;kiSX;w;ZC5cU#rXT+fsOgYu3M+N!_uTN!AW zU2oVE`su?E$&g;pMa5H!M&H7wfG@#CGSK(IomjeqD`F__Qi=gMDxk8w6-@pRgWU>9 zvCN44i47eez@4{`xu&-fnVAM~tsX0Y*i6$`Gii5Q|H+z400doOLlMTvHZUJ~+SuNw|BPKG9YX087FbiZh%>2MF4rtOVQ^r@l zEpD|1YA3g~dku|Co-x8SC1+g%>(Fx~nOhkgi^`>9Louq7(Fx5(K*0raE_*`-V*=5M zNUR%S?dE*EZBHkAm(&SjLf>oofOtkMPDJ)`(o`*t!UXk<-Y{6=<;`6@txeZe(uU_E0mXLe|}S6 z-EyNvakiWLMsY6OT9PLVHe|(e(6ym+)i9A8sVvgF_p4XeEzUd17lFN3P)RfCu$Jci(`l^l;@}Uk@m#UB3Ot_RQ$v>d_UU%bbUUy&~ zFKF@|zT@K9k|{r1QmqZXkC4HB@lk&c3iaAx9Cd?nR)T@jggT_n!hW3L{8V)Ic9qcU zY}9@y4-gs-w$(j)?ORp~6d3${S1Fa71Y!h=K_N%}LP%hI$-Hl)SoSPPBxQ5O5bk6Z zIHAfS_P@OAC+>*Wlk$vlYiDl`;ql*en8NC7_?=c*xTwl#$_RJhJwh6%Ab}Y*n$%kG}F>4?fBB#a$D^;D?o-eTB9f;x113qrH14nX-2w6GitM z3pw`v{kHbCD^drg&mR{gjg^GAleCMUx@3V!VOAE$kF=e((3g6V{}Gj*K1%yLTp06- zY|?Al>$0tU^w?_=r!|_cu;6Fqc_-NfJeGfiCGH&-_3ud?RDSMs#Q%&C7X1gf^4vBy z^e4+7s7V=K>>iRJ5HcBX2-IWUED=6+qNq7`D+$wH3opM_L4#>-$#t3pOyE&zUaT(t z3=pOHu5E~meQFjS;XE4HM5f5N9!A+io3R=k3PPt{6-?T~%gM|`PkS)EAZU^ZuEg-A z`Nk=-uKeVY>k0ZKWz75Rsk+Dc1C9vUNkG*6{?-E(L$tIR!S{s`-2V{u=!f+NG1Q*2 zOwny>yZ5}qkJsInG_JA`2=iHNT*-Uj_%>@tK8JXKHBG?yhbs87bhS_(fw_p;Ebl`? z;zQl%(-^SORi4Y%r5Kl6MTrcPJ+!3@ov3)+DQsa*)jmP2M6hLAna$x9KE|4{P>7S2-d= z#)$2@j^0pXdFcS0dL@)Z+3$GewbG6i*r-)IMRxMrz*uKVmD@}N_@1T=A+ zRQNwWvp4*B*(~=hxS3@PGmGZ7(}15|G;r3te<|zgoT?uL2P4vUqMt=tZa>GtC4Jn; zEn6qsl3w9L-l-#h+)Uw8tLVTMO`Uq<(5Jbzl^I*%GwP?d=i84Hvm?J6g4OYJF!d_m zdnFPv{>^cI-!hSvzejh+iQQuBq z`?3W`AWd_x3lCF8o>rebTe5UY;^&knbMdVGP>D%hi;(AE#3-1U8RueP4mpSrhGR?=!?@&(I^5w&BwL0Qhg8U8S zibUz`>0B9jKnY-%awd);VQnSdO666N@_luBLD0u7UmR3;@N2F`#;2C?Qe{!6B)bb! zm1Tao#O*Xj1Mo=H23 z)D~L#x->>vZd9cm32VFK=WmzrcV9rrGn5t)!K$d|@NxZ*-_(fF? zMD=uN(T7A(w+}f1(XQbw`1C4e10o^Fq<0+sV*$E9=9>zleN+I7#}mqua{bvRUIGo%zY&0Lyr7c|c>zsP& z_HFNumG>GeW2_1CKjVL5Tx~RRtuw(TQhtdj*ekAa zy^J}3cE4OwBB;Hv2n!Rj|6pqXW^m`f>HuoYCJ5DuBCT?I#U#YyH|HHeuCSwCl1mp5 z_}N*C7NtyWLRzg_uO~3t@H!9v2r3j?cl)ssu8vu}-?Q@a!T5fYejHgjp!JO@YFf`j z$#s;ih{{tn-gE`k80TK_*Esf+@BomHIt3+B<%Ixf*Y&aGjU!WM&||-z@%hacHQT_E*H9+(`z`<^C3Z{7?8lE^U4Jw<?LA-!XM#ZzgsMLt)uLq+K z_N-$3sk5gRK;-^oVLq(32Sn;XsrV>6ar*t0lQfaI9_T>p_^*c&5fe8!tq}XH*!qX$ z501nSh64ei1VnUr7G(X*m~Aouf=I!nseWA8sRtF3H!mb&O?^az`_g5CVmVMQO}Ken=5YaxjPRi{(#Thicc)Kn5dCtRXpKdk{I9JluO+Av(MWGkfZ9E<5CKX zcDMn5k6EdEwKDiC2tyHNScGfU>D|lgnk7i3IyDo*VR|gitn9lM{*m8(5B7lSI|)bO zn>5avDp4+9`X;8q!G-JoRElo~f^fMrIVj0qHl*r4%)ETEVk)xr|0+D#->MeUTOT}8 zTTxzFGUep%!IwG8tCmEVA#NBAFgn-Z`h4_}9IwZyKYir}c4R-=KSj8rMP@{V0y}> zGcqnE9#`Skr!)g(F4<|t#QIlzBSiV;;hW3W)n5JG>rz62B&QwbW$b=`#<}hkFUQ_|2h1Uo9sQ8bD8N*d*WEdlKPFS;~MXQ^#t;4 zA#$EGAJ{**9OAAyffTB#^Jn@392QU7<)2kWS??+nB``82PwFr+uks~3C-NsZg(dYdQi1-0Df?-|8aPo zz9I-xSR8x8SI=dxuhqGO+J)JkRAmBSIC}Q+{bv5;c;a&bl8Mp38r$IMJ{lZ>)U1ze z@~P6&GF>jxo7e}_bKw?R8Ban>PwLD-vsfc@r$%7?S}NrZxB<@ZOVQv7i(|GxO2_9? z%JFaJJ35rkF7I$yb2+3fgKEYzH1<AbYZMS?=jrU5ha3-^SF_tbv#&xyP1i}I-6WP`#Lz--9lD^dW%JAp6lGdz8w+9Ydb zD0Y!x-~OqD{Zy-ifw9`JNA&2|>NjCr938cr9hHWc!Z%Ffqsd=lE%M5L(hBe07H(C5 z&Ccp7{|ta(0QB%BA#)S7%m)ppJj&4y1U*>%MQ$+XjIma*czLQ?grbAZyz+q|uupOC zON6^IS$Lp|14UeF6(WFCLH_|@pg29lC;76O9IpI)3#iWQLqcPq%z|z&@ZC?uBBv0> zKE=0oz|#3RlS%>OwLaAT?){f%+aA{aHXZU5vR~c-F{a{U13eitnH$;0YY2+|GQLL= zehNNQW{cia1KST0Tb*t*xgM8VDP*hGcjX>%7Wug%{4G>5`&X@AN6L?$+GWGREJxvf z1PH)Ey11#j803aEY9H*i8C|S!C+?^3T?{aKOq9-_M3)WDA8)lZfgoQP#)3I??-cRHB9xv7Z=oXQ>QB(DS~fgE32JbwOW1Xo$JE1` zeU5fH+UsBhGlZ8Y<;!yc1a(-uI5f^d*Fm14jj)x8N1-4sNc+9V8}!?8?F!=)sl%KR9jr>CgwUrUD>HJ02Afp4Kq{*-(uNK5E?jg zmZi+tP>MS1ot05~3ez3lNK3S66aLU87WO9kSwgR1yNL(4TtUnS%dW#$WVLxP^;4uX z1ePoAh!uC-Jw|sbZQ6MebJFyHq{niblL(Ysso#H z^KBmo{pkq5O#kgf+x>*sNwYFwBo<^qs|IL;Gj0;FP-h5qv^+(%K5N0og~{!JLIW`G?W7yn19>I1(Zv%h#f zMS%0h_Xk~~YSC~nHK!<-+6lzZDo`+J%D zZ4dY0wkn{hOq3!9f6A1;zt#@vf3}Xy-cny9VPjfd#jGseUdgqI(iK7_-Db2;x|hP}=Pme&qrEQ#S*8mmkX-E0zF zcaf1u(OMuWA_;Oy(1Bsk9FL9ad>J7^t%hN`KOSsd=J#O*i^lxQ$}3NGyvt6xTe(5=a?EhVJk>f0*S-C@Cd$2O!l9-~p+*3{1~Ai%r>KDt zSA6*4-R*ph-TXsAwv)pZ_o3LUOfhOost<+dD6F(K0N>n5tmY(%CC39x>iTwLhaU((>Hq;@or=KX?255@>KHAs*a7v?##Gm#%F9`aTqI<0#B84e4h_&xiKd= zOW7kv%Dm@6Urd8~bpX(LaE%nP* zyDg43|6Bo)ZJqcSj3(c3Hc3xy_U))M_buHN%3#@z8APqX-twj3}!m!A^e6L+!JhXK7M|3g)UUqUOv}vB+la<&QSWO`R5?imd zMAeZns2~_|HTuU68`zSBn~gi?zd%)buZ{bjy~}@h+g0T=;8UDg598cKWqJSDCGk^H zShUm53${8B;Jc=Vq>3s)(F3SeQU`9g1h-NYHUy*G7X%UOv&zK>Svlmqf1ICMUbOlF znjI8)drq<>pTj4BLE9#}zVrM~e4VpA&h19*-djSMxJH&!8;b`bQt+BosrxPo4sI43 z{cxh@<(hpG&#M_YvO#gTj9iaH0+?p4nh5GaXeBB+7(@+qhHYX}d<<1fPqC&o`p{tn z7<9kM0IY%2GA)1G@yrq+-6hQ&5$931TyPQ!Lm*FI@#FldU~1YOrW;VMuvx%T79%{0 zjWx$5`qph?x_tTi|#$h`bE82b?dNK13kV4EMXGDbkpLkjtXtv zWL0kZK>LAXz5?o={T1*^?WnJIK+*lzd4^yYPr4x<(*!Wv2AbjEgEV`-oZflBMVfc? z1t^6YFm{D=fC#{W4cAQlg;g!qa$dxT@9ij7JHDpE8{L;u-b0FK;iLIW?>>84aueat zwWcITZb+V#cptjEAD$?JOMi4+q0EEeB@84Li{)?;LS;B%cJbBDAYEKa^s-aT{;&Yp z9rdF~vG8TdLnI62uD9hz+G9!3rLLb9P%Y0IR%C{16bR8Lx* zSI^?{W%tlrnqvz~#Yp*?8sJL0#M5Jf+Fl%bn9|Q;S0-*re^a)KPE+MO#X$*L=5MoK zr9i;py9LSKNkz~6Y<(N!Y0iJcI(0K);z@wTVoBF!!2pe{vA@M>D`6G1nB0Sev$@B- zbn3Ah(JIvLttL_?41#14;yt}bd8+eqb3VQA$QlnC{BoQubACy`{#c)~69avF^$BP% zmb`3q9O3YbeI=ZZk#fd4_N}+3P;71S%=Vk67^~Ul*^f}#)A09I_E*Y}=Vy#)$Hn5- z&zrZ(3_>G0_VqKfLS0?dOw3{+mUxbH9@jDGto0e#HKOCo#X2$757vYP?YAWVshp%- zAQ(Lv3GVK&pYN#rwmHT0sK#X52Dr)8`R};}!^kttQ2i$eC|DMLssM2l^j@(8X};d9 zEuBDX@!0Sp4M_?boq?CQF*>JxrEeAMfV=pEX$bJYKS#@?x!`IED47x_>GfoyxqiI* zOfoI9@)i1kXG&#}6x}>yX)n;hX0O|@eWUF`_*M){s*@T>w7~$QTB;hQNcCxDri%%l z7JxZ}pP$BGD+)Y12&!;I1+V>ak>nQY3xQ;o$%*u#qrQCTs4zJ1eCaBT5;7f?`%F`Dxrm~Y4xFNkktl{E9W$x&@M8z4UXa1j>z2S#tiGyk9f zE*Dh#<{iZ;kCkv8lc=9`JhosViI7f8%9p{~LB`YyC9bYYb@OI$9QI~l#)~68L5b)z zc&Xn2NdFgSNk?fVWu3skSWj*k4&Dkjp+|`T0%F6YI&BJuHng46ol(Z!yqyR4Holgv zZii|8iry<_X~Q?|C^h@~x37amOa_@ID7_cff{cFI=Z1PH-4|>#1K-797)kM|HJEss z@NS4;-s_d)-V3jE#Qn0NS>51^2w9_Xc(_Oe>bB66Og^duBhp2@SLzeiO@Lyh&F6!MxVRTkY5_%AN4G2aV*RU7}JSyK1=QPh!^cK-ImxT~btWe5dX zin9unAbyi`Sbx%K*|-zm;Du_IdgYpA5o1xJ?xXGd`0X;4#tsgJh&R4D%uTjO9FIDM zLQ7oKKfR%Y@QY2!z#&?dJQH#u#)b}<%RU)q+^a>@R*x4Ihvt=RO2X`~1EH7KXYJQ(Kc-s?daQ4^Kj>SG> zS8sy8av~U3*553n0xee`P%rgU$Mt(t1|`u`Oxxp>_c4-b7 zJ%>U6d3Gd3Vp5V5Gs*^~P^n_hnS=XF&p!qBvk241>_+;&Qj1hYeacBte-#EY{f5O= z;22Xhak`T(@!FtXL(KbBCk+u66;2EEKR_$k$+B7Ty8XMyaL2I(k_YTl*ejt+7xda! z+ZWl>Uvb5cK2U9%`~$81lo_b|_Z9Ca(WffF05tRqI}Jl%JADhF@qZz>7}b%$boq#| zxZ$rTJ_f^F@IhZPq)ilHM&1Og+DABxhj6L&fh`f)6C?#LJ#r=k1SLBp#r|^srIwvq zImo}j4c$NCK(>5?fQaadhW;pptqpo_{e9TJ23db~PSy_L^tedTUuXiqM) zG%iIOTDvc}MOxpHHOp|OM@DMUqyW#of70oNa{&Yio`-KTHTfN}loL7_OXb*>4PHk; zmYu7GK;S*CUJ!cw7n~OeU)Sri?PMFf_NuA!#}8s(dNNX=MiQ`>2IyyY;Q}W5V9}jj z!nL2{x7@VXjW}RrWRXi&%c(VX!aA2`S=2qxn-)=jkJFa4fmEWLN`R>|C~TpvpaU7e zX)7lGGyd8Uk_ljTc@cVnJ0zpN^C;It*SCP~2lw|*E_XRG?6&|xp;#OqcFQg6QiASP z2FB7uhzk)hn1C%TE@Hz+|A1HCVX209p7DJv7|1-Oot9>5 zn1dZ($Vf2D^SGvw(Fhbv%Le1QJ^6fCI$6;^)n<+-1w@e6)p(f!2ey@;4y~qz%LyC_ zAEiwhiK+^)8RP-d5pA(yyYzB8y)T8QbgdH2Y9YADeY%`#!z9)ewPh&CqOA1;KN~=b z1G|IkC*alot)-eZ3fI>733fkZ1$F)R;dT-w2Fn?kRYqb-)1tIoW;2MmyOSu6|1Sya z(?qCILgaz5NFbY`OEi&}6K#cUoF?sQxMT=1SX*NC*j;f`dEz$Dcj=$vdY5ZfsPX`8 zvvoH5f9-UPH(keyn4)I0Cn^BVU&s;GE7rSoCnf~^)i%g5<^~tP=crUT~7>BV1w_(xO1X#CjC@Syvn+RA{svZYjxL(;ZX zNKfTMVjgWo*g8f{hTl)4iNVZ=rjq?GANXtI&*Xs2m8***-gGOhqZ>K9O%Yv99HLm; z2L9=~dcQAylyOr3ez_hH504{$`CW_w13!vI%(*!z-@Rw{U;XX9^9#WB5O8ZYFc;2K zmA^4Vz*kmEmX`weD`8y5WC~JuZi58mpFIO%B9QT6=DoFc%~$2U7~MkJb~7i?_961V z`G?+CQDY)j`_zyw>Vh!g@gl-vXOpCh?Ri|U?Fh=dHTyRT8ktwrfs^rAwkZnd;Ap zRc@z#d<1g`JFDldZo+(kfMg048Vh2X1mLR(le#)p`q#y2!{uK#0atGEw2nbnesg_W~EA?{r(Ha@PZttI=zR{9#K0E@vG@WH^O zl-I?qxpsIKh$IRfjB~Y$;j}SM^(6-D8%^gntd(QDrEq-+mmo70xZWO88xWE?M~iQ0 zX;!E2_GaA56E41stXvd)ba*smOlw5!RK?V3?4@HEy<$f-kg~epZ96BS5UI(FR_d{r z-nURz+V8o8m$`-d)rJ3#P|zf`r3=384oj;Un9w?$ENAuD{|r>u7V={&Jr*P-ozMR5 zJYttN42zihk{E}Htw-$wSM~DG7`|7l#@G@5>l-cDNJ%G`sD_a(+)^)>DuXa<3oA@*n&VMD1{K#@li= zK}cTnBC^V;<7SHPu0knttM8AC+veWT`Cdmh?=jsCHks@VEEBGDlz|)76=UBrkJ)Rp zr6|9ZUo5>BM!W}dwuW?PUrl*VdA5*^2-=Nm%TDrH19kpCci47y&~?5~om-Vbck6QP zKgR^ENA>m%N(*!KdaUgE{=M(kN3-=na3?jO*bG2?0QpmQ5(k^f+r%<{l``+|WjP@h zAz>e(P=7bU67@bSmN6jszvjMrOLk)p$^3Zay-M2eFAtWa*dW6+NOaf&IpAg$me2mw z8wUm}T%)8PPZ=}5Vgh%8>6Pkd-_djKS6+nBZ-aqwIcjE%TGi4dgkWQxG&$L~acR5k zm5{4Ov#cI>xk2}Crr(7S;-^NP{PQ!F-(uv(xQJOrC4z8bLPWqVvp?cWvvw|X{*Kzo zN$6l~yfEQPa4Zmj0=CFHcy?#5qmLUZd;KaV&OFvOR3sU2xcq%jh6!1O{e0n4MtSxk z_EEQ9;onuG?gi~>0o#tBSbJow9r>8~^=7t#O6vZwP?s{reGBmTS;HHNa^@;B*xs{8 zesa4noeDb-;!GNx2Mb+hCjVK(4>M;6j2mkqq7G_ znm)Fs#P^pFr^XW^%AZn+EpN-}bbSN-lrhWqeh@%{2KvHublyUzcYxfUooQi1x1Den zRpWyCB{icM)PVLzKvuJKt(GDp4x+k+%<6F#Ztrl1iDqBNwQIdbyf`}tJXNQ-4mGOLate_cgjC8{`9#S ze3iL#6`Lmrf9+-P_wAF520Im44LqnD6-h@wG&jWovYFz&%c^MP9m?)a%q#S8I*P)> zw3&WZ_pjC64-^3Q3x(TYoSoCl-(mZEvcEmNCwb0*5`ihjAXfV!Cr>kDAM>fe%6@oDZR^=z;dH22+ z>*+X2Vm}`~F*6kY=+?l%rBH*EHpk-yPwe)|)r}g(e#-l!)8ZX_oO#ohy5#^X-P@~} zOs2&nb5kaDs7Ab8M7>u+0s64a*<~L}YyxKZ_8-hyPeursHRDfElH7v4PtxxV*h|z> z*MXj6ET!f7uokR}(B5G(TpDla#UAEr?o~Gqz!U$r$$x+FV8L!K$DPNf;97Fdqd;h_(Kt)I^Ln!dFhM^`s$V{2EWC{cX;B?e?U2%O= z_r7$LXyUNk(0BLZS0qZ|-;C0pa-l=od@Xp#PW~1rIvWuy773NzoW#-7zUrd3eH02& zk?5}`u+C(Y*Q%l$k^{_n5N08nf4Kj?U#0bVkg-w--LaKfXQ03^ep(-}PTa+P_4uge zSP=G*jY!T8YMSX<4jHhkA}5v;tc-ONfuXB1F~7?~-8QTVO`mZ4GuDWmDR4n)1hmjH zE;3?kil{EC+`+?ISp61=KUpI1^6$tP@TIBdQH##q0z1^U;1$o6f65smDaDbiSUM_} zn`;%>L+#ni^L*yDuk|H2Dnc8@g?GmtmsEz4G()$(I#t`JlW;}dazMu<>qOPIYDr(J zraUg%V^ISGOu6Eb4ZZ3eu72Y;Y0v3M2lI?tz)yM;NYM-!_yNNVpvbs##Jb}f%I;xD zyc>{CW-)_MLUMWwfIW|yMlBZ=777A6@sN~BKY1YF!+C9ndDKc~{hNmi6c%P6Ts-$4*L~nbM6+f?|LVNXbrdjWb zQ>SYbqt)l|#d7v9GV@8-p5Mz`)NoRGW6;W5+Nb;VqdOC9JXxT&XM&0L;(-4OIvxGRnTAc6Aw@rrs& zmruqnf7RvLmo`!2E1SzB8SN>XRP44!I+jJS71Yi$EImszuS^n`po?WiVg)6_s{EBC{%UK{K}pOV}`*S`KrG^Sj-= zh-;j1+8!YaBpn=@)4YcBSB1WO%y7ZVu9@X?e-X!<5A|?O*E;!YlG?M>L!PO(K! zKS6H#u1&e4)wQ^10cvC4vW#r>Mb@?p8`m9MSW77Une8U4-)L2Rs93qv;{Iro8j$te zs)dN^c7$`%V~*NhuVSbIDQ7`ZwA-bXBP(R1`Vyg(FH#CV(#4ez!(69yg%nE~_{Bo=e9`;0Wo|il zZq=D@w*i9H45!~W=$qQJ9*9FBJhAdSA=RBKpVw%*R6uUZ`X!`r24eU!IdSpVpc%vi z8PW`$IJIE>^~B_6{F#2IhpXixBe@)at?#@0)zzK-5XoNh4#>}TU>K_|Miz^)4tgn7C1+n365wheZ&4l?QF-l#u_oEFFNxxtVZ+*I{b#n+t===;*gTr=TY z#6Sg?7z-`)j($CDG+MLkC-@3{Rp8hYU`Dero`UDsnoqsz-0rQ}>hafF^bdfR&y}AX zh)TH|ANqArP%r?a6KVl>_oaY}8Oz&vjO?w4X@FJ1$@pAlJfXDVtodYoy7r|bP-Y*b z;#+|EO$HKc1B%nOA3R0b056nc^=RQkot4KQSzpWfiIx7Qk?Bd2!hf_#^B_aNZqiW-)DITX7yZ(mT#y`K zc-J)HzW!t+gQ^5wDB6~Lw$pZCzl)7qbBY&JBVI)JFClZ^g`wMChV0v~O^&|S<7>DKst2hTJVgez1VpdEX%;H(eC((Xuf!~r z2WYJ#c>Kl1PUqt9yyhvC~n3yG2;RQrQpXsMx02QL4%;|+@q`~*?-p6z+w=~*;q$h zJ&o=Ept_M=JgfhzAc~gOu!;4lWcX9dw&3GRc(3PoPLSUMcj_>MnZ5QeAjibxDJIXz6^1SUM9eADL~|QBnY)o3ycEz ziw!5fXyRbTZKMHq@R7((5XZWT4cBPeexDenN0`Ip8`c{wohtV!`$wC`g#_u$gOi88 z-t&VW8xyp{E;xfhlqPl@@?vGcfC}l~zg>JNsXh`LP2d3-Vz^qtvI2GD-h>Z&rDdgV zi{6TTH%z+I&jBrRv-gS&vU1=XP(hb7wasAjZ@2JJg4-MPsM2`fAssxW99HAIuMA$= zmiOZl<+MW9j#?V%bCt$*&E)D=2-JtFIs)xs1Bx^LXPQ-yP8YwzP5hKl2}jsJ<&}$O zN@1S*!UmOIWUockNzmZ;i>RrYYRHn>{vy!Z;;`%a|6nY>=N^^+3AYXxP~gu$WLx{r z8$Synon+{ub)!vgSVv>|AC!BqazcEcda$$PIr`D>l5>DoHv~(Z;kEV!1}3#KA^wdU z>Ng&@?}!Zq8N|OYzS?ilFl4JdQMvhhbIFgsUrheRBi6p*CKT}h^ft&+cmKjb`X8`c zk9&Esh`U2JGE(q+>l-N@4%%@g5AwdYV%RZb9Y8u*an8~|rhxBLSVTjaOIDmNSCq=J z;B`Qae>(8h3oJNt3nTh67s{g1F&e5a=&rPkR50@K^Yh}i$Cu6-sh67@W zms-7O$(|(0{-79WxD@)-&(?jSA`x0n-pa(upKvRw%#f4BCDcIuZ`jk#65vlT17?iJ z%qK_;p|~m|;214?cz#SheaV!eA50~<<93psW~YY-V3{YYr z{OgfFVQ!7I+OpWRsla2{^1R;@JFoY3ROcNHsPc!SQWD{yxQ;>?qNGtF%ZYxI2Eq9rdx^__gdU8(@I3Mt=X={>NHqOP1m$a24AhmSrsES)$OMJdJf`i zqohTWo;-A*4qvQCV* z3JwY-L%!CIf5MQg|8W1rQW`+3TKi(^*xr#u`+gGqf_0%rQgi};LgcGGf}708Im;}^ zj8b*tHQ5sS_}BY<>T7Y!{%zfCU$OO3c!X-8obehA>n&bR6Fc)>IfC*iCa++I3zajl zKAHO0dsYhfKYbpr$!~qLTIqsE)Oxr~CQ|Qa$gb1Rs=Co-JX24bsEQcv{0Jk zzN-`yn1$fIaopI5?gkq8&yg;wlW_y7`k#40xxveFNy}i_8|)K{3fM zap`LLqUEJ+yTn|f0{ZT(-WLH!ig+_S9%p{p*4XM&2XSq-%ZS;aSBM)LNXY|w z@(fS*1bLhn%=AS&8P)EE{%#Gu$fYH}hBoEGnReR@sB082UoQ#w@dsiXG7WHzt{UTe z=Y5wksXq&cXdD-azB%>~7~Rubs5A_?#lQAp4(T-8`GY;gmHkpGhPsq5D4lF7iN0@( zim1H^q|Mjcd2=8d8jqe1fnUBHA3M{$Q@~&1ev80NhIrA5KPggpeLR`o(!#KdL^jjt zaKd~xFy?*~E=h%@4p!EKYIF!CTLAN!QZ^Zz{6(B+sp94}~Z6%N17;LaDq+Uy1Ja*^{;iOwW}^~q{7&&*$FC4J_aEb?%= zTw7|)x#haLrSgb12p9pErOKUyUP^?x} zj1yZKg(r^#n$ zVpD1~Br>@eBxtI|XE|R-BY|<=uD*8tIOS0P59IiZPpWfMeT9(?no$i|oSYtmeFB@f zEN-V%oZJFbpI%Xi2!M|@wis;OomNZ=9w-I69P2WXGuMCP4LBcT9(3)V6E!D3| zix2q*sJJJ2-upr<)4;L784Lx|>9obql$1bA1HT%A(%s(%0NFHhq_rCQP1HoPO@D7% zO}*NuQa38qS>fi;*n+RRdX`Qdp}Tg;U48fMdlVo#`Po;Y!Zu~{zvQb7D`n|2-eO?H z;l0Q8f>CyoeErTTs=L*)7odfspKWg##76nS!7xa9#y5I9oI0ZAY8$fBAZb9`eNP07 zLCRNWD&zwB_8FM=3ZcV(fZrQj1^Pd3Z%{TwxV>2Ns^$8N z$Bb3kTMkXFotWgg-^I>!6P~~rzkJ7Ro31M@OgpFQ1=FWL7hX4rF8sq8DQi?7O=9wJ zKOGZTFQ4kihv=Hl?3AE5g-O#)zCX=s2}qZ2RC8$;xl{Ci@IlSS2pHHw%ly#b|Nv_%ISSNtXY;Iv7rRa9h?Hk!jnP8mw_+D${0Qds$U5bC? z-`3ji|5$;jGZ~g^-fn-2K6abgYa2N>)SF&dc$j!~9);6SrnXEO(v!Hy^2o0o&+cBw zx%2v924|Oj1of{xJoKL`VwGD{83x6|?{%^w0THnz{M;-^|$`>5}MszNeL^HoehglRsWfF0IOmGkrAu%&O(oX(JtA1bY0g zk0FT%XqWrpWhxsQ$|sB*Ap1xpZ z1wAy&F7x{!%eSw!heXD&H-FFGoMMP+3HXfE-#Ik=5I#fVo>l*6*d|F#jd}uJTc=-t zn>V$m!;`KA`65m#qgv_|i9xRQxzvyXlEr>%p(XrgDf%#EXfzRsS#?B7Jz3b%>flAl zo?@-P!9d3NYCP|E{8LvpFf;&N+7oY!YE?}0R)yj^Yy%NUFnP0?pxY-{u^d;4(ECUA z*0ZR@1e>((G_eR925W$I)FXC@-j)!IyvdiUzU4Q>X2O$cl#j;tzQ3wm0OizOqO}(1 z_3SX(+*V9`nHhHY+tFYKhR`5M(|?XVr6W!x{FZqdC2aU)qZ$0L>4x^(S!TF&)rLQRaXSn>@HLgO)3f%q`ALJU}9S6tS zUI$*QXNqiVNHf$^&4uIDXZZ?zN;vyHq0e)t&sP{RsPh%cdBs`%TfBXc=V(fIUhX0I z%Zq|(fvR96%)gjyXgHBl7-V7+S^WNxFFIhNP>SX+&hkHyS5Zdx*$jnpkmHM08!mkw zU1Ym$=JAoRya@0otryk3%<-T20GHnr7?JP#&o+#}hKZb82lrErJ$gq*>C)B6%Y0wz z$blPkiW=!xH5sw+b2W~3Yt{a7&F+`v#ExKb>GA0rcq)N=#-9c0MtU4jL6(#Vo$Rkx z9r=38FzauR!YIC;^c#750iug{6bng0En^P; z!ALA&JQd_=-8uDy%H;4<-3LU2*B#$1ed9ZOHpU9U2+TSJ_}-&*Q&G@L^1qxa|00|p z<}dWU{3)CiD*l)nugdlbR62-za3nBxd2u2EJo|4icYnRgAnmr>4;MMY&G2-MnmRyp zz1N4lORESN^4>;YW;gBynNsZ-lT;>*t9+aLf)h^`)Rd|*|Jb-pkt~t#0v3caQZcE zP65_wQ%o>_^fV){_c<)4R~XVBm1TRIlR+i>pm2v zcWzUXc&it>D0Mu@?Tj%uJGyILc0&Z8VlY^Emm3=lI|Q<+!p{}W_&Y$?N^P(MLSE#b{p2)ye3lJDJne=;%&L9yt-I?FW?{}?qWP2$MA8l5a_}S zcO)t4qcCr7r5Kg3g{la3}a=Tu;V_&60S8BQLwm0SpE0i{HJe zH%)hemN1Qv9`XGAv(IIiT+eMut5CR?bpei-sGk{pdq8Xmam%Ht%5H@Bu6%pj0R+Fe z7e}gcE|6w2Zv_X#DbZSquxzO0e^KBG@Q5it8K5e48y{T_7P7v!5&K&ymX4FGa4?_! zkZ{6;KWbxhXmn_G>(Mf?=(S8yruXrr`1xHggJ z3ayY*ely_v@;euc%I|^H&4U{@9sVkN&%_>M$8NpRn~Iz^?v50T6AoGZF@G?`-ENwB z=QR^bX8%QwZ1{lA%2DOi0ZGA;0;knv?IIhaz?%iHLLcNMz5O34h0J)^zMm$|5Yj-@ zhzRzCk~AtzELtKVk+V4;7iL;xQ=gx{kl9#B9we7d(kLE7m1T&~h;*+Y3z5!e?#LM{frIBvg3H%Mlav2-` z1>W^Z&RaDiDXGv*V7|O}$SWv%Os2B@&X%H^VqcTk%1^@i()|1U81gx5Oc;=JV9wl_ z^8&b$3XZ{ld=aSqusxsjpcU=GK>fXl7mv9pGF*VYsYo8ekj?&> zFM4cf)NC2uMRPgZ9fYZBCR4u-YKmJLVu^P{HqdRM3Ll>^zTB0Hx=E7$;8 z5MRm+&?7eq(xk0#_W8gkoPS<*u+yT|Jg#d(2CSrvYrRlqBBqX6QhK5gKwy`ar(f;% z18zP;-^2%GW|#S?pL>OkH2>t=K8Vdsz3tA}5J#S1>1PLv@B0A{j^IkV*d` ztM;3T{qVZFDVCFjaq-?pJ%=Y0;aYbe25d&ub>f+KSf`Bo+9qsJ8A7!K{b?ERnwoiZ zmV0F^yRH(@^GwWrCHui>U~*yWd3ATGAA|o<9Nlba_(y!nj^?Vzw8eFbLUH0^g#7tR zE7cmy?ENIs#i7U5ci80f(NHT7oLk_NWcCh%^WC#R8Az>$3XWp7Ne#`U9qJ%;_RZ(M zK_zax@iKTtjl$Jc)Eubw!s#_bMJR)&T}nte-Lr-Bi_7JE3j5AX+Xy^l2*M1S`!zl{ z7(WdgBb|xR#nvq7^3U0A!u1#ufr(P!GTy+}UUtfxPOXc&@Wo?FxxFyiBg#$1O8kp; z)MT>CuU*6vZ<2yt^wfiX(#9&La-0T6@hk1>i<2bHrLz|&h=x_9oYD6NNkh-YlTi%< z6Zem>_@us~Ip$MT+@lABjOZDr?MYpZ9b5Yjp1~bDBAvKbb6L0a=hY{#)?40v8>;tX z>IfrMG_Up*y?k7-EdcYkp21I~QolWN`T)|4I~FNav|A_pa)V}EO6@~eegB6C9W4qc ziVnk@b;%;pg*4#eQqV-eCx@hmd3%_s+sn}q@%4hFG-2c2mV##uTyhX;52%A-Vfn_q z=spoufi0~1${Jg-`0#4bhMI)z9X4rfW#9Xt5!)?8Z}H(B^^$91Vs|KABLL^V5MkSr z?C3irF^+j|G+IaXn{spTY?&<=$Bk@}^n{q(nkBZhcABON%*tbCrhR}IW&jSY(P;XEbu$3HaE zm9Sc~2FlRky;QOH2QBIE+zoI~t?XN^If-gOH9vv2!kUuT$!E?i$9z6%Le*mH@cAa` z`Xc*#cCg|biX`f{$-GHSP^XX$aLb04;Z7rzA>2C^$EryHn z%yD_>He;`R?4QAT1`wQ@gacU&8T_T%U1!;b=%xiKaMttlBQ`obus+bLd$i-_;Kp~F zaQM&^dh%J2n{9HZ;eW$?dN3h!^f&*-%!_)z2bzse!bP( zrzt`o^Zm&K^0Rlt3$pSBF%!iGbEg!JSGA@uHPe@Nje41XSrO~RIPK4c5nMbwVdE5& zbFL+bZ3R#W&Pq8fABp+cwE3h(stY~m5asLHu@FL=)nbrZj>rJsB`*s zU`n`TWkv>CJTF^icTWvn4KnCB`nq^__M>{$3cV~EUNP7Tffr_Im zS6Po&`H+K>lThZBuuYQe)ZtO^m6VW2c+&}|crVJgQlP4lfEbV_$3 z+-J+yu^JM65`2Ma9(<(7pHfn2_uK-;ZK!XdaY=P7I)Snw8>mVTXkrAyHlk-Vy2f8y zLsld*U?4=nX^a*HoTaJ~a3Ox{{S>2=|M}UUvsHIla>rn*bi9MHpoiu2T)mj=0*y}H z7}1W)*}LYIAQ+S|c?@hJ<{Zt{=Kk|`dV$+TZDZSS*z^sFkp4)acY;!o2=P z=jaI$oc}#K#=7g`F~vHF?DP$tACdG$Kj8m3NW(vcO@E_cyoLh`;q{j0vM++EEB3`V zaNj8r0f<0{Ml_;P{jJLSutsxp&}(V(K8c%rC=}on{S4fp%|A#d{CM?rHK>!PKBd2r z^8_NwF3b0JSMjEY-O~4){FIDZ3;IfW*&|m3Eh&GE#-Ob+bU;4JQHc-G!8AVM+@#w% zZ@7Hq`4lXzJ^ojFExSE1kcmA5dOHJVOV&2jbvVM>Y*28b>I*dIloMDkDtu}w?)7fnw~;+{B4-?7@z!3R^$ z2iV7ZIhT4-up-*`eoTg@Utu-LYRlZu{d>QC2x7x%q2^ya>E*v}JLHP|U63H}`=LEU zt*kfDqL`IxdbTIgU8w6v7hstp&JVF)Z`fB3!8TSXfyshoCEsDR5dZV8yYC5tBZG7Dh@ktbB`zJ zQ!-Go#Av*RWuitC1kNo*@uv$^(@M8jG;PLTc^g%u&F&x-(}J}!<4v#0X#vPNXjY4O zOqtlLIRNT{zZ8yfdT+B_^;LKk4(pMUcV{IC=b50P9Ba6|Kh(j{baI4s`)`8jF!se; z#ncsR7v(UTvWxBe+w}^qq0?sg2uj9-q}MP@pdg)JnWM&2CiiwU-M#TxwzQ(ThO1p^ z7SN7Cua#q70q$k>X%lQRaSg=?a>0j!t% zZ_QLQj{|@I#!m)W=X0_<(ZyVS2sfHXI8hVj^?^8Zs>6pYdGRM=c_k`*eYAT?Ew#`9 zI*|AM#=-kc^~3-Q4=9XF^7^g!1+``6&vL* zMYo7Ply3p-d*gkjyn@*4(AEo_czyv3gl0dh`n;f@(hNZCT~DWpp-HBu^wUR;gFJ=q z#rIUaEwyZ+@?soL&vQ`v&aa%j&45ySORtQd%Zt^W{|(4MwGVID;cJ`!=Kl<|f?IE@ z%$c@ouJFW3A@_B2HAd|gz>c!7P3YN~uUhcrP96CuC5?&?`_hv7vI~~mj!RsVu-LS7 z_M;9M0Asu6L57uu^`xlpbl)ZOZ(?6lbi^tLoJY}SaJm%Nt)Ws(CLv!QwB?*{2SdX21^#hyUqKbuo?6iNZ5h)Sdz0On@4d{#lxRBfOuP5HL_L1tO=wP_5ZSs#}q|`0xK=31cVKAHyYB1K8_+pDf^UJk02a+c$x? zG$>TLs3t_Lzx}+C?o~Si2kma`WBqr9 zry`#)%P@M^{RqVagt3waAZ4^gNKffzCe12S8(R>M(9|x@^VHrmLG&;;lE{v*A1GZw zZ_Q((d8AT5^@o5yq|jo}WZ^$&YWF@0MF7smM}WBtz58m+|8{#&1N#VaxtOHF>EeBB zma(N;lLLWb`pn!ND^d%^(2V z3<&Suw$kEt8Ilrcwqjq*_V#U$zX5o&bLMRnC^5r*35*K0u zxS3^(f0nJM=`}}=vZe%0B3XLuq#eZ!QqkUzH>{=UO)#%?LY5j0>VoM5p_Z*v7jCe(U-^#(I&%e74DWlZjlF5g z&Hwq~r;n~ZVQpJJt5#)bB|Y6{zv#=rm~I;RW;ed@UEl?JI!oe9fc1>kIMWqS;khiO zS-t%x@I>Z6`+HhR?P5X%Kxiq=LiOx!m46=|A$9iHdR5cI{DB-=Npj!V2M7q)eO?C@ zuf}O~D4uDk;GolIQvd+B;2i}J5p%9%3Tq{3E1UKh*d2gf$5GD_H7$_^C0JJG zyRZsc2|~Z5PlHaO0^awP;+pofrF;#=(Cs#642c8h|J3g%{PU?lqnX>li|NthtdLOc z1WlfN(enI`hLH2v8+tmtNK2w04L0a+%&f1C;I99-#VFnZ`o`*3P5HeC! z{vx)`tV{CIXmbT4i2HSow&Dw|GV|EJh~j#3&psOOrKC-oNzk=_&7%WJ{p`?Zm<*QptU59E^h@akRTovSyjCFFLDcmPj9LCj*0Uwuhx~}Tv|a+WOBQLp0a=$B2n8v z^P@9hsX2K6W?`6Z(kBRtezossS1hhKMfF_oSErIwX2jF%$8%&srcB#7R6&UP#-W-m(A7R7rSE(jfl8?CJHB007%R4FK@SuSWn< z#P!$Lz~ +
+
+ + + + 慧遇书院 + 电子证书服务 + + + 证书查询与核验 +
+
+ + + diff --git a/frontend/src/design.css b/frontend/src/design.css index 3e1c494..bcaade5 100644 --- a/frontend/src/design.css +++ b/frontend/src/design.css @@ -1,34 +1,39 @@ :root { - --app-bg: #f5f8fa; + --app-bg: #f3f5f7; --app-surface: #ffffff; - --app-surface-soft: #f9fbfc; - --app-border: #dbe6ea; - --app-border-strong: #c8d7dd; - --app-text: #172033; - --app-muted: #64748b; - --app-primary: #16817e; - --app-primary-strong: #0f6f6b; - --app-primary-soft: #e6f5f3; - --app-blue-soft: #eef5fb; - --app-gold: #b88a2d; - --app-danger: #c9413a; - --app-warning: #b7791f; - --app-success: #16817e; - --app-shadow: 0 14px 36px rgba(42, 64, 78, 0.08); - --app-shadow-soft: 0 8px 22px rgba(42, 64, 78, 0.055); + --app-surface-soft: #f7f9fa; + --app-border: #dce3e7; + --app-border-strong: #c7d1d7; + --app-text: #17212b; + --app-muted: #647381; + --app-primary: #176f69; + --app-primary-strong: #105b57; + --app-primary-soft: #e8f3f1; + --app-gold: #b28a43; + --app-gold-soft: #f6f0e5; + --app-danger: #b83b36; + --app-warning: #a76518; + --app-success: #176f69; + --app-shadow: 0 12px 32px rgba(27, 43, 53, 0.08); + --app-shadow-soft: 0 4px 14px rgba(27, 43, 53, 0.05); } * { box-sizing: border-box; } +html, +body, +#app { + min-height: 100%; +} + body { margin: 0; color: var(--app-text); - background: - linear-gradient(180deg, #f7fafb 0%, #eef4f6 100%); - font-family: - Inter, "Microsoft YaHei", "PingFang SC", "Helvetica Neue", Arial, sans-serif; + background: var(--app-bg); + font-family: Inter, "PingFang SC", "Microsoft YaHei", "Helvetica Neue", Arial, sans-serif; + -webkit-font-smoothing: antialiased; } button, @@ -38,25 +43,36 @@ select { font: inherit; } +a { + color: var(--app-primary-strong); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + .page-head { display: flex; justify-content: space-between; - align-items: flex-end; - gap: 18px; - margin-bottom: 18px; + align-items: center; + gap: 20px; + margin-bottom: 22px; } .page-head h2 { margin: 0; color: var(--app-text); - font-size: 24px; - font-weight: 750; + font-size: 26px; + font-weight: 720; letter-spacing: 0; } .page-head p { + max-width: 760px; margin: 7px 0 0; color: var(--app-muted); + font-size: 14px; line-height: 1.6; } @@ -64,21 +80,62 @@ select { .el-card.panel, .el-card.stat { border: 1px solid var(--app-border); - border-radius: 10px; + border-radius: 7px; background: var(--app-surface); box-shadow: var(--app-shadow-soft); } +.panel + .panel { + margin-top: 18px; +} + +.panel .el-card__body { + padding: 22px; +} + +.panel-head, +.form-section-head { + display: flex; + justify-content: space-between; + align-items: flex-start; + gap: 16px; + margin-bottom: 20px; +} + +.panel-head h3, +.form-section-head h3 { + margin: 0; + font-size: 17px; + font-weight: 700; +} + +.panel-head p, +.form-section-head p { + margin: 5px 0 0; + color: var(--app-muted); + font-size: 13px; + line-height: 1.55; +} + .el-card { --el-card-border-color: var(--app-border); - --el-card-border-radius: 10px; + --el-card-border-radius: 7px; } .el-button { - --el-button-border-radius: 7px; + --el-button-border-radius: 6px; + min-height: 38px; + padding-right: 16px; + padding-left: 16px; font-weight: 600; } +.el-button--small { + min-height: 30px; + padding-right: 11px; + padding-left: 11px; +} + .el-button--primary { --el-button-bg-color: var(--app-primary); --el-button-border-color: var(--app-primary); @@ -91,7 +148,8 @@ select { .el-input__wrapper, .el-select__wrapper, .el-textarea__inner { - border-radius: 8px; + min-height: 40px; + border-radius: 6px; box-shadow: 0 0 0 1px var(--app-border) inset; } @@ -104,75 +162,98 @@ select { .el-input__wrapper.is-focus, .el-select__wrapper.is-focused, .el-textarea__inner:focus { - box-shadow: 0 0 0 1px var(--app-primary) inset, 0 0 0 3px rgba(22, 129, 126, 0.12); + box-shadow: 0 0 0 1px var(--app-primary) inset, 0 0 0 3px rgba(23, 111, 105, 0.1); } .el-form-item__label { - color: #415466; + color: #3f505e; font-weight: 650; } .el-table { - --el-table-border-color: #e5edf0; - --el-table-header-bg-color: #f6fafb; - --el-table-header-text-color: #52677a; - --el-table-row-hover-bg-color: #f8fcfc; - border-radius: 8px; + --el-table-border-color: #e3e9ec; + --el-table-header-bg-color: #f5f7f8; + --el-table-header-text-color: #536572; + --el-table-row-hover-bg-color: #f6faf9; + border-radius: 6px; overflow: hidden; } .el-table th.el-table__cell { + height: 44px; font-weight: 700; } +.el-table td.el-table__cell { + height: 48px; +} + .el-tag { border-radius: 999px; font-weight: 650; } .el-dialog { - border-radius: 12px; + border-radius: 8px; + box-shadow: 0 28px 72px rgba(20, 35, 45, 0.2); } .el-dialog__header { - padding: 22px 24px 12px; + padding: 22px 24px 14px; margin: 0; + border-bottom: 1px solid #edf1f3; } .el-dialog__body { - padding: 14px 24px 22px; + padding: 20px 24px 24px; +} + +.el-dialog__footer { + padding: 14px 24px 20px; + border-top: 1px solid #edf1f3; } .el-dialog__title { color: var(--app-text); - font-size: 20px; - font-weight: 750; + font-size: 19px; + font-weight: 720; } .el-segmented { - --el-segmented-item-selected-bg-color: var(--app-primary); - --el-segmented-item-selected-color: #ffffff; + --el-segmented-item-selected-bg-color: #ffffff; + --el-segmented-item-selected-color: var(--app-primary-strong); border: 1px solid var(--app-border); - background: #f4f8fa; + border-radius: 7px; + background: #eef2f3; } .form-grid { display: grid; - grid-template-columns: repeat(4, minmax(0, 1fr)); - gap: 14px; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 16px 18px; } .form-grid .el-form-item { margin-bottom: 0; } +.form-actions { + display: flex; + grid-column: 1 / -1; + justify-content: flex-end; + gap: 10px; + margin-top: 4px; + padding-top: 18px; + border-top: 1px solid #edf1f3; +} + .toolbar, .filters { align-items: center; } .pager { - border-top: 1px solid #edf2f4; + border-top: 1px solid #edf1f3; padding-top: 12px; } @@ -190,15 +271,6 @@ select { transform: translateY(-1px); } -a { - color: var(--app-primary-strong); - text-decoration: none; -} - -a:hover { - text-decoration: underline; -} - @media (max-width: 1100px) { .form-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); @@ -211,7 +283,25 @@ a:hover { align-items: start; } + .page-head h2 { + font-size: 23px; + } + .form-grid { grid-template-columns: 1fr; } + + .form-actions { + display: grid; + grid-template-columns: 1fr 1fr; + } + + .form-actions .el-button { + width: 100%; + margin: 0; + } + + .el-dialog { + width: calc(100% - 24px) !important; + } } diff --git a/frontend/src/views/AdminCertificates.vue b/frontend/src/views/AdminCertificates.vue index 480dace..1ddc9ca 100644 --- a/frontend/src/views/AdminCertificates.vue +++ b/frontend/src/views/AdminCertificates.vue @@ -5,7 +5,7 @@

证书管理

支持单张新增、预览、下载、作废、链接重置和批量预生成PDF。

- 创建证书 + 创建证书 @@ -81,23 +81,27 @@
- - - - - - - - - - - - - - 搜索 - 预生成所选PDF - 预生成当前批次全部 - 导出 +
+ + + + + + + + + + + + + + 搜索 +
+
+ 导出 + 预生成当前批次 + 预生成所选 PDF +
@@ -183,6 +187,7 @@ diff --git a/frontend/src/views/AdminLogin.vue b/frontend/src/views/AdminLogin.vue index 99c3e4c..f81c7fd 100644 --- a/frontend/src/views/AdminLogin.vue +++ b/frontend/src/views/AdminLogin.vue @@ -1,15 +1,26 @@ diff --git a/frontend/src/views/CertificateQuery.vue b/frontend/src/views/CertificateQuery.vue index b0cbc1a..2dec50b 100644 --- a/frontend/src/views/CertificateQuery.vue +++ b/frontend/src/views/CertificateQuery.vue @@ -1,45 +1,73 @@ diff --git a/frontend/src/views/CertificateView.vue b/frontend/src/views/CertificateView.vue index a72b55e..e9578e4 100644 --- a/frontend/src/views/CertificateView.vue +++ b/frontend/src/views/CertificateView.vue @@ -1,11 +1,18 @@