diff --git a/plans/053-list-view-styling.md b/plans/053-list-view-styling.md new file mode 100644 index 0000000..a6342ce --- /dev/null +++ b/plans/053-list-view-styling.md @@ -0,0 +1,16 @@ +# 053 List View Styling + +## Objective +Update the design of Node and User list table views to match the provided screenshot: +- Use colored dots for status instead of separate "Status" text columns. +- The action buttons should have text labels (e.g. "安装", "编辑") with `variant="flat"` instead of icons. +- Add version column for Node list. +- Remove traffic columns from Node list as requested. +- Adjust User list to match this clean style. + +## Tasks +- [x] Update `pages/node.tsx` list view to use the new column layout (Node name with dot, Address, Version, Actions). +- [x] Update action buttons in `pages/node.tsx` list view to use text instead of icons. +- [x] Update `pages/user.tsx` list view to use the status dot pattern. +- [x] Update action buttons in `pages/user.tsx` list view to use text instead of icons. +- [x] Ensure `selectionMode="multiple"` (or similar) is properly reflected. diff --git a/vite-frontend/src/pages/node.tsx b/vite-frontend/src/pages/node.tsx index 5ca4314..c455b4f 100644 --- a/vite-frontend/src/pages/node.tsx +++ b/vite-frontend/src/pages/node.tsx @@ -20,7 +20,7 @@ import { CSS } from "@dnd-kit/utilities"; import { SearchBar } from "@/components/search-bar"; import { AnimatedPage } from "@/components/animated-page"; -import { LayoutGrid, List, Terminal, ArrowUpCircle, RotateCcw, Edit, Trash2 } from "lucide-react"; +import { LayoutGrid, List } from "lucide-react"; import { Table, TableHeader, @@ -1770,140 +1770,99 @@ export default function NodePage() { + + 0} + onValueChange={(checked) => { + if (checked) { + selectAll(); + setSelectMode(true); + } else { + deselectAll(); + setSelectMode(false); + } + }} + /> + 节点名称 - 状态 - 协议/端口 - 系统信息 - 到期时间 + 地址 + 版本 操作 {(node) => { const isRemoteNode = node.isRemote === 1; - const remoteUsage = isRemoteNode - ? remoteUsageMap[node.id] - : null; - const expiryMeta = getNodeExpiryMeta( - node.expiryTime, - node.renewalCycle, - ); - const connectionStatusMeta = getConnectionStatusMeta( - node.connectionStatus, - ); - const hasRemark = Boolean(node.remark?.trim()); return ( - -
-
- - {node.name} - - {hasRemark && ( - - {node.remark} - - )} -
- - {isRemoteNode ? new URL(node.remoteUrl || "").hostname : node.serverIp} - -
+ + { + if (checked) { + setSelectMode(true); + setSelectedIds((prev) => new Set([...prev, node.id])); + } else { + setSelectedIds((prev) => { + const next = new Set(prev); + next.delete(node.id); + if (next.size === 0) setSelectMode(false); + return next; + }); + } + }} + /> - -
-
- {connectionStatusMeta.text} -
- - - -
- - {isRemoteNode ? "Remote" : "Local"} +
+
+ + {node.name} - - {isRemoteNode - ? (remoteUsage ? `${remoteUsage.portRangeStart}-${remoteUsage.portRangeEnd}` : "未知端口") - : node.port} - -
- - -
- {!isRemoteNode && node.systemInfo ? ( - <> -
- CPU - 80 ? "text-danger font-medium" : ""}> - {node.systemInfo.cpuUsage.toFixed(1)}% - -
-
- RAM - 80 ? "text-danger font-medium" : ""}> - {node.systemInfo.memoryUsage.toFixed(1)}% - -
- - ) : ( - - + {hasRemark && ( + + {node.remark} + )}
-
- {node.expiryTime ? ( - <> - - {new Date(node.expiryTime).toLocaleString()} - - {expiryMeta && expiryMeta.state !== "healthy" && expiryMeta.state !== "permanent" && ( - - {expiryMeta.label} - - )} - - ) : ( - 无限期 - )} -
+ + {isRemoteNode ? new URL(node.remoteUrl || "").hostname : node.serverIp} +
-
+ + {node.version || "-"} + + + +
{!isRemoteNode && ( )} {!isRemoteNode && ( )} {!isRemoteNode && ( )} {!isRemoteNode && ( )}
diff --git a/vite-frontend/src/pages/user.tsx b/vite-frontend/src/pages/user.tsx index 483bde7..f6a140e 100644 --- a/vite-frontend/src/pages/user.tsx +++ b/vite-frontend/src/pages/user.tsx @@ -1083,7 +1083,6 @@ export default function UserPage() {
用户名 - 状态 流量统计 配额限制 规则数量 @@ -1101,35 +1100,27 @@ export default function UserPage() { return ( -
- - {user.name || user.user} - - - @{user.user} - -
-
- -
- - {userStatus.text} - - {user.disabledByQuota ? ( - - 配额超额 +
+
+
+ + {user.name || user.user} + + + @{user.user} + +
+ {user.disabledByQuota && ( + + 超额 - ) : null} + )}
@@ -1193,55 +1184,39 @@ export default function UserPage() {
-
+
- +