"use client"; import Link from "next/link"; import { Activity, AlertTriangle, BarChart3, Check, FileText, LogOut, ShieldAlert, Users } from "lucide-react"; import { useEffect, useState } from "react"; import { apiFetch } from "@/lib/api"; import { clearToken, getRoleLabel } from "@/lib/auth"; import type { UserPayload } from "@/types/api"; interface DashboardData { overview?: { total_customers?: number; signed_customers?: number; total_aum?: string }; todos?: { pending?: number } } interface RiskAlert { id: number; customer_id: number; alert_type: string; alert_level: string; status: string } interface WorkOrder { id: number; work_order_no: string; order_type: string; status: string; priority: string } interface Customer { customer_id?: number; id?: number; real_name?: string; name?: string; risk_level?: string; total_aum?: string | number } interface Todo { id: number; todo_type: string; status: string; priority: string } interface Visit { id: number; customer_id: number; visit_type?: string; content?: string } function Frame({ title, subtitle, role, children }: { title: string; subtitle: string; role: string; children: React.ReactNode }) { return

Huaxia Fund Operations

{title}

{role}

{subtitle}

{children}
; } async function getMe() { return (await apiFetch<{ user: UserPayload }>("/auth/me")).user; } function Notice({ children }: { children: React.ReactNode }) { return
{children}
; } export function AdvisorWorkspace() { const [user, setUser] = useState(null); const [dashboard, setDashboard] = useState(null); const [customers, setCustomers] = useState([]); const [todos, setTodos] = useState([]); const [visits, setVisits] = useState([]); const [report, setReport] = useState | null>(null); const [error, setError] = useState(""); async function load() { try { const [current, overview, customerData, todoData, visitData, personalReport] = await Promise.all([getMe(), apiFetch("/advisor/dashboard"), apiFetch<{ items?: Customer[] }>("/advisor/customers?page=1&page_size=50"), apiFetch<{ items?: Todo[] }>("/advisor/todos?page=1&page_size=20"), apiFetch<{ items?: Visit[] }>("/advisor/visits?page=1&page_size=20"), apiFetch>("/advisor/report/personal")]); setUser(current); setDashboard(overview); setCustomers(customerData.items ?? []); setTodos(todoData.items ?? []); setVisits(visitData.items ?? []); setReport(personalReport); } catch { setError("部分投顾数据加载失败,请确认投顾权限或后端服务状态。"); } } useEffect(() => { void load(); }, []); async function finishTodo(id: number) { await apiFetch(`/advisor/todos/${id}/handle`, { method: "POST", body: JSON.stringify({ action: "done" }) }); await load(); } const overview = dashboard?.overview; return {error && {error}}

名下客户

{overview?.total_customers ?? "--"}

签约客户

{overview?.signed_customers ?? "--"}

管理资产

{overview?.total_aum ? `¥${overview.total_aum}` : "--"}

待办事项

{dashboard?.todos?.pending ?? "--"}

客户管理

{customers.slice(0, 8).map((item) =>
{item.real_name ?? item.name ?? `客户 #${item.customer_id ?? item.id}`}{item.risk_level ?? "未评估"} · {item.total_aum ?? "--"}
)}{!customers.length &&

暂无客户数据

}

待办处理

{todos.slice(0, 6).map((todo) =>
{todo.todo_type} · {todo.priority}
)}{!todos.length &&

暂无待办

}

回访记录

{visits.slice(0, 5).map((visit) =>
客户 #{visit.customer_id} · {visit.visit_type ?? "回访"}

{visit.content ?? "暂无内容"}

)}{!visits.length &&

暂无回访记录

}

个人绩效

{report ? JSON.stringify(report, null, 2) : "暂无绩效数据"}
; } export function RiskWorkspace() { const [user, setUser] = useState(null); const [alerts, setAlerts] = useState([]); const [orders, setOrders] = useState([]); const [error, setError] = useState(""); async function load() { try { const [current, alertData, orderData] = await Promise.all([getMe(), apiFetch<{ items?: RiskAlert[] }>("/risk/alert/list?page=1&page_size=10"), apiFetch<{ items?: WorkOrder[] }>("/work-order/list?page=1&page_size=10")]); setUser(current); setAlerts(alertData.items ?? []); setOrders(orderData.items ?? []); } catch { setError("风控数据加载失败,请确认风控权限或后端服务状态。"); } } useEffect(() => { void load(); }, []); async function alertAction(id: number, action: "release" | "block" | "freeze") { await apiFetch(`/risk/alert/${id}/${action}`, { method: "POST" }); await load(); } async function orderAction(id: number, action: "claim" | "submit-review" | "review") { const body = action === "review" ? { work_order_id: id, approve: window.confirm("确认通过该工单?"), comment: "前端工作区复核" } : { work_order_id: id }; await apiFetch(`/work-order/${action}`, { method: "POST", body: JSON.stringify(body) }); await load(); } return {error && {error}}

当前预警

{alerts.length}

高风险事项

{alerts.filter((item) => item.alert_level === "高").length}

工单数量

{orders.length}

风险预警处置

{alerts.map((alert) =>
{alert.alert_type} · 客户 #{alert.customer_id}{alert.status}
)}{!alerts.length &&

暂无风险预警

}

业务工单

{orders.map((item) =>
{item.work_order_no} · {item.order_type} · {item.status}
)}{!orders.length &&

暂无工单

}
; } export function CommonWorkspace() { const [user, setUser] = useState(null); useEffect(() => { void getMe().then(setUser).catch(() => undefined); }, []); const isAdmin = user?.user_type === "ADMIN"; return

基金数据

查看真实基金产品和历史净值

{isAdmin ?

NL2SQL 配置

管理员专用:运行配置和查询权限管理

:

数据查询

员工自然语言查询与历史记录

}{isAdmin &&

知识库管理

管理员专用:文档上传、预览和删除

}
; }