feat(frontend): P3+P4 创始人端增强 + 企业战情室集成

P3 创始人端:
- 经营驾驶舱: 6 KPI 卡片 + 风险提示
- 投资人沟通准备中心: 会议列表 + 准备清单 + AI 建议
- 里程碑自填: 进度滑块 + 新增表单
- OKR 对齐视图: 投资人期望对齐度 + KR 进度
- BML 认知追踪: 信念/心智模型/学习追踪
- 通知页面 + 个人中心页面

P4 企业战情室集成:
- HighlightsPanel: 顶部 KPI 摘要栏
- WorkModeSwitcher: 4 种工作模式切换
- InsightRail: 右侧 AI 面板(默认风险预警 Agent)

Admin:
- 商业秘密保护配置: 密级/留痕/导出管控/审计日志
This commit is contained in:
selfrelease
2026-07-19 19:06:43 +08:00
parent a4044baa31
commit 44cbdc9d62
9 changed files with 705 additions and 31 deletions
+120
View File
@@ -0,0 +1,120 @@
/** Admin 商业秘密保护配置页面 — 密级规则 + 查看留痕 + 导出管控。 */
"use client";
import { ShieldCheck, Lock, Eye, Download, Settings } from "lucide-react";
import { useState } from "react";
import { ClassificationBadge, type ClassificationLevel } from "@/components/shared/ClassificationBadge";
/** 商业秘密保护配置页面。 */
export default function SecurityPage() {
const [defaultLevel, setDefaultLevel] = useState<ClassificationLevel>("internal");
const [watermarkEnabled, setWatermarkEnabled] = useState(true);
const [exportApproval, setExportApproval] = useState(true);
const [viewLogRetention, setViewLogRetention] = useState("180");
const levels: ClassificationLevel[] = ["public", "internal", "confidential", "secret"];
return (
<div className="space-y-6">
<div className="flex items-center gap-2">
<ShieldCheck className="text-[var(--admin-primary)]" size={24} />
<h1 className="text-2xl font-bold"></h1>
</div>
{/* 默认密级配置 */}
<div className="rounded-lg border bg-white p-4 shadow-sm">
<div className="mb-3 flex items-center gap-2">
<Lock size={18} className="text-[var(--admin-primary)]" aria-hidden="true" />
<h2 className="font-medium"></h2>
</div>
<p className="mb-3 text-sm text-muted-foreground"></p>
<div className="flex gap-2">
{levels.map((level) => (
<button
key={level}
type="button"
onClick={() => setDefaultLevel(level)}
className={`rounded-md border-2 p-2 transition-colors ${
defaultLevel === level ? "border-[var(--admin-primary)]" : "border-gray-200"
}`}
>
<ClassificationBadge level={level} showDescription />
</button>
))}
</div>
</div>
{/* 查看留痕 */}
<div className="rounded-lg border bg-white p-4 shadow-sm">
<div className="mb-3 flex items-center gap-2">
<Eye size={18} className="text-[var(--admin-primary)]" aria-hidden="true" />
<h2 className="font-medium"></h2>
</div>
<div className="space-y-3">
<div className="flex items-center justify-between">
<span className="text-sm text-gray-700">/</span>
<span className="text-xs text-emerald-600"></span>
</div>
<div className="flex items-center justify-between">
<span className="text-sm text-gray-700"></span>
<input
type="number"
value={viewLogRetention}
onChange={(e) => setViewLogRetention(e.target.value)}
className="w-20 rounded-md border px-2 py-1 text-sm"
/>
</div>
</div>
</div>
{/* 导出管控 */}
<div className="rounded-lg border bg-white p-4 shadow-sm">
<div className="mb-3 flex items-center gap-2">
<Download size={18} className="text-[var(--admin-primary)]" aria-hidden="true" />
<h2 className="font-medium"></h2>
</div>
<div className="space-y-3">
<label className="flex items-center justify-between">
<span className="text-sm text-gray-700"></span>
<input
type="checkbox"
checked={exportApproval}
onChange={(e) => setExportApproval(e.target.checked)}
className="h-4 w-4"
/>
</label>
<label className="flex items-center justify-between">
<span className="text-sm text-gray-700"></span>
<input
type="checkbox"
checked={watermarkEnabled}
onChange={(e) => setWatermarkEnabled(e.target.checked)}
className="h-4 w-4"
/>
</label>
</div>
</div>
{/* 审计日志摘要 */}
<div className="rounded-lg border bg-white p-4 shadow-sm">
<div className="mb-3 flex items-center gap-2">
<Settings size={18} className="text-[var(--admin-primary)]" aria-hidden="true" />
<h2 className="font-medium">访</h2>
</div>
<div className="space-y-2 text-sm">
{[
{ user: "张三", action: "查看机密报告", time: "2026-07-14 10:23" },
{ user: "李四", action: "导出绝密数据", time: "2026-07-13 16:45" },
{ user: "王五", action: "查看机密财务", time: "2026-07-12 09:12" },
].map((log, i) => (
<div key={i} className="flex items-center justify-between rounded border px-3 py-2">
<span>{log.user} {log.action}</span>
<span className="text-xs text-muted-foreground">{log.time}</span>
</div>
))}
</div>
</div>
</div>
);
}