调整dashboard项目结构

This commit is contained in:
mlogclub
2026-04-24 11:27:49 +08:00
parent eb353cbbc8
commit 5fa30d29ef
88 changed files with 71 additions and 40 deletions
@@ -12,10 +12,10 @@ import {
type DashboardOverview,
type DashboardRange,
} from "@/lib/api/dashboard"
import { SummaryCards } from "./_components/summary-cards"
import { TrendPanel } from "./_components/trend-panel"
import { TeamLoadPanel } from "./_components/team-load-panel"
import { AlertList } from "./_components/alert-list"
import { SummaryCards } from "./summary-cards"
import { TrendPanel } from "./trend-panel"
import { TeamLoadPanel } from "./team-load-panel"
import { AlertList } from "./alert-list"
const rangeOptions: Array<{ value: DashboardRange; label: string }> = [
{ value: "today", label: "今天" },
@@ -39,7 +39,7 @@ function LoadingCards() {
)
}
export default function DashboardPage() {
export function DashboardHome() {
const [range, setRange] = useState<DashboardRange>("7d")
const [data, setData] = useState<DashboardOverview | null>(null)
const [loading, setLoading] = useState(true)
+5
View File
@@ -0,0 +1,5 @@
import { DashboardHome } from "./_components/dashboard-home"
export default function DashboardHomePage() {
return <DashboardHome />
}
@@ -236,7 +236,7 @@ export default function TicketRiskPage() {
]}
/>
</div>
<Link href="/tickets">
<Link href="/dashboard/tickets">
<Button variant="outline"></Button>
</Link>
<Button variant="outline" onClick={() => void loadData()} disabled={loading}>
@@ -224,7 +224,7 @@ export function TicketStatusDialog({
<div className="mt-2 rounded-lg border border-amber-200 bg-amber-50/70 p-3 text-xs text-amber-900">
<Link
href="/ticket-resolution-codes"
href="/dashboard/ticket-resolution-codes"
target="_blank"
rel="noreferrer"
className="ml-1 font-medium underline underline-offset-4"
@@ -810,7 +810,7 @@ export default function TicketDetailPage() {
SLA SLA
使
<Link
href="/ticket-priorities"
href="/dashboard/ticket-priorities"
className="ml-1 font-medium underline underline-offset-4"
>
@@ -912,7 +912,7 @@ export default function TicketDetailPage() {
<Button
variant="outline"
className="w-full"
onClick={() => router.push("/conversations")}
onClick={() => router.push("/dashboard/conversations")}
>
<RotateCcwIcon className="size-4" />
+1 -1
View File
@@ -27,7 +27,7 @@ function WxWorkLoginCallbackContent() {
const ticket = searchParams.get("ticket")?.trim() ?? ""
const next = searchParams.get("next")
const nextPath = next && next.startsWith("/") ? next : "/"
const nextPath = next && next.startsWith("/") ? next : "/dashboard"
if (!ticket) {
toast.error("企业微信登录票据不存在")
+25
View File
@@ -0,0 +1,25 @@
import Link from "next/link"
export default function HomePage() {
return (
<main className="flex min-h-svh items-center justify-center bg-[linear-gradient(145deg,#fff7ed_0%,#ffffff_38%,#ecfeff_100%)] px-6 py-16">
<div className="w-full max-w-3xl rounded-[32px] border border-white/70 bg-white/90 p-10 shadow-[0_24px_80px_rgba(15,23,42,0.08)] backdrop-blur">
<div className="inline-flex rounded-full border border-amber-200 bg-amber-50 px-3 py-1 text-xs font-medium tracking-[0.18em] text-amber-900 uppercase">
Landing Page
</div>
<h1 className="mt-6 text-4xl font-semibold tracking-tight text-foreground">TODO</h1>
<p className="mt-4 max-w-2xl text-sm leading-6 text-muted-foreground">
</p>
<div className="mt-8 flex flex-wrap gap-3">
<Link href="/dashboard">
</Link>
<Link href="/login">
</Link>
</div>
</div>
</main>
)
}
+1 -1
View File
@@ -46,7 +46,7 @@ export function AppSidebar({ ...props }: ComponentProps<typeof Sidebar>) {
<SidebarMenuItem>
<SidebarMenuButton
className="data-[slot=sidebar-menu-button]:p-1.5!"
render={<Link href="/" />}
render={<Link href="/dashboard" />}
>
<BotMessageSquareIcon className="size-5!" />
<span className="text-base font-semibold">AGENT</span>
+5 -4
View File
@@ -33,6 +33,7 @@ export function AuthProvider({ children }: { children: ReactNode }) {
const router = useRouter()
const [session, setSession] = useState<AuthSession | null>(null)
const [ready, setReady] = useState(false)
const requiresAuth = pathname?.startsWith("/dashboard") ?? false
const refreshProfile = useCallback(async () => {
const stored = readSession()
@@ -55,7 +56,7 @@ export function AuthProvider({ children }: { children: ReactNode }) {
} catch {
clearSession()
setSession(null)
if (pathname && !pathname.startsWith("/login")) {
if (requiresAuth) {
startTransition(() => {
router.replace("/login")
})
@@ -63,7 +64,7 @@ export function AuthProvider({ children }: { children: ReactNode }) {
} finally {
setReady(true)
}
}, [pathname, router])
}, [requiresAuth, router])
async function signOut() {
const current = readSession()
@@ -83,12 +84,12 @@ export function AuthProvider({ children }: { children: ReactNode }) {
}
setReady(true)
if (pathname && !pathname.startsWith("/login")) {
if (requiresAuth) {
startTransition(() => {
router.replace("/login")
})
}
}, [pathname, refreshProfile, router])
}, [requiresAuth, refreshProfile, router])
return (
<AuthContext.Provider value={{ session, ready, refreshProfile, signOut }}>
+1 -1
View File
@@ -4,7 +4,7 @@ import { useEffect, useMemo, useState } from "react"
import { ChevronsUpDownIcon, PlusIcon } from "lucide-react"
import { toast } from "sonner"
import { EditDialog as CompanyEditDialog } from "@/app/(dashboard)/companies/_components/edit"
import { EditDialog as CompanyEditDialog } from "@/app/dashboard/companies/_components/edit"
import { Button } from "@/components/ui/button"
import {
Command,
+1 -1
View File
@@ -36,7 +36,7 @@ export function LoginForm({
const nextPath = searchParams.get("next")
const wxworkError = searchParams.get("wxworkError")
const redirectPath =
nextPath && nextPath.startsWith("/") ? nextPath : "/"
nextPath && nextPath.startsWith("/") ? nextPath : "/dashboard"
useEffect(() => {
if (session) {
+23 -23
View File
@@ -98,42 +98,42 @@ export const dashboardNavSections: DashboardNavSectionConfig[] = [
items: [
{
title: "总览",
url: "/",
url: "/dashboard",
icon: <LayoutDashboardIcon />,
},
{
title: "会话",
url: "/conversations",
url: "/dashboard/conversations",
icon: <BotMessageSquareIcon />,
requiredPermission: "conversation.view",
},
{
title: "工单",
url: "/tickets",
url: "/dashboard/tickets",
icon: <FileTextIcon />,
requiredPermission: "ticket.view",
},
{
title: "会话监控",
url: "/conversation-monitor",
url: "/dashboard/conversation-monitor",
icon: <BotMessageSquareIcon />,
requiredPermission: "conversation.view",
},
{
title: "SLA风险",
url: "/ticket-risk",
url: "/dashboard/ticket-risk",
icon: <ChartColumnIncreasingIcon />,
requiredPermission: "ticket.view",
},
{
title: "客户管理",
url: "/customers",
url: "/dashboard/customers",
icon: <UsersIcon />,
requiredPermission: "customer.view",
},
{
title: "公司管理",
url: "/companies",
url: "/dashboard/companies",
icon: <Building2Icon />,
requiredPermission: "company.view",
},
@@ -144,43 +144,43 @@ export const dashboardNavSections: DashboardNavSectionConfig[] = [
items: [
{
title: "分类标签",
url: "/tags",
url: "/dashboard/tags",
icon: <TagsIcon />,
requiredPermission: "tag.view",
},
{
title: "快捷回复",
url: "/quick-replies",
url: "/dashboard/quick-replies",
icon: <MessageSquareMoreIcon />,
requiredPermission: "quickReply.view",
},
{
title: "工单优先级",
url: "/ticket-priorities",
url: "/dashboard/ticket-priorities",
icon: <Settings2Icon />,
requiredPermission: "ticketPriorityConfig.view",
},
{
title: "工单解决码",
url: "/ticket-resolution-codes",
url: "/dashboard/ticket-resolution-codes",
icon: <KeyRoundIcon />,
requiredPermission: "ticketResolutionCode.view",
},
{
title: "客服档案",
url: "/agents",
url: "/dashboard/agents",
icon: <UserCogIcon />,
requiredPermission: "agent.view",
},
{
title: "客服组排班",
url: "/agent-team-schedules",
url: "/dashboard/agent-team-schedules",
icon: <CalendarClockIcon />,
requiredPermission: "agentTeamSchedule.view",
},
{
title: "接入渠道",
url: "/channels",
url: "/dashboard/channels",
icon: <GlobeIcon />,
requiredPermission: "channel.view",
},
@@ -191,37 +191,37 @@ export const dashboardNavSections: DashboardNavSectionConfig[] = [
items: [
{
title: "知识库",
url: "/knowledge",
url: "/dashboard/knowledge",
icon: <FileTextIcon />,
requiredPermission: "knowledgeBase.view",
},
{
title: "AI配置",
url: "/ai-configs",
url: "/dashboard/ai-configs",
icon: <BrainCircuitIcon />,
requiredPermission: "aiConfig.view",
},
{
title: "AI Agent",
url: "/ai-agents",
url: "/dashboard/ai-agents",
icon: <MessageSquareMoreIcon />,
requiredPermission: "aiAgent.view",
},
{
title: "Skills",
url: "/skill-definition",
url: "/dashboard/skill-definition",
icon: <MessageSquareCodeIcon />,
requiredPermission: "skillDefinition.view",
},
{
title: "MCP调试",
url: "/mcp",
url: "/dashboard/mcp",
icon: <MessageSquareCodeIcon />,
requiredPermission: "mcp.view",
},
{
title: "Agent日志",
url: "/agent-run-logs",
url: "/dashboard/agent-run-logs",
icon: <ActivitySquareIcon />,
requiredPermission: "conversation.view",
},
@@ -232,19 +232,19 @@ export const dashboardNavSections: DashboardNavSectionConfig[] = [
items: [
{
title: "用户管理",
url: "/users",
url: "/dashboard/users",
icon: <UsersIcon />,
requiredPermission: "user.view",
},
{
title: "角色管理",
url: "/roles",
url: "/dashboard/roles",
icon: <ShieldCheckIcon />,
requiredPermission: "role.view",
},
{
title: "权限管理",
url: "/permissions",
url: "/dashboard/permissions",
icon: <KeyRoundIcon />,
requiredPermission: "permission.view",
},