chore: freeze local demo baseline
This commit is contained in:
@@ -5,7 +5,7 @@ import { useApp } from "@/lib/store";
|
||||
import ChatMessage from "./ChatMessage";
|
||||
import ChatInput from "./ChatInput";
|
||||
import RawTraceExplorer from "./RawTraceExplorer";
|
||||
import { Sparkles, Workflow } from "lucide-react";
|
||||
import { FileText, Blocks, ShieldCheck, Users, Workflow } from "lucide-react";
|
||||
|
||||
export default function ChatPanel() {
|
||||
const { messages, sessionId } = useApp();
|
||||
@@ -22,20 +22,19 @@ export default function ChatPanel() {
|
||||
<div className="flex-1 min-h-0 overflow-y-scroll scroll-shadow">
|
||||
{messages.length === 0 ? (
|
||||
<div className="flex flex-col items-center justify-center h-full">
|
||||
<div className="w-14 h-14 rounded-2xl bg-gradient-to-br from-[#002fa7] to-[#4070ff] flex items-center justify-center mb-4 shadow-lg shadow-[#002fa7]/15">
|
||||
<Sparkles className="w-7 h-7 text-white" />
|
||||
</div>
|
||||
<div className="xingbang-chat-mark" aria-hidden="true">兴</div>
|
||||
<p className="text-[10px] font-semibold tracking-[0.18em] text-[#6f8a7c] mb-2">兴邦金租 · 项目评审协同</p>
|
||||
<h2 className="text-lg font-semibold text-gray-800 mb-1">
|
||||
Hi, how can I help?
|
||||
从项目事实开始评审
|
||||
</h2>
|
||||
<p className="text-[13px] text-gray-400 max-w-xs text-center leading-relaxed">
|
||||
Ask me anything, or try{" "}
|
||||
<span className="text-[#ff6723] font-medium">"查询北京天气"</span>
|
||||
<p className="text-[13px] text-gray-400 max-w-md text-center leading-relaxed">
|
||||
选择一个工作问题,或在下方输入项目资料与任务。
|
||||
</p>
|
||||
<div className="flex flex-wrap gap-2 mt-5 max-w-md justify-center">
|
||||
{["你好,介绍一下自己", "查询北京天气", "帮我写一段Python代码"].map((hint) => (
|
||||
<QuickHint key={hint} text={hint} />
|
||||
))}
|
||||
<div className="grid grid-cols-2 gap-2 mt-5 max-w-lg w-full px-4">
|
||||
<QuickHint icon={ShieldCheck} text="帮我做一次项目风险研判" />
|
||||
<QuickHint icon={FileText} text="根据研判快照建立评审底稿" />
|
||||
<QuickHint icon={Users} text="整理上会待办并推荐主审员" />
|
||||
<QuickHint icon={Blocks} text="核验租赁物与增信覆盖能力" />
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
@@ -72,13 +71,14 @@ export default function ChatPanel() {
|
||||
);
|
||||
}
|
||||
|
||||
function QuickHint({ text }: { text: string }) {
|
||||
function QuickHint({ text, icon: Icon }: { text: string; icon: typeof ShieldCheck }) {
|
||||
const { sendMessage, isStreaming } = useApp();
|
||||
return (
|
||||
<button
|
||||
onClick={() => !isStreaming && sendMessage(text)}
|
||||
className="px-3 py-1.5 rounded-full text-[12px] text-gray-500 bg-white/60 border border-black/[0.04] hover:bg-white hover:shadow-sm hover:text-gray-700 transition-all"
|
||||
className="min-h-11 flex items-center gap-2 px-3 py-2 rounded-lg text-left text-[12px] leading-snug text-gray-600 bg-white/65 border border-black/[0.05] hover:bg-white hover:shadow-sm hover:text-[#17634c] transition-all"
|
||||
>
|
||||
<Icon className="w-4 h-4 shrink-0 text-[#4f8a70]" />
|
||||
{text}
|
||||
</button>
|
||||
);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { PanelLeft, PanelRight } from "lucide-react";
|
||||
import { LayoutDashboard, PanelLeft, PanelRight } from "lucide-react";
|
||||
import { useApp } from "@/lib/store";
|
||||
|
||||
export default function Navbar() {
|
||||
@@ -25,23 +25,21 @@ export default function Navbar() {
|
||||
|
||||
{/* Center — Brand */}
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="w-6 h-6 rounded-md bg-gradient-to-br from-[#002fa7] to-[#4070ff] flex items-center justify-center">
|
||||
<svg width="13" height="13" viewBox="0 0 24 24" fill="none">
|
||||
<path d="M12 2L2 7L12 12L22 7L12 2Z" fill="white" fillOpacity="0.9" />
|
||||
<path d="M2 17L12 22L22 17" stroke="white" strokeOpacity="0.7" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
|
||||
<path d="M2 12L12 17L22 12" stroke="white" strokeOpacity="0.85" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
|
||||
</svg>
|
||||
</div>
|
||||
<span className="font-semibold text-[14px] tracking-tight text-gray-800">
|
||||
mini OpenClaw
|
||||
</span>
|
||||
<a href="/xingbang-workbench" className="flex items-center gap-2" title="进入兴邦项目工作台">
|
||||
<span className="xingbang-mark" aria-hidden="true">兴</span>
|
||||
<span className="flex flex-col leading-none text-left">
|
||||
<span className="font-semibold text-[14px] tracking-tight text-[#17634c]">兴邦金租</span>
|
||||
<span className="mt-1 text-[9px] tracking-[0.16em] text-gray-400">MINI OPENCLAW</span>
|
||||
</span>
|
||||
</a>
|
||||
{/* 兴邦智能体工作台入口 */}
|
||||
<button
|
||||
onClick={() => (window.location.href = "/xingbang-unified")}
|
||||
onClick={() => (window.location.href = "/xingbang-workbench")}
|
||||
className="ml-3 flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-[12px] font-semibold transition-all
|
||||
bg-gradient-to-r from-emerald-600 to-teal-600 text-white shadow-sm hover:shadow-md hover:from-emerald-500 hover:to-teal-500"
|
||||
>
|
||||
🏢 兴邦金租智能评审
|
||||
<LayoutDashboard className="w-3.5 h-3.5" />
|
||||
进入项目工作台
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -24,7 +24,6 @@ import {
|
||||
Shield,
|
||||
FileText,
|
||||
Users,
|
||||
Bot,
|
||||
Blocks,
|
||||
} from "lucide-react";
|
||||
import { useApp } from "@/lib/store";
|
||||
@@ -101,12 +100,17 @@ export default function Sidebar() {
|
||||
{/* Divider */}
|
||||
<div className="mx-3 h-px bg-black/[0.04]" />
|
||||
|
||||
{/* Xingbang Assistants section */}
|
||||
{/* Xingbang business navigation */}
|
||||
<div className="shrink-0 px-1.5 py-2">
|
||||
<p className="px-3 pt-1 pb-2 text-[10px] font-semibold text-gray-400 uppercase tracking-widest">
|
||||
兴邦助手
|
||||
兴邦项目工作区
|
||||
</p>
|
||||
<div className="space-y-0.5">
|
||||
<a href="/xingbang-workbench" className="w-full flex items-center gap-2 px-3 py-2 text-[13px] font-medium text-[#17634c] hover:bg-[#eaf3ef] rounded-lg transition-all">
|
||||
<Building2 className="w-3.5 h-3.5" />
|
||||
<span>项目总览</span>
|
||||
</a>
|
||||
<p className="px-3 pt-3 pb-1 text-[10px] font-semibold text-gray-400 uppercase tracking-widest">四 Agent 协同</p>
|
||||
<a
|
||||
href="/data-access"
|
||||
className="w-full flex items-center gap-2 px-3 py-2 text-[13px] text-gray-600 hover:bg-white/40 hover:text-gray-800 rounded-lg transition-all"
|
||||
@@ -116,7 +120,7 @@ export default function Sidebar() {
|
||||
</a>
|
||||
<a href="/review-workbench" className="w-full flex items-center gap-2 px-3 py-2 text-[13px] text-gray-600 hover:bg-white/40 rounded-lg">
|
||||
<Users className="w-3.5 h-3.5" />
|
||||
<span>评审协同助手</span>
|
||||
<span>评审协同</span>
|
||||
</a>
|
||||
<a href="/collateral-workbench" className="w-full flex items-center gap-2 px-3 py-2 text-[13px] text-gray-600 hover:bg-white/40 rounded-lg">
|
||||
<Blocks className="w-3.5 h-3.5" />
|
||||
@@ -124,28 +128,7 @@ export default function Sidebar() {
|
||||
</a>
|
||||
<a href="/report-workbench" className="w-full flex items-center gap-2 px-3 py-2 text-[13px] text-gray-600 hover:bg-white/40 rounded-lg">
|
||||
<FileText className="w-3.5 h-3.5" />
|
||||
<span>报告与经验助手</span>
|
||||
</a>
|
||||
<a
|
||||
href="/rule-engine"
|
||||
className="w-full flex items-center gap-2 px-3 py-2 text-[13px] text-gray-600 hover:bg-white/40 hover:text-gray-800 rounded-lg transition-all"
|
||||
>
|
||||
<FileText className="w-3.5 h-3.5" />
|
||||
<span>规则引擎管理</span>
|
||||
</a>
|
||||
<a
|
||||
href="/historical-data"
|
||||
className="w-full flex items-center gap-2 px-3 py-2 text-[13px] text-gray-600 hover:bg-white/40 hover:text-gray-800 rounded-lg transition-all"
|
||||
>
|
||||
<Database className="w-3.5 h-3.5" />
|
||||
<span>历史数据分析</span>
|
||||
</a>
|
||||
<a
|
||||
href="/xingbang-workbench"
|
||||
className="w-full flex items-center gap-2 px-3 py-2 text-[13px] text-gray-600 hover:bg-white/40 hover:text-gray-800 rounded-lg transition-all"
|
||||
>
|
||||
<Bot className="w-3.5 h-3.5" />
|
||||
<span>兴邦项目总览</span>
|
||||
<span>报告与经验</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
@@ -153,6 +136,17 @@ export default function Sidebar() {
|
||||
{/* Divider */}
|
||||
<div className="mx-3 h-px bg-black/[0.04]" />
|
||||
|
||||
<div className="shrink-0 px-1.5 py-2">
|
||||
<p className="px-3 pt-1 pb-1 text-[10px] font-semibold text-gray-400 uppercase tracking-widest">系统工具</p>
|
||||
<p className="px-3 pb-2 text-[10px] leading-relaxed text-gray-400">为 Agent 01 提供规则与历史案例依据</p>
|
||||
<div className="space-y-0.5">
|
||||
<a href="/data-access?view=rules" className="w-full flex items-center gap-2 px-3 py-2 text-[13px] text-gray-600 hover:bg-white/40 hover:text-gray-800 rounded-lg transition-all"><FileText className="w-3.5 h-3.5" /><span>规则集管理</span></a>
|
||||
<a href="/data-access?view=history" className="w-full flex items-center gap-2 px-3 py-2 text-[13px] text-gray-600 hover:bg-white/40 hover:text-gray-800 rounded-lg transition-all"><Database className="w-3.5 h-3.5" /><span>历史研判记录</span></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mx-3 h-px bg-black/[0.04]" />
|
||||
|
||||
{/* Raw Messages section */}
|
||||
<div className="shrink-0">
|
||||
<div className="flex items-center">
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import {ArrowLeft, Blocks, FileText, LayoutDashboard, ShieldCheck, Users} from "lucide-react";
|
||||
import {useEffect, useState} from "react";
|
||||
import {Blocks, FileText, LayoutDashboard, ShieldCheck, Users} from "lucide-react";
|
||||
import "./navigation.css";
|
||||
|
||||
export const agents = [
|
||||
@@ -10,7 +11,20 @@ export const agents = [
|
||||
{id:"collateral",name:"租赁物与增信核验",href:"/collateral-workbench",icon:Blocks},
|
||||
];
|
||||
export function projectLink(href:string, project?:string){return href+(project?`?project=${encodeURIComponent(project)}`:"");}
|
||||
export function requestedProject(){return typeof window==="undefined"?"":new URLSearchParams(window.location.search).get("project")||"";}
|
||||
export function useRequestedProject(){
|
||||
const [project,setProject]=useState("");
|
||||
useEffect(()=>setProject(new URLSearchParams(window.location.search).get("project")||""),[]);
|
||||
return project;
|
||||
}
|
||||
export default function AgentNav({active,project}:{active:string;project?:string}){
|
||||
return <nav className="xb-agent-nav" aria-label="兴邦四 Agent 导航"><a href="/" className="xb-home"><ArrowLeft size={15}/><span>mini-openclaw</span></a><a href={projectLink("/xingbang-workbench",project)} className={active==="overview"?"selected":""}><LayoutDashboard size={15}/><span>项目总览</span></a>{agents.map((a,i)=><a key={a.id} href={projectLink(a.href,project)} className={active===a.id?"selected":""} aria-current={active===a.id?"page":undefined}><a.icon size={15}/><span><small>0{i+1}</small>{a.name}</span></a>)}{project&&<span className="xb-project-context">{project}</span>}</nav>;
|
||||
return <nav className="xb-agent-nav" aria-label="兴邦四 Agent 导航">
|
||||
<a href={projectLink("/xingbang-workbench",project)} className="xb-brand" title="兴邦金租项目工作台">
|
||||
<span className="xb-brand-mark" aria-hidden="true">兴</span>
|
||||
<span><b>兴邦金租</b><small>智能评审工作台</small></span>
|
||||
</a>
|
||||
<a href={projectLink("/xingbang-workbench",project)} className="xb-home"><LayoutDashboard size={16}/><span>项目总览</span></a>
|
||||
<span className="xb-agent-label">四 Agent 工作区</span>
|
||||
{agents.map((a,i)=><a key={a.id} href={projectLink(a.href,project)} className={active===a.id?"selected":""} aria-current={active===a.id?"page":undefined}><a.icon size={16}/><span><small>0{i+1}</small>{a.name}</span></a>)}
|
||||
{project&&<span className="xb-project-context">当前项目:{project}</span>}
|
||||
</nav>;
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
.xb-agent-nav{font-family:Arial,"Microsoft YaHei",sans-serif;letter-spacing:0;display:flex;align-items:center;gap:6px 12px;flex-wrap:wrap;padding:12px 22px;background:#fff;border-bottom:1px solid #e1e7e4;min-width:0;color:#667b6d}.xb-agent-nav a{display:flex;align-items:center;gap:6px;font-size:11px;padding:7px 8px;border-radius:4px;min-height:31px}.xb-agent-nav a:hover{background:#f2f6f3}.xb-agent-nav .selected{background:#eaf4ee;color:#216b48}.xb-agent-nav small{font-size:9px;margin-right:5px;color:#899e8e}.xb-agent-nav .xb-home{border-right:1px solid #e4eae5;border-radius:0;padding-right:18px}.xb-project-context{font-size:10px;margin-left:auto;color:#7b9382;overflow-wrap:anywhere}.xb-overview{max-width:1480px;margin:auto;padding:32px}.xb-overview h1{font-size:26px;font-weight:600}.xb-overview-heading{display:flex;justify-content:space-between;gap:16px;align-items:center;margin-bottom:28px}.xb-overview-heading p{font-size:12px;color:#84948b;margin-top:9px}.xb-overview-tools{display:flex;align-items:center;gap:10px;margin-bottom:20px}.xb-overview-tools input{background:#fff;border:1px solid #dce4df;padding:10px 12px;font-size:12px;border-radius:5px;width:280px;max-width:100%}.xb-project-table{width:100%;border-collapse:collapse;font-size:12px;background:#fff}.xb-project-table th{font-weight:500;font-size:11px;color:#85948a;text-align:left;padding:17px 20px;border-bottom:1px solid #e2e8e3}.xb-project-table td{padding:22px 20px;border-bottom:1px solid #e6ebe7;vertical-align:top}.xb-project-table b{display:block;color:#34573f;margin-bottom:8px}.xb-project-table small{display:block;font-size:10px;color:#8a9b90;line-height:1.8}.xb-project-table a{color:#387451;display:inline-flex;align-items:center;gap:6px;line-height:1.8}.xb-project-table .muted{color:#93a096}.xb-table-wrap{overflow:auto}.xb-overview-stat{display:flex;gap:40px;padding:22px 0;border-top:1px solid #dce5df;border-bottom:1px solid #dce5df;margin-bottom:25px}.xb-overview-stat strong{font-size:25px;font-weight:500;color:#316448;margin-right:12px}.xb-overview-stat span{font-size:12px;color:#7c9183}@media(max-width:760px){.xb-agent-nav{padding:10px 12px;gap:3px 5px}.xb-agent-nav a{font-size:10px;gap:4px;padding:6px}.xb-agent-nav .xb-home{padding-right:8px}.xb-project-context{width:100%;margin:5px 0 0 6px}.xb-overview{padding:24px 16px}.xb-overview-heading{align-items:start;flex-wrap:wrap}.xb-overview-stat{gap:16px;flex-wrap:wrap}.xb-project-table{min-width:780px}.xb-overview-tools{flex-wrap:wrap}}
|
||||
.xb-agent-nav{position:sticky;top:0;z-index:100;font-family:Arial,"Microsoft YaHei",sans-serif;letter-spacing:0;display:flex;align-items:center;gap:7px 10px;flex-wrap:wrap;padding:10px 22px;background:rgba(255,255,255,.98);backdrop-filter:blur(12px);border-bottom:1px solid #dfe7e3;min-width:0;color:#667b6d;box-shadow:0 2px 9px rgba(30,61,46,.05)}.xb-agent-nav a{display:flex;align-items:center;gap:7px;font-size:12px;font-weight:500;padding:8px 10px;border-radius:6px;min-height:36px}.xb-agent-nav a:hover{background:#f2f6f3;color:#216b48}.xb-agent-nav .selected{background:#e4f1e9;color:#17633f;box-shadow:inset 0 0 0 1px #cce2d4}.xb-agent-nav small{font-size:9px;margin-right:5px;color:#899e8e}.xb-agent-nav .xb-brand{gap:8px;padding:2px 14px 2px 0;margin-right:2px;border-right:1px solid #e4eae5;border-radius:0;min-height:38px}.xb-brand-mark{width:30px;height:30px;display:grid;place-items:center;border-radius:7px;background:#17634c;color:#fff;font-size:15px;font-weight:700;box-shadow:inset 0 -2px 0 rgba(0,0,0,.12)}.xb-brand b{display:block;color:#17634c;font-size:13px;font-weight:700;line-height:1.1}.xb-brand small{display:block;margin:4px 0 0;color:#91a197;font-size:9px;line-height:1.1}.xb-agent-nav .xb-home{border-right:1px solid #e4eae5;border-radius:0;padding-right:17px}.xb-agent-label{font-size:10px;font-weight:600;letter-spacing:.06em;color:#819187;text-transform:uppercase}.xb-project-context{font-size:11px;margin-left:auto;color:#58705f;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;background:#f2f7f3;border:1px solid #deebe1;border-radius:999px;padding:7px 11px;max-width:255px}.xb-agent-shell .ra-sidebar{top:57px}.xb-overview{max-width:1480px;margin:auto;padding:32px}.xb-overview h1{font-size:26px;font-weight:600}.xb-overview-heading{display:flex;justify-content:space-between;gap:16px;align-items:center;margin-bottom:28px}.xb-overview-heading p{font-size:12px;color:#84948b;margin-top:9px}.xb-overview-tools{display:flex;align-items:center;gap:10px;margin-bottom:20px}.xb-overview-tools input{background:#fff;border:1px solid #dce4df;padding:10px 12px;font-size:12px;border-radius:5px;width:280px;max-width:100%}.xb-project-table{width:100%;border-collapse:collapse;font-size:12px;background:#fff}.xb-project-table th{font-weight:500;font-size:11px;color:#85948a;text-align:left;padding:17px 20px;border-bottom:1px solid #e2e8e3}.xb-project-table td{padding:22px 20px;border-bottom:1px solid #e6ebe7;vertical-align:top}.xb-project-table b{display:block;color:#34573f;margin-bottom:8px}.xb-project-table small{display:block;font-size:10px;color:#8a9b90;line-height:1.8}.xb-project-table a{color:#387451;display:inline-flex;align-items:center;gap:6px;line-height:1.8}.xb-project-table .muted{color:#93a096}.xb-table-wrap{overflow:auto}.xb-overview-stat{display:flex;gap:40px;padding:22px 0;border-top:1px solid #dce5df;border-bottom:1px solid #dce5df;margin-bottom:25px}.xb-overview-stat strong{font-size:25px;font-weight:500;color:#316448;margin-right:12px}.xb-overview-stat span{font-size:12px;color:#7c9183}@media(max-width:760px){.xb-agent-nav{padding:8px 10px;gap:3px 5px}.xb-agent-nav a{font-size:10px;gap:4px;padding:6px}.xb-agent-nav .xb-brand{padding-right:8px;margin-right:0;border-right:0}.xb-agent-nav .xb-brand small{display:none}.xb-agent-nav .xb-home{padding-right:8px}.xb-agent-label{display:none}.xb-project-context{width:100%;max-width:none;margin:3px 0 0 1px}.xb-agent-shell .ra-sidebar{top:auto}.xb-overview{padding:24px 16px}.xb-overview-heading{align-items:start;flex-wrap:wrap}.xb-overview-stat{gap:16px;flex-wrap:wrap}.xb-project-table{min-width:780px}.xb-overview-tools{flex-wrap:wrap}}
|
||||
|
||||
Reference in New Issue
Block a user