From ca8aa782da77cc774a37a0d20a5148a7637652e4 Mon Sep 17 00:00:00 2001 From: Misaka_Company Date: Thu, 4 Jun 2026 10:31:58 +0800 Subject: [PATCH] feat: add column visibility toggle with localStorage persistence MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a "列设置" dropdown next to the results header that lets users check/uncheck columns to show or hide them. Preferences persist across page refreshes via localStorage. Also add allowedDevOrigins to next.config.ts for LAN access. Co-Authored-By: Claude Opus 4.6 --- app/page.tsx | 97 +++++++++++++++++++++++++++++++++++++++++++++++--- next.config.ts | 2 +- 2 files changed, 94 insertions(+), 5 deletions(-) diff --git a/app/page.tsx b/app/page.tsx index f3b2ba9..90997a1 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -4,6 +4,7 @@ import { useState, useEffect, useCallback, useRef } from "react"; import { Search, ChevronLeft, ChevronRight, ChevronUp, ChevronDown, X, CheckCircle2, Circle, ArrowUpDown, Boxes, SlidersHorizontal, Loader2, + Settings2, Check, } from "lucide-react"; import type { WarehouseRow, QueryResult, FilterOptions } from "@/types/warehouse"; @@ -107,6 +108,39 @@ export default function WarehouseDashboard() { const [data, setData] = useState(null); const [filterOptions, setFilterOptions] = useState(null); + /* ── Column visibility ── */ + const ALL_COL_KEYS = COLUMNS.map((c) => c.key); + const [visibleKeys, setVisibleKeys] = useState>(() => new Set(ALL_COL_KEYS)); + const [showColumnConfig, setShowColumnConfig] = useState(false); + const columnConfigRef = useRef(null); + + /* Hydrate from localStorage after mount to avoid SSR mismatch */ + useEffect(() => { + try { + const saved = localStorage.getItem("warehouse-visible-columns"); + if (saved) setVisibleKeys(new Set(JSON.parse(saved) as string[])); + } catch { /* ignore */ } + }, []); + + const visibleColumns = COLUMNS.filter((c) => visibleKeys.has(c.key)); + + /* Persist column visibility to localStorage */ + useEffect(() => { + localStorage.setItem("warehouse-visible-columns", JSON.stringify([...visibleKeys])); + }, [visibleKeys]); + + /* Close column config on outside click */ + useEffect(() => { + if (!showColumnConfig) return; + const handler = (e: MouseEvent) => { + if (columnConfigRef.current && !columnConfigRef.current.contains(e.target as Node)) { + setShowColumnConfig(false); + } + }; + document.addEventListener("mousedown", handler); + return () => document.removeEventListener("mousedown", handler); + }, [showColumnConfig]); + const searchTimeout = useRef | null>(null); /* Fetch filter options on mount */ @@ -309,7 +343,62 @@ export default function WarehouseDashboard() { {/* ── 查询结果 ── */}
-

查询结果

+
+

查询结果

+
+ + {showColumnConfig && ( +
+
+ {COLUMNS.map((col) => ( + + ))} +
+
+ + +
+
+ )} +
+
数据来源:生产合同 + 装箱明细 + 库位 + 入库记录(LEFT JOIN)
@@ -333,7 +422,7 @@ export default function WarehouseDashboard() { - {COLUMNS.map((col) => ( + {visibleColumns.map((col) => ( {!loading && rows.length === 0 ? ( -
toggleSort(col.key)} @@ -354,7 +443,7 @@ export default function WarehouseDashboard() {
+
未找到匹配的记录
@@ -368,7 +457,7 @@ export default function WarehouseDashboard() { key={`${r.zongpai}-${r.boxNo}-${i}`} className={`transition-colors ${i % 2 === 0 ? "bg-white hover:bg-slate-50" : "bg-blue-50 hover:bg-blue-100"}`} > - {COLUMNS.map((col) => { + {visibleColumns.map((col) => { const raw = r[col.key as keyof WarehouseRow]; const empty = raw === "" || raw == null; const align = col.align === "right" ? "text-right" : "text-left"; diff --git a/next.config.ts b/next.config.ts index e9ffa30..c37a068 100644 --- a/next.config.ts +++ b/next.config.ts @@ -1,7 +1,7 @@ import type { NextConfig } from "next"; const nextConfig: NextConfig = { - /* config options here */ + allowedDevOrigins: ["192.168.110.146"], }; export default nextConfig;