From de2209d1777bd840c12e2f4850fbfdb1227d408a Mon Sep 17 00:00:00 2001 From: wood chen Date: Thu, 13 Mar 2025 00:54:29 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=8C=87=E6=A0=87=E5=A4=84?= =?UTF-8?q?=E7=90=86=E9=80=BB=E8=BE=91=EF=BC=8C=E7=A7=BB=E9=99=A4=E9=94=99?= =?UTF-8?q?=E8=AF=AF=E7=BB=9F=E8=AE=A1=E9=83=A8=E5=88=86=E5=B9=B6=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E5=89=8D=E7=AB=AF=E5=B1=95=E7=A4=BA=E3=80=82=E6=9B=B4?= =?UTF-8?q?=E6=96=B0.gitignore=E4=BB=A5=E5=BF=BD=E7=95=A5.cursor=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + internal/handler/metrics.go | 32 +-------- web/app/dashboard/config/page.tsx | 113 ++++++++++++++++-------------- web/app/dashboard/page.tsx | 64 ----------------- 4 files changed, 63 insertions(+), 147 deletions(-) diff --git a/.gitignore b/.gitignore index 62f22e7..b20f803 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,4 @@ web/dist/ data/config.json data/config.json kaifa.md +.cursor diff --git a/internal/handler/metrics.go b/internal/handler/metrics.go index 084b53b..b389150 100644 --- a/internal/handler/metrics.go +++ b/internal/handler/metrics.go @@ -51,13 +51,6 @@ type Metrics struct { Distribution map[string]int64 `json:"distribution"` } `json:"latency_stats"` - // 错误统计 - ErrorStats struct { - ClientErrors int64 `json:"client_errors"` - ServerErrors int64 `json:"server_errors"` - Types map[string]int64 `json:"types"` - } `json:"error_stats"` - // 带宽统计 BandwidthHistory map[string]string `json:"bandwidth_history"` CurrentBandwidth string `json:"current_bandwidth"` @@ -115,26 +108,8 @@ func (h *ProxyHandler) MetricsHandler(w http.ResponseWriter, r *http.Request) { } } - // 计算客户端错误和服务器错误数量 - var clientErrors, serverErrors int64 + // 处理状态码统计数据 statusCodeStats := models.SafeStatusCodeStats(stats["status_code_stats"]) - for code, count := range statusCodeStats { - codeInt := utils.ParseInt(code, 0) - if codeInt >= 400 && codeInt < 500 { - clientErrors += count - } else if codeInt >= 500 { - serverErrors += count - } - } - - // 创建错误类型统计 - errorTypes := make(map[string]int64) - if clientErrors > 0 { - errorTypes["客户端错误"] = clientErrors - } - if serverErrors > 0 { - errorTypes["服务器错误"] = serverErrors - } metrics := Metrics{ Uptime: metrics.FormatUptime(uptime), @@ -197,11 +172,6 @@ func (h *ProxyHandler) MetricsHandler(w http.ResponseWriter, r *http.Request) { metrics.LatencyStats.Distribution["gt1s"] = 0 } - // 填充错误统计数据 - metrics.ErrorStats.ClientErrors = clientErrors - metrics.ErrorStats.ServerErrors = serverErrors - metrics.ErrorStats.Types = errorTypes - w.Header().Set("Content-Type", "application/json") if err := json.NewEncoder(w).Encode(metrics); err != nil { log.Printf("Error encoding metrics: %v", err) diff --git a/web/app/dashboard/config/page.tsx b/web/app/dashboard/config/page.tsx index a6a795a..dd4bdb0 100644 --- a/web/app/dashboard/config/page.tsx +++ b/web/app/dashboard/config/page.tsx @@ -25,7 +25,7 @@ import { } from "@/components/ui/dialog" import { Switch } from "@/components/ui/switch" import { Slider } from "@/components/ui/slider" -import { Plus, Trash2, Edit, Save, Download, Upload } from "lucide-react" +import { Plus, Trash2, Edit, Download, Upload } from "lucide-react" import { AlertDialog, AlertDialogAction, @@ -66,6 +66,10 @@ export default function ConfigPage() { // 使用 ref 来保存滚动位置 const scrollPositionRef = useRef(0) + // 添加一个ref来跟踪是否是初始加载 + const isInitialLoadRef = useRef(true) + // 添加一个防抖定时器ref + const saveTimeoutRef = useRef(null) // 对话框状态 const [pathDialogOpen, setPathDialogOpen] = useState(false) @@ -139,7 +143,8 @@ export default function ConfigPage() { fetchConfig() }, [fetchConfig]) - const handleSave = async () => { + + const handleSave = useCallback(async () => { if (!config) return setSaving(true) @@ -172,7 +177,7 @@ export default function ConfigPage() { toast({ title: "成功", - description: "配置已保存", + description: "配置已自动保存", }) } catch (error) { toast({ @@ -183,7 +188,35 @@ export default function ConfigPage() { } finally { setSaving(false) } - } + }, [config, router, toast]) + + // 添加自动保存的useEffect + useEffect(() => { + // 如果是初始加载或者配置为空,不触发保存 + if (isInitialLoadRef.current || !config) { + isInitialLoadRef.current = false + return + } + + // 清除之前的定时器 + if (saveTimeoutRef.current) { + clearTimeout(saveTimeoutRef.current) + } + + // 设置新的定时器,延迟1秒后保存 + saveTimeoutRef.current = setTimeout(() => { + handleSave() + }, 1000) + + // 组件卸载时清除定时器 + return () => { + if (saveTimeoutRef.current) { + clearTimeout(saveTimeoutRef.current) + } + } + }, [config, handleSave]) // 监听config变化 + + // 处理对话框打开和关闭时的滚动位置 const handleDialogOpenChange = useCallback((open: boolean, handler: (open: boolean) => void) => { @@ -289,11 +322,6 @@ export default function ConfigPage() { } setPathDialogOpen(false) - - toast({ - title: "成功", - description: `${editingPathData ? '更新' : '添加'}路径配置成功`, - }) } const deletePath = (path: string) => { @@ -306,10 +334,6 @@ export default function ConfigPage() { delete newConfig.MAP[deletingPath] setConfig(newConfig) setDeletingPath(null) - toast({ - title: "成功", - description: "路径映射已删除", - }) } const updateCompression = (type: 'Gzip' | 'Brotli', field: 'Enabled' | 'Level', value: boolean | number) => { @@ -397,11 +421,6 @@ export default function ConfigPage() { setExtensionMapDialogOpen(false) setEditingExtension(null) setNewExtension({ ext: "", target: "" }) - - toast({ - title: "成功", - description: "扩展名映射已更新", - }) } const deleteExtensionMap = (path: string, ext: string) => { @@ -419,15 +438,8 @@ export default function ConfigPage() { } setConfig(newConfig) setDeletingExtension(null) - toast({ - title: "成功", - description: "扩展名映射已删除", - }) } - - - const openAddPathDialog = () => { setEditingPathData(null) setNewPathData({ @@ -571,34 +583,31 @@ export default function ConfigPage() { return (
- -
-
- Proxy Go配置 -

编辑后需要点击右上角保存配置按钮

-
-
- +
+ + + {saving && ( +
+ + 正在自动保存... +
+ )}
diff --git a/web/app/dashboard/page.tsx b/web/app/dashboard/page.tsx index f529c8b..03beac7 100644 --- a/web/app/dashboard/page.tsx +++ b/web/app/dashboard/page.tsx @@ -37,11 +37,6 @@ interface Metrics { max: string distribution: Record } - error_stats: { - client_errors: number - server_errors: number - types: Record - } bandwidth_history: Record current_bandwidth: string total_bytes: number @@ -325,65 +320,6 @@ export default function DashboardPage() {
- {/* 错误统计卡片 */} - - - 错误统计 - - -
-
-
客户端错误 (4xx)
-
- {metrics.error_stats?.client_errors || 0} -
-
- 占总请求的 {metrics.total_requests ? - ((metrics.error_stats?.client_errors || 0) / metrics.total_requests * 100).toFixed(2) : 0}% -
-
- -
-
服务器错误 (5xx)
-
- {metrics.error_stats?.server_errors || 0} -
-
- 占总请求的 {metrics.total_requests ? - ((metrics.error_stats?.server_errors || 0) / metrics.total_requests * 100).toFixed(2) : 0}% -
-
- -
-
总错误率
-
- {(metrics.error_rate * 100).toFixed(2)}% -
-
- 总错误数: {metrics.total_errors || 0} -
-
-
- - {metrics.error_stats?.types && Object.keys(metrics.error_stats.types).length > 0 && ( -
-
错误类型分布
-
- {Object.entries(metrics.error_stats.types).map(([type, count]) => ( -
-
{type}
-
{count}
-
- {metrics.total_errors ? ((count / metrics.total_errors) * 100).toFixed(1) : 0}% -
-
- ))} -
-
- )} -
-
- {/* 引用来源统计卡片 */} {metrics.top_referers && metrics.top_referers.length > 0 && (