增加了基础的块功能

This commit is contained in:
2026-02-25 14:57:25 +08:00
parent 5709ef2966
commit f7c2f8f53e
11 changed files with 1565 additions and 16 deletions
+91 -2
View File
@@ -1,12 +1,13 @@
"use client";
import { useState } from "react";
import { Lock, Save, Sparkles, Type, Upload, Download, Loader2 } from "lucide-react";
import { useEffect, useState } from "react";
import { Lock, Save, Sparkles, Type, Upload, Download, Loader2, History, Trash2 } from "lucide-react";
import { ResizableSidebar } from "@/components/sidebar";
import { PromptManagement } from "@/components/settings/prompt-management";
import { ImportProvider } from "@/components/import-context";
import { useSettingsStore, fontOptions, timezoneOptions } from "@/lib/settings-store";
import { useConfirm } from "@/components/confirm-provider";
import { cleanupAllPageHistories, estimateAllPageHistoriesUsage, trimAllPageHistoriesToRecent } from "@/lib/page-history";
export default function SettingsPage() {
const confirm = useConfirm();
@@ -21,6 +22,8 @@ export default function SettingsPage() {
setTableLineHeight,
timezone,
setTimezone,
localHistory,
setLocalHistory,
aiConfig,
setAIConfig,
} = useSettingsStore();
@@ -30,8 +33,15 @@ export default function SettingsPage() {
const [confirmPassword, setConfirmPassword] = useState("");
const [isExporting, setIsExporting] = useState(false);
const [isRestoring, setIsRestoring] = useState(false);
const [historyMsg, setHistoryMsg] = useState<string | null>(null);
const [trimRecentCount, setTrimRecentCount] = useState(10);
const [historyStats, setHistoryStats] = useState({ keys: 0, snapshots: 0, bytes: 0 });
const [msg, setMsg] = useState<{ type: "success" | "error"; text: string } | null>(null);
useEffect(() => {
setHistoryStats(estimateAllPageHistoriesUsage());
}, []);
const handlePasswordChange = async (e: React.FormEvent) => {
e.preventDefault();
setMsg(null);
@@ -151,6 +161,85 @@ export default function SettingsPage() {
</label>
</section>
<section className="ui-card ui-enter-delayed space-y-5 p-4 md:p-6">
<div className="flex items-center gap-2 border-b pb-2">
<History size={18} className="text-primary" />
<h2 className="text-lg font-semibold md:text-xl"></h2>
</div>
<p className="text-sm text-muted-foreground">
</p>
<div className="grid gap-4 md:grid-cols-2">
<label className="space-y-2 text-sm">
<span className="font-medium">: {localHistory.maxSnapshotsPerPage} </span>
<input
type="range"
min="5"
max="200"
step="1"
value={localHistory.maxSnapshotsPerPage}
onChange={(e) =>
setLocalHistory({ maxSnapshotsPerPage: parseInt(e.target.value, 10) })
}
className="w-full accent-primary"
/>
</label>
<label className="space-y-2 text-sm">
<span className="font-medium">: {localHistory.retentionDays} </span>
<input
type="range"
min="1"
max="365"
step="1"
value={localHistory.retentionDays}
onChange={(e) => setLocalHistory({ retentionDays: parseInt(e.target.value, 10) })}
className="w-full accent-primary"
/>
</label>
</div>
<div className="rounded-md border border-border/60 bg-muted/20 px-3 py-2 text-xs text-muted-foreground">
<div>: {historyStats.keys}</div>
<div>: {historyStats.snapshots}</div>
<div>: {(historyStats.bytes / 1024).toFixed(1)} KB</div>
</div>
<div className="flex flex-wrap items-center gap-3">
<button
onClick={() => {
const result = cleanupAllPageHistories();
setHistoryStats(estimateAllPageHistoriesUsage());
setHistoryMsg(`已清理本地历史键 ${result.touched}`);
}}
className="ui-btn-secondary"
>
<Trash2 size={14} />
</button>
<div className="flex items-center gap-2">
<input
type="number"
min={1}
max={200}
value={trimRecentCount}
onChange={(e) => setTrimRecentCount(Math.max(1, Math.min(200, parseInt(e.target.value || "1", 10))))}
className="ui-input h-9 w-24"
/>
<button
onClick={() => {
const result = trimAllPageHistoriesToRecent(trimRecentCount);
setHistoryStats(estimateAllPageHistoriesUsage());
setHistoryMsg(
`已处理 ${result.touched} 项,删除快照 ${result.removedSnapshots} 条(每篇保留最近 ${trimRecentCount} 条)`
);
}}
className="ui-btn-secondary"
>
N
</button>
</div>
{historyMsg && <span className="text-xs text-muted-foreground">{historyMsg}</span>}
</div>
</section>
<section className="ui-card ui-enter-delayed space-y-5 p-4 md:p-6">
<div className="flex items-center gap-2 border-b pb-2">
<Sparkles size={18} className="text-primary" />