diff --git a/src/components/setting/mods/clash-port-viewer.tsx b/src/components/setting/mods/clash-port-viewer.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..53de768c66155a0ea95962c91eb22cb6db011787
--- /dev/null
+++ b/src/components/setting/mods/clash-port-viewer.tsx
@@ -0,0 +1,103 @@
+import useSWR from "swr";
+import { useEffect, useState } from "react";
+import { useSetRecoilState } from "recoil";
+import { useTranslation } from "react-i18next";
+import { useLockFn } from "ahooks";
+import {
+  Button,
+  Dialog,
+  DialogActions,
+  DialogContent,
+  DialogTitle,
+  List,
+  ListItem,
+  ListItemText,
+  TextField,
+} from "@mui/material";
+import { atomClashPort } from "@/services/states";
+import { getClashConfig } from "@/services/api";
+import { patchClashConfig } from "@/services/cmds";
+import { ModalHandler } from "@/hooks/use-modal-handler";
+import Notice from "@/components/base/base-notice";
+
+interface Props {
+  handler: ModalHandler;
+}
+
+const ClashPortViewer = ({ handler }: Props) => {
+  const { t } = useTranslation();
+
+  const { data: config, mutate: mutateClash } = useSWR(
+    "getClashConfig",
+    getClashConfig
+  );
+
+  const [open, setOpen] = useState(false);
+  const [port, setPort] = useState(config?.["mixed-port"] ?? 9090);
+
+  const setGlobalClashPort = useSetRecoilState(atomClashPort);
+
+  if (handler) {
+    handler.current = {
+      open: () => setOpen(true),
+      close: () => setOpen(false),
+    };
+  }
+
+  useEffect(() => {
+    if (open && config?.["mixed-port"]) {
+      setPort(config["mixed-port"]);
+    }
+  }, [open, config?.["mixed-port"]]);
+
+  const onSave = useLockFn(async () => {
+    if (port < 1000) {
+      return Notice.error("The port should not < 1000");
+    }
+    if (port > 65536) {
+      return Notice.error("The port should not > 65536");
+    }
+
+    setOpen(false);
+    if (port === config?.["mixed-port"]) return;
+
+    await patchClashConfig({ "mixed-port": port });
+    setGlobalClashPort(port);
+    Notice.success("Change Clash port successfully!", 1000);
+    mutateClash();
+  });
+
+  return (
+    <Dialog open={open} onClose={() => setOpen(false)}>
+      <DialogTitle>{t("Clash Port")}</DialogTitle>
+
+      <DialogContent sx={{ width: 300 }}>
+        <List>
+          <ListItem sx={{ padding: "5px 2px" }}>
+            <ListItemText primary="Mixed Port" />
+            <TextField
+              size="small"
+              autoComplete="off"
+              sx={{ width: 135 }}
+              value={port}
+              onChange={(e) =>
+                setPort(+e.target.value?.replace(/\D+/, "").slice(0, 5))
+              }
+            />
+          </ListItem>
+        </List>
+      </DialogContent>
+
+      <DialogActions>
+        <Button variant="outlined" onClick={() => setOpen(false)}>
+          {t("Cancel")}
+        </Button>
+        <Button onClick={onSave} variant="contained">
+          {t("Save")}
+        </Button>
+      </DialogActions>
+    </Dialog>
+  );
+};
+
+export default ClashPortViewer;
diff --git a/src/components/setting/setting-clash.tsx b/src/components/setting/setting-clash.tsx
index 78d0ea3ababf17334964427a0b1e9d29c3cf653b..5e13d6b6e5c836fd5c96636f1db11b40af58b23f 100644
--- a/src/components/setting/setting-clash.tsx
+++ b/src/components/setting/setting-clash.tsx
@@ -1,5 +1,4 @@
 import useSWR from "swr";
-import { useSetRecoilState } from "recoil";
 import { useTranslation } from "react-i18next";
 import {
   TextField,
@@ -9,17 +8,16 @@ import {
   Typography,
   IconButton,
 } from "@mui/material";
-import { atomClashPort } from "@/services/states";
 import { ArrowForward } from "@mui/icons-material";
 import { patchClashConfig } from "@/services/cmds";
 import { SettingList, SettingItem } from "./setting";
 import { getClashConfig, getVersion, updateConfigs } from "@/services/api";
 import useModalHandler from "@/hooks/use-modal-handler";
-import Notice from "../base/base-notice";
 import GuardState from "./mods/guard-state";
 import CoreSwitch from "./mods/core-switch";
 import WebUIViewer from "./mods/web-ui-viewer";
 import ClashFieldViewer from "./mods/clash-field-viewer";
+import ClashPortViewer from "./mods/clash-port-viewer";
 
 interface Props {
   onError: (err: Error) => void;
@@ -41,10 +39,9 @@ const SettingClash = ({ onError }: Props) => {
     "mixed-port": mixedPort,
   } = clashConfig ?? {};
 
-  const setGlobalClashPort = useSetRecoilState(atomClashPort);
-
   const webUIHandler = useModalHandler();
   const fieldHandler = useModalHandler();
+  const portHandler = useModalHandler();
 
   const onSwitchFormat = (_e: any, value: boolean) => value;
   const onChangeData = (patch: Partial<ApiType.ConfigData>) => {
@@ -55,21 +52,6 @@ const SettingClash = ({ onError }: Props) => {
     await patchClashConfig(patch);
   };
 
-  const onUpdatePort = async (port: number) => {
-    if (port < 1000) {
-      throw new Error("The port should not < 1000");
-    }
-    if (port > 65536) {
-      throw new Error("The port should not > 65536");
-    }
-    await patchClashConfig({ "mixed-port": port });
-    setGlobalClashPort(port);
-    Notice.success("Change Clash port successfully!", 1000);
-
-    // update the config
-    mutateClash();
-  };
-
   // get clash core version
   const clashVer = versionData?.premium
     ? `${versionData.version} Premium`
@@ -79,6 +61,7 @@ const SettingClash = ({ onError }: Props) => {
     <SettingList title={t("Clash Setting")}>
       <WebUIViewer handler={webUIHandler} onError={onError} />
       <ClashFieldViewer handler={fieldHandler} />
+      <ClashPortViewer handler={portHandler} />
 
       <SettingItem label={t("Allow Lan")}>
         <GuardState
@@ -114,10 +97,10 @@ const SettingClash = ({ onError }: Props) => {
           onChange={(e) => onChangeData({ "log-level": e })}
           onGuard={(e) => onUpdateData({ "log-level": e })}
         >
-          <Select size="small" sx={{ width: 120, "> div": { py: "7.5px" } }}>
+          <Select size="small" sx={{ width: 100, "> div": { py: "7.5px" } }}>
             <MenuItem value="debug">Debug</MenuItem>
             <MenuItem value="info">Info</MenuItem>
-            <MenuItem value="warning">Warning</MenuItem>
+            <MenuItem value="warn">Warn</MenuItem>
             <MenuItem value="error">Error</MenuItem>
             <MenuItem value="silent">Silent</MenuItem>
           </Select>
@@ -125,20 +108,16 @@ const SettingClash = ({ onError }: Props) => {
       </SettingItem>
 
       <SettingItem label={t("Mixed Port")}>
-        <GuardState
+        <TextField
+          autoComplete="off"
+          size="small"
           value={mixedPort ?? 0}
-          onCatch={onError}
-          onFormat={(e: any) => +e.target.value?.replace(/\D+/, "")}
-          onChange={(e) => onChangeData({ "mixed-port": e })}
-          onGuard={onUpdatePort}
-          waitTime={1000}
-        >
-          <TextField
-            autoComplete="off"
-            size="small"
-            sx={{ width: 120, input: { py: "7.5px" } }}
-          />
-        </GuardState>
+          sx={{ width: 100, input: { py: "7.5px" } }}
+          onClick={(e) => {
+            portHandler.current.open();
+            (e.target as any).blur();
+          }}
+        />
       </SettingItem>
 
       <SettingItem label={t("Web UI")}>