Browse Source

feat: 增加qu全局loading

周玉环 1 tuần trước cách đây
mục cha
commit
47b784eb6b
5 tập tin đã thay đổi với 71 bổ sung16 xóa
  1. 1 1
      .env.development
  2. 3 2
      src/App.tsx
  3. 18 0
      src/pages/login/index.module.css
  4. 31 13
      src/pages/login/index.tsx
  5. 18 0
      src/utils/lodash.ts

+ 1 - 1
.env.development

@@ -10,4 +10,4 @@ VITE_APP_TITLE=Content Management System (Dev)
 VITE_USE_MOCK=false
 
 # jeecg跳转路由
-VITE_JEECG_DOAMAIN=/admin
+VITE_JEECG_DOAMAIN=https://yongwei.advichcloud.com/admin

+ 3 - 2
src/App.tsx

@@ -1,4 +1,5 @@
 import { AuthProvider, useAuth } from "./contexts/AuthContext";
+import { Spinner } from "@contentful/f36-components";
 import { MenuProvider } from "./contexts/MenuContext";
 import { RouterProvider } from "react-router-dom";
 import { createAppRouter } from "./router";
@@ -12,7 +13,7 @@ function AppRouter() {
     if (window.location.pathname.includes("/login")) {
       return createAppRouter([]);
     }
-    
+
     if (menus.length === 0) {
       return null;
     }
@@ -29,7 +30,7 @@ function AppRouter() {
           height: "100vh",
         }}
       >
-        加载中...
+        <Spinner variant="primary" size="large"/>
       </div>
     );
   }

+ 18 - 0
src/pages/login/index.module.css

@@ -59,6 +59,24 @@
   text-decoration: underline;
 }
 
+/* 密码输入框相关样式 */
+.passwordInputWrapper {
+  position: relative;
+  display: flex;
+  align-items: center;
+}
+
+.passwordToggle {
+  position: absolute;
+  right: 8px;
+  z-index: 1;
+  color: #8091a5;
+}
+
+.passwordToggle:hover {
+  color: #0066ff;
+}
+
 /* 验证码相关样式 */
 .captchaInputWrapper {
   flex: 1;

+ 31 - 13
src/pages/login/index.tsx

@@ -6,11 +6,14 @@ import {
   Button,
   FormControl,
   Note,
+  IconButton,
 } from "@contentful/f36-components";
+import { EyeIcon, EyeClosedIcon } from "@contentful/f36-icons";
 import { useNavigate } from "react-router-dom";
 import { authApi } from "@/services/modules/system";
 import { useAuth } from "@/contexts/AuthContext";
 import { useLoginAuth } from "./hooks/useAuth";
+import { debounce } from "@/utils/lodash";
 import styles from "./index.module.css";
 
 export default function LoginPage() {
@@ -20,6 +23,7 @@ export default function LoginPage() {
   const [captchaKey, setCaptchaKey] = useState("");
   const [captchaImage, setCaptchaImage] = useState("");
   const [errorMessage, setErrorMessage] = useState("");
+  const [showPassword, setShowPassword] = useState(false);
   
   const navigate = useNavigate();
   const { refreshAuth } = useAuth();
@@ -120,18 +124,32 @@ export default function LoginPage() {
               {/* Password */}
               <FormControl className={styles.form_control}>
                 <FormControl.Label>密码</FormControl.Label>
-                <TextInput
-                  type="password"
-                  value={password}
-                  onChange={(e) => {
-                    setPassword(e.target.value);
-                    // 清除错误提示
-                    if (errorMessage) {
-                      setErrorMessage("");
-                    }
-                  }}
-                  placeholder="请输入你的密码"
-                />
+                <Box className={styles.passwordInputWrapper}>
+                  <TextInput
+                    type={showPassword ? "text" : "password"}
+                    value={password}
+                    onChange={(e) => {
+                      setPassword(e.target.value);
+                      // 清除错误提示
+                      if (errorMessage) {
+                        setErrorMessage("");
+                      }
+                    }}
+                    placeholder="请输入你的密码"
+                  />
+                  <IconButton
+                    aria-label={showPassword ? "隐藏密码" : "显示密码"}
+                    icon={showPassword ? <EyeClosedIcon/> : <EyeIcon />}
+                    variant="transparent"
+                    size="small"
+                    onClick={() => setShowPassword(!showPassword)}
+                    className={styles.passwordToggle}
+                    style={{ 
+                      opacity: showPassword ? 0.5 : 1,
+                      transform: showPassword ? 'scale(0.9)' : 'scale(1)'
+                    }}
+                  />
+                </Box>
               </FormControl>
 
               {/* Captcha */}
@@ -152,7 +170,7 @@ export default function LoginPage() {
                     />
                   </Box>
                   <Box
-                    onClick={fetchCaptcha}
+                    onClick={debounce(fetchCaptcha, 500)}
                     className={styles.captchaImage}
                   >
                     {captchaImage ? (

+ 18 - 0
src/utils/lodash.ts

@@ -0,0 +1,18 @@
+/**
+ * 防抖函数
+ * @param fn 
+ * @param delay 
+ * @returns 
+ */
+export function debounce<T extends (...args: any[]) => void>(
+  fn: T,
+  delay = 500
+): (...args: Parameters<T>) => void {
+  let timer: ReturnType<typeof setTimeout> | null = null;
+  return function (this: ThisParameterType<T>, ...args: Parameters<T>) {
+    if (timer) clearTimeout(timer);
+    timer = setTimeout(() => {
+      fn.apply(this, args);
+    }, delay);
+  };
+}