From 3fe2863ff72ac5c87c7d5b6e1c94564afdaf4753 Mon Sep 17 00:00:00 2001 From: Buer <42402987+MartialBE@users.noreply.github.com> Date: Sat, 6 Apr 2024 19:44:23 +0800 Subject: [PATCH] feat: berry theme update & bug fix (#1282) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ⚡️ improve: delete google fonts * ⚡️ improve: Optimized priority input handling in TableRow component. * 🔖 chore: channel batch add * ✨ feat: add dark mod * ✨ feat: support token limit ip range and models * ✨ feat: add MessagePusher * ✨ feat: add lark login --- web/berry/.prettierrc | 8 + web/berry/public/index.html | 5 - web/berry/src/App.js | 13 +- web/berry/src/assets/fonts/roboto-500.woff2 | Bin 0 -> 11072 bytes web/berry/src/assets/fonts/roboto-700.woff2 | Bin 0 -> 11040 bytes .../src/assets/fonts/roboto-regular.woff2 | Bin 0 -> 11028 bytes web/berry/src/assets/images/icons/lark.svg | 1 + web/berry/src/assets/images/logo-white.svg | 13 + .../src/assets/scss/_themes-vars.module.scss | 10 + web/berry/src/assets/scss/fonts.scss | 32 +++ web/berry/src/assets/scss/style.scss | 1 + web/berry/src/hooks/useLogin.js | 24 +- .../MainLayout/Header/ProfileSection/index.js | 4 +- .../src/layout/MainLayout/Header/index.js | 6 +- .../MainLayout/Sidebar/MenuCard/index.js | 3 +- .../src/layout/MainLayout/Sidebar/index.js | 16 +- .../src/layout/MinimalLayout/Header/index.js | 174 +++++++++--- web/berry/src/layout/MinimalLayout/index.js | 10 +- web/berry/src/routes/OtherRoutes.js | 5 + web/berry/src/store/actions.js | 1 + web/berry/src/store/customizationReducer.js | 8 +- web/berry/src/themes/compStyleOverride.js | 39 ++- web/berry/src/themes/index.js | 59 +++- web/berry/src/themes/palette.js | 2 +- web/berry/src/themes/typography.js | 13 + web/berry/src/ui-component/Logo.js | 6 +- web/berry/src/ui-component/ThemeButton.js | 50 ++++ web/berry/src/ui-component/cards/MainCard.js | 2 +- web/berry/src/ui-component/cards/SubCard.js | 10 +- web/berry/src/utils/chart.js | 3 +- web/berry/src/utils/common.js | 7 + .../views/Authentication/Auth/LarkOAuth.js | 94 +++++++ .../Authentication/AuthForms/AuthLogin.js | 28 +- .../src/views/Authentication/AuthWrapper.js | 2 +- .../src/views/Channel/component/EditModal.js | 101 ++++--- .../src/views/Channel/component/TableRow.js | 61 ++--- .../component/StatisticalLineChartCard.js | 2 +- web/berry/src/views/Profile/index.js | 16 +- .../views/Setting/component/SystemSetting.js | 134 ++++++++- .../src/views/Token/component/EditModal.js | 254 ++++++++++-------- 40 files changed, 936 insertions(+), 281 deletions(-) create mode 100644 web/berry/.prettierrc create mode 100644 web/berry/src/assets/fonts/roboto-500.woff2 create mode 100644 web/berry/src/assets/fonts/roboto-700.woff2 create mode 100644 web/berry/src/assets/fonts/roboto-regular.woff2 create mode 100644 web/berry/src/assets/images/icons/lark.svg create mode 100644 web/berry/src/assets/images/logo-white.svg create mode 100644 web/berry/src/assets/scss/fonts.scss create mode 100644 web/berry/src/ui-component/ThemeButton.js create mode 100644 web/berry/src/views/Authentication/Auth/LarkOAuth.js diff --git a/web/berry/.prettierrc b/web/berry/.prettierrc new file mode 100644 index 0000000000..d5fba07c11 --- /dev/null +++ b/web/berry/.prettierrc @@ -0,0 +1,8 @@ +{ + "bracketSpacing": true, + "printWidth": 140, + "singleQuote": true, + "trailingComma": "none", + "tabWidth": 2, + "useTabs": false +} diff --git a/web/berry/public/index.html b/web/berry/public/index.html index 6f232250ab..abd079e17a 100644 --- a/web/berry/public/index.html +++ b/web/berry/public/index.html @@ -11,11 +11,6 @@ name="description" content="OpenAI 接口聚合管理,支持多种渠道包括 Azure,可用于二次分发管理 key,仅单可执行文件,已打包好 Docker 镜像,一键部署,开箱即用" /> - -
diff --git a/web/berry/src/App.js b/web/berry/src/App.js index fc54c632d1..d6422a0f54 100644 --- a/web/berry/src/App.js +++ b/web/berry/src/App.js @@ -1,8 +1,9 @@ -import { useSelector } from 'react-redux'; +import { useEffect } from 'react'; +import { useSelector, useDispatch } from 'react-redux'; import { ThemeProvider } from '@mui/material/styles'; import { CssBaseline, StyledEngineProvider } from '@mui/material'; - +import { SET_THEME } from 'store/actions'; // routing import Routes from 'routes'; @@ -20,8 +21,16 @@ import { SnackbarProvider } from 'notistack'; // ==============================|| APP ||============================== // const App = () => { + const dispatch = useDispatch(); const customization = useSelector((state) => state.customization); + useEffect(() => { + const storedTheme = localStorage.getItem('theme'); + if (storedTheme) { + dispatch({ type: SET_THEME, theme: storedTheme }); + } + }, [dispatch]); + return (VvN-kMGuIJPr>{e*hXNo?jo&^>&iT z2m`Ql^DO?P_@3eUQ@9=Mjkt$l1%!xswdm{QgnM9g^6%=|;cnj;4$>>Y&M|)b1~&J9 z65rjgPk2Di){0oyqFf_W@4|mF4&P)Nlwy|{_%&>pbw-)&A(%UE? z{BO{ZGH&_2!9&K6uC9Ds8RenkH`*89E#3imG3Cyw$7gwh{r@X3uW(wP(B)%?ul8@= zp+%P7yK!yE?L2tu;GiyIbj(3;P!0#NeT4pi$`da|2aQX>#oNUV=lo)!ud{FQIqFu| zyPHxH>8%RbAFmc#?ON?WzQF!yRR9Z)2EaXP0Fk+yis-+ytKF8}mY-+Pe{U*Eq<2eq zEZrSl= 7L8iqvEp@)sLRmFb}kV zrh+F36@_q76cmYiYU)HiMFpasx*AarjM{8Ny|Kni=;Xo49MR9CpKl+XIQ;hDi-{w* zk1mYPmy7oNk1k!pIaA2?D+d&SNRMfS- w{QuQn?;BP%nzB)GS~gq)q1 znVol?R59M?TAG%TnXQ-*8RkFrko@)`#cyiUZ{h*@{X??f1RUcv#=3A=jD0SWNRud( zxbXXeY@uwLY|(eCF>Xla5M34>UH-ZZI(;KO%{DamyKNjppT8b?HM0W&rJ*U|8BWHA zNp|<-?@K@QcPRGnX|yFsX(W3z^GvL4v&~O3NZGMrk!en57NJ%N-hDx~MbiEzeEOo7 zPe+-$S>}s(%6 ;2atI~FJIUVG*2JxjT3>LGySb*4tETjbMadDadIC>V;Sp1=hVgs0 zdc$$L!+kWLzcdp^`}=f8?%RTMFPDaaX;er;gl|AYSeutjELlxQTC$bHr#&tuwK$u4 z(N);QIsT0K@y1k=K3FPC*}%o4A)}bc77eg^#eChSTocOtEih+iT4*L*+(L_{gsKt_ z$^_KlG_G@%_Ej0EsT-CjWobF6$ZKok9Uv2A>)3Br+yo)YAgQ?gZDEO@e@V&PvT{ U!KlRg!S(_&xX9$b_sLVZNa>>HIU-Nc8Be Fa_Ds;)pJ*SCdIic3+~7C(1E` GF69aWo&aXY7FqXaS8bx6 zT|ra!Mt{Gz#)|?C-uBL+YaUkD8gh5bdf}pSul|g7>=Adol|}NRtG7o?_5WQtoOi-d z&UcCQb5)2!7uwn5-WVO>-el~aX8@MIJGb&RIy?S-dSW;N5xb@@mo}#Fzr5F^D&ndc z#7{VVo?zaQXOg1d@~UUpr1_MMWdB6W33*prOARS4yS8MLWD}d{QA1OE7n2_JS1@wn z`;%TpFnD23qmSGytJrAy^q6Sx PTFb?M$( LbD^pR_+#oy2#^~?~nxS9Im1xuIvwHm-Qgqs_P(#0KE6Be@!6+uJp&%xs zAs{eiqzyEJwfCOyeeKZH)eqLy)6|eM&(O!z+{S}xXp`|uy1FHv_W)m~->kktTd=HaBZQW2B-v{FU&^AGPYe zuOoTT-J4zU3Wt4l`!w8_@9UTayHnpe#piz{(Fx|a9sS_t25LQ}nKdoDoML =(9y zg3|obJ`PUaEa3M#=NKE&92M%~D*JAZiQt-%P$P&-5H3lItE#)I`ba^Qjm_PI%kozw-M %!z2{urLqr z&@i`?P9Y)Q?qR`*11Jl9z1DCfiT6FT0S?@1dLpl8f6am>zyG!Dg#3*I9@w@UEkyxN zVxkkF2jk%65hkQHvo%gWc5Uo`{}cH`q8=8V^gQZWSlz;0 vxBl7 zLEPS8%x=7ST<;d +%gL^6t+>b5L xgs8ZYKBzwZypbN6;%fNP9Q!TNOz-n= IPD4wc3~eoDErVt;UDw0lI)NM{pLj8jR26 t_ z*Nz}T`Zw6U-fT5!by~vZ0IbNVDcZ%*QlrC~YN+Yeb;xz)|KGg&0K9owVWw^^M#r^u z)CjUN1VbeSWerfRJ9}*C?B21#jRymC=*+m^d_Usf2kTKyU+%A&c>a4^n`}}?`!c{O z;Q0l>1U&zK6;n9Psj!m60T++PTlpndiI{=ttzz+4Au+|L +8BuTZly3fJjT|z?s0`NMJFpw1H3X?6-TQt3YQL;CA z3iwT?DWIQ31G!3ckZ*%_xLKr&9b%_=OY9=u7LLe25JL_EDgNiAa&C|pbaL1n&2&7; zUqdOWKlGY`gR%_`h1E$mHBwfxNhESw3QuG4i=3UKX>F(=l#-G|uSw}oa*JFD)r`VW z3c1j0q0pZcZicj9vT4Z7N${c!c`eG2IZ=kZb; O*}oPQDGBCjv-g%?70X+l z2toza3mw3vvER-lfE99Se$?pnb7pRCJv|ip+ZeNUz|gwe?vbArSM`>5&dN1v8yM?b zs@>u9Q99NJ*@OIS>qg8hdHXzt2efs2`9)L^&x@${E}z$Uv3_ZT@ 2A%a0r?C(F%dm==Z?qje8GDrAGA69^SomHINZy_rJ!OTlxX*UXa`Y2Mq&c>Gr{iE z)~^oWLiTK5jY-^`6XWq>*{?>-?bJ3~2d*UF`iL%&E^j|%fqV#_xFa3denyM)F>OdV zD1WuDj9HsX2XG dc1IMG-&v0Fv+`g>mq#7}@_e)4-ySw{K5+4OX5k3{UirC~ z1mM$Q_TA4D|GyX zLRuwWxm~Iea_Tv8Wy!_<4Ett|r?Ja#O1v6gex(`n>;u6_?WRLkS5vRJ(AZ|dBH1Gw z)-Fc7@k2c8Qvb?&POrY%@2Z06b^%Y%O0sb|Tjw#=51C{s)MA6rcZIziMy`}W=j%yT z3wAYLRF!00sd>}&ndg@-)Kq5mitx-PIwR4&FJQ6B=)PX0tHSFw>=)9LdDeI3DE-`o zxgIOD>=S6aj#iu_Wf{A*HOn_CW|a2FN3@xu NL+Y}MnOzq*(=O(B;Gs`urV4O&^ qq zC8F|ybT3E%v_+J6lHyY@_w;~FnkHTN_!Uuv!c00(NNM%baxlN_%c7LIkiU|v8Jrpm z|C*?xHWI22T g}5ILyl80DVvZIWPu8L%wZj^ZJ^unjtWcr84lPmVNdy%eiI~ z-!fQtjhUo*R0)xa(V|o~q4?u0+F}$1(KLta-ku$F$=uaoNEV4Mw=7TGiMM3V7NZ0U z#k?W#?Tc?~d?xm9&*CbnwM$e5$0s8i0#cPlfDtSNU
6JF4eIskhD=>UWX zrvp$pg*BqvjTjt&bqbB)5L ;(pe2m5;akj11WrBXnQ7^vX)^9 YU%RufBGi(-oDgHgoyUF^w-oQ! ZoPhWo83kou z%?hT&UO*})2jL|W3AMysgEDhpwe=Ja4EAPzV(tSE@XW5_WT2~|Wn^CX1s5^NpFHQ) G*P{Yv 4gdfE093R904m7<0RR9100000000000000000000 z0000QWE+|u9EDy6U;u+45ey3QAle}dgbDxwHUcCAh!6xI1%iGDARDwr1>=|lY#ab# z_FE~6axqGxC>@j$#s75zH-^ajC{-A8uj302J;$f06~!{K2!{}8qDGs(Y6YcG9w`_w z(3`J|U49TEN^3PFJO>BwsZ52VQ-=~BIdcY%^HFo5f3|ra8=yNHgUQe>q0RAr;OEx+ z+lW$1Fo+Gb5vdUaBx-}+7?QD#F-C<*j*uz=sZe61O(?C0g^?% cHY4 iTDzlTn4ZeIRdQI*lj z)y@`;Q3IS_D8&x!h@S=rFnf4qvrKo?w+A}Y{Bz`!0V4&WiS@1z5~mKL+1}Od&W`p# zd!Uu>9`>I0^q@UG96d<}o$5X^U`!AKNzeK>A!HCbNGSdwa^%c$h#aJ$GxLytBEJ-< zfQR3(W=&JMG>Z@LQW}1q4s61U{|sn2oDdFjt0*gi`?=2$JP~Pgt8mBkIs}nHf(;TR zEa`DRezjrFkX@+>A;wI8dkj~X^|>`J5EFHN{Nlo(>;M4tPy`)t62gopM4UK?6e$pC z(jYiE5ZSUJ&dP&m)dA&}e;EV{5CH`QU=VQ-fVZC#%xP}z2nVmYa3&nQ!vlih;Oi5~ zf`gDJAe;rF5IaZ$zyJ>5i0cIU3jubl!vH$Wlr)ddqf`1+J{!;WGi~;qYPx6lpJ|=Z zBYRG->BIfr%<7AMb#7mv7H2O4=k6Lfuqa)$&Q}-XG(4Y27he@3X|wTo``NRGHjXv7 zqmd4BH89!_YThZ80s~H0s-LxX1B|IaTJL)AVrnV1YoqJF*rV(5>#Z4_-zw^??)9~A z*!x_c%8FsdN1kQm*(vs0)V$SOpK)Hbx1mlct~PyW?LKvv)iR*5EWX7@|7oh=+q@p} zXtzr7ZC?C~PPfc&C-N)ek`rsbzGwDwZ-JK1^W37Rdg>0mk>2&x@7S{#jkQ@lG2%_O z*k|d3w??cz3#T1CP+RYftGrdp%DHYpL9~I!3s`@@ott8xI}Aozd(;3kCzg@?KxCT} zyR}%E5*s*hZ_iDZzs>01Em@<@F!QHWyu3R5MdDYaI6Fj11>felwtbV2`=^(||J`21 z6Q5h1Tcc@|>MK!3tEq3TwEiDbQ@hk2%!$qGYMGGL+zx6!tX^R3YMa%E9<_ktnT*XS zY#P6#c(&Bc=(5@!^8wX^-Z$uvd^39K5g pArU_nqWehPK0A;h Z4CS+wvv0TldvB z-{VKC{yh jzwY)i^Hch4%a@jiXz9eAQ=@j<+onyMHf^r75-h4jL}FEx*r?f`YBx7R@`ijb zOO~xzjgPT?^4XRzV>HEjIQNNL3sW!BGNZm4=0dUT<67$wDHkJ7?;zM>*r^@e4V+sZ zJg1&=ZW#0(4XImV|46AGr!m=$I^V-E#b^szq>x$?LDwFqD3W+T3Ra{DQHmm78SQ{0 zFqCKzpzY-1H)CNB5>$qDxGV>b |;=rgLIEWRLo(DI6`?SQ$Z)F5EUv#ogy@-ByB1}hYBLly>#hrdQ_A? z6?T&DWJY N &7v1ndMM5XI;`5`>im z5*nZZ jE>?H%Gim)4o?X!y%X}j$i50)hfr4r_aRi2F~mk%ur z+6vx?U;(9+pl)3{_2BB&r{91 )vbTDeKEo2XY+&DTPkL!3q zyQ`^#vS~M{zArEUG(fttc3b2ave^^sh!ajY0v3$l6Z`=e_No9Z )#LOy&bdF+GmIrbi*g`^Y z^ DY=5Mx){iM _+KTi{)*4y7x_&Sj-@&!=}!GpR292Y;;(1CNOo&V|c~b zG%0c^weJg& u{ekSH;42&f>~k`g>1=b1-I@-|@f_z=G1QhRsB2tUQ&ESIw68 z1N&3n+9{4({tk}IBbuve%3z5SiIr>QiO#O&JW)@RP#wmIny3eAq0N*_9Lu8=#u}o4 z ~=DI;#;Bse&OV4C`jB;ZWGHtc9Sy zPQ^>0rMaZfw3pi9ErPS=7Q??3RK@XZMR7a~b> 5y}+zv6JHJ{T>5>@ z-LTUTwVrO*gGSA;a^x<#k}~Qx#5OF*=zJOda181sGc~c`m)tNkG~ActuCI4R+ku1i zCc>&LwehsLvVx 0%s@!&X8MfNi`2PbHV}N)~G@u&Rv3bZT0grp*F| z7S7NXa3-bpHM}%$2l&Eqr|) y{m#bmqtoSFoBB116{38BE>Lh05okjGCn!jG*ti zppa8HsS_NSbC=PPmT79(=Ktky++&DU }uIvOldEZ+@rp zQstUtHItXrrcedDGIfI;N6kHDx ~0GjT*?ehqy*#u}!lIR+)y%|Eysu zXtc$IZ_RU-2&epz`;ij3&a#KbO+Yfbgm7jb2S-D#>(jYIWj?}Jw}`5cKq87`--Di- zg%>;Yl*(O;adL@-B0?siye#dnGnyw9D7-~l6bOYIB{297izNh59 cgRBZLxx5iB&jzlw(}L)EZ7)XV$+qSSGO417e|_+_kF|^}{mjfTe&W zvDfB_;>HGpLzPc&BxaJyM>RwZNsVx3Fb*vNuF3`OL|ZWMs}$?h5DFs^S1aIgCjt{v zOKhd8KSpK{;TYL-D;QORd)5q%)Rq7V3ewXZL4^{ -5Y*rZVvU=`UL1}n8SlO1FYnF{=gbmisP4&I z6&EEUN}+m7SnNW&`@_fx>=n6XtVTVIWbpJUhYBjy5Bh~IUk~)2ZN|*}vJG(=eTG*t zh)!v5LYA4N0L5JqHqw(aj{b{4JO2R1EsCc^8h@2)UXVl;fhpF~{{Ta*`oy`YW{GVk zbBk8r`;Q~Fj+#Y3PaBEdy8$F_(n$^oC*%d#6aC2DoF #QZ z%#B_wyx$%)w^xIQSlRs~6E3l!wb-~q relgfUlQY81y0bEc^+ r_&v5X^ij8_h10>Y8tDJMhwYenu~ z^23G6x7Bwx7%<7l<+m1Qvt|#LPO@2FQkLqU4;5t9T0~n*+mbu3({Rv?0raWa@UvO7 zj7M%^u{3GOM<~`S)f=ny{b?zXptwd2hdfbliX08eA(v2PYFgxib;nBfrcat))GQmG z{qamDy5b7rT95^qXIWA$u&*L~U3xa1&*B^1rSgnGeEbjTcOYa0nn1Mdd@e@gdvwfq zIdNW2mf )>RA%1?N?UP1ll5 zutstvXInIu=ubppAVxlDsl}W~uKZ;CyYZDF)@!6|c^F};Ym;s;Xv{9v<5dwE3%uOa ziO6XJsOU%aj_-M2Jh+1vc!laqdzbz%PL8j0+;}71aACiV(&5i2#Vrki<^qy4)x=oT zl8BYkot;3mCHhcR KTy;S|&sz`Lq+6J g*hRUi<4hRPOq6gRm+(`LCkz=l-xsK54=VQWsSSo>ekbTW^h$|J1`i`s0 doeS0b0k{);|4Q{PjH;$PrxMHRrx=I zt&cx-Q2T{df9bybsg2r?-81OhOb_&~LACn!d3OdgJX(+ofWx^uGd5hG$OCD4^6@us zy8C$xA0L*RFPp KW2 zfQ%KMmpA?6+I*GbkHz-H-rT#k_FQu5296vb6#pzOo2M=tI z>_4cUYmCA|-fhY|l`RuR?Lf`QdmG4VUi9l%@fGQB8L4CF1UY_JroXc V$(OM9)I5xM(YYwBF~}pl zI4UNh2uyeFP{i+0RWzNPU&nw^`f&!m$z6r6me3b>lkd%>z}vC7gnpW;y9%v|arMW` zNAv$a7gaa&3JLRY4`F+I1c!NhGD2iuP+bDa4laJqr(EdG&U8=-H)pdd##Z>>79@UL zNY5=?C`b^2u3#p;&Pv1_wm!#-HVm8lTNKBXgf@7d3ayQeVOD}OU1xeX{(i`&3*QZf zzUxVwN#{$zb*Aa8lxA4ShI`am(%?FrYtk}Muj{YfQDf=sir6V2!(W~}m|wedjcQfy z>1J 6TL>N#4}&Y(sI~H;Eas=2V! LSwHN`kqZq@427$H-gOX8yCPvsp<3=^`HM(NX2jj+3`dZnx^5 z=o$ur$QyTxxL1~tM>el7z3+vSi!p|r=B<0c!=2l1bTf?4q!?0^c+$XjR_ya=kG*W~ zeTXq|L#DY(2YKlCy!fPK`&G2!_q`kYB@(kDV$anr!J@}f*IIjrg~d;?SNcF!0VOtx z4Kzc^mSn5M*f{}8kCq4U`E30BLPXvQvi?Ll*d@TnDIh8YNEX#?^$qVpY1%;e>o5!l zXL2L}x;~%Y>gZku+rpLh$4Z-GbH*(k&zJ4qU8+B~J6%t }+l_YfzcCpv^B(X2j^_O$9FrJI3qGC3LL`8E^U|F(rAXJU8^i7Re~CK%yET%Z zcJ05xWKq&f56Y4!Qwap}4r45u|4UdxctB8ORNNM5IV4eIT($gNReof=i%!4%Z%}p3 zHk $P_mZpc3V(k>BS_$crA7B)D>39OrM4Bt??ae2ED zY _ z4qQ2MD~|~~3hu-R{(-~&S4F?MwB7G} duomybSv zfQ%*3fyDy+I|Pc3vmYezy0EC3O^a-=yLTzK^UtNvka5z=+J! #j1NiIjn+l^K{UN?=|oOmS%(;cyJ_0`8DsWYgpu1%521IjB4+ zN1c69BkXMMv1~~rP?@*)JB1K;LP*rm9sk5tp@SHS{{@b$-u}9bjO;`xel&7GU~!9F zTR;&Q?f<=aY@#+W>aYUv0*^>|Fz3R^vJ&=tCA}elqshLAXJ_08Z;6jb6}M%YPQ!9e z>FYnzNOZ3VJ@*W=%_BCi*3j)$pkP|86C+|raIrMv 4j?510vReoXl zOQKqX(zSi3bbM22(H*e6WIQ~(+Z$6ki0ksObM`o+?StTe7jRIoKu}PVHgcj^S)QU8 z89P&oohh(ak`UE@W3u1MM082}P} 1Me%4OWvXC@& GuTw*znx(`!>yC%@4U3@67cp^toF&x}~Znz%s7alSFYz& # z@K$Hr3^IKUH{fnZ_K4RD`iUce(ZPm L_E+M4jE=@|CEYG#99h9-RkACT@J(f~@^$J&lJtFgv$1Tns3r_w5w z8n}EEPt%K#PO<+{_;GY>?)z9Z?xdYPm1Jk6uHs5~a+I|9J>_oc@1dEj2i`I5zT#+W zx`PYF@g&HUnF?N+zapde&`8Dnh2tJq6&^K<+WA^R_#VPYxzRl|g^W(%u60zEXa@XI zAcz9md-|!e)I32_Y(^Q3# n?$@Z#roU` 9Q^LxCyEq~KB$sepI*Bv`%r#S>iK=# zb@?~bZyRMUzd{;C5vpIHLtsED)Zy9#3qjq0CnrIln75_4in|~3%2_~Y!wMnzL&!0|C%Prt!`BhKcVb&KECracMR)vq o5FI=_92v?IO!bS737) I);2OELy z#!4wksdcMGsP%j`p3#LfBKt7=rZL|!KpJ~H)ZoksxY{E=`2~@CbQ=pUXFSiaBP ?!N!&$IiDixKr_rU{;KcDTzf2^SK$~QF%Yy@`#@q*)rkK zD`N*`kCU#pQHMYpPsQ61^-o%nXjYbq)|U6xHSLK6U0V`fqwv)NW)B=IyBiFz&kuxk z56{;&bvBpPc)O9E-TgVhPKXNNxVyO6`?jRFmdS`+XsQ!!s+M=Gk{4|?6z`~zcMxrx zz3O5)nS5ZumkP6YZnzRBM#hL!*IdADw2Ef!kQkjBPiM8ob_J@Ri8LarsdS3ax|6dq zs|zypeD>ITr5vX0Z_i>_0aaJk8T7=Wr!ff^O@R6o`kWm^Z;$5xmd{-sD#&{(y0Vhk zZ2dVERx__jxoGuRy|t0C&H0QhOHTt0b8~__
~gudl5S_}+8F8yZ+4we`!jH6hHV znw|W3Q**qAsTIS*ibk}6qm*vq7LoazX}4u}>bLj=#(TpX2CA4ja==!hNIQC|b)A@t zyl_6Vv_3h;+#({_sU+MB#3aMWG0uwFsz )t&v< z57$P;N&ug~PyO&s&5^NIV%@cy=WB1=YU;-Lx`)`?x(0){y^ni{ovk}F5YDA$=r`4t zXj{mTl+IV#xVj+rIAmn&@q wi?BC R2#CVxdv9e40HY7!-$a6p;O5G7Vql$8o`L1xG0-cc_$_7>qM=`1{&;n z)d(fu8_k};qUdYe8>^}{yE4OtnMpF9P62@5wdW5HWLkEni+w0BDO^fQev`HGO>izN z*h-}$l06(}6IS6JVNr6>b>YK_-n0u$>#&Q@O~@r-;iW0;n0()$xPe+QRnx^RW18em zT`5Ehce0s@3)#}@6lJ|oPn0i8fTN6Aena4csZ#U*b}6lU+3&F^X$X8cSA^9`J#2%P z&_BkAXdbQz-|z6({9$@jJ(zq+o&EjTzZHP5UO_SJ+c>#!fDg-i*=ssJU<6O&{9 2>gPXyI0jG)NE$bO1ycsIuT;6mUI`Q1r zYd}8O5cmH|PSwiU(v0%Q$m4IwW^MjXc4}e}H3RFQWP6pU^UN@2?QCgw=>y55Xe?hf zyOGHVtM5A((ZryKH4(VYHa=lH8KHZ9+ !)vkW`VMYa;wK;OzSk+%wH@CuN{& zpJq;ix5x9pMBhLyK@~lDG-eSm|7XDYO-nmXV Oq+6B+dMgkZ1{`jmfFIz!@+ zz6zrK)nAQknT4MU-~#g>mV2SKh_S;I7nfAi9px0a5@gc()b{fI?5ONW6#XuW{?wD= zrKjefhc6!TZu|CPZ7S^&?Z6=Y3(Jeh^7cuVtBnjj9a<)ryxE)5li!oYtN;TAN3TsU z7|bIdA2sCm_m^)oM+rwh`p5)}o}BGhdNltiFjIk`02*dks(|Hq8!5Xq6}o)%j>xr@ z+4%~xJn(!|Sct~_`>p5PtYNaN^!f+d--F)sw;tvI!|SsT3tgUzc(7CfEAi~|zF@>5 z>u%qD_vqfbYxsGK@Jx$z(2Zl6+*)2%SeJt&-4-u7rgKKa%U##iP}$9T#&!0>tYtrj zlW?^5 6DTZc_MA0t>Bb>*4^Bgo-!uF8pA@nF&^ zD#_*)6<#VEtJ^1>O-+mKZA~j|ZiPzSr!Swbi8V1iWbuZS8Ur4iD7q5COe+`+9__%j z>`=gsPqwU2Kz-`KrGc3L2-aef@}j7y@5=gf(_R14^cP)40NW5B1Sj45o2Wa~$VZo# z=sJpE-Is1%@x_Amjn !_61P~`EilpEd3SnHdra{h^0jq9wU^<^}~t=3>m zJ(Q!Gxt1Tm`fbDd$yW=!(A`GGLg!W#FDzKO%Gk<6Pl|VNn<{U(w=1^`aY5Woy2%|f zSMHVj *?WRa=IMF){l)}qQ0 z_^6K2#$^$C(bq1+N99PnnDJhSxp%AGpuS3dy4o{|-00T6y~bu*wvjIqtu`(Y#22j( ztNe_Hc#jXX)4S#&tIL9)oB~cuRm{&eE*0d-UFYzNjH{r$CaJ78?r$AEkf%vk^2shD zAB(m{SLZY~n{wBLuG&dZWL@6N4}}m4 hBXmIBDscl32YFN*XZXz3;aV9wt8vk}F(fwR*G5EetCQz6zN8Y3^6Vo( zY`KQ=TJ0UL>HW^XX90jWe-cv$;NwF6 zkTA&X+gAnqRS%L9jNy?yCPr+lSY_hJP_Qv4p< zPuxqSjhGWdqDAP$-_ln-)=pvUbnKy%;xw~VRw{_CKOOH!ST$dKZ9}O|k5f~Zn#pkA zu_1zIYbz5}Wf|*mlUyZgYeyY;YjVz$IMSJpCcfNYmfPnKlBvk1i*FjB*mjZ1FHre8 zQs{`S-XQiTQm>#?iy`qSjkIK%DMC|;ai%g(3Szt_n?=kr9xddBgyd*QbD<$GY5E{E z6VQ{xcv{M6jScmcr5ytVCo859k@h8-6t^oe&@J3DnyCb@uIERgsbGY$ OqBMzPf}WQiJ!FW_l8Qe3CIu5)(uucmmB-} z#!s2GU3C2m)HW<&lIA$Y@T@ P!F9qqL^b>n ebk%6POf7-)R+;+q;zB=?)se^G3Xh-d+)2M7Tr6_8?!2LiAP z2&g^q(wkZcgofk{oC(P82w|Qab(9&qqe%%b#9((G2W4?y d41=(=YVY(0Y%TFUMqDNV%HT zcTV~dlFSm+`^SGh2NxgQ4IxKH2%++IPDfx)WPl>_%>m8re#M9yVHBWX5-F7uQqmzc zYE(#$!GMuzK+B*vR4P;~Flk9U{qOf{cK*IAwqjDDC8jfk3dQ5aJ4s&d3sj+0(3+L8 zsJ9Ic@bxqRj&xcxvSgUiN)JRew|CV8t#)Pm?h-cWfCbY?Nhc*m^8`hE-+xD?YzO}N z{^zvdk_cT_S);p6e;ASQsP_Dvno$IIJPP~&ud{4*hrL0Ea1?f#qTRD)xK2@}sH7)p zwEus3j0^TGkw#1M%$%$}i*mpV*ae6x9D9M#U63o}lA%kPlcGu6Wy=u5Kecq0&C62y zr`uBH35js) r1t mjSqQ8Ox4tNr0@=PAmhLV|o7MYc2siA6g8NFuZ(SHmdv&O3N)_8x`9M{L4Id(#c z 3z{8YwcEC0vlXzvg8bqL0_S?)r7j1T7=d!hgCLtjg+6M6A3#Kh zpCCF%&NA_QtHgS*UWZ%28iY5ltr+*4b~#@?m?V$uM=|ElJ!Af4XnM`=Q7msz> cweWb83^3quL3f!KN5LMx*6%ltBZT*i@~(q=Qg!5vl1 zQ)EAEqh2>IUwvJtM?k*NIa1o#d 0llxZ_&-FC-abLK60?1`tAY}&GI$6N2b_rXV>eD}jo zzx;+!%%?Dv@l!#dM$i&L2)+~|g(n3Oc8e#PHY65)fFgc+Ez|Ec1A!sV!xGl{ZQ5er zD-P{&7M7E-@`fr_qw;v#n7|~aFpU{`IhU C_>OL-$-+r$>Ov4eMbj}Q2WPx9w{ z SbD>Lh1aN?(hx9qHQ#|PjB2VM&<6zQ9AB=Q|4i)VO_7g!A31BVB@ z?$b@6-wp#{i1V rrFfJnDo`nJ {jVH-R0Pdt9%cOX0c-Y|e6&chlx*uW;X zu#KJBqZ#35M}{L_IF=cE2j1fYKH^g#7Eh)jpd3}Gp;++-Z}0|h@J1n!oiQP1FwbvU z65H}PV)rg$@4*Lr#HYnaJDOwcde5;HXq>r4t1sLW8^x%1x%~ U;!ImUIXsoDfVl3O}4_6j&?-k5CBzK@)Wn z#u;*0DN;wEN8dh%qJxa1hg@LgFdK<*h#uv{#W7jY<4RRIq2{j=#_W*v)+g4!`^^!G z0tWW5hXdw7j8Me1&vEfOA;d{xNr;W4*hxu{tPpbIrzlQJVxz46RJ50>c&Leky13~H z=bTvRR|H}lfH#<93mBFN&8or@?*Kl-8Y2Q{v2qcYEYGrIZR}A_<-pFBiBzR3A;TPq zTNE*F2FmR3c-=M!Yu;0cXBM$pk|>8|FX3!N1#H@Z_x3i%JD;HUHL?0x-$N(7@NV$q z)rugg1Nc2oY@nQ0k0R3VA#VdkUWIbD!bRZ#HdqmW4{q4uNyM=s#Ci1yZJ@zypjjh? ztvJ|MuoOD*z;AF$MJU-q$+?XvRzi?ec;SZ^{tbSkctHT?QFMZW6?Vgt?2rkOpktl? z>>DijI`5x4)`K8|2>P0Y?bP#w1A+X1>%4;ObNzhWp+upobJMv&5rIHIH`tR1eYXxt zaO1+B*65|;`)O?Ql&RB%Zon|t?|W(%(1B&oqxFOk!M!c4 3@pGTqY# zSsZRMYIW54)q+64->z_2uzoWr-_)Eg519!TfE9FNWni`k2GqO6TEtG<#);u&xhp z;QSxR|0cJwSm3etFuup!nGCueckdqGh8~m&GZAeNNSx8A6UT0!7AQ?P0u96d`0Jnl z2*5LeASl@HAe0ImZo1_F0fP3}Yo9^pA^cFvU|efG4G|@Bp(_P{1Gqne2}%(**R^ZY zfv!`RZasRT#A4GYR+w=81~4!Ux&eVGfZ~M+g(w^f3co`DmBR+X5qz|v2&mx*5`i%x zK^_I47k|C_P7mvybHl5+|2(rzG(b7gto55~l+7WKd7~RS@?b%~t;>Q~N6n~jxVQoQ zTuQpEY7;mZ>lVZQ-)8!t3G(j)|G?>=iULBAy8&(YPA4>jXjiCW4H8N9V eOp@-LNV5ZTk??Vc~J#)k1rP4j#3PkW#TCzqLU)M+xKzP(l6$ z>5%fP@pt
$n1w@AwBC5hrhn_9idnZ(NXl`EDDkyh6sWYzAf_HkIAZ`2a^ z!pX)wDsSKX6sewh?uA85(xh9qV%3^;FOg-Gy$=bBOrL%6)i>W|`2m4~hsyu391snF zG6DDtEd36wc_cvF9+a;Ex=NJ#m?N;zkX)1sRChE~s@X%8h1O<+a#WilK#in~hS(i1 zF9cqQ1PWt0##;olqXCc_r4*fuL}gS+9Sr*rqBqGfEv+8Ri#G3$=7aP4eNN%C0%sF| zyKaS7xCORs-C&T$5Ja@uRk0bn? nD(`P=C;iPt73J40D7We~~}PrlNy4UL6B z4cJQRrgTD+g$}?jj?JK~v^1`hese3CV?F~P4y&93U&Xx2TuCo$!Z0;VuNbOi^O#G0 z+Kf5)`Bd5jL?* q9+?jVSOP>iDQSJT&i@C?UPgZIU?DvyMnu_JnF1;l6XDb#3gJb|RRe z4Qa5BSNPt$FhSK5sA^mLd^;3Q#lAEn(~=fHXc9)Yi)%<2$e~Vv!kO}3TU!euh@X?R zsZdRZ7ei)3b$CyJTF^!_8W8u#t#dVKa2%Fw^t=o2mQjtV7&*N>n-0xJ6w|19^-&^O zdy+<2kOO<&Iw7xkvtf(#otj*N0tH&`h8f~I=8)lJwGUYewpj6?pxa5DYfdXvr$9-& z@+Xtgxt7E{r-NVrAL&;A4U->6zt8m4PR6JHKR5Mp))Jk3aQy4n#~;KboYQS}fkh>> zJI!6S?X_QRDxwPb(*D!I(80=GzdoWRUFrp(RIlV@HS6ODO8G|@eQq4FG9!T-!d-GV z1Wp)P)Tl2cT-65mN2L%xsd`zQ@oC4$P{^}!u^W1 9Uc9g>^$&Z>9(CdQxB%cU9NTOT@fB>1y3R? zoG(ZlHTt8LCE@9e=2J@MoE{5hE_nrS-3|93e= ?4GMTbyld-N%AXG&RgbDMrb~C02IQt%DIUi z=QN^ayHPZE8g}V_WiAF0EWf$hsJ*U1hqxr}5%OZH+thcQ_F|y!J!n}FH+E~I06A7R zlT~@R GtpfVRy5$zQc3OaRrMDB=z }T$ zyN50fN*=*tgSD7?_5fv4jEz^9dK%%9^O~ G1oNNsR ( z8@9IK)wKjD0p1PQmV{Up*i3OXb5of?85R>bjyvz!eGjX=vfzHQ3yh#Fp`NS_A(hS# zp<_v1oPEAwT+33L2bv~>Q`#}-7-Hqe;3&L$1Cyu>p}q(CC$?w^c|=Qcs378QNgGSJ z%1)b01+Mo?1*a%+(HtUF^L8EeRp7%J#n4WF&chyed*rc{VZnyUj8ZG`fTj?}`p&5( zL3nYwX0;E+TO-y={?%?h& PN)Sz3SKVt-^2D4EBlYO?WUFge^?*G*3~KfYO!id zn51Q#se83cuhJ{ WnJedY*CEWCy=d$6|1d>g*N!$gplbcEG=a7V+=MBwW zRlasnh^eRiaN}Vruf`_iY24!1&3@TQ=(N3x>&N=y+)_vfDIdG#ID#X0je__vTC!mX z!TGRI7siuayEBQlcl7S|p+R{i5udm8P2&2Utc-HzrRcm$+2Z) oGJ* ONjLENi=TeoXzqm0swbr_{;YQ^y zH1#K@Q+chO^TR>lhFOybWt|q#c*6=5(O#8h6E)v;C?KN=$Gno1sdTaaye{d(Mvu!o zMg5+>_`?FVi1rmF5pw uoCRqD;7jfR=P!_=v_bt%Xct5Z11=`0+xa&tYY=XdX= z0oxevv>@i7;Uv$Byt-E@rFYT%{g?ES9$J8ifX|&-VaFj{;Fel`){T?c!c67nbc{f$ z6JWCbm+uAx0ikaa-sa9r PJm_MP0@>d&mQ%%9*sCt5N9+vR5Zf8z$iztr8too?+{D$2VU#wL*BvgHk&h} z865tU @;ct3Zr|&;mic>Cx4dc*{CJe&K|VRkDJh{$ zW?pmje*M*34;uJh6fZUkGGE^v$VtCOib{wLx|kL%< u2hS-$IvK-XWO}7YI zgoTczw2iusr=78dYY=cR EkQwdCA{o|eX4<2NO=VF10o^x(AKx=kh_^!NUFg*>&Qyrzw$)fUc5v+7;jt7 z>U1Jdyi~?vf-BCMain{1yaSwk$yw4-a))`x{SV#DgmhtFediQ(R%36zx5o@{9NsD2 z0h*f>jnp9}(N4+%dVH-IPP_&*F9+%^sl3@;kweRT*IGLJ_Vv;kl+pml>(s}z+~fsh z>BJk#Dm63h5$Yv8V?GF{H1SRz0$FDIcgf&Hs~T%kW`0;!SyeV;2KD{f?bq|2Pk2wH zH@twoo-))Fq&S@f|Fc|5D5L$)#@O8Mvr*UBPQTMpqA4Ah#{c&fu++y4E6z+L=TK8G zRb~_*R8Vx^oh_ZUU|N(0o*4T$as2bt#H=mceP+1us@3Flw!b=MY8SV<_6hZT 8jOk-@8vIh3hLu>fuv@4$xx}Z!Kj=6R_;Ii zvw9;k>1L>un`Ce^ap3ink>NK_Si@XnE6RVBl>R8lNlhut<@MShNG68|r%{&ED9f2t zkX=tw(yg;}OJv4*uTlzvc5lZ~p8n9@qtI+dw!j>#I=+Gay2bm`xhnLirBPq?%b3_g zW_fY$FtDVC{u!4Qjw_HAjvWWJD-zoE+M3#R+92JPRfM`F?;cwq?;bY{Ugb!nbf&Ro z3fa;n&@V93?_yklBLk^lpX|H&aJI9fzL^+cU|u$?x{iPL5bM9Oe|)m1cTlcT-YUz& zC^vtbaEI$^H0oBN--S!3%+zI161ECMsVmrSLfW}f)0wlA-BD~`*}v0>V#5y{dQNv8 zBR#$&?f1)PwX1=BKRaQmFYev@pPno2*EH8cICIQP?No!jkGkN+zr|}tl)VMj2k{=1 zxJi)-dXvZkeWGjM`|nNA3|RW&+jnEb7sIMNPelk(29n1AuIwl_aj20ivSL{dYm|#5 zmLw3PsYKdAFiD= uB zj;4C14g;1>u9^Jg2`0lshJJWodKX_qi7YaE$xy~ma6@3{@WQaXkjTg+7eLh46`>(w zy`+Kug(@B}PlA#9<$6aAhe^w%5r}%UmLSzjA7Od$>-B?YAD5 a> z;`1IJBUZPm_!l3aAuum!eoRwmX{5KYHWer$cl{pbYq7Pob+9$jG#73m=zIKwefRlM zUju$WJj`I;=0g1eUnOO)9~t}JbA6tf$8UVMsj{!Ql9!osr7{=g1?Gh2N9j`0*67 egJA?=9 ?W>7f2=JwvmI6 znCL5?ibZXCzGT~0+KcEf=UYwLhPi__iucFMGsAa-^YHO4fCGkFa8}mpN%R2bX8zsG zezWFztLC2c!n>fB;#nBQV&8#rifA173|hj7!I7G zlMNQBQzySlS8On^Q!{UL& z1cx|c0Py!H_bVPylP>x$r>?1OIY>BsCP-ePY3K-yFJaN~)>E(dh&1 q|Uy)&@OM%<{IgRjb32PhWn8cd@^F$eCC)FZ?^liD+C$Jz}KUU&4{a< zM)p6fGB}9U#{XT;q%HAC|KqHQ{ 3xwm8+*w3waQ_zbkxdB3lT zk4%KbvoZktycr)ALY)~~7sU;r`zs$&nk 9*BL2Ojv-gw7#OE4BFQh&3id{5 z;$~^HwOaC;T0(Ip27G$)3B_5p6SN5&$Rq^>BtB^GnTGLU#^AT (1BgRe)qgeOdn2Q62^cU5_S)AAJe*r{UpcKv >BJh=TL;ZTA;&O47gjxK=?JQiDO;d z?y>B-uzP#|eQi+^UAl7>1|Ghj&!7K1d!uLVx-^)6X02g9%`~_q*HmbD^pvTkze^ob z*MFC4Ox5V9`#ECl66OlctxYh`Kgv;ToPi$>!xXQ=XcoH;Y{JAeZQm~ARhRJ8fyJZq zGY9EH>x`9R!J$Xk;-x56Jlci>Szc7AIV?dHzS<;OIt6jXvn*b#uEV3JzPz2jwe+ZS zC?GK|*e|&}0gu+G2Hg)KHK`Bo)g-59B$KnUeJW??f-e`8Bxe*9S4WMF*F+bUrcz4E z125km_pZsMrDiCj;^Ih;#$wjTVnZIr*}=x6Lqf-*?yUj{ckh!eSqQp^P0+oj8?UQ9 zqOBgUeoZ}rMIPf%p@4G_bI&yM8x!>NJ8m+pbfxq&yqeIH8zIwY^%S#0?lO>+?vg6X zwQx849N+tDy^=#gP8Gq-URy1xa~WO@Y*WiS=(W3ygvJVLZXL-(@2nYF^RQWyeu$e= z(%}~SJx2S@2u5Cd=j6@Ov<_ULoA6nB>Dgrw0cY)arJ=-jXg`(WRn_}sUEWq#Q+?xM zUl9G)!^*nWE5!w#E>?~%0hw{3(TiERI5}B*|4VJFJw~{u$$M?{oj_YlwJ@QfzK-u| z%~4YGEYsd-GRbg~X+JyBZEJLYa>8h?*B1PSJFU-KCq*U4`2;sawGrhq;`L1BW$V~| zT9Y%=%X7)9?)%IgV^7;2XXb`jfStOm3#hC`G4bj38esp_dyF)RW_oq?d`(rtZLL*8 zeDzPDp)VFW7x>GYQWD}WX~sxHxta}@C;t&ch})Hf?zmK?kJxG{7@DYhWr575U>&Uv z@W+OIiz@wn3o88l3yOXHii`gVC>WkoQZ_VFIBR4|G%|z}g*L=eVohUBa%pmPBR~IV zoiZJ0sjwxU-beJ-lm4T6{@i(`YEnZXzC1C=*WcgLv?GrOJVh6+jPzBd#COjr8OfZi z_P87ypII60dsfduYj4pBntyXVCGA>5K#jPmiq1I$71_{A#18l-VU=C97zE^$W8m_| z%J3<*QX!^tBc9|$ZYeZ3SlG^%2FQ4;E&Sid3#|XPH~~wCf~S9)JXR&IlXBruciH{| z_u3E|&fm;NR`SeGcl?obcvn$v|3op#Bb)#%S3PS6M=L4^hZ~G)nIm#HN3LDQdbx#K zS-OzCO+DR0EibqRB5rWL5&TXhx<>R5vw83bhLHlj;zJx6NZsn~{_%zB?)KX2#1Ji$ zf??HMii)49ix?3CVO(x 7siIU-(9jB#yFdy(B0x0ZV7x5E00&Es2h+Ey)1T zW!T=Id&TS-@2X9>G^;0T Z>?d-eIbK3D#1vmM$d_ah^g`A=5jRKp@3-(!a zRxUpNcF#q@bd?{Q(XDB{=A6?w*j8G--oCVA9S|7n>qiZ|&`+R!>=_K}u#mP;H*L4^ zd$ #k=bG?8PiW+f7fI18 !~+1bwu4LpWYQXTrF6l>neU(dRcWZ;QQ z<=n%OW#E)wf2%ROVJs=3Y;6FvAKGmVY`H4sN6&Ur4obr$ekgQ^exYOktY*=IoKG4Q z#(UoxE!V7x`@2HP^R*T+EQ y;C%xFzOa$)4O7j)%eW2r_UzHvcp%K+VGqK+N6W^ znzPg~6hcx* +m^T^ObS(ji>;_1WM}H zj61>Vo@ySGA>>6C$$ta*{@N$h%-Y9ueRWT>GU^w!??3h|zATW*wLgJU3{qb2*vgBW zi<-+hzH*0vNJNrtT)3lCY(!gZ%s_06k+r0@j $ZjqYW7C~ZcDt#y z9Xweh9fu2uraB)Db5#;Pa#~SG9C)_){Pdj?Q3aHN@QZF!z*;2etM8PIqUH6cfT!Ce zWbgMia7aYuM>4#;J!T;LjIX`}1y#miTqSxuT-4BRLgv)~xBGy c5)0QI*Zx{ z2D&&01=+zNQ6xJ@ER|0zEeE*5dY9@hGZ)E0a^Z5I&%a$HpZl;p;ZPEKwEMxeaBpG0 z+NeX(KMo$lvUkOIWp*WWv0@J%{_Iaa%vVno3A#$3#SUIdNXkqCwM}7arW}=$>98+^ zmP^YG+2` v1?*Esi8@-IV~OPQBf2cpmS1zJ@>&ZR%7Z;d z7&*M=AQiO87Al|bbvNzUJ 0T~v&!JYfLT&Dqigs#FX)97yg&WRFM|XFR zQq#~qfS=v?e+bM@1*8NtS2ssty`!=9al0$R>=2wHoxhysEYPfZ&?qUF5))sWM~-Po zz 7#kV3fJo}$R9<#O@VUM*DUzHQ6<$-GMs2uODtmwF pRdGco3JZE|MiRaBu`RW_g7 zrIJ+l*lL%P=Tt3CLyMWJ%6Us2EkhGf+sNRUr~z}sZtq8BrBk;JmkwY0_d@lFTmSr> z>B$Q}j;j}I^@~3M8zcMyFe2pl6Xv+bN)H^KB_{sbfBxCEp_~6gf8A2B>%t#AVYlat zUDoXS*bATg>E*E+`@A7DJPwL=qOBeth|*bll>t9>kS>+Zx%L4V|7)f>x$5GtW_XoO zFk2crpucR%QCVof-D-e$D;V&1tahM`KnLY^Z?2nLEZuh6F57K;QoYyU?EeR5|3NbX zj{vHd*Ve{FgI($_sZh|m5o^fJHM5*&B9uS+`)M*u3-i$8_-xF2nBO^hsq1%WgB!83 z++0QD{>Bk^b!&7Z$h*0zIqqLbkipCEARDJFLea{$uL(ET>%~0Vp_*ZR9WV(>-u6z1 zLghv*rkiVg+~1d=W&x$DCyp!tk%PJyd>Z7Q-;C#-jmi0Kud$t_`HDU0(~X8T^b;Z& zLd{B>1Zg|oVBB9W)IHt5)D1*@<%wPwOXR`ZXsZ@DQzr$>;M}v8xTGz^nYzT5Q}akD z3-+Fvvi8`d?fr>W-kQANY|a6kd;Nb72VkdwqYOdzu(xYpvNl*F3;l;^F#gC-)jQK} zxWTafx`1AIEN{LK@?Vo*S76h1a$z~Fec(l<)vI>TuB=AaUe=&r+uNB7UPExp-}gaR z3bo}_5&7clGsW^9=`uL*QEh^SJOJE~UuVt(3Z=3Pb~^K&Q>yzwj52>aN7e{z?AG2# zImb1avD&(AxbsV~9z3x(BiK8IypwQY$Jv5%P46dKjucK*pM#*UH7eZ7L^=(>!OJIK z)T@i9eOxnW`;FS*X8FGg;_|p39h4*S z(U_J|A#M1L8?+~y6nHMqs{vrE{w6q4<#Xip>VCdyrkn+zvxD;7EOHXW8T~)p1j;V> z{@=rv7;Jf;J}w*7&-xpVoQshg0BX#3=@TfvvzQ%JWWj~=pL7k>xZY=k{T1CCp&V6t z+a?(L>BoV#Lm%hzJo^cgkE@U9bQO^i2W7HU@07+wYPMJZ(LZ1ru*2N)2v9ay#l7&l z>A6*Z$M2f}@ZwLr5&*mt7Qg*E@ONRBn! (BJ&gP}H z{%vp7vK;CP4W+#mHHm`mBER{`dwKKOH>8(oVwL1z%VfF=94hie%K>@S7~we<23p_@ z7s#UmX)r-ZvAxy@ +?xWT*pw#AYw^=s(h=OY1 zgydtbb~H~FOo^!#&q3fM$Zk@cCY9@`ao$r@TLQQ7l^q}D#BL4^7wI2WjcA}Y|L5xR zINICUTz9WRXmP8tHb0cQN_arS>H6KtIzv#HUDeiHpLJmK^-!r%K5BF0Hw_$b534VW zJ6 SwB>M+7|=n^NN{!lnhmE!oNa;)e3 z(dB-|HJ5fVXHwkogSZa~ dwS%1Vh9mi*5Z?%B{nEOoIq_bf?gC}4L7Ioxosj_n(SSyf6)Xf`87NR2!a;z^ zMQBK41#mpj?T_H#vOfwJ|6Fu`E(Z3;5)-{Y&OtS+%f$+ljyu62F(f}9-*6!rDQQzJ zq#vxRpXeQE800Czv=R_Q7S |qg3MsA-7qI(fGGAYbY1cipg zAlb7jNJc;FXH4RE3hoXMQI<5NQB0!1Laf`<*IS}7(u8Ef&vPP(u;!OEHq_BGwRA!p ON3B$ub4ks;IsgFgYn-P5 literal 0 HcmV?d00001 diff --git a/web/berry/src/assets/images/icons/lark.svg b/web/berry/src/assets/images/icons/lark.svg new file mode 100644 index 0000000000..239e1bef65 --- /dev/null +++ b/web/berry/src/assets/images/icons/lark.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/berry/src/assets/images/logo-white.svg b/web/berry/src/assets/images/logo-white.svg new file mode 100644 index 0000000000..d6289b9af6 --- /dev/null +++ b/web/berry/src/assets/images/logo-white.svg @@ -0,0 +1,13 @@ + \ No newline at end of file diff --git a/web/berry/src/assets/scss/_themes-vars.module.scss b/web/berry/src/assets/scss/_themes-vars.module.scss index a470b033eb..661bb6c6cc 100644 --- a/web/berry/src/assets/scss/_themes-vars.module.scss +++ b/web/berry/src/assets/scss/_themes-vars.module.scss @@ -46,11 +46,16 @@ $grey600: #4b5565; $grey700: #364152; $grey900: #121926; +$tableBackground: #f4f6f8; +$tableBorderBottom: #f1f3f4; + // ==============================|| DARK THEME VARIANTS ||============================== // // paper & background $darkBackground: #1a223f; // level 3 $darkPaper: #111936; // level 4 +$darkDivider: rgba(227, 232, 239, 0.2); +$darkSelectedBack : rgba(124, 77, 255, 0.15); // dark 800 & 900 $darkLevel1: #29314f; // level 1 @@ -154,4 +159,9 @@ $darkTextSecondary: #8492c4; darkSecondaryDark: $darkSecondaryDark; darkSecondary200: $darkSecondary200; darkSecondary800: $darkSecondary800; + + darkDivider: $darkDivider; + darkSelectedBack: $darkSelectedBack; + tableBackground: $tableBackground; + tableBorderBottom: $tableBorderBottom; } diff --git a/web/berry/src/assets/scss/fonts.scss b/web/berry/src/assets/scss/fonts.scss new file mode 100644 index 0000000000..c792aab27c --- /dev/null +++ b/web/berry/src/assets/scss/fonts.scss @@ -0,0 +1,32 @@ + +/* roboto-regular */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: local('Roboto'), url('../fonts/roboto-regular.woff2') format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; + } + + /* roboto-500 */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 500; + font-display: swap; + src: local('Roboto'), url('../fonts/roboto-500.woff2') format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} + + +/* roboto-700 */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: local('Roboto'), url('../fonts/roboto-700.woff2') format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} + \ No newline at end of file diff --git a/web/berry/src/assets/scss/style.scss b/web/berry/src/assets/scss/style.scss index 17d566e623..5d2d897533 100644 --- a/web/berry/src/assets/scss/style.scss +++ b/web/berry/src/assets/scss/style.scss @@ -1,3 +1,4 @@ +@import 'fonts.scss'; // color variants @import 'themes-vars.module.scss'; diff --git a/web/berry/src/hooks/useLogin.js b/web/berry/src/hooks/useLogin.js index 53626577ba..39d8b40741 100644 --- a/web/berry/src/hooks/useLogin.js +++ b/web/berry/src/hooks/useLogin.js @@ -48,6 +48,28 @@ const useLogin = () => { } }; + const larkLogin = async (code, state) => { + try { + const res = await API.get(`/api/oauth/lark?code=${code}&state=${state}`); + const { success, message, data } = res.data; + if (success) { + if (message === 'bind') { + showSuccess('绑定成功!'); + navigate('/panel'); + } else { + dispatch({ type: LOGIN, payload: data }); + localStorage.setItem('user', JSON.stringify(data)); + showSuccess('登录成功!'); + navigate('/panel'); + } + } + return { success, message }; + } catch (err) { + // 请求失败,设置错误信息 + return { success: false, message: '' }; + } + }; + const wechatLogin = async (code) => { try { const res = await API.get(`/api/oauth/wechat?code=${code}`); @@ -72,7 +94,7 @@ const useLogin = () => { navigate('/'); }; - return { login, logout, githubLogin, wechatLogin }; + return { login, logout, githubLogin, wechatLogin, larkLogin }; }; export default useLogin; diff --git a/web/berry/src/layout/MainLayout/Header/ProfileSection/index.js b/web/berry/src/layout/MainLayout/Header/ProfileSection/index.js index 3e3512546a..e1392dc00a 100644 --- a/web/berry/src/layout/MainLayout/Header/ProfileSection/index.js +++ b/web/berry/src/layout/MainLayout/Header/ProfileSection/index.js @@ -71,8 +71,8 @@ const ProfileSection = () => { alignItems: 'center', borderRadius: '27px', transition: 'all .2s ease-in-out', - borderColor: theme.palette.primary.light, - backgroundColor: theme.palette.primary.light, + borderColor: theme.typography.menuChip.background, + backgroundColor: theme.typography.menuChip.background, '&[aria-controls="menu-list-grow"], &:hover': { borderColor: theme.palette.primary.main, background: `${theme.palette.primary.main}!important`, diff --git a/web/berry/src/layout/MainLayout/Header/index.js b/web/berry/src/layout/MainLayout/Header/index.js index 51d40c7546..8fd9c950c8 100644 --- a/web/berry/src/layout/MainLayout/Header/index.js +++ b/web/berry/src/layout/MainLayout/Header/index.js @@ -7,6 +7,7 @@ import { Avatar, Box, ButtonBase } from '@mui/material'; // project imports import LogoSection from '../LogoSection'; import ProfileSection from './ProfileSection'; +import ThemeButton from 'ui-component/ThemeButton'; // assets import { IconMenu2 } from '@tabler/icons-react'; @@ -37,9 +38,8 @@ const Header = ({ handleLeftDrawerToggle }) => { sx={{ ...theme.typography.commonAvatar, ...theme.typography.mediumAvatar, + ...theme.typography.menuButton, transition: 'all .2s ease-in-out', - background: theme.palette.secondary.light, - color: theme.palette.secondary.dark, '&:hover': { background: theme.palette.secondary.dark, color: theme.palette.secondary.light @@ -55,7 +55,7 @@ const Header = ({ handleLeftDrawerToggle }) => { - + > ); diff --git a/web/berry/src/layout/MainLayout/Sidebar/MenuCard/index.js b/web/berry/src/layout/MainLayout/Sidebar/MenuCard/index.js index 16b132319b..dadd3ecab6 100644 --- a/web/berry/src/layout/MainLayout/Sidebar/MenuCard/index.js +++ b/web/berry/src/layout/MainLayout/Sidebar/MenuCard/index.js @@ -36,7 +36,7 @@ import { useNavigate } from 'react-router-dom'; // })); const CardStyle = styled(Card)(({ theme }) => ({ - background: theme.palette.primary.light, + background: theme.typography.menuChip.background, marginBottom: '22px', overflow: 'hidden', position: 'relative', @@ -121,7 +121,6 @@ const MenuCard = () => { /> - {/* */} ); diff --git a/web/berry/src/layout/MainLayout/Sidebar/index.js b/web/berry/src/layout/MainLayout/Sidebar/index.js index e3c6d12d3a..10652ba691 100644 --- a/web/berry/src/layout/MainLayout/Sidebar/index.js +++ b/web/berry/src/layout/MainLayout/Sidebar/index.js @@ -39,7 +39,13 @@ const Sidebar = ({ drawerOpen, drawerToggle, window }) => { - @@ -48,7 +54,13 @@ const Sidebar = ({ drawerOpen, drawerToggle, window }) => {+ - diff --git a/web/berry/src/layout/MinimalLayout/Header/index.js b/web/berry/src/layout/MinimalLayout/Header/index.js index 4f61da6088..feaeb60356 100644 --- a/web/berry/src/layout/MinimalLayout/Header/index.js +++ b/web/berry/src/layout/MinimalLayout/Header/index.js @@ -1,10 +1,30 @@ // material-ui -import { useTheme } from "@mui/material/styles"; -import { Box, Button, Stack } from "@mui/material"; -import LogoSection from "layout/MainLayout/LogoSection"; -import { Link } from "react-router-dom"; -import { useLocation } from "react-router-dom"; -import { useSelector } from "react-redux"; +import { useState } from 'react'; +import { useTheme } from '@mui/material/styles'; +import { + Box, + Button, + Stack, + Popper, + IconButton, + List, + ListItemButton, + Paper, + ListItemText, + Typography, + Divider, + ClickAwayListener +} from '@mui/material'; +import LogoSection from 'layout/MainLayout/LogoSection'; +import { Link } from 'react-router-dom'; +import { useLocation } from 'react-router-dom'; +import { useSelector } from 'react-redux'; +import ThemeButton from 'ui-component/ThemeButton'; +import ProfileSection from 'layout/MainLayout/Header/ProfileSection'; +import { IconMenu2 } from '@tabler/icons-react'; +import Transitions from 'ui-component/extended/Transitions'; +import MainCard from 'ui-component/cards/MainCard'; +import { useMediaQuery } from '@mui/material'; // ==============================|| MAIN NAVBAR / HEADER ||============================== // @@ -12,16 +32,26 @@ const Header = () => { const theme = useTheme(); const { pathname } = useLocation(); const account = useSelector((state) => state.account); + const [open, setOpen] = useState(null); + const isMobile = useMediaQuery(theme.breakpoints.down('sm')); + + const handleOpenMenu = (event) => { + setOpen(open ? null : event.currentTarget); + }; + + const handleCloseMenu = () => { + setOpen(null); + }; return ( <>+ @@ -31,43 +61,99 @@ const Header = () => { - - - - {account.user ? ( - + + {isMobile ? ( + <> + + ++ + + > ) : ( - + <> + + ++ + {account.user ? ( + <> + + + > + ) : ( + + )} + > )} + {({ TransitionProps }) => ( + > ); }; diff --git a/web/berry/src/layout/MinimalLayout/index.js b/web/berry/src/layout/MinimalLayout/index.js index c2919c6d79..81047fd165 100644 --- a/web/berry/src/layout/MinimalLayout/index.js +++ b/web/berry/src/layout/MinimalLayout/index.js @@ -1,6 +1,6 @@ import { Outlet } from 'react-router-dom'; import { useTheme } from '@mui/material/styles'; -import { AppBar, Box, CssBaseline, Toolbar } from '@mui/material'; +import { AppBar, Box, CssBaseline, Toolbar, Container } from '@mui/material'; import Header from './Header'; import Footer from 'ui-component/Footer'; @@ -22,9 +22,11 @@ const MinimalLayout = () => { flex: 'none' }} > -+ + )} ++ ++ ++ ++
++ + +首页} /> + + +关于} /> + + {account.user ? ( + + 控制台 + + ) : ( ++ 登录 + + )} +- +- + + ++ diff --git a/web/berry/src/routes/OtherRoutes.js b/web/berry/src/routes/OtherRoutes.js index 085c4add76..58c0b660e6 100644 --- a/web/berry/src/routes/OtherRoutes.js +++ b/web/berry/src/routes/OtherRoutes.js @@ -8,6 +8,7 @@ import MinimalLayout from 'layout/MinimalLayout'; const AuthLogin = Loadable(lazy(() => import('views/Authentication/Auth/Login'))); const AuthRegister = Loadable(lazy(() => import('views/Authentication/Auth/Register'))); const GitHubOAuth = Loadable(lazy(() => import('views/Authentication/Auth/GitHubOAuth'))); +const LarkOAuth = Loadable(lazy(() => import('views/Authentication/Auth/LarkOAuth'))); const ForgetPassword = Loadable(lazy(() => import('views/Authentication/Auth/ForgetPassword'))); const ResetPassword = Loadable(lazy(() => import('views/Authentication/Auth/ResetPassword'))); const Home = Loadable(lazy(() => import('views/Home'))); @@ -48,6 +49,10 @@ const OtherRoutes = { path: '/oauth/github', element: }, + { + path: '/oauth/lark', + element: + }, { path: '/404', element: diff --git a/web/berry/src/store/actions.js b/web/berry/src/store/actions.js index 221e8578e6..f1592d17d7 100644 --- a/web/berry/src/store/actions.js +++ b/web/berry/src/store/actions.js @@ -7,3 +7,4 @@ export const SET_BORDER_RADIUS = '@customization/SET_BORDER_RADIUS'; export const SET_SITE_INFO = '@siteInfo/SET_SITE_INFO'; export const LOGIN = '@account/LOGIN'; export const LOGOUT = '@account/LOGOUT'; +export const SET_THEME = '@customization/SET_THEME'; diff --git a/web/berry/src/store/customizationReducer.js b/web/berry/src/store/customizationReducer.js index bd8e5f00e3..0c10402577 100644 --- a/web/berry/src/store/customizationReducer.js +++ b/web/berry/src/store/customizationReducer.js @@ -9,7 +9,8 @@ export const initialState = { defaultId: 'default', fontFamily: config.fontFamily, borderRadius: config.borderRadius, - opened: true + opened: true, + theme: 'light' }; // ==============================|| CUSTOMIZATION REDUCER ||============================== // @@ -38,6 +39,11 @@ const customizationReducer = (state = initialState, action) => { ...state, borderRadius: action.borderRadius }; + case actionTypes.SET_THEME: + return { + ...state, + theme: action.theme + }; default: return state; } diff --git a/web/berry/src/themes/compStyleOverride.js b/web/berry/src/themes/compStyleOverride.js index b6e87e0182..67a3dd1486 100644 --- a/web/berry/src/themes/compStyleOverride.js +++ b/web/berry/src/themes/compStyleOverride.js @@ -1,5 +1,5 @@ export default function componentStyleOverrides(theme) { - const bgColor = theme.colors?.grey50; + const bgColor = theme.mode === 'dark' ? theme.backgroundDefault : theme.colors?.grey50; return { MuiButton: { styleOverrides: { @@ -12,15 +12,7 @@ export default function componentStyleOverrides(theme) { } } }, - MuiMenuItem: { - styleOverrides: { - root: { - '&:hover': { - backgroundColor: theme.colors?.grey100 - } - } - } - }, //MuiAutocomplete-popper MuiPopover-root + //MuiAutocomplete-popper MuiPopover-root MuiAutocomplete: { styleOverrides: { popper: { @@ -226,12 +218,12 @@ export default function componentStyleOverrides(theme) { MuiTableCell: { styleOverrides: { root: { - borderBottom: '1px solid rgb(241, 243, 244)', + borderBottom: '1px solid ' + theme.tableBorderBottom, textAlign: 'center' }, head: { color: theme.darkTextSecondary, - backgroundColor: 'rgb(244, 246, 248)' + backgroundColor: theme.headBackgroundColor } } }, @@ -239,7 +231,7 @@ export default function componentStyleOverrides(theme) { styleOverrides: { root: { '&:hover': { - backgroundColor: 'rgb(244, 246, 248)' + backgroundColor: theme.headBackgroundColor } } } @@ -247,10 +239,29 @@ export default function componentStyleOverrides(theme) { MuiTooltip: { styleOverrides: { tooltip: { - color: theme.paper, + color: theme.colors.paper, background: theme.colors?.grey700 } } + }, + MuiCssBaseline: { + styleOverrides: ` + .apexcharts-title-text { + fill: ${theme.textDark} !important + } + .apexcharts-text { + fill: ${theme.textDark} !important + } + .apexcharts-legend-text { + color: ${theme.textDark} !important + } + .apexcharts-menu { + background: ${theme.backgroundDefault} !important + } + .apexcharts-gridline, .apexcharts-xaxistooltip-background, .apexcharts-yaxistooltip-background { + stroke: ${theme.divider} !important; + } + ` } }; } diff --git a/web/berry/src/themes/index.js b/web/berry/src/themes/index.js index 6e694aa6f7..addd61f74f 100644 --- a/web/berry/src/themes/index.js +++ b/web/berry/src/themes/index.js @@ -15,19 +15,10 @@ import themeTypography from './typography'; export const theme = (customization) => { const color = colors; - + const options = customization.theme === 'light' ? GetLightOption() : GetDarkOption(); const themeOption = { colors: color, - heading: color.grey900, - paper: color.paper, - backgroundDefault: color.paper, - background: color.primaryLight, - darkTextPrimary: color.grey700, - darkTextSecondary: color.grey500, - textDark: color.grey900, - menuSelected: color.secondaryDark, - menuSelectedBack: color.secondaryLight, - divider: color.grey200, + ...options, customization }; @@ -53,3 +44,49 @@ export const theme = (customization) => { }; export default theme; + +function GetDarkOption() { + const color = colors; + return { + mode: 'dark', + heading: color.darkTextTitle, + paper: color.darkLevel2, + backgroundDefault: color.darkPaper, + background: color.darkBackground, + darkTextPrimary: color.darkTextPrimary, + darkTextSecondary: color.darkTextSecondary, + textDark: color.darkTextTitle, + menuSelected: color.darkSecondaryMain, + menuSelectedBack: color.darkSelectedBack, + divider: color.darkDivider, + borderColor: color.darkBorderColor, + menuButton: color.darkLevel1, + menuButtonColor: color.darkSecondaryMain, + menuChip: color.darkLevel1, + headBackgroundColor: color.darkBackground, + tableBorderBottom: color.darkDivider + }; +} + +function GetLightOption() { + const color = colors; + return { + mode: 'light', + heading: color.grey900, + paper: color.paper, + backgroundDefault: color.paper, + background: color.primaryLight, + darkTextPrimary: color.grey700, + darkTextSecondary: color.grey500, + textDark: color.grey900, + menuSelected: color.secondaryDark, + menuSelectedBack: color.secondaryLight, + divider: color.grey200, + borderColor: color.grey300, + menuButton: color.secondaryLight, + menuButtonColor: color.secondaryDark, + menuChip: color.primaryLight, + headBackgroundColor: color.tableBackground, + tableBorderBottom: color.tableBorderBottom + }; +} diff --git a/web/berry/src/themes/palette.js b/web/berry/src/themes/palette.js index 097685553a..70c7878251 100644 --- a/web/berry/src/themes/palette.js +++ b/web/berry/src/themes/palette.js @@ -5,7 +5,7 @@ export default function themePalette(theme) { return { - mode: 'light', + mode: theme.mode, common: { black: theme.colors?.darkPaper }, diff --git a/web/berry/src/themes/typography.js b/web/berry/src/themes/typography.js index 24bfabb936..f20d87a5fb 100644 --- a/web/berry/src/themes/typography.js +++ b/web/berry/src/themes/typography.js @@ -132,6 +132,19 @@ export default function themeTypography(theme) { width: '44px', height: '44px', fontSize: '1.5rem' + }, + menuButton: { + color: theme.menuButtonColor, + background: theme.menuButton + }, + menuChip: { + background: theme.menuChip + }, + CardWrapper: { + backgroundColor: theme.mode === 'dark' ? theme.colors.darkLevel2 : theme.colors.primaryDark + }, + SubCard: { + border: theme.mode === 'dark' ? '1px solid rgba(227, 232, 239, 0.2)' : '1px solid rgb(227, 232, 239)' } }; } diff --git a/web/berry/src/ui-component/Logo.js b/web/berry/src/ui-component/Logo.js index a34fe8954c..52e61f4f6c 100644 --- a/web/berry/src/ui-component/Logo.js +++ b/web/berry/src/ui-component/Logo.js @@ -1,6 +1,8 @@ // material-ui -import logo from 'assets/images/logo.svg'; +import logoLight from 'assets/images/logo.svg'; +import logoDark from 'assets/images/logo-white.svg'; import { useSelector } from 'react-redux'; +import { useTheme } from '@mui/material/styles'; /** * if you want to use image instead of + @@ -205,6 +210,13 @@ export default function Profile() { )} + {status.lark_client_id && !inputs.lark_id && ( ++ + + )}+ {' '} + 用以支持通过飞书进行登录注册, + + 点击此处 + + 管理你的飞书应用 + + } + > + + ++ ++ 主页链接填 +{inputs.ServerAddress}
+ ,重定向 URL 填{`${inputs.ServerAddress}/oauth/lark`}
++ ++ +App ID ++ + ++ +App Secret ++ + + +{ ++ 用以推送报警信息, + + 点击此处 + + 了解 Message Pusher + + } + > + + ++ ++ +Message Pusher 推送地址 ++ + ++ +Message Pusher 访问凭证 ++ + + +; +const checkedIcon = ; +const filter = createFilterOptions(); const validationSchema = Yup.object().shape({ is_edit: Yup.boolean(), - name: Yup.string().required("名称 不能为空"), - remain_quota: Yup.number().min(0, "必须大于等于0"), + name: Yup.string().required('名称 不能为空'), + remain_quota: Yup.number().min(0, '必须大于等于0'), expired_time: Yup.number(), - unlimited_quota: Yup.boolean(), + unlimited_quota: Yup.boolean() }); const originInputs = { is_edit: false, - name: "", + name: '', remain_quota: 0, expired_time: -1, unlimited_quota: false, + subnet: '', + models: [] }; const EditModal = ({ open, tokenId, onCancel, onOk }) => { const theme = useTheme(); const [inputs, setInputs] = useState(originInputs); + const [modelOptions, setModelOptions] = useState([]); const submit = async (values, { setErrors, setStatus, setSubmitting }) => { setSubmitting(true); values.remain_quota = parseInt(values.remain_quota); let res; + let models = values.models.join(','); if (values.is_edit) { - res = await API.put(`/api/token/`, { ...values, id: parseInt(tokenId) }); + res = await API.put(`/api/token/`, { ...values, id: parseInt(tokenId), models: models }); } else { - res = await API.post(`/api/token/`, values); + res = await API.post(`/api/token/`, { ...values, models: models }); } const { success, message } = res.data; if (success) { if (values.is_edit) { - showSuccess("令牌更新成功!"); + showSuccess('令牌更新成功!'); } else { - showSuccess("令牌创建成功,请在列表页面点击复制获取令牌!"); + showSuccess('令牌创建成功,请在列表页面点击复制获取令牌!'); } setSubmitting(false); setStatus({ success: true }); @@ -78,61 +91,55 @@ const EditModal = ({ open, tokenId, onCancel, onOk }) => { const { success, message, data } = res.data; if (success) { data.is_edit = true; + if (data.models === '') { + data.models = []; + } else { + data.models = data.models.split(','); + } setInputs(data); } else { showError(message); } }; + const loadAvailableModels = async () => { + let res = await API.get(`/api/user/available_models`); + const { success, message, data } = res.data; + if (success) { + setModelOptions(data); + } else { + showError(message); + } + }; useEffect(() => { if (tokenId) { loadToken().then(); } else { - setInputs({...originInputs}); + setInputs({ ...originInputs }); } + loadAvailableModels().then(); }, [tokenId]); return ( -