diff --git a/src-tauri/src/config/verge.rs b/src-tauri/src/config/verge.rs
index 1cb058ed48184f8ff8628045bad5b1c95dfd3fb1..834fe5d0402b8f1ee30198eb7c5477b3db98a162 100644
--- a/src-tauri/src/config/verge.rs
+++ b/src-tauri/src/config/verge.rs
@@ -68,6 +68,9 @@ pub struct IVerge {
 
     /// 是否使用内部的脚本支持,默认为真
     pub enable_builtin_enhanced: Option<bool>,
+
+    /// proxy 页面布局 列数
+    pub proxy_layout_column: Option<i32>,
 }
 
 #[derive(Default, Debug, Clone, Deserialize, Serialize)]
@@ -117,6 +120,7 @@ impl IVerge {
             proxy_guard_duration: Some(30),
             auto_close_connection: Some(true),
             enable_builtin_enhanced: Some(true),
+            proxy_layout_column: Some(1),
             ..Self::default()
         }
     }
@@ -159,6 +163,7 @@ impl IVerge {
         patch!(auto_close_connection);
         patch!(default_latency_test);
         patch!(enable_builtin_enhanced);
+        patch!(proxy_layout_column);
     }
 
     /// 在初始化前尝试拿到单例端口的值
diff --git a/src/components/proxy/proxy-groups.tsx b/src/components/proxy/proxy-groups.tsx
index c3cb26bb525fa0870037508ca3089fe90e74f8f6..e852391a14b7e2bf741121d58f930010e2e984fe 100644
--- a/src/components/proxy/proxy-groups.tsx
+++ b/src/components/proxy/proxy-groups.tsx
@@ -68,8 +68,10 @@ export const ProxyGroups = (props: Props) => {
   // 测全部延迟
   const handleCheckAll = useLockFn(async (groupName: string) => {
     const proxies = renderList
-      .filter((e) => e.type === 2 && e.group?.name === groupName)
-      .map((e) => e.proxy!)
+      .filter(
+        (e) => e.group?.name === groupName && (e.type === 2 || e.type === 4)
+      )
+      .flatMap((e) => e.proxyCol || e.proxy!)
       .filter(Boolean);
 
     const providers = new Set(proxies.map((p) => p!.provider!).filter(Boolean));
@@ -92,7 +94,10 @@ export const ProxyGroups = (props: Props) => {
     const { name, now } = group;
 
     const index = renderList.findIndex(
-      (e) => e.type === 2 && e.group?.name === name && e.proxy?.name === now
+      (e) =>
+        e.group?.name === name &&
+        ((e.type === 2 && e.proxy?.name === now) ||
+          (e.type === 4 && e.proxyCol?.some((p) => p.name === now)))
     );
 
     if (index >= 0) {
diff --git a/src/components/proxy/proxy-item-mini.tsx b/src/components/proxy/proxy-item-mini.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..3e82c9e0b1142249f396fed29aecf02d7470f057
--- /dev/null
+++ b/src/components/proxy/proxy-item-mini.tsx
@@ -0,0 +1,182 @@
+import { useEffect, useState } from "react";
+import { useLockFn } from "ahooks";
+import { CheckCircleOutlineRounded } from "@mui/icons-material";
+import {
+  alpha,
+  Box,
+  ListItemButton,
+  ListItemIcon,
+  ListItemText,
+  styled,
+} from "@mui/material";
+import { BaseLoading } from "@/components/base";
+import delayManager from "@/services/delay";
+
+interface Props {
+  groupName: string;
+  proxy: IProxyItem;
+  selected: boolean;
+  showType?: boolean;
+  onClick?: (name: string) => void;
+}
+
+// 多列布局
+export const ProxyItemMini = (props: Props) => {
+  const { groupName, proxy, selected, showType = true, onClick } = props;
+
+  // -1/<=0 为 不显示
+  // -2 为 loading
+  const [delay, setDelay] = useState(-1);
+
+  useEffect(() => {
+    delayManager.setListener(proxy.name, groupName, setDelay);
+
+    return () => {
+      delayManager.removeListener(proxy.name, groupName);
+    };
+  }, [proxy.name, groupName]);
+
+  useEffect(() => {
+    if (!proxy) return;
+    setDelay(delayManager.getDelayFix(proxy, groupName));
+  }, [proxy]);
+
+  const onDelay = useLockFn(async () => {
+    setDelay(-2);
+    setDelay(await delayManager.checkDelay(proxy.name, groupName));
+  });
+
+  return (
+    <ListItemButton
+      dense
+      selected={selected}
+      onClick={() => onClick?.(proxy.name)}
+      sx={[
+        { borderRadius: 1, pl: 1.5, pr: 1 },
+        ({ palette: { mode, primary } }) => {
+          const bgcolor =
+            mode === "light"
+              ? alpha(primary.main, 0.15)
+              : alpha(primary.main, 0.35);
+          const color = mode === "light" ? primary.main : primary.light;
+          const showDelay = delay > 0;
+
+          return {
+            "&:hover .the-check": { display: !showDelay ? "block" : "none" },
+            "&:hover .the-delay": { display: showDelay ? "block" : "none" },
+            "&:hover .the-icon": { display: "none" },
+            "&.Mui-selected": { bgcolor },
+            "&.Mui-selected .MuiListItemText-secondary": { color },
+          };
+        },
+      ]}
+    >
+      <ListItemText
+        title={proxy.name}
+        secondary={
+          <div>
+            <div
+              style={{
+                textOverflow: "ellipsis",
+                wordBreak: "break-all",
+                overflow: "hidden",
+                whiteSpace: showType ? "nowrap" : "inherit",
+              }}
+            >
+              {proxy.name}
+            </div>
+
+            {showType && (
+              <>
+                {!!proxy.provider && (
+                  <TypeBox component="span">{proxy.provider}</TypeBox>
+                )}
+                <TypeBox component="span">{proxy.type}</TypeBox>
+                {proxy.udp && <TypeBox component="span">UDP</TypeBox>}
+              </>
+            )}
+          </div>
+        }
+      />
+
+      <ListItemIcon sx={{ justifyContent: "flex-end", color: "primary.main" }}>
+        {delay === -2 && (
+          <Widget>
+            <BaseLoading />
+          </Widget>
+        )}
+
+        {!proxy.provider && delay !== -2 && (
+          // provider的节点不支持检测
+          <Widget
+            className="the-check"
+            onClick={(e) => {
+              e.preventDefault();
+              e.stopPropagation();
+              onDelay();
+            }}
+            sx={({ palette }) => ({
+              display: "none", // hover才显示
+              ":hover": { bgcolor: alpha(palette.primary.main, 0.15) },
+            })}
+          >
+            Check
+          </Widget>
+        )}
+
+        {delay > 0 && (
+          // 显示延迟
+          <Widget
+            className="the-delay"
+            onClick={(e) => {
+              if (proxy.provider) return;
+              e.preventDefault();
+              e.stopPropagation();
+              onDelay();
+            }}
+            color={
+              delay > 500
+                ? "error.main"
+                : delay < 100
+                ? "success.main"
+                : "text.secondary"
+            }
+            sx={({ palette }) =>
+              !proxy.provider
+                ? { ":hover": { bgcolor: alpha(palette.primary.main, 0.15) } }
+                : {}
+            }
+          >
+            {delay > 1e5 ? "Error" : delay > 3000 ? "Timeout" : `${delay}`}
+          </Widget>
+        )}
+
+        {delay !== -2 && delay <= 0 && selected && (
+          // 展示已选择的icon
+          <CheckCircleOutlineRounded
+            className="the-icon"
+            sx={{ fontSize: 16 }}
+          />
+        )}
+      </ListItemIcon>
+    </ListItemButton>
+  );
+};
+
+const Widget = styled(Box)(() => ({
+  padding: "3px 6px",
+  fontSize: 14,
+  borderRadius: "4px",
+}));
+
+const TypeBox = styled(Box)(({ theme }) => ({
+  display: "inline-block",
+  border: "1px solid #ccc",
+  borderColor: alpha(theme.palette.text.secondary, 0.36),
+  color: alpha(theme.palette.text.secondary, 0.42),
+  borderRadius: 4,
+  fontSize: 10,
+  marginRight: "4px",
+  padding: "0 2px",
+  lineHeight: 1.25,
+}));
diff --git a/src/components/proxy/proxy-render.tsx b/src/components/proxy/proxy-render.tsx
index 2eb4b5f02cea88985e678beb0ff1b7580ce0db2d..b5f50d05e65c06316598fc3b403b0dbc7c7868ca 100644
--- a/src/components/proxy/proxy-render.tsx
+++ b/src/components/proxy/proxy-render.tsx
@@ -14,6 +14,7 @@ import {
 import { HeadState } from "./use-head-state";
 import { ProxyHead } from "./proxy-head";
 import { ProxyItem } from "./proxy-item";
+import { ProxyItemMini } from "./proxy-item-mini";
 import type { IRenderItem } from "./use-render-list";
 
 interface RenderProps {
@@ -28,7 +29,7 @@ interface RenderProps {
 export const ProxyRender = (props: RenderProps) => {
   const { indent, item, onLocation, onCheckAll, onHeadState, onChangeProxy } =
     props;
-  const { type, group, headState, proxy } = item;
+  const { type, group, headState, proxy, proxyCol } = item;
 
   if (type === 0) {
     return (
@@ -105,6 +106,32 @@ export const ProxyRender = (props: RenderProps) => {
     );
   }
 
+  if (type === 4) {
+    return (
+      <Box
+        sx={{
+          display: "grid",
+          gap: 1,
+          pl: indent ? 4 : 2,
+          pr: 2,
+          pb: 1,
+          gridTemplateColumns: `repeat(${item.col! || 2}, 1fr)`,
+        }}
+      >
+        {proxyCol?.map((proxy) => (
+          <ProxyItemMini
+            key={item.key + proxy.name}
+            groupName={group.name}
+            proxy={proxy!}
+            selected={group.now === proxy?.name}
+            showType={headState?.showType}
+            onClick={() => onChangeProxy(group, proxy!)}
+          />
+        ))}
+      </Box>
+    );
+  }
+
   return null;
 };
 
diff --git a/src/components/proxy/use-render-list.ts b/src/components/proxy/use-render-list.ts
index b11a462a5e07273b2af219fadbc7616f2f06c8e5..22fc96db900c54191cf4778bcdee5efdf0c71860 100644
--- a/src/components/proxy/use-render-list.ts
+++ b/src/components/proxy/use-render-list.ts
@@ -1,6 +1,7 @@
 import useSWR from "swr";
-import { getProxies } from "@/services/api";
 import { useEffect, useMemo } from "react";
+import { getProxies } from "@/services/api";
+import { useVerge } from "@/hooks/use-verge";
 import { filterSort } from "./use-filter-sort";
 import {
   useHeadStateNew,
@@ -9,10 +10,13 @@ import {
 } from "./use-head-state";
 
 export interface IRenderItem {
-  type: 0 | 1 | 2 | 3; // 组 | head | item | empty
+  // 组 | head | item | empty | item col
+  type: 0 | 1 | 2 | 3 | 4;
   key: string;
   group: IProxyGroupItem;
   proxy?: IProxyItem;
+  col?: number;
+  proxyCol?: IProxyItem[];
   headState?: HeadState;
 }
 
@@ -23,6 +27,9 @@ export const useRenderList = (mode: string) => {
     { refreshInterval: 45000 }
   );
 
+  const { verge } = useVerge();
+  const col = verge?.proxy_layout_column || 1;
+
   const [headStates, setHeadState] = useHeadStateNew();
 
   // make sure that fetch the proxies successfully
@@ -62,10 +69,24 @@ export const useRenderList = (mode: string) => {
           headState.sortType
         );
 
-        ret.push({ type: 1, key: `head${group.name}`, group, headState });
+        ret.push({ type: 1, key: `head-${group.name}`, group, headState });
 
         if (!proxies.length) {
-          ret.push({ type: 3, key: `empty${group.name}`, group, headState });
+          ret.push({ type: 3, key: `empty-${group.name}`, group, headState });
+        }
+
+        // 支持多列布局
+        if (col > 1) {
+          return ret.concat(
+            groupList(proxies, col).map((proxyCol) => ({
+              type: 4,
+              key: `col-${group.name}`,
+              group,
+              headState,
+              col,
+              proxyCol,
+            }))
+          );
         }
 
         return ret.concat(
@@ -83,7 +104,7 @@ export const useRenderList = (mode: string) => {
 
     if (!useRule) return retList.slice(1);
     return retList;
-  }, [headStates, proxiesData, mode]);
+  }, [headStates, proxiesData, mode, col]);
 
   return {
     renderList,
@@ -91,3 +112,18 @@ export const useRenderList = (mode: string) => {
     onHeadState: setHeadState,
   };
 };
+
+function groupList<T = any>(list: T[], size: number): T[][] {
+  return list.reduce((p, n) => {
+    if (!p.length) return [[n]];
+
+    const i = p.length - 1;
+    if (p[i].length < size) {
+      p[i].push(n);
+      return p;
+    }
+
+    p.push([n]);
+    return p;
+  }, [] as T[][]);
+}
diff --git a/src/components/setting/mods/misc-viewer.tsx b/src/components/setting/mods/misc-viewer.tsx
index 81b235cde7d0fe5075d9dd1fca22f9709d02c2f0..02a0692a0c07d58a484b72b43f65762e455a9a74 100644
--- a/src/components/setting/mods/misc-viewer.tsx
+++ b/src/components/setting/mods/misc-viewer.tsx
@@ -1,7 +1,15 @@
 import { forwardRef, useImperativeHandle, useState } from "react";
 import { useLockFn } from "ahooks";
 import { useTranslation } from "react-i18next";
-import { List, ListItem, ListItemText, Switch, TextField } from "@mui/material";
+import {
+  List,
+  ListItem,
+  ListItemText,
+  MenuItem,
+  Select,
+  Switch,
+  TextField,
+} from "@mui/material";
 import { useVerge } from "@/hooks/use-verge";
 import { BaseDialog, DialogRef, Notice } from "@/components/base";
 
@@ -12,6 +20,8 @@ export const MiscViewer = forwardRef<DialogRef>((props, ref) => {
   const [open, setOpen] = useState(false);
   const [values, setValues] = useState({
     autoCloseConnection: false,
+    enableBuiltinEnhanced: true,
+    proxyLayoutColumn: 1,
     defaultLatencyTest: "",
   });
 
@@ -19,7 +29,9 @@ export const MiscViewer = forwardRef<DialogRef>((props, ref) => {
     open: () => {
       setOpen(true);
       setValues({
-        autoCloseConnection: verge?.auto_close_connection || false,
+        autoCloseConnection: verge?.auto_close_connection ?? false,
+        enableBuiltinEnhanced: verge?.enable_builtin_enhanced ?? true,
+        proxyLayoutColumn: verge?.proxy_layout_column || 1,
         defaultLatencyTest: verge?.default_latency_test || "",
       });
     },
@@ -30,6 +42,8 @@ export const MiscViewer = forwardRef<DialogRef>((props, ref) => {
     try {
       await patchVerge({
         auto_close_connection: values.autoCloseConnection,
+        enable_builtin_enhanced: values.enableBuiltinEnhanced,
+        proxy_layout_column: values.proxyLayoutColumn,
         default_latency_test: values.defaultLatencyTest,
       });
       setOpen(false);
@@ -42,7 +56,7 @@ export const MiscViewer = forwardRef<DialogRef>((props, ref) => {
     <BaseDialog
       open={open}
       title={t("Miscellaneous")}
-      contentSx={{ width: 420 }}
+      contentSx={{ width: 450 }}
       okBtn={t("Save")}
       cancelBtn={t("Cancel")}
       onClose={() => setOpen(false)}
@@ -61,6 +75,38 @@ export const MiscViewer = forwardRef<DialogRef>((props, ref) => {
           />
         </ListItem>
 
+        <ListItem sx={{ padding: "5px 2px" }}>
+          <ListItemText primary="Enable Builtin Enhanced" />
+          <Switch
+            edge="end"
+            checked={values.enableBuiltinEnhanced}
+            onChange={(_, c) =>
+              setValues((v) => ({ ...v, enableBuiltinEnhanced: c }))
+            }
+          />
+        </ListItem>
+
+        <ListItem sx={{ padding: "5px 2px" }}>
+          <ListItemText primary="Proxy Layout Column" />
+          <Select
+            size="small"
+            sx={{ width: 100, "> div": { py: "7.5px" } }}
+            value={values.proxyLayoutColumn}
+            onChange={(e) => {
+              setValues((v) => ({
+                ...v,
+                proxyLayoutColumn: e.target.value as number,
+              }));
+            }}
+          >
+            {[1, 2, 3, 4, 5].map((i) => (
+              <MenuItem value={i} key={i}>
+                {i}
+              </MenuItem>
+            ))}
+          </Select>
+        </ListItem>
+
         <ListItem sx={{ padding: "5px 2px" }}>
           <ListItemText primary="Default Latency Test" />
           <TextField
@@ -69,7 +115,7 @@ export const MiscViewer = forwardRef<DialogRef>((props, ref) => {
             autoCorrect="off"
             autoCapitalize="off"
             spellCheck="false"
-            sx={{ width: 200 }}
+            sx={{ width: 250 }}
             value={values.defaultLatencyTest}
             placeholder="http://www.gstatic.com/generate_204"
             onChange={(e) =>
diff --git a/src/services/types.d.ts b/src/services/types.d.ts
index 35fb4372d3d38259d99691969075b5f7c96d23dc..de3541d754279b5d68fd18e7cf4e6ca08a47f384 100644
--- a/src/services/types.d.ts
+++ b/src/services/types.d.ts
@@ -163,6 +163,8 @@ interface IVergeConfig {
   };
   auto_close_connection?: boolean;
   default_latency_test?: string;
+  enable_builtin_enhanced?: boolean;
+  proxy_layout_column?: number;
 }
 
 type IClashConfigValue = any;