From 299a3eb8038624134809fdde1c27db7d7b6dc36f Mon Sep 17 00:00:00 2001 From: NathanAlex7 <18898599977@163.com> Date: Wed, 9 Sep 2026 12:32:46 +0800 Subject: [PATCH] chore: freeze local demo baseline --- src/app/collateral-workbench/page.tsx | 6 +- src/app/data-access/page.tsx | 9 +- src/app/globals.css | 30 + src/app/historical-data/page.tsx | 370 ------- src/app/layout.tsx | 4 +- src/app/policy-verification/page.tsx | 706 ------------- src/app/report-assistant/page.tsx | 370 ------- src/app/report-workbench/page.tsx | 8 +- src/app/review-allocation/page.tsx | 698 ------------- src/app/review-assist/page.tsx | 1282 ------------------------ src/app/review-workbench/page.tsx | 9 +- src/app/risk-assess-simple/page.tsx | 78 -- src/app/risk-assess/page.tsx | 706 ------------- src/app/rule-engine/page.tsx | 273 ----- src/app/trajectory/page.tsx | 12 +- src/app/xingbang-unified/page.tsx | 44 - src/app/xingbang-v2/page.tsx | 370 ------- src/app/xingbang/page.tsx | 330 ------ src/components/chat/ChatPanel.tsx | 28 +- src/components/layout/Navbar.tsx | 24 +- src/components/layout/Sidebar.tsx | 46 +- src/components/xingbang/AgentNav.tsx | 20 +- src/components/xingbang/navigation.css | 2 +- 23 files changed, 123 insertions(+), 5302 deletions(-) delete mode 100644 src/app/historical-data/page.tsx delete mode 100644 src/app/policy-verification/page.tsx delete mode 100644 src/app/report-assistant/page.tsx delete mode 100644 src/app/review-allocation/page.tsx delete mode 100644 src/app/review-assist/page.tsx delete mode 100644 src/app/risk-assess-simple/page.tsx delete mode 100644 src/app/risk-assess/page.tsx delete mode 100644 src/app/rule-engine/page.tsx delete mode 100644 src/app/xingbang-unified/page.tsx delete mode 100644 src/app/xingbang-v2/page.tsx delete mode 100644 src/app/xingbang/page.tsx diff --git a/src/app/collateral-workbench/page.tsx b/src/app/collateral-workbench/page.tsx index 2b27629..9f6c76f 100644 --- a/src/app/collateral-workbench/page.tsx +++ b/src/app/collateral-workbench/page.tsx @@ -1,14 +1,14 @@ "use client"; import {useEffect,useState} from "react"; import {Blocks,Check,FileCheck2,FileUp,RefreshCw,ShieldAlert,Sparkles,Plus,X} from "lucide-react"; -import AgentNav,{requestedProject} from "@/components/xingbang/AgentNav"; +import AgentNav,{useRequestedProject} from "@/components/xingbang/AgentNav"; import "../data-access/workspace.css"; import "./collateral.css"; const BASE="/api/risk-agent/collateral"; const kinds:any={asset:"租赁物",insurance:"保险",deposit:"保证金",guarantee:"保证",mortgage:"抵押",pledge:"质押"}; function H(){const t=sessionStorage.getItem("xingbang-access-token");return {"Content-Type":"application/json",...(t?{Authorization:`Bearer ${t}`}:{})}} async function api(path:string,body?:any){const r=await fetch(BASE+path,{method:body?"POST":"GET",headers:H(),body:body?JSON.stringify(body):undefined});const d=await r.json();if(!r.ok)throw Error(d.detail||"请求失败");return d} -export default function Collateral(){const [cases,setCases]=useState([]),[runs,setRuns]=useState([]),[rules,setRules]=useState([]),[selected,setSelected]=useState(""),[tab,setTab]=useState("checks"),[error,setError]=useState(""),[busy,setBusy]=useState(false),[show,setShow]=useState(false),[form,setForm]=useState({}),[file,setFile]=useState(null);const requested=requestedProject();const c=cases.find(x=>x.id===selected);const rule=rules.find(x=>x.status==="published"); +export default function Collateral(){const [cases,setCases]=useState([]),[runs,setRuns]=useState([]),[rules,setRules]=useState([]),[selected,setSelected]=useState(""),[tab,setTab]=useState("checks"),[error,setError]=useState(""),[busy,setBusy]=useState(false),[show,setShow]=useState(false),[form,setForm]=useState({}),[file,setFile]=useState(null);const requested=useRequestedProject();const c=cases.find(x=>x.id===selected);const rule=rules.find(x=>x.status==="published"); async function load(){try{const [w,r]=await Promise.all([api("/workspace"),fetch("/api/risk-agent/runs/history",{headers:H()}).then(x=>x.json())]);setCases(w.cases);setRules(w.rules);setRuns(r);setSelected(s=>w.cases.some((x:any)=>x.id===s)?s:(w.cases.find((x:any)=>x.project_id===requested)||w.cases[0])?.id||"")}catch(e:any){setError(e.message)}}useEffect(()=>{load()},[]);async function act(fn:()=>Promise){setBusy(true);setError("");try{await fn()}catch(e:any){setError(e.message)}finally{setBusy(false)}}function update(x:any){setCases(xs=>xs.map(y=>y.id===x.id?x:y));setSelected(x.id)} async function create(){await act(async()=>{const x=await api("/cases",{run_id:form.run_id,lease_end:form.lease_end});update(x);setShow(false)})}async function upload(){if(!file||!c)return;await act(async()=>{const body=new FormData();body.append("file",file);body.append("version",String(c.version));const r=await fetch(`${BASE}/cases/${c.id}/documents`,{method:"POST",headers:(()=>{const h:any={};const t=sessionStorage.getItem("xingbang-access-token");if(t)h.Authorization=`Bearer ${t}`;return h})(),body});const d=await r.json();if(!r.ok)throw Error(d.detail);update(d);setFile(null)})}async function evaluate(){await act(async()=>update(await api(`/cases/${c.id}/evaluate`,{version:c.version,rules_id:rule.id,haircut:20,note:"已检查输入,执行确定性核验"})))} - return

04 / COLLATERAL & ENHANCEMENT

租赁物与增信措施核验

把资产、保单、保证金和担保放到当前方案下,核对真实性、有效性和覆盖能力。

{error&&
{error}
}
{!c?

选择或接入一个项目

:

{c.project_id} · 授信 {c.amount} 万元

风险缓释有效性视图

租期到期日:{c.lease_end} · 数据版本:{c.input_revision}
{c.stale&&结果已失效}
已接入措施{c.measures.length}
材料页数{c.documents.reduce((n:any,d:any)=>n+d.pages.length,0)}
待落实问题{(c.result?.checks||[]).filter((x:any)=>x.status!=="pass").length}
折价覆盖{c.result?`${(Number(c.result.scenario.coverage)*100).toFixed(1)}%`:"--"}
{tab==="checks"&&

核验清单

{rule&&}
{c.measures.map((m:any)=>
{m.name}{m.confirmed_by?"已确认":"待人工确认"}

{kinds[m.kind]} · {m.amount??"金额待补充"} 万元 · 标识 {m.resource_key||"缺失"}

{m.evidence?.reference||"暂无来源材料"}{m.evidence?.document_id?` · 第 ${m.evidence.page} 页:${m.evidence.quote}`:""}
)}{!c.measures.length&&
暂无措施,请补充租赁物、保单和增信信息。
}{c.result&&
{c.result.checks.filter((x:any)=>x.status!=="pass").length?"存在待落实问题":"所选规则检查通过"}

规则 {c.result.rules.name} v{c.result.rules.version} · {c.result.scenario.formula}

}
}{tab==="docs"&&

原始材料与页码证据

{file&&}
{c.documents.map((d:any)=>
{d.name}SHA-256 {d.sha256.slice(0,16)}… · {d.pages.length} 页{d.pages.map((p:any)=>

第 {p.number} 页 · {p.status} · {p.text.slice(0,180)||"无文本"}

)}
)}{!c.documents.length&&
上传 PDF 或 UTF-8 文本后,系统保存文件哈希和页级提取结果。扫描件需要配置本地 OCR。
}
}{tab==="scenario"&&

确定性覆盖测算

默认折价率 20%,仅计算已确认资产与已到账保证金
{c.result?<>
资产折价净值{c.result.scenario.asset_recovery} 万元
已到账保证金{c.result.scenario.deposit_recovery} 万元
总回收{c.result.scenario.total_recovery} 万元
未覆盖敞口{c.result.scenario.uncovered} 万元
{c.result.scenario.formula}
:
执行核验后查看折价情景。
}
}{tab==="advice"&&

mini-openclaw 核验建议

{c.advice?<>

{c.advice.text}

Agent 工具轨迹
{JSON.stringify(c.advice.trace.messages,null,2)}
:
程序先做核验,模型只解释证据并提出待办。
}
}
}
{show&&

接入核验项目

{e.preventDefault();create()}}>
}
} + return

04 / COLLATERAL & ENHANCEMENT

租赁物与增信措施核验

把资产、保单、保证金和担保放到当前方案下,核对真实性、有效性和覆盖能力。

{error&&
{error}
}
{!c?

选择或接入一个项目

:

{c.project_id} · 授信 {c.amount} 万元

风险缓释有效性视图

租期到期日:{c.lease_end} · 数据版本:{c.input_revision}
{c.stale&&结果已失效}
已接入措施{c.measures.length}
材料页数{c.documents.reduce((n:any,d:any)=>n+d.pages.length,0)}
待落实问题{(c.result?.checks||[]).filter((x:any)=>x.status!=="pass").length}
折价覆盖{c.result?`${(Number(c.result.scenario.coverage)*100).toFixed(1)}%`:"--"}
{tab==="checks"&&

核验清单

{rule&&}
{c.measures.map((m:any)=>
{m.name}{m.confirmed_by?"已确认":"待人工确认"}

{kinds[m.kind]} · {m.amount??"金额待补充"} 万元 · 标识 {m.resource_key||"缺失"}

{m.evidence?.reference||"暂无来源材料"}{m.evidence?.document_id?` · 第 ${m.evidence.page} 页:${m.evidence.quote}`:""}
)}{!c.measures.length&&
暂无措施,请补充租赁物、保单和增信信息。
}{c.result&&
{c.result.checks.filter((x:any)=>x.status!=="pass").length?"存在待落实问题":"所选规则检查通过"}

规则 {c.result.rules.name} v{c.result.rules.version} · {c.result.scenario.formula}

}
}{tab==="docs"&&

原始材料与页码证据

{file&&}
{c.documents.map((d:any)=>
{d.name}SHA-256 {d.sha256.slice(0,16)}… · {d.pages.length} 页{d.pages.map((p:any)=>

第 {p.number} 页 · {p.status} · {p.text.slice(0,180)||"无文本"}

)}
)}{!c.documents.length&&
上传 PDF 或 UTF-8 文本后,系统保存文件哈希和页级提取结果。扫描件需要配置本地 OCR。
}
}{tab==="scenario"&&

确定性覆盖测算

默认折价率 20%,仅计算已确认资产与已到账保证金
{c.result?<>
资产折价净值{c.result.scenario.asset_recovery} 万元
已到账保证金{c.result.scenario.deposit_recovery} 万元
总回收{c.result.scenario.total_recovery} 万元
未覆盖敞口{c.result.scenario.uncovered} 万元
{c.result.scenario.formula}
:
执行核验后查看折价情景。
}
}{tab==="advice"&&

mini-openclaw 核验建议

{c.advice?<>

{c.advice.text}

Agent 工具轨迹
{JSON.stringify(c.advice.trace.messages,null,2)}
:
程序先做核验,模型只解释证据并提出待办。
}
}
}
{show&&

接入核验项目

{e.preventDefault();create()}}>
}
} diff --git a/src/app/data-access/page.tsx b/src/app/data-access/page.tsx index c6b9eec..ffaeb73 100644 --- a/src/app/data-access/page.tsx +++ b/src/app/data-access/page.tsx @@ -4,6 +4,7 @@ import { useEffect, useState } from "react"; import { Activity, ArrowLeft, ArrowRight, Boxes, Check, CheckCircle2, ChevronRight, CircleDashed, Copy, Database, FileCode2, History, Layers3, Loader2, Pencil, Play, Plus, Search, ShieldCheck, Sparkles, Trash2, Workflow, X } from "lucide-react"; import "./workspace.css"; import {ConnectionFields, AlignmentFields, RuleFields, AccessDialog, Reviews, ResultExtras} from "./Enhancements"; +import AgentNav from "@/components/xingbang/AgentNav"; type Item = { id: string; name: string; description?: string; status: string; version: string; [key: string]: any }; type Kind = "connections" | "cards" | "skills" | "rules" | "plans"; @@ -29,7 +30,7 @@ export default function RiskAgentConsole() { async function reload() { setCatalog(await api("/catalog")); } const [access,setAccess]=useState({role:"admin",preview:true}),[accessOpen,setAccessOpen]=useState(false),[reviewItems,setReviewItems]=useState([]),[previous,setPrevious]=useState(null); const canManage=access.role!=="manager", canEdit=access.role==="admin"; - async function connectIdentity(){try{const user=await api("/access/context");setAccess(user);setResult(null);setHistory([]);setEditor(null);setView(user.role==="manager"?"run":"cards");await reload();if(user.role!=="manager")setNativeSkills(await api("/native-skills/list"));setAccessOpen(false);setError("")}catch(e:any){setError(e.message);setCatalog(EMPTY);setAccessOpen(true)}finally{setLoading(false)}} + async function connectIdentity(){try{const user=await api("/access/context");const requested=typeof window!=="undefined"?new URLSearchParams(window.location.search).get("view"):null;const initialView=requested&&["run","history","rules"].includes(requested)?requested:(user.role==="manager"?"run":"cards");setAccess(user);setResult(null);setHistory([]);setEditor(null);setView(initialView as Kind|"run"|"history");await reload();if(user.role!=="manager")setNativeSkills(await api("/native-skills/list"));setAccessOpen(false);setError("")}catch(e:any){setError(e.message);setCatalog(EMPTY);setAccessOpen(true)}finally{setLoading(false)}} useEffect(()=>{connectIdentity()},[]); async function perform(fn:()=>Promise){setBusy(true);setError("");setNotice("");try{await fn()}catch(e:any){setError(e.message)}finally{setBusy(false)}} function open(kind:Kind,item?:Item) { @@ -51,8 +52,8 @@ export default function RiskAgentConsole() { const title=view==="reviews"?"发布审核":view==="run"?"项目提交前自查":view==="history"?"研判运行记录":META[view as Kind].label; const subtitle=view==="cards"?"把业务数据封装成可复用的数据卡,连接每一次风险研判。":view==="skills"?"组合专业检查、确定性计算与语义分析能力。":view==="plans"?"选择数据、能力与规则,形成客户经理的一键自查方案。":view==="run"?"项目事实、专业检查与制度规则在同一条证据链上汇合。":view==="rules"?"管理检查条件与核查建议,保留每一个制度版本。":view==="connections"?"统一维护连接配置,由数据卡复用。":view==="reviews"?"核对提交版本,由独立审核员发布或驳回。":"回看数据快照、配置版本、执行结果与证据。"; const items=view in META?catalog[view as Kind].filter(x=>(status==="all"||x.status!=="archived")&&(x.name+" "+x.description).toLowerCase().includes(search.toLowerCase())):[]; - return
- + return
+
风险研判 Agent {title}
业务验证版
RISK AGENT / {view.toUpperCase()}

{title}

{subtitle}

{canEdit&&view in META&&}
{error&&
{error}
}{notice&&
{notice}
} @@ -69,7 +70,7 @@ export default function RiskAgentConsole() {
} {confirmDelete&&

归档「{confirmDelete.item.name}」?

配置将停止使用,历史运行快照保留。被其他有效配置引用时需要先解除关联。

{error&&

{error}

}
} {accessOpen&&setAccessOpen(false)} connected={connectIdentity}/>} -
; +
; } function Field({label,children}:{label:string;children:React.ReactNode}){return } function CheckList({title,items,checked,onToggle}:{title:string;items:Item[];checked:string[];onToggle:(id:string)=>void}){return

{title}{checked.length} 已选

{items.map(item=>)}
} diff --git a/src/app/globals.css b/src/app/globals.css index eb8426c..4503fbd 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -59,6 +59,36 @@ body { border-radius: 10px; min-height: 40px; } + +.xingbang-mark { + width: 28px; + height: 28px; + display: grid; + place-items: center; + flex: 0 0 auto; + border-radius: 7px; + background: #17634c; + color: #fff; + font-family: "Microsoft YaHei", sans-serif; + font-size: 15px; + font-weight: 700; + box-shadow: inset 0 -2px 0 rgba(0,0,0,.12); +} + +.xingbang-chat-mark { + width: 58px; + height: 58px; + display: grid; + place-items: center; + margin-bottom: 16px; + border-radius: 16px; + background: #17634c; + color: #fff; + font-family: "Microsoft YaHei", sans-serif; + font-size: 28px; + font-weight: 700; + box-shadow: 0 8px 20px rgba(23,99,76,.18), inset 0 -3px 0 rgba(0,0,0,.12); +} ::-webkit-scrollbar-thumb:hover { background: #596f91; } ::-webkit-scrollbar-thumb:active { background: var(--accent); } diff --git a/src/app/historical-data/page.tsx b/src/app/historical-data/page.tsx deleted file mode 100644 index 5cd64c9..0000000 --- a/src/app/historical-data/page.tsx +++ /dev/null @@ -1,370 +0,0 @@ -"use client"; - -import { useState } from "react"; -import { Database, Search, Filter, Calendar, TrendingUp, CheckCircle, XCircle, AlertCircle } from "lucide-react"; - -interface HistoricalCase { - case_id: string; - customer_name: string; - project_type: string; - amount: number; - debt_ratio: number; - credit_query_count: number; - litigation_count: number; - decision: string; - decision_date: string; - processing_days: number; - mitigation_measures: string; - final_outcome: string; - risk_level: "high" | "medium" | "low"; -} - -export default function HistoricalDataPage() { - const [searchTerm, setSearchTerm] = useState(""); - const [selectedDecision, setSelectedDecision] = useState("all"); - const [selectedRiskLevel, setSelectedRiskLevel] = useState("all"); - const [dateRange, setDateRange] = useState("12"); - - // 模拟历史案例数据 - const [cases] = useState([ - { - case_id: "CAS-2025-08-156", - customer_name: "华东光伏设备公司", - project_type: "新能源设备", - amount: 2.8, - debt_ratio: 0.68, - credit_query_count: 7, - litigation_count: 1, - decision: "降额通过", - decision_date: "2025-08-15", - processing_days: 4, - mitigation_measures: "降低授信额度15%,增加法人个人担保,提供政府补贴承诺函", - final_outcome: "已放款,回款正常", - risk_level: "medium" - }, - { - case_id: "CAS-2025-07-089", - customer_name: "绿能公交运营公司", - project_type: "对公新能源", - amount: 3.5, - debt_ratio: 0.72, - credit_query_count: 9, - litigation_count: 0, - decision: "降额通过", - decision_date: "2025-07-22", - processing_days: 6, - mitigation_measures: "降低授信额度12%,调整还款期限,追加车辆抵押", - final_outcome: "已放款,回款正常", - risk_level: "high" - }, - { - case_id: "CAS-2025-06-234", - customer_name: "中部新能源投资", - project_type: "新能源投资", - amount: 4.2, - debt_ratio: 0.65, - credit_query_count: 6, - litigation_count: 2, - decision: "附加条件通过", - decision_date: "2025-06-18", - processing_days: 5, - mitigation_measures: "要求季度现金流报告,设置财务预警指标,增加母公司担保", - final_outcome: "已放款,回款正常", - risk_level: "high" - }, - { - case_id: "CAS-2025-08-201", - customer_name: "南方物流运输公司", - project_type: "物流运输", - amount: 1.8, - debt_ratio: 0.58, - credit_query_count: 4, - litigation_count: 0, - decision: "直接通过", - decision_date: "2025-08-28", - processing_days: 2, - mitigation_measures: "无需额外措施", - final_outcome: "已放款,回款正常", - risk_level: "low" - }, - { - case_id: "CAS-2025-07-145", - customer_name: "东部制造业集团", - project_type: "设备制造", - amount: 5.5, - debt_ratio: 0.75, - credit_query_count: 12, - litigation_count: 3, - decision: "退回", - decision_date: "2025-07-10", - processing_days: 8, - mitigation_measures: "要求补充材料后重新申请", - final_outcome: "客户未重新申请", - risk_level: "high" - }, - { - case_id: "CAS-2025-06-098", - customer_name: "西部能源开发公司", - project_type: "能源开发", - amount: 6.0, - debt_ratio: 0.62, - credit_query_count: 5, - litigation_count: 1, - decision: "附加条件通过", - decision_date: "2025-06-05", - processing_days: 7, - mitigation_measures: "增加土地使用权抵押,提供项目收益权质押", - final_outcome: "已放款,回款正常", - risk_level: "medium" - }, - { - case_id: "CAS-2025-08-178", - customer_name: "北方建筑工程公司", - project_type: "建筑工程", - amount: 3.2, - debt_ratio: 0.70, - credit_query_count: 8, - litigation_count: 2, - decision: "降额通过", - decision_date: "2025-08-20", - processing_days: 5, - mitigation_measures: "降低授信额度20%,要求项目方连带担保", - final_outcome: "已放款,回款正常", - risk_level: "high" - }, - { - case_id: "CAS-2025-07-167", - customer_name: "中部科技创新公司", - project_type: "科技研发", - amount: 2.0, - debt_ratio: 0.55, - credit_query_count: 3, - litigation_count: 0, - decision: "直接通过", - decision_date: "2025-07-28", - processing_days: 3, - mitigation_measures: "无需额外措施", - final_outcome: "已放款,回款正常", - risk_level: "low" - } - ]); - - const decisions = ["all", "直接通过", "降额通过", "附加条件通过", "退回"]; - const riskLevels = ["all", "high", "medium", "low"]; - - const filteredCases = cases.filter(c => { - const matchesSearch = c.customer_name.toLowerCase().includes(searchTerm.toLowerCase()) || - c.case_id.toLowerCase().includes(searchTerm.toLowerCase()); - const matchesDecision = selectedDecision === "all" || c.decision === selectedDecision; - const matchesRisk = selectedRiskLevel === "all" || c.risk_level === selectedRiskLevel; - return matchesSearch && matchesDecision && matchesRisk; - }); - - // 统计数据 - const stats = { - total: cases.length, - approved: cases.filter(c => c.decision.includes("通过")).length, - rejected: cases.filter(c => c.decision === "退回").length, - avgProcessingDays: (cases.reduce((sum, c) => sum + c.processing_days, 0) / cases.length).toFixed(1) - }; - - const getDecisionBadge = (decision: string) => { - if (decision.includes("直接通过")) { - return {decision}; - } else if (decision.includes("通过")) { - return {decision}; - } else if (decision === "退回") { - return {decision}; - } - return {decision}; - }; - - const getRiskBadge = (level: string) => { - switch (level) { - case "high": return 高风险; - case "medium": return 中风险; - case "low": return 低风险; - default: return null; - } - }; - - return ( -
- {/* Header */} -
-
-
-

- 💾 历史数据分析 -

-

案例数据查询与分析(轨道2:数据驱动)

-
-
-
- - {/* 统计卡片 */} -
-
-
{stats.total}
-
历史案例总数
-
-
-
{stats.approved}
-
通过案例
-
-
-
{stats.rejected}
-
退回案例
-
-
-
{stats.avgProcessingDays}
-
平均处理天数
-
-
- - {/* 搜索和筛选 */} -
-
- {/* 搜索框 */} -
- - setSearchTerm(e.target.value)} - className="w-full pl-10 pr-4 py-2 bg-slate-900 border border-slate-700 rounded-lg text-white focus:outline-none focus:border-blue-500" - /> -
- - {/* 筛选器 */} -
- {/* 决策筛选 */} -
- 决策结果: -
- {decisions.map(dec => ( - - ))} -
-
- - {/* 风险等级筛选 */} -
- 风险等级: -
- {riskLevels.map(level => ( - - ))} -
-
- - {/* 时间范围 */} -
- - -
-
- -
- 找到 {filteredCases.length} 个匹配案例 -
-
-
- - {/* 案例列表 */} -
- {filteredCases.length === 0 ? ( -
- 未找到匹配的案例 -
- ) : ( - filteredCases.map(case_ => ( -
- {/* 标题行 */} -
-
-
- {case_.case_id} - {getDecisionBadge(case_.decision)} - {getRiskBadge(case_.risk_level)} -
-

{case_.customer_name}

-

{case_.project_type}

-
-
-
{case_.amount.toFixed(1)}亿
-
{case_.decision_date}
-
-
- - {/* 关键指标 */} -
-
-
资产负债率
-
{(case_.debt_ratio * 100).toFixed(0)}%
-
-
-
征信查询
-
{case_.credit_query_count}次
-
-
-
涉诉记录
-
{case_.litigation_count}起
-
-
-
处理时长
-
{case_.processing_days}天
-
-
- - {/* 风控措施 */} -
-
风控措施
-
{case_.mitigation_measures}
-
- - {/* 最终结果 */} -
-
最终结果
-
{case_.final_outcome}
-
-
- )) - )} -
-
- ); -} diff --git a/src/app/layout.tsx b/src/app/layout.tsx index b52c870..c700a42 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -2,8 +2,8 @@ import type { Metadata } from "next"; import "./globals.css"; export const metadata: Metadata = { - title: "mini OpenClaw", - description: "A lightweight, transparent AI Agent system", + title: "兴邦金租智能评审工作台", + description: "兴邦金租项目评审与四 Agent 协同工作台", }; export default function RootLayout({ diff --git a/src/app/policy-verification/page.tsx b/src/app/policy-verification/page.tsx deleted file mode 100644 index 1fc6556..0000000 --- a/src/app/policy-verification/page.tsx +++ /dev/null @@ -1,706 +0,0 @@ -"use client"; - -import { useState } from "react"; -import { Shield, Upload, FileText, AlertTriangle, CheckCircle, Download, Eye, File } from "lucide-react"; - -interface PolicyCheckResult { - policy_id: string; - customer_name: string; - check_timestamp: string; - policy_info: { - insurance_company: string; - policy_number: string; - coverage_types: string[]; - coverage_amount: number; - lease_amount: number; - coverage_ratio: number; - }; - compliance_items: Array<{ - category: string; - item: string; - status: "pass" | "fail" | "warning"; - detail: string; - }>; - exclusions: Array<{ - clause: string; - risk_level: "high" | "medium" | "low"; - description: string; - }>; - overall_result: "compliant" | "non_compliant" | "needs_review"; - recommendations: string[]; -} - -interface ReportTemplate { - id: string; - name: string; - description: string; - sections: string[]; -} - -export default function PolicyVerificationPage() { - const [activeTab, setActiveTab] = useState<"upload" | "results" | "templates">("upload"); - const [selectedFile, setSelectedFile] = useState(null); - const [selectedTemplate, setSelectedTemplate] = useState("TPL-POLICY-001"); - - const [checkForm, setCheckForm] = useState({ - customer_name: "远东新能源公交公司", - lease_amount: 8000, - project_type: "新能源设备" - }); - - const [loading, setLoading] = useState(false); - const [checkResult, setCheckResult] = useState(null); - const [generatedReport, setGeneratedReport] = useState(null); - - // 报告模板 - const [templates] = useState([ - { - id: "TPL-POLICY-001", - name: "标准保单核验报告", - description: "适用于常规设备和车辆的保单核验", - sections: ["保单基本信息", "合规性检查", "除外责任分析", "风险评估", "核验结论", "整改建议"] - }, - { - id: "TPL-POLICY-002", - name: "新能源专项保单核验", - description: "针对新能源设备的专项核验报告", - sections: ["保单基本信息", "新能源特殊险种", "合规性检查", "政策补贴覆盖", "除外责任分析", "核验结论"] - }, - { - id: "TPL-POLICY-003", - name: "大额设备保单核验", - description: "5000万以上大额设备的详细核验", - sections: ["保单基本信息", "保额充足性分析", "多保险公司协同", "合规性检查", "除外责任分析", "风险评估", "核验结论"] - }, - { - id: "TPL-POLICY-004", - name: "快速核验简报", - description: "低风险项目的快速核验简报", - sections: ["保单基本信息", "合规性检查", "核验结论"] - } - ]); - - const handleFileChange = (e: React.ChangeEvent) => { - if (e.target.files && e.target.files[0]) { - setSelectedFile(e.target.files[0]); - } - }; - - const handlePolicyCheck = async () => { - if (!selectedFile) { - alert("请先上传保单PDF文件"); - return; - } - - setLoading(true); - setCheckResult(null); - setGeneratedReport(null); - - try { - // 模拟OCR识别和保单核验 - await new Promise(resolve => setTimeout(resolve, 2500)); - - const mockResult: PolicyCheckResult = { - policy_id: "POL-2026-001", - customer_name: checkForm.customer_name, - check_timestamp: new Date().toLocaleString('zh-CN'), - policy_info: { - insurance_company: "中国人民财产保险股份有限公司", - policy_number: "PICC-FZL-20260801-0156", - coverage_types: ["设备损失险", "盗抢险", "第三者责任险", "营业中断险"], - coverage_amount: 9600, - lease_amount: checkForm.lease_amount, - coverage_ratio: (9600 / checkForm.lease_amount) * 100 - }, - compliance_items: [ - { - category: "保额覆盖", - item: "保额 ≥ 授信金额 × 120%", - status: "pass", - detail: `保额9600万元 ≥ 授信${checkForm.lease_amount}万元 × 120% = ${(checkForm.lease_amount * 1.2).toFixed(0)}万元` - }, - { - category: "险种完整性", - item: "必备险种齐全", - status: "pass", - detail: "设备损失险、盗抢险、第三者责任险均已投保" - }, - { - category: "保险期限", - item: "保险期限覆盖租赁期", - status: "pass", - detail: "保险期限36个月,租赁期36个月,完全覆盖" - }, - { - category: "第一受益人", - item: "兴邦金租为第一受益人", - status: "pass", - detail: "保单明确载明:第一受益人为兴邦融资租赁有限公司" - }, - { - category: "除外责任", - item: "高频风险不得除外", - status: "fail", - detail: "保单除外责任包含「泡水」和「自然灾害」,属于高频风险,不应除外" - }, - { - category: "保费支付", - item: "保费按期支付证明", - status: "warning", - detail: "仅提供首期保费缴纳凭证,后续保费需持续跟踪" - } - ], - exclusions: [ - { - clause: "因泡水、浸水导致的设备损失", - risk_level: "high", - description: "极端天气下泡水风险较高,尤其是户外设备。此条款将导致泡水事故无法理赔,风险敞口较大。" - }, - { - clause: "因自然灾害(台风、暴雨、洪水)导致的损失", - risk_level: "high", - description: "自然灾害属于不可抗力但发生概率较高,此条款将导致重大自然灾害损失无法理赔。" - }, - { - clause: "战争、核辐射、恐怖袭击", - risk_level: "low", - description: "此类风险发生概率极低,属于常规除外责任,可接受。" - }, - { - clause: "故意损坏、违法使用", - risk_level: "low", - description: "此类风险属于人为因素,常规除外责任,可接受。" - } - ], - overall_result: "non_compliant", - recommendations: [ - "【必须整改】要求保险公司删除「泡水」除外责任条款,或增加泡水附加险", - "【必须整改】要求保险公司删除「自然灾害」除外责任条款,或增加自然灾害附加险", - "【建议跟踪】建立保费缴纳监控机制,每期保费到期前提醒客户缴纳", - "【风险提示】如客户无法调整保单条款,建议在合同中明确:保单除外责任导致的损失由客户承担" - ] - }; - - setCheckResult(mockResult); - setActiveTab("results"); - } catch (error) { - alert("保单核验失败"); - } finally { - setLoading(false); - } - }; - - const handleGenerateReport = () => { - if (!checkResult) return; - - const template = templates.find(t => t.id === selectedTemplate)!; - let reportContent = ""; - - reportContent += `# ${checkResult.customer_name} - 保单合规核验报告\n\n`; - reportContent += `**报告模板**: ${template.name}\n`; - reportContent += `**核验时间**: ${checkResult.check_timestamp}\n`; - reportContent += `**保单编号**: ${checkResult.policy_info.policy_number}\n`; - reportContent += `**核验结果**: ${checkResult.overall_result === "compliant" ? "✅ 合规" : checkResult.overall_result === "non_compliant" ? "❌ 不合规" : "⚠️ 需要复核"}\n\n`; - reportContent += `---\n\n`; - - template.sections.forEach(section => { - switch (section) { - case "保单基本信息": - reportContent += `## 一、保单基本信息\n\n`; - reportContent += `| 项目 | 内容 |\n|------|------|\n`; - reportContent += `| 保险公司 | ${checkResult.policy_info.insurance_company} |\n`; - reportContent += `| 保单号 | ${checkResult.policy_info.policy_number} |\n`; - reportContent += `| 投保险种 | ${checkResult.policy_info.coverage_types.join("、")} |\n`; - reportContent += `| 保险金额 | ${checkResult.policy_info.coverage_amount}万元 |\n`; - reportContent += `| 授信金额 | ${checkResult.policy_info.lease_amount}万元 |\n`; - reportContent += `| 覆盖比例 | ${checkResult.policy_info.coverage_ratio.toFixed(1)}% |\n\n`; - break; - - case "合规性检查": - reportContent += `## 二、合规性检查\n\n`; - checkResult.compliance_items.forEach((item, idx) => { - const icon = item.status === "pass" ? "✅" : item.status === "fail" ? "❌" : "⚠️"; - reportContent += `### ${idx + 1}. ${icon} ${item.item}\n\n`; - reportContent += `**检查类别**: ${item.category}\n\n`; - reportContent += `**检查结果**: ${item.status === "pass" ? "通过" : item.status === "fail" ? "不通过" : "需关注"}\n\n`; - reportContent += `**详细说明**: ${item.detail}\n\n`; - }); - break; - - case "除外责任分析": - reportContent += `## 三、除外责任条款分析\n\n`; - const highRiskExclusions = checkResult.exclusions.filter(e => e.risk_level === "high"); - const mediumRiskExclusions = checkResult.exclusions.filter(e => e.risk_level === "medium"); - const lowRiskExclusions = checkResult.exclusions.filter(e => e.risk_level === "low"); - - if (highRiskExclusions.length > 0) { - reportContent += `### 🔴 高风险除外责任(${highRiskExclusions.length}项)\n\n`; - highRiskExclusions.forEach((exc, idx) => { - reportContent += `**${idx + 1}. ${exc.clause}**\n\n`; - reportContent += `${exc.description}\n\n`; - }); - } - - if (mediumRiskExclusions.length > 0) { - reportContent += `### 🟡 中风险除外责任(${mediumRiskExclusions.length}项)\n\n`; - mediumRiskExclusions.forEach((exc, idx) => { - reportContent += `**${idx + 1}. ${exc.clause}**\n\n`; - reportContent += `${exc.description}\n\n`; - }); - } - - if (lowRiskExclusions.length > 0) { - reportContent += `### 🟢 低风险除外责任(${lowRiskExclusions.length}项,可接受)\n\n`; - lowRiskExclusions.forEach((exc, idx) => { - reportContent += `- ${exc.clause}\n`; - }); - reportContent += `\n`; - } - break; - - case "风险评估": - reportContent += `## 四、风险评估\n\n`; - const failedItems = checkResult.compliance_items.filter(i => i.status === "fail"); - const warningItems = checkResult.compliance_items.filter(i => i.status === "warning"); - reportContent += `**不合规项**: ${failedItems.length}项\n\n`; - reportContent += `**关注项**: ${warningItems.length}项\n\n`; - reportContent += `**高风险除外**: ${checkResult.exclusions.filter(e => e.risk_level === "high").length}项\n\n`; - reportContent += `**综合评估**: ${checkResult.overall_result === "compliant" ? "保单符合公司要求,可以接受" : checkResult.overall_result === "non_compliant" ? "保单存在重大不合规项,建议要求客户整改" : "保单基本合规,但存在需要关注的项目"}\n\n`; - break; - - case "核验结论": - reportContent += `## ${template.sections.indexOf(section) + 1}. 核验结论\n\n`; - if (checkResult.overall_result === "compliant") { - reportContent += `✅ **结论**: 保单合规,符合兴邦金租保单管理要求\n\n`; - } else if (checkResult.overall_result === "non_compliant") { - reportContent += `❌ **结论**: 保单不合规,存在以下重大问题:\n\n`; - checkResult.compliance_items.filter(i => i.status === "fail").forEach(item => { - reportContent += `- ${item.item}: ${item.detail}\n`; - }); - reportContent += `\n`; - } else { - reportContent += `⚠️ **结论**: 保单基本合规,但需要关注以下事项\n\n`; - } - break; - - case "整改建议": - case "核验建议": - reportContent += `## ${template.sections.indexOf(section) + 1}. 整改建议\n\n`; - checkResult.recommendations.forEach((rec, idx) => { - reportContent += `${idx + 1}. ${rec}\n\n`; - }); - break; - - case "新能源特殊险种": - reportContent += `## 二、新能源特殊险种核验\n\n`; - reportContent += `- 新能源设备特殊险种覆盖情况\n`; - reportContent += `- 电池、充电设施专项保险\n`; - reportContent += `- 技术更新换代风险覆盖\n\n`; - break; - - case "政策补贴覆盖": - reportContent += `## 三、政策补贴覆盖情况\n\n`; - reportContent += `- 政府补贴延迟风险保险\n`; - reportContent += `- 补贴政策变更风险覆盖\n\n`; - break; - - case "保额充足性分析": - reportContent += `## 二、保额充足性深度分析\n\n`; - reportContent += `- 大额设备分段保险情况\n`; - reportContent += `- 累计风险敞口分析\n`; - reportContent += `- 保额动态调整机制\n\n`; - break; - - case "多保险公司协同": - reportContent += `## 三、多保险公司协同核验\n\n`; - reportContent += `- 多家保险公司分担情况\n`; - reportContent += `- 主次保险责任划分\n`; - reportContent += `- 理赔协调机制\n\n`; - break; - } - }); - - reportContent += `---\n\n`; - reportContent += `**核验人**: AI智能核验系统\n\n`; - reportContent += `**复核人**: [待人工复核]\n\n`; - reportContent += `**核验日期**: ${checkResult.check_timestamp}\n`; - - setGeneratedReport(reportContent); - }; - - const getStatusBadge = (status: string) => { - switch (status) { - case "pass": - return 通过; - case "fail": - return 不通过; - case "warning": - return 需关注; - default: - return null; - } - }; - - const getRiskBadge = (level: string) => { - switch (level) { - case "high": - return 高风险; - case "medium": - return 中风险; - case "low": - return 低风险; - default: - return null; - } - }; - - return ( -
- {/* Header */} -
-
-
-

- 保单条款智能核验 -

-

OCR识别 + 条款解析 + 合规核验 + 报告生成

-
-
-
- - {/* Tab Navigation */} -
- - - -
- - {/* Upload Tab */} - {activeTab === "upload" && ( -
- {/* Project Info */} -
-

项目信息

-
-
- - setCheckForm({ ...checkForm, customer_name: e.target.value })} - className="w-full px-3 py-2 bg-slate-900 border border-slate-700 rounded-lg text-white focus:outline-none focus:border-green-500" - /> -
-
- - setCheckForm({ ...checkForm, lease_amount: parseFloat(e.target.value) })} - className="w-full px-3 py-2 bg-slate-900 border border-slate-700 rounded-lg text-white focus:outline-none focus:border-green-500" - /> -
-
- - setCheckForm({ ...checkForm, project_type: e.target.value })} - className="w-full px-3 py-2 bg-slate-900 border border-slate-700 rounded-lg text-white focus:outline-none focus:border-green-500" - /> -
-
-
- - {/* Upload Section */} -
-

上传保单PDF

- -
- - - -
- - -
-
- )} - - {/* Results Tab */} - {activeTab === "results" && checkResult && ( -
- {/* Summary Card */} -
-
-
-

{checkResult.customer_name}

-

核验时间: {checkResult.check_timestamp}

-
-
-
- {checkResult.overall_result === "compliant" ? "✅" : - checkResult.overall_result === "non_compliant" ? "❌" : "⚠️"} -
-
- {checkResult.overall_result === "compliant" ? "合规" : - checkResult.overall_result === "non_compliant" ? "不合规" : "需复核"} -
-
-
- -
-
-
保险金额
-
{checkResult.policy_info.coverage_amount}万
-
-
-
授信金额
-
{checkResult.policy_info.lease_amount}万
-
-
-
覆盖比例
-
{checkResult.policy_info.coverage_ratio.toFixed(1)}%
-
-
-
高风险除外
-
{checkResult.exclusions.filter(e => e.risk_level === "high").length}项
-
-
-
- - {/* Compliance Items */} -
-

- - 合规性检查结果 -

-
- {checkResult.compliance_items.map((item, idx) => ( -
-
-
-
- {getStatusBadge(item.status)} - {item.item} -
-
检查类别: {item.category}
-
-
-

{item.detail}

-
- ))} -
-
- - {/* Exclusions */} -
-

- - 除外责任条款分析 -

-
- {checkResult.exclusions.map((exc, idx) => ( -
-
- {getRiskBadge(exc.risk_level)} - {exc.clause} -
-

{exc.description}

-
- ))} -
-
- - {/* Recommendations */} -
-

整改建议

-
    - {checkResult.recommendations.map((rec, idx) => ( -
  • - {idx + 1}. - {rec} -
  • - ))} -
-
- - {/* Generate Report */} -
-

生成核验报告

- -
- - -
- - - - {generatedReport && ( -
-
-

报告预览

-
- - -
-
-
-                  {generatedReport}
-                
-
- )} -
-
- )} - - {/* Templates Tab */} - {activeTab === "templates" && ( -
-
-

核验报告模板库

-
- - {templates.map(template => ( -
-
-
-
- -

{template.name}

- {template.id} -
-

{template.description}

-
-
- -
- {template.sections.map((section, idx) => ( - - {section} - - ))} -
-
- ))} -
- )} -
- ); -} diff --git a/src/app/report-assistant/page.tsx b/src/app/report-assistant/page.tsx deleted file mode 100644 index 0dd5535..0000000 --- a/src/app/report-assistant/page.tsx +++ /dev/null @@ -1,370 +0,0 @@ -"use client"; - -import { useState } from "react"; -import { FileText, Download, Eye, Edit, Plus, Trash2, CheckSquare, Square } from "lucide-react"; - -interface ReportTemplate { - id: string; - name: string; - description: string; - sections: string[]; - created_at: string; - usage_count: number; -} - -interface GeneratedReport { - template_name: string; - generated_at: string; - content: { - title: string; - sections: Array<{ - name: string; - content: string; - }>; - }; -} - -export default function ReportAssistantPage() { - const [activeTab, setActiveTab] = useState<"generate" | "templates">("generate"); - const [selectedTemplate, setSelectedTemplate] = useState(""); - const [projectInfo, setProjectInfo] = useState({ - customer_name: "远东新能源公交公司", - project_type: "对公新能源", - amount: 3.0, - risk_level: "medium" - }); - - const [loading, setLoading] = useState(false); - const [generatedReport, setGeneratedReport] = useState(null); - - // 模拟报告模板数据 - const [templates] = useState([ - { - id: "TPL-001", - name: "标准风险评审报告", - description: "适用于常规项目的风险评审报告,包含完整的风险分析和建议", - sections: ["项目概况", "风险识别", "财务分析", "法律合规性", "综合评审意见", "审批建议"], - created_at: "2025-01-15", - usage_count: 156 - }, - { - id: "TPL-002", - name: "新能源项目专项报告", - description: "针对新能源行业的专项评审报告,关注政策补贴和行业风险", - sections: ["项目概况", "行业政策分析", "技术可行性", "财务测算", "风险评估", "审批建议"], - created_at: "2025-02-10", - usage_count: 89 - }, - { - id: "TPL-003", - name: "大额授信专项报告", - description: "5亿元以上大额授信项目的详细评审报告", - sections: ["项目概况", "企业背景调查", "深度财务分析", "抵押物评估", "风险缓释措施", "总部审批建议"], - created_at: "2025-01-20", - usage_count: 34 - }, - { - id: "TPL-004", - name: "快速审批简报", - description: "低风险项目的快速审批简报,简化流程", - sections: ["项目基本信息", "快速风险评估", "审批建议"], - created_at: "2025-02-01", - usage_count: 203 - } - ]); - - const handleGenerateReport = async () => { - if (!selectedTemplate) { - alert("请先选择报告模板"); - return; - } - - setLoading(true); - setGeneratedReport(null); - - try { - // 模拟生成报告 - await new Promise(resolve => setTimeout(resolve, 2000)); - - const template = templates.find(t => t.id === selectedTemplate)!; - - const mockReport: GeneratedReport = { - template_name: template.name, - generated_at: new Date().toLocaleString('zh-CN'), - content: { - title: `${projectInfo.customer_name} - ${template.name}`, - sections: template.sections.map(sectionName => ({ - name: sectionName, - content: generateMockSectionContent(sectionName, projectInfo) - })) - } - }; - - setGeneratedReport(mockReport); - } catch (error) { - alert("生成报告失败"); - } finally { - setLoading(false); - } - }; - - const generateMockSectionContent = (sectionName: string, info: any): string => { - switch (sectionName) { - case "项目概况": - return `客户名称:${info.customer_name}\n项目类型:${info.project_type}\n授信金额:${info.amount}亿元\n风险等级:${info.risk_level === 'high' ? '高风险' : info.risk_level === 'medium' ? '中风险' : '低风险'}\n\n本项目为${info.project_type}类型融资租赁项目,客户${info.customer_name}申请授信金额${info.amount}亿元。经初步评估,项目风险等级为${info.risk_level === 'high' ? '高风险' : info.risk_level === 'medium' ? '中风险' : '低风险'}。`; - - case "风险识别": - case "风险评估": - return `基于双轨驱动分析(规则引擎+历史数据),识别出以下主要风险点:\n\n1. 财务风险:资产负债率接近行业警戒线,需关注偿债能力\n2. 信用风险:征信查询次数偏高,需核实融资需求真实性\n3. 法律风险:存在未结案涉诉记录,需评估潜在影响\n\n历史数据显示,类似项目的通过率为73%,其中60%需要附加风控措施。`; - - case "财务分析": - case "深度财务分析": - return `关键财务指标分析:\n\n• 资产负债率:65%(行业平均60%)\n• 流动比率:1.2(良好)\n• 净资产收益率:8.5%(中等)\n• 现金流覆盖倍数:1.8倍\n\n综合评估:财务状况整体可控,但需关注债务结构优化。`; - - case "审批建议": - case "综合评审意见": - return `综合评审意见:\n\n建议:附加条件通过\n\n理由:\n1. 客户基本面良好,行业前景明朗\n2. 财务指标整体可控,但需加强风险缓释\n3. 历史同类案例成功率较高\n\n附加条件:\n• 建议降低授信额度10-15%\n• 要求增加抵押物或第三方担保\n• 设置季度财务监控机制`; - - case "行业政策分析": - return `${info.project_type}行业政策环境:\n\n• 国家政策支持力度大,补贴政策稳定\n• 地方政府配套措施完善\n• 行业准入门槛提高,竞争格局改善\n• 需关注补贴退坡风险`; - - case "技术可行性": - return `技术方案评估:\n\n• 技术路线成熟,市场验证充分\n• 设备供应商资质良好\n• 运营团队经验丰富\n• 维护保养体系完善`; - - default: - return `${sectionName}相关内容...\n\n[此部分内容由AI根据项目实际情况和历史数据自动生成]`; - } - }; - - return ( -
- {/* Header */} -
-
-
-

- 报告助手 -

-

智能报告生成与模板管理

-
-
-
- - {/* Tab Navigation */} -
- - -
- - {/* Generate Report Tab */} - {activeTab === "generate" && ( -
- {/* Project Info Form */} -
-

项目信息

-
-
- - setProjectInfo({ ...projectInfo, customer_name: e.target.value })} - className="w-full px-3 py-2 bg-slate-900 border border-slate-700 rounded-lg text-white focus:outline-none focus:border-purple-500" - /> -
-
- - setProjectInfo({ ...projectInfo, project_type: e.target.value })} - className="w-full px-3 py-2 bg-slate-900 border border-slate-700 rounded-lg text-white focus:outline-none focus:border-purple-500" - /> -
-
- - setProjectInfo({ ...projectInfo, amount: parseFloat(e.target.value) })} - className="w-full px-3 py-2 bg-slate-900 border border-slate-700 rounded-lg text-white focus:outline-none focus:border-purple-500" - /> -
-
- - -
-
-
- - {/* Template Selection */} -
-

选择报告模板

-
- {templates.map(template => ( -
setSelectedTemplate(template.id)} - className={`p-4 rounded-lg border-2 cursor-pointer transition-all ${ - selectedTemplate === template.id - ? "border-purple-500 bg-purple-900/30" - : "border-slate-700 bg-slate-900/50 hover:border-slate-600" - }`} - > -
-
- {selectedTemplate === template.id ? ( - - ) : ( - - )} -

{template.name}

-
- {template.id} -
-

{template.description}

-
- 使用次数: {template.usage_count} - 创建: {template.created_at} -
-
- 章节: {template.sections.join(" · ")} -
-
- ))} -
- - -
- - {/* Generated Report */} - {generatedReport && ( -
-
-
-

{generatedReport.content.title}

-

生成时间: {generatedReport.generated_at}

-
-
- - -
-
- -
- {generatedReport.content.sections.map((section, idx) => ( -
-

{section.name}

-

- {section.content} -

-
- ))} -
-
- )} -
- )} - - {/* Templates Tab */} - {activeTab === "templates" && ( -
-
-

报告模板库

- -
- -
- {templates.map(template => ( -
-
-
-
- -

{template.name}

- {template.id} -
-

{template.description}

-
-
- - -
-
- -
- {template.sections.map((section, idx) => ( - - {section} - - ))} -
- -
- 使用次数: {template.usage_count} - 创建时间: {template.created_at} -
-
- ))} -
-
- )} -
- ); -} diff --git a/src/app/report-workbench/page.tsx b/src/app/report-workbench/page.tsx index f3b662c..b5958dc 100644 --- a/src/app/report-workbench/page.tsx +++ b/src/app/report-workbench/page.tsx @@ -1,6 +1,7 @@ "use client"; import {useEffect,useState} from "react"; -import {ArrowLeft,BookOpen,Check,Download,FileText,Lock,Plus,Save,Sparkles,Unlock} from "lucide-react"; +import {BookOpen,Check,Download,FileText,Lock,Plus,Save,Sparkles,Unlock} from "lucide-react"; +import AgentNav,{useRequestedProject} from "@/components/xingbang/AgentNav"; import "../data-access/workspace.css"; import "./report.css"; @@ -10,6 +11,7 @@ async function call(path:string,body?:unknown){const r=await fetch(BASE+path,{me const states:Record={draft:"待复核草稿",final:"已定稿"}; export default function Reports(){ const [docs,setDocs]=useState([]),[runs,setRuns]=useState([]),[doc,setDoc]=useState(null),[selectedRun,setSelectedRun]=useState(""),[section,setSection]=useState("0"),[text,setText]=useState(""),[note,setNote]=useState(""),[error,setError]=useState(""),[busy,setBusy]=useState(false),[view,setView]=useState("report"),[approval,setApproval]=useState(""),[outcome,setOutcome]=useState(""); + const requested=useRequestedProject(); const update=(d:any)=>{setDoc(d);setDocs(xs=>xs.some(x=>x.id===d.id)?xs.map(x=>x.id===d.id?d:x):[d,...xs]);setText(d.sections.find((s:any)=>s.id===section)?.text||"")}; useEffect(()=>{Promise.all([call("/reports/documents"),call("/runs/history")]).then(([d,r])=>{setDocs(d);setRuns(r);setSelectedRun(r[0]?.id||"");if(d[0]){setDoc(d[0]);setText(d[0].sections[0].text)}}).catch(e=>setError(e.message))},[]); async function perform(task:()=>Promise){setBusy(true);setError("");try{await task()}catch(e:any){setError(e.message)}finally{setBusy(false)}} @@ -19,12 +21,12 @@ export default function Reports(){ const dirty=current&&text!==current.text; const selectDoc=(d:any)=>{if(dirty&&!window.confirm("放弃当前未保存的修改?"))return;setDoc(d);setSection("0");setText(d.sections[0].text);setApproval(d.experience?.approval_result||"");setOutcome(d.experience?.post_lease_result||"")}; async function download(){await perform(async()=>{const r=await fetch(BASE+`/reports/documents/${doc.id}/export`,{headers:headers()});if(!r.ok)throw Error("导出失败,请检查访问权限");const url=URL.createObjectURL(await r.blob());const a=document.createElement("a");a.href=url;a.download=`${doc.project_id}-评审底稿.docx`;a.click();setTimeout(()=>URL.revokeObjectURL(url),1000)})} - return
风险研判
兴邦金租 · 报告与经验助手
Agent 02 / 业务验证版
REPORT & EXPERIENCE

从项目事实,到评审底稿

源研判快照 · 章节确认 · 正式定稿 · 经验沉淀

{error&&
{error}
} + return
02 / REPORT & EXPERIENCE

从项目事实,到评审底稿

源研判快照 · 章节确认 · 正式定稿 · 经验沉淀

{error&&
{error}
}