diff --git a/front-end/src/app/App.tsx b/front-end/src/app/App.tsx index e7d9a4e..78c90d7 100644 --- a/front-end/src/app/App.tsx +++ b/front-end/src/app/App.tsx @@ -12,15 +12,11 @@ import { ProjectDetail } from "./pages/ProjectDetail"; import { SupplierShortlist } from "./pages/SupplierShortlist"; import { BidOpeningHall } from "./pages/BidOpeningHall"; import { EvaluationRoom } from "./pages/EvaluationRoom"; -import { AwardApproval } from "./pages/AwardApproval"; -import { ContractGeneration } from "./pages/ContractGeneration"; import { SupplierManagement } from "./pages/SupplierManagement"; import { ExpertManagement } from "./pages/ExpertManagement"; import { ReportCenter } from "./pages/ReportCenter"; import { Placeholder } from "./pages/Placeholder"; -import { ApprovalCenter } from "./pages/ApprovalCenter"; import { BiddingCenter } from "./pages/BiddingCenter"; -import { MergeBidding } from "./pages/MergeBidding"; import { SmartSourcing } from "./pages/SmartSourcing"; import { DepositManagement } from "./pages/DepositManagement"; import { ExceptionDecision } from "./pages/ExceptionDecision"; @@ -28,10 +24,7 @@ import { ExpertTasks } from "./pages/ExpertTasks"; import { AuditLog } from "./pages/AuditLog"; import { CollusionAnalysis } from "./pages/CollusionAnalysis"; import { EvidenceVerification } from "./pages/EvidenceVerification"; -import { ContractManagement } from "./pages/ContractManagement"; -import { SupplierInbound } from "./pages/SupplierInbound"; import { UserManagement } from "./pages/admin/UserManagement"; -import { ProcessConfig } from "./pages/admin/ProcessConfig"; import { KeyManagement } from "./pages/admin/KeyManagement"; export default function App() { @@ -51,20 +44,11 @@ export default function App() { } /> } /> } /> - } /> - } /> - {/* 招标专员 */} - } /> } /> {/* 资源管理 */} } /> } /> } /> - {/* 采购专员 */} - } /> - } /> - {/* 审批人 */} - } /> {/* 领导小组 */} } /> {/* 评标专家 */} @@ -77,7 +61,6 @@ export default function App() { } /> {/* 管理员 */} } /> - } /> } /> } /> diff --git a/front-end/src/app/components/AgentTaskMonitor.tsx b/front-end/src/app/components/AgentTaskMonitor.tsx new file mode 100644 index 0000000..1ac0537 --- /dev/null +++ b/front-end/src/app/components/AgentTaskMonitor.tsx @@ -0,0 +1,112 @@ +import { Bot, XCircle } from "lucide-react"; +import { Card } from "./ui/card"; +import { AiBadge } from "./shared/common"; +import { toast } from "sonner"; + +type AgentStatus = "queued" | "running" | "done" | "failed"; + +interface AgentTask { + icon: string; + name: string; + project: string; + status: AgentStatus; + progress: number; + result: string; + remain: string; +} + +// 示例数据(评审说明书第 6 节) +const TASKS: AgentTask[] = [ + { icon: "🔍", name: "AI 智慧寻源", project: "年产5万吨聚丙烯项目", status: "running", progress: 70, result: "已匹配:8 家供应商", remain: "预计剩余 2 分钟" }, + { icon: "🔬", name: "AI 雷同检测", project: "DCS 控制系统升级采购", status: "running", progress: 30, result: "已扫描:3 / 10 份", remain: "预计剩余 5 分钟" }, + { icon: "📊", name: "AI 价格分析", project: "环氧丙烷装置大修工程", status: "done", progress: 100, result: "发现 1 份报价偏离 >20%", remain: "09:35 完成" }, + { icon: "👨‍🏫", name: "AI 专家推荐", project: "污水处理提标改造工程", status: "queued", progress: 0, result: "排队中…", remain: "—" }, + { icon: "📄", name: "AI 评标报告生成", project: "实验室耗材集采", status: "failed", progress: 45, result: "模板解析异常,请重试", remain: "已终止" }, +]; + +const STATUS: Record = { + queued: { bar: "bg-[#9e9e9e]", barBg: "bg-[#eeeeee]", label: "⏸ 待执行", chip: "bg-slate-100 text-slate-500", dot: "#9e9e9e" }, + running: { bar: "bg-gradient-to-r from-[#fb8c00] to-[#ffb74d]", barBg: "bg-[#fff3e0]", label: "⏳ 执行中", chip: "bg-amber-50 text-amber-600", dot: "#ff9800" }, + done: { bar: "bg-[#4caf50]", barBg: "bg-[#e8f5e9]", label: "✅ 已完成", chip: "bg-emerald-50 text-emerald-600", dot: "#4caf50" }, + failed: { bar: "bg-[#f44336]", barBg: "bg-[#ffebee]", label: "❌ 执行失败", chip: "bg-red-50 text-red-600", dot: "#f44336" }, +}; + +export function AgentTaskMonitor() { + const running = TASKS.filter((t) => t.status === "running").length; + + return ( + +
+
+ +

后台智能体任务

+ + {running} 个执行中 +
+ + 每 3 秒实时刷新 + +
+ +
+ {TASKS.map((t, i) => { + const st = STATUS[t.status]; + return ( +
+ {/* 状态色条 */} + + {/* 图标 */} +
+ {t.icon} +
+ {/* 任务信息 */} +
+
+ {t.name} + {st.label} +
+
+ {t.project} · {t.result} +
+
+ {/* 进度条 */} +
+
+
+
+
+ {t.progress}% + {t.remain} +
+
+ {/* 操作 */} +
+ {t.status === "running" && ( + + )} + {t.status === "done" && ( + + )} + {t.status === "failed" && ( + + )} +
+
+ ); + })} +
+ + ); +} diff --git a/front-end/src/app/components/XiaobinAssistant.tsx b/front-end/src/app/components/XiaobinAssistant.tsx index dfac591..a4f3dac 100644 --- a/front-end/src/app/components/XiaobinAssistant.tsx +++ b/front-end/src/app/components/XiaobinAssistant.tsx @@ -1,14 +1,19 @@ import { useState, useRef, useEffect } from "react"; import { useNavigate } from "react-router"; -import { X, Send, Minus, Lock, ArrowRight } from "lucide-react"; +import { X, Send, Minus, Lock, ArrowRight, Sparkles } from "lucide-react"; import { Button } from "./ui/button"; import { cn } from "./ui/utils"; import { useRole } from "../role-context"; import type { RoleId } from "../roles"; +interface MsgAction { + label: string; + to: string; +} interface Msg { role: "bot" | "user"; text: string; + actions?: MsgAction[]; } type ProactiveType = "urgent" | "ai" | "todo" | "risk" | "suggestion"; @@ -23,8 +28,8 @@ interface Proactive { const TYPE_STYLE: Record = { urgent: { bg: "bg-[#fff3e0]", border: "border-[#ffcc80]", title: "text-[#e65100]", badge: "🔥" }, - ai: { bg: "bg-[#e8f5e9]", border: "border-[#a5d6a7]", title: "text-[#2e7d32]", badge: "✅" }, - todo: { bg: "bg-[#e3f2fd]", border: "border-[#90caf9]", title: "text-[#0d47a1]", badge: "📋" }, + ai: { bg: "bg-[#e3f2fd]", border: "border-[#90caf9]", title: "text-[#0d47a1]", badge: "✅" }, + todo: { bg: "bg-[#e8f0fe]", border: "border-[#a3c2f0]", title: "text-[#1565c0]", badge: "📋" }, risk: { bg: "bg-[#ffebee]", border: "border-[#ef9a9a]", title: "text-[#c62828]", badge: "⚠️" }, suggestion: { bg: "bg-[#f5f5f5]", border: "border-[#e0e0e0]", title: "text-[#455a64]", badge: "💡" }, }; @@ -32,61 +37,112 @@ const TYPE_STYLE: Record> = { specialist: [ - { type: "urgent", title: "BID-2026-005 今日需开标", content: "“2026年度防腐保温工程框架”已到开标时间,请立即组织评标", to: "/app/projects", actionLabel: "去处理" }, - { type: "ai", title: "AI 已完成:寻源报告生成", content: "“年产5万吨聚丙烯项目”已自动寻源,匹配到 12 家潜在供应商", to: "/app/projects", actionLabel: "查看" }, - { type: "todo", title: "您有 3 个委托单待审核", content: "来自技术部、采购部的委托申请已提交,请及时审核确认", to: "/app/delegation", actionLabel: "去审核" }, + { type: "urgent", title: "BID-2026-005 今日需开标", content: "「2026年度防腐保温工程框架」已到开标时间,请立即组织评标。", to: "/app/projects", actionLabel: "去处理" }, + { type: "ai", title: "AI 智慧寻源已完成", content: "「年产5万吨聚丙烯项目」已自动寻源,匹配到 12 家潜在供应商,请确认寻源结果。", to: "/app/projects/P2026005/sourcing", actionLabel: "查看结果" }, + { type: "todo", title: "您有 3 个委托单待受理", content: "来自采购需求人员的委托申请已提交,请及时受理并立项。", to: "/app/projects", actionLabel: "去受理" }, ], - supplier: [ - { type: "urgent", title: "报名即将截止", content: "“年产5万吨聚丙烯项目”报名将于 7月15日截止,请尽快完成报名", to: "/app/bidding", actionLabel: "去报名" }, - { type: "todo", title: "2 笔保证金待缴纳", content: "有 2 个项目需缴纳投标保证金,逾期将影响投标资格", to: "/app/bidding", actionLabel: "去缴纳" }, - { type: "ai", title: "开标结果已公布", content: "“数字化交付平台”项目已完成开标,点击查看评标结果", to: "/app/bidding", actionLabel: "查看" }, + requester: [ + { type: "ai", title: "阀门采购项目已定标", content: "您的「氯碱车间耐腐蚀阀门采购」已完成定标,下一步请进入 SRM 生成采购合同。", to: "/app/projects", actionLabel: "查看项目" }, + { type: "todo", title: "2 个 AI 预填委托单待确认", content: "AI 已根据采购计划为您预填委托单,确认无误后即可提交立项。", to: "/app/delegation", actionLabel: "去确认" }, ], expert: [ - { type: "urgent", title: "您收到催化剂采购项目的评标邀请", content: "请查看详情,接受邀请或申请回避(剩余不足 24 小时)", to: "/app/expert-tasks", actionLabel: "去查看" }, - { type: "todo", title: "《评标纪律承诺书》待签署", content: "进入评审前需先签署当前项目的评标纪律承诺书", to: "/app/expert-tasks", actionLabel: "去签署" }, - { type: "suggestion", title: "3 个评审项目待完成", content: "建议优先处理即将截止的评审任务,避免影响评审资格", to: "/app/expert-tasks", actionLabel: "查看" }, + { type: "urgent", title: "保温材料招标项目评标邀请", content: "您有一个「保温材料招标项目」的评标邀请,可以选择接受或拒绝,点击查看详情。", to: "/app/expert-tasks", actionLabel: "查看详情" }, + { type: "todo", title: "《评标纪律承诺书》待签署", content: "进入评审前需先签署当前项目的评标纪律承诺书。", to: "/app/expert-tasks", actionLabel: "去签署" }, ], - approver: [ - { type: "todo", title: "待审批事项 2 项", content: "有 2 个定标 / 立项审批等待您处理", to: "/app/approvals", actionLabel: "去审批" }, + supplier: [ + { type: "ai", title: "聚丙烯项目报名已通过", content: "您在「年产5万吨聚丙烯项目」中的报名已通过,请查看招标文件;如确认投标,可缴纳投标保证金。", to: "/app/bidding", actionLabel: "查看招标文件" }, + { type: "urgent", title: "报名即将截止", content: "「污水处理提标改造工程」报名将于 7月15日截止,请尽快完成报名。", to: "/app/bidding", actionLabel: "去报名" }, ], committee: [ - { type: "risk", title: "异常决策待处理", content: "检测到 1 个项目触发异常上报,需领导小组决策", to: "/app/exceptions", actionLabel: "去处理" }, + { type: "risk", title: "异常决策待处理", content: "检测到 1 个项目触发异常上报(有效投标人不足 3 家),需领导小组决策。", to: "/app/exceptions", actionLabel: "去处理" }, ], auditor: [ - { type: "risk", title: "围串标风险提示", content: "AI 检测到 1 组投标文件相似度偏高,建议核查", to: "/app/collusion", actionLabel: "去核查" }, + { type: "risk", title: "围串标风险提示", content: "AI 检测到 1 组投标文件相似度偏高,建议核查。", to: "/app/collusion", actionLabel: "去核查" }, ], }; -const quickReplies = ["如何发起招标委托?", "公开招标和邀请招标的区别?", "在线评标怎么打分?", "供应商如何入库?"]; +const quickReplies = [ + "如何发起招标委托?", + "帮我统计本年度项目预算总和", + "在线评标怎么打分?", + "公开招标和邀请招标的区别?", +]; -const knowledge: Record = { - 委托: - "发起招标委托很简单:① 点击工作台或项目管理页的「发起委托」按钮;② 在「填写需求」步骤用自然语言描述需求,点击「AI 智能解析」即可自动生成《招标委托表》;③ 确认预填单后提交审批即可。需要我带您过去吗?", - 区别: - "公开招标面向所有符合条件的供应商发布寻源公告,参与方需报名审核;邀请招标则由您从长名单中筛选短名单进行定向邀请。两者在本平台均支持全流程线上闭环。", - 评标: - "进入「在线评标室」后:左栏选择匿名投标人,中栏查看脱敏标书,右栏按技术分/商务分/价格分录入分数并填写评分说明,系统会同步展示 AI 雷同检测与价格合理性分析,最后点击「提交评分」。", - 入库: - "在「供应商管理」页点击「发起入库流程」,或在短名单管理中对供应商点击「发起入库」,系统将自动同步工商风险信息并进入审批。", - 合并: - "当系统中存在同类型未完成立项的委托时,系统会自动推送合并建议。您可以在立项阶段的「合并招标建议」卡片中查看并确认合并。", - 上传: - "进入「投标中心」→ 选择项目 → 在「上传投标文件」区域上传文件,系统会自动加密并上链存证。开标前任何人都无法查看,投标截止前还可撤回重传。", -}; +interface Knowledge { + text: string; + actions?: MsgAction[]; +} + +const knowledge: { key: string; ans: Knowledge }[] = [ + { + key: "委托", + ans: { + text: + "发起招标委托很简单:①点击工作台或项目管理页的「发起委托」按钮;②在「填写需求」步骤用自然语言描述需求,点击「AI 智能解析」即可自动生成《招标委托书》;③确认预填单后提交审批即可。", + actions: [{ label: "现在去发起委托", to: "/app/delegation" }], + }, + }, + { + key: "统计", + ans: { + text: "据统计,本年度一共有 13 个项目,预算总和为 12,348 万元。", + actions: [{ label: "查看项目列表", to: "/app/projects" }], + }, + }, + { + key: "预算", + ans: { + text: "据统计,本年度一共有 13 个项目,预算总和为 12,348 万元。", + actions: [{ label: "查看项目列表", to: "/app/projects" }], + }, + }, + { + key: "区别", + ans: { + text: + "公开招标面向所有符合条件的供应商发布寻源公告,参与方需报名审核;邀请招标则由您从长名单中筛选短名单进行定向邀请。招标方式在需求委托阶段即已确定,两者均支持全流程线上闭环。", + }, + }, + { + key: "评标", + ans: { + text: + "进入「在线评标室」后:左栏选择匿名投标人,中栏查看脱敏标书,右栏按技术分/商务分/价格分录入分数并填写评分说明,系统会同步展示 AI 雷同检测与价格合理性分析,最后点击「提交评分」。", + actions: [{ label: "进入在线评标室", to: "/app/projects/P2026001/evaluation" }], + }, + }, + { + key: "入库", + ans: { + text: + "供应商在「供应商管理」中提交入库申请,AI 会自动核验工商与风险信息;审核通过后系统将自动入库,无需单独操作。", + actions: [{ label: "前往供应商管理", to: "/app/suppliers" }], + }, + }, + { + key: "上传", + ans: { + text: + "进入「投标中心」→ 选择项目 → 在「上传投标文件」区域上传文件,系统会自动加密并上链存证。开标前任何人都无法查看,投标截止前还可撤回重传。", + actions: [{ label: "进入投标中心", to: "/app/bidding" }], + }, + }, +]; const dataKeywords = ["报价", "投标价", "多少钱", "金额", "中标", "得分", "分数", "名单", "谁"]; export function XiaobinAssistant() { const { sensitive, role, roleId } = useRole(); const navigate = useNavigate(); - const [open, setOpen] = useState(false); + // 默认展开:用户进入工作台即可看到小滨的主动提醒,可随时收起 + const [open, setOpen] = useState(true); const [showChat, setShowChat] = useState(false); const [input, setInput] = useState(""); const [proactive, setProactive] = useState(PROACTIVE[roleId] ?? []); const [msgs, setMsgs] = useState([ { role: "bot", - text: "您好,我是智能助手「小滨」👋 我可以为您解答系统操作与业务咨询。注意:我不参与任何业务决策哦。请问有什么可以帮您?", + text: "您好,我是智能助手「小滨」👋 我可以为您解答系统操作与业务咨询。注意:我不参与任何业务决策哦。请问有什么可以帮您?", }, ]); const endRef = useRef(null); @@ -103,14 +159,19 @@ export function XiaobinAssistant() { const gradient = `linear-gradient(135deg, ${role.bannerFrom}, ${role.bannerTo})`; const unread = proactive.length; - function answer(q: string) { + function answer(q: string): Knowledge { if (sensitive && dataKeywords.some((k) => q.includes(k))) { - return "当前为流程敏感期(如开标前),数据类问题暂无法回答。请等待系统通知。我可以继续为您讲解系统操作哦~"; + return { + text: "当前为流程敏感期(如开标前),数据类问题暂无法回答。请等待系统通知。我可以继续为您讲解系统操作哦~", + }; } - const key = Object.keys(knowledge).find((k) => q.includes(k)); - return key - ? knowledge[key] - : "这是一个很好的问题。作为操作助手,我建议您查阅对应模块的帮助说明,或描述更具体的操作场景,我会尽力为您讲解系统使用方法。(温馨提示:业务决策需由有权限的人员完成)"; + const hit = knowledge.find((k) => q.includes(k.key)); + return ( + hit?.ans ?? { + text: + "这是一个很好的问题。作为操作助手,我建议您查阅对应模块的帮助说明,或描述更具体的操作场景,我会尽力为您讲解系统使用方法。(温馨提示:业务决策需由有权限的人员完成)", + } + ); } function send(text: string) { @@ -119,17 +180,19 @@ export function XiaobinAssistant() { setShowChat(true); setMsgs((m) => [...m, { role: "user", text: q }]); setInput(""); - setTimeout(() => setMsgs((m) => [...m, { role: "bot", text: answer(q) }]), 500); + setTimeout(() => { + const a = answer(q); + setMsgs((m) => [...m, { role: "bot", text: a.text, actions: a.actions }]); + }, 500); } function handleAction(p: Proactive) { if (p.to) navigate(p.to); - setOpen(false); } return ( <> - {/* 悬浮球 + 呼吸光环 */} + {/* 悬浮球 + 呼吸光环(收起状态) */} {!open && (
-
- - -
+ {sensitive && ( @@ -182,6 +240,19 @@ export function XiaobinAssistant() {
{!showChat ? ( <> +
+ + 📢 为您整理的今日提醒({proactive.length}) + + {proactive.length > 0 && ( + + )} +
{proactive.length === 0 && (
🎉 暂无待办,继续保持! @@ -206,7 +277,7 @@ export function XiaobinAssistant() { {p.to && ( @@ -238,13 +309,26 @@ export function XiaobinAssistant() {
- {m.text} +
{m.text}
+ {m.actions && m.actions.length > 0 && ( +
+ {m.actions.map((a) => ( + + ))} +
+ )}
))} diff --git a/front-end/src/app/components/shared/icons.ts b/front-end/src/app/components/shared/icons.ts index b456f52..c903864 100644 --- a/front-end/src/app/components/shared/icons.ts +++ b/front-end/src/app/components/shared/icons.ts @@ -24,6 +24,8 @@ import { Eye, CheckCircle2, TrendingUp, + FilePlus2, + Bot, } from "lucide-react"; export const ICONS: Record = { @@ -52,4 +54,6 @@ export const ICONS: Record = { Eye, CheckCircle2, TrendingUp, + FilePlus2, + Bot, }; diff --git a/front-end/src/app/data/workbench.ts b/front-end/src/app/data/workbench.ts index 0bcbcaa..f67def1 100644 --- a/front-end/src/app/data/workbench.ts +++ b/front-end/src/app/data/workbench.ts @@ -22,7 +22,9 @@ export interface WbConfig { stats: WbStat[]; groups: WbGroup[]; /** 角色专属附加组件标识 */ - extra?: "specialist" | "supplier" | "admin" | "auditor" | "committee" | "expert" | "approver"; + extra?: "specialist" | "supplier" | "admin" | "auditor" | "committee" | "expert" | "requester"; + /** 是否展示后台智能体任务监控模块 */ + agentMonitor?: boolean; primaryAction?: { label: string; link: string }; } @@ -32,16 +34,19 @@ export const WORKBENCH: Record = { stats: [ { label: "进行中项目", value: "4" }, { label: "已定标", value: "7" }, + { label: "保证金在途(万元)", value: "42" }, { label: "被驳回", value: "1", alert: true }, ], + extra: "requester", primaryAction: { label: "✨ AI 发起新委托", link: "/app/delegation" }, groups: [ { stage: "我的待办", todos: [ { title: "待确认的 AI 预填委托单", count: 2, project: "氯碱车间耐腐蚀阀门采购", link: "/app/delegation", ai: true, priority: "高" }, - { title: "待参与的技术标评审", count: 1, project: "DCS 控制系统升级采购", link: "/app/projects/P2026001/evaluation", priority: "中" }, { title: "待补充需求资料", count: 1, project: "污水处理提标改造工程", link: "/app/projects/P2026004", priority: "低" }, + { title: "待确认中标结果", count: 1, project: "环氧丙烷装置大修工程", link: "/app/projects/P2026003", priority: "高" }, + { title: "待缴纳 / 退还保证金", count: 3, link: "/app/deposits", priority: "中" }, ], }, ], @@ -55,13 +60,13 @@ export const WORKBENCH: Record = { { label: "超时预警", value: "2", alert: true }, ], extra: "specialist", - primaryAction: { label: "+ 新建招标项目", link: "/app/delegation" }, + agentMonitor: true, + primaryAction: { label: "+ 新建招标项目", link: "/app/projects" }, groups: [ { stage: "需求阶段", todos: [ - { title: "待确认委托单", count: 3, link: "/app/delegation", ai: true, priority: "高" }, - { title: "待合并招标建议", count: 1, link: "/app/merge", ai: true, priority: "中" }, + { title: "待受理委托单", count: 3, link: "/app/projects", ai: true, priority: "高" }, ], }, { @@ -74,35 +79,15 @@ export const WORKBENCH: Record = { { stage: "评标阶段", todos: [ - { title: "待确认专家抽取", count: 1, link: "/app/experts", priority: "高" }, + { title: "待组织专家抽取", count: 1, link: "/app/projects/P2026001", priority: "高" }, { title: "待处理评标异常", count: 1, link: "/app/projects/P2026001/evaluation", priority: "高" }, ], }, { stage: "定标阶段", todos: [ - { title: "待生成评标报告", count: 1, link: "/app/projects/P2026003/award", ai: true, priority: "中" }, - { title: "待发起定标审批", count: 1, link: "/app/projects/P2026003/award", priority: "高" }, - ], - }, - ], - }, - purchaser: { - greeting: "中标结果确认、合同生成与保证金管理一站式处理。", - stats: [ - { label: "待签约合同", value: "3" }, - { label: "本月应入库供应商", value: "5" }, - { label: "保证金应收(万元)", value: "126" }, - ], - primaryAction: { label: "✨ AI 生成合同", link: "/app/contracts" }, - groups: [ - { - stage: "我的待办", - todos: [ - { title: "待确认中标结果", count: 1, project: "环氧丙烷装置大修工程", link: "/app/projects/P2026003/award", priority: "高" }, - { title: "待生成合同", count: 2, link: "/app/contracts", ai: true, priority: "高" }, - { title: "待收取履约保证金", count: 3, link: "/app/deposits", priority: "中" }, - { title: "待发起供应商入库", count: 5, link: "/app/inbound", priority: "中" }, + { title: "待生成评标报告", count: 1, link: "/app/projects/P2026003", ai: true, priority: "中" }, + { title: "待提交定标结果", count: 1, link: "/app/projects/P2026003", priority: "高" }, ], }, ], @@ -145,26 +130,6 @@ export const WORKBENCH: Record = { }, ], }, - approver: { - greeting: "AI 已为每项审批提炼关键信息,助您高效决策。", - stats: [ - { label: "待审批总数", value: "12" }, - { label: "平均审批耗时", value: "2.4h" }, - { label: "本月已审批", value: "38" }, - ], - extra: "approver", - groups: [ - { - stage: "按类型分组", - todos: [ - { title: "待审批委托", count: 4, link: "/app/approvals", priority: "中" }, - { title: "待审批立项", count: 3, link: "/app/approvals", priority: "中" }, - { title: "待审批公告", count: 2, link: "/app/approvals", priority: "高" }, - { title: "待审批定标", count: 3, link: "/app/approvals", priority: "高" }, - ], - }, - ], - }, supplier: { greeting: "AI 已为您推荐高匹配度项目,请关注报名与投标截止时间。", stats: [ @@ -193,13 +158,14 @@ export const WORKBENCH: Record = { { label: "待处理告警", value: "2", alert: true }, ], extra: "admin", + agentMonitor: true, groups: [ { stage: "待处理事项", todos: [ { title: "用户权限申请", count: 3, link: "/app/admin/users", priority: "中" }, - { title: "流程配置变更", count: 1, link: "/app/admin/process", priority: "中" }, { title: "密钥漂移待执行", count: 1, link: "/app/admin/keys", priority: "高" }, + { title: "系统告警待处理", count: 2, link: "/app/audit-logs", priority: "高" }, ], }, ], diff --git a/front-end/src/app/pages/ApprovalCenter.tsx b/front-end/src/app/pages/ApprovalCenter.tsx deleted file mode 100644 index 2afe304..0000000 --- a/front-end/src/app/pages/ApprovalCenter.tsx +++ /dev/null @@ -1,183 +0,0 @@ -import { useState } from "react"; -import { Sparkles, ClipboardCheck, ArrowLeft, ThumbsUp, RotateCcw, Forward, FileText, Paperclip } from "lucide-react"; -import { toast } from "sonner"; -import { Button } from "../components/ui/button"; -import { Card } from "../components/ui/card"; -import { Tabs, TabsList, TabsTrigger } from "../components/ui/tabs"; -import { PageHeader, ApprovalTracker } from "../components/shared/common"; -import { approvals, type ApprovalItem } from "../data/mock"; - -export function ApprovalCenter() { - const [filter, setFilter] = useState("全部"); - const [active, setActive] = useState(null); - const [selected, setSelected] = useState([]); - - const types = ["全部", "委托审批", "立项审批", "公告审批", "定标审批"]; - const list = approvals.filter((a) => filter === "全部" || a.type === filter); - - if (active) return setActive(null)} />; - - function toggle(id: string) { - setSelected((s) => (s.includes(id) ? s.filter((x) => x !== id) : [...s, id])); - } - - return ( -
- 0 ? ( - - ) : undefined - } - /> - - - - {types.map((t) => ( - - {t} - {t !== "全部" && ( - - {approvals.filter((a) => a.type === t).length} - - )} - - ))} - - - -
- {list.map((a) => ( - - toggle(a.id)} - /> -
- -
-
-
- {a.type} - {a.urgent && 超时预警} -
-
{a.project}
-
- 申请人 {a.applicant} · 金额 {a.amount.toLocaleString()} 万元 · {a.time} -
-
- -
- ))} -
-
- ); -} - -function ApprovalDetail({ item, onBack }: { item: ApprovalItem; onBack: () => void }) { - return ( -
-
- -
-

{item.type}

-

{item.project}

-
-
- -
-
- {/* AI 审批摘要 */} - -
- -

AI 审批摘要

-
-

{item.summary}

-
- {[ - { l: "申请金额", v: `${item.amount.toLocaleString()} 万元` }, - { l: "申请人", v: item.applicant }, - { l: "提交时间", v: item.time }, - ].map((x) => ( -
-
{x.l}
-
{x.v}
-
- ))} -
-
- - {/* 申请单据(只读) */} - -
- -

申请单据(只读)

-
-
- {[ - ["项目名称", item.project], - ["审批类型", item.type], - ["预算/金额", `${item.amount.toLocaleString()} 万元`], - ["申请部门", "招标采购中心"], - ["事项说明", item.summary], - ].map(([l, v]) => ( -
- {l} - {v} -
- ))} -
-
- - {item.project}-申请附件.pdf - -
-
- - {/* 审批操作 */} - -

审批操作

- -