🎉 init: 小龙的工作空间
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
"use client";
|
||||
import { Card } from "@/components/ui/Card";
|
||||
|
||||
const approvals = [
|
||||
{ id: "a1", type: "请假", applicant: "张三", status: "pending", date: "2026-06-05" },
|
||||
{ id: "a2", type: "报销", applicant: "李四", status: "approved", date: "2026-06-04" },
|
||||
{ id: "a3", type: "加班", applicant: "王五", status: "rejected", date: "2026-06-03" },
|
||||
];
|
||||
const statusMap: Record<string, { label: string; color: string }> = {
|
||||
pending: { label: "待审批", color: "bg-yellow-100 text-yellow-700" },
|
||||
approved: { label: "已通过", color: "bg-green-100 text-green-700" },
|
||||
rejected: { label: "已驳回", color: "bg-red-100 text-red-700" },
|
||||
};
|
||||
|
||||
export default function ApprovalPage() {
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<h1 className="text-xl font-bold text-gray-800">我的审批</h1>
|
||||
{approvals.map(a => {
|
||||
const s = statusMap[a.status];
|
||||
return (
|
||||
<Card key={a.id}>
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<p className="font-medium text-gray-800">{a.type}申请 — {a.applicant}</p>
|
||||
<p className="text-xs text-gray-400 mt-1">{a.date}</p>
|
||||
</div>
|
||||
<span className={`text-xs px-2 py-1 rounded ${s.color}`}>{s.label}</span>
|
||||
</div>
|
||||
</Card>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
"use client";
|
||||
import { useState } from "react";
|
||||
import { Card } from "@/components/ui/Card";
|
||||
import { Button } from "@/components/ui/Button";
|
||||
|
||||
export default function AttendancePage() {
|
||||
const [checkedIn, setCheckedIn] = useState(false);
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<h1 className="text-xl font-bold text-gray-800">考勤打卡</h1>
|
||||
<Card className="text-center py-8">
|
||||
<p className="text-4xl mb-2">{checkedIn ? "✅" : "🕐"}</p>
|
||||
<p className="text-sm text-gray-500">{new Date().toLocaleString("zh-CN")}</p>
|
||||
<Button onClick={() => setCheckedIn(!checkedIn)} variant={checkedIn ? "secondary" : "primary"} className="mt-4" size="lg" disabled={checkedIn}>
|
||||
{checkedIn ? "已打卡" : "打卡签到"}
|
||||
</Button>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
"use client";
|
||||
import { Card } from "@/components/ui/Card";
|
||||
import { Input } from "@/components/ui/Input";
|
||||
|
||||
export default function ContactPage() {
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<h1 className="text-xl font-bold text-gray-800">通讯录</h1>
|
||||
<Input placeholder="搜索同事..." />
|
||||
<div className="space-y-2">
|
||||
{["张三 · 技术部", "李四 · 产品部", "王五 · 设计部"].map((n, i) => (
|
||||
<Card key={i}><p className="text-sm text-gray-700">{n}</p></Card>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
body {
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import { Card } from "@/components/ui/Card";
|
||||
import { Button } from "@/components/ui/Button";
|
||||
import { EmptyState } from "@/components/ui/EmptyState";
|
||||
import { useItems } from "@/hooks/useItems";
|
||||
|
||||
export default function PagePage() {
|
||||
const { data, loading, error, refetch } = useItems();
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<h1 className="text-xl font-bold text-gray-800">优先级管理</h1>
|
||||
<p className="text-sm text-gray-500 mt-1">优先级管理</p>
|
||||
</div>
|
||||
<Button onClick={() => setOpen(true)} variant="primary" size="sm">新增</Button>
|
||||
</div>
|
||||
|
||||
{loading ? (
|
||||
<div className="flex justify-center py-12">
|
||||
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-500" />
|
||||
</div>
|
||||
) : error ? (
|
||||
<Card className="text-center py-8">
|
||||
<p className="text-red-500 text-sm">{error}</p>
|
||||
<Button onClick={refetch} variant="secondary" size="sm" className="mt-2">重试</Button>
|
||||
</Card>
|
||||
) : data.length === 0 ? (
|
||||
<EmptyState
|
||||
icon="📭"
|
||||
title="暂无数据"
|
||||
description="还没有任何记录,点击上方按钮开始"
|
||||
action={<Button onClick={() => setOpen(true)} variant="primary" size="sm">创建第一条</Button>}
|
||||
/>
|
||||
) : (
|
||||
<div className="space-y-3">
|
||||
{data.map((item: any) => (
|
||||
<Card key={item.id}>
|
||||
<h3 className="font-medium text-gray-800">{item.title || item.name || `Item ${item.id.slice(0, 8)}`}</h3>
|
||||
<p className="text-xs text-gray-400 mt-1">{item.createdAt || ""}</p>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
import type { Metadata } from "next";
|
||||
import "./globals.css";
|
||||
import { Sidebar } from "@/components/layout/Sidebar";
|
||||
import { BottomNav } from "@/components/layout/BottomNav";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "OAFlow",
|
||||
description: "一款支持审批流、考勤管理、部门协作的企业办公自动化系统。",
|
||||
};
|
||||
|
||||
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
<html lang="zh-CN">
|
||||
<body className="bg-gray-50 min-h-screen">
|
||||
<div className="flex">
|
||||
{/* Desktop Sidebar */}
|
||||
<Sidebar items={[{"name":"首页","href":"/home","icon":"🏠"},{"name":"工单创建","href":"/tickets","icon":"📋"},{"name":"分配","href":"/items","icon":"📅"},{"name":"处理流程","href":"/items","icon":"✏️"},{"name":"优先级管理","href":"/items","icon":"📸"}] } projectName="OAFlow" />
|
||||
{/* Main Content */}
|
||||
<main className="flex-1 lg:pl-64 pb-20 lg:pb-0">
|
||||
<div className="max-w-2xl mx-auto px-4 py-6">
|
||||
{children}
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
{/* Mobile Bottom Nav */}
|
||||
<BottomNav items={[{"name":"首页","href":"/home","icon":"🏠"},{"name":"工单创建","href":"/tickets","icon":"📋"},{"name":"分配","href":"/items","icon":"📅"},{"name":"处理流程","href":"/items","icon":"✏️"}] } />
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import { Card } from "@/components/ui/Card";
|
||||
import { Button } from "@/components/ui/Button";
|
||||
import { EmptyState } from "@/components/ui/EmptyState";
|
||||
import { useNotices } from "@/hooks/useNotices";
|
||||
|
||||
export default function PagePage() {
|
||||
const { data, loading, error, refetch } = useNotices();
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<h1 className="text-xl font-bold text-gray-800">公告</h1>
|
||||
<p className="text-sm text-gray-500 mt-1">公告列表、详情</p>
|
||||
</div>
|
||||
<Button onClick={() => setOpen(true)} variant="primary" size="sm">新增</Button>
|
||||
</div>
|
||||
|
||||
{loading ? (
|
||||
<div className="flex justify-center py-12">
|
||||
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-500" />
|
||||
</div>
|
||||
) : error ? (
|
||||
<Card className="text-center py-8">
|
||||
<p className="text-red-500 text-sm">{error}</p>
|
||||
<Button onClick={refetch} variant="secondary" size="sm" className="mt-2">重试</Button>
|
||||
</Card>
|
||||
) : data.length === 0 ? (
|
||||
<EmptyState
|
||||
icon="📭"
|
||||
title="暂无数据"
|
||||
description="还没有任何记录,点击上方按钮开始"
|
||||
action={<Button onClick={() => setOpen(true)} variant="primary" size="sm">创建第一条</Button>}
|
||||
/>
|
||||
) : (
|
||||
<div className="space-y-3">
|
||||
{data.map((item: any) => (
|
||||
<Card key={item.id}>
|
||||
<h3 className="font-medium text-gray-800">{item.title || item.name || `Item ${item.id.slice(0, 8)}`}</h3>
|
||||
<p className="text-xs text-gray-400 mt-1">{item.createdAt || ""}</p>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
import Link from "next/link";
|
||||
|
||||
export default function HomePage() {
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
{/* Hero Section */}
|
||||
<section className="bg-gradient-to-br from-blue-500 to-blue-700 rounded-2xl p-6 text-white">
|
||||
<h1 className="text-2xl font-bold">OAFlow</h1>
|
||||
<p className="mt-2 text-blue-100 text-sm">应用首页</p>
|
||||
</section>
|
||||
|
||||
{/* Quick Actions */}
|
||||
<section>
|
||||
<h2 className="text-lg font-semibold text-gray-800 mb-3">快捷入口</h2>
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
<Link key="0" href="/home" className="bg-white rounded-xl border border-gray-100 p-4 text-center hover:shadow-md transition-shadow">
|
||||
<span className="text-2xl block mb-1">📋</span>
|
||||
<span className="text-sm text-gray-600">工单创建</span>
|
||||
</Link>
|
||||
<Link key="1" href="/home" className="bg-white rounded-xl border border-gray-100 p-4 text-center hover:shadow-md transition-shadow">
|
||||
<span className="text-2xl block mb-1">📅</span>
|
||||
<span className="text-sm text-gray-600">分配</span>
|
||||
</Link>
|
||||
<Link key="2" href="/home" className="bg-white rounded-xl border border-gray-100 p-4 text-center hover:shadow-md transition-shadow">
|
||||
<span className="text-2xl block mb-1">📝</span>
|
||||
<span className="text-sm text-gray-600">处理流程</span>
|
||||
</Link>
|
||||
<Link key="3" href="/home" className="bg-white rounded-xl border border-gray-100 p-4 text-center hover:shadow-md transition-shadow">
|
||||
<span className="text-2xl block mb-1">📸</span>
|
||||
<span className="text-sm text-gray-600">优先级管理</span>
|
||||
</Link>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Recent Activity / Stats */}
|
||||
<section>
|
||||
<h2 className="text-lg font-semibold text-gray-800 mb-3">今日概览</h2>
|
||||
<div className="bg-white rounded-xl border border-gray-100 p-4">
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<p className="text-sm text-gray-500">欢迎使用 OAFlow</p>
|
||||
<p className="text-xs text-gray-400 mt-1">开始探索功能吧</p>
|
||||
</div>
|
||||
<span className="text-3xl">👋</span>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import { Card } from "@/components/ui/Card";
|
||||
import { Button } from "@/components/ui/Button";
|
||||
import { EmptyState } from "@/components/ui/EmptyState";
|
||||
|
||||
|
||||
export default function PagePage() {
|
||||
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<h1 className="text-xl font-bold text-gray-800">我的</h1>
|
||||
<p className="text-sm text-gray-500 mt-1">个人资料、请假余额、设置</p>
|
||||
</div>
|
||||
<Button onClick={() => setOpen(true)} variant="primary" size="sm">新增</Button>
|
||||
</div>
|
||||
|
||||
{<Card>
|
||||
<p className="text-gray-500 text-sm">我的 页面内容</p>
|
||||
<p className="text-xs text-gray-400 mt-1">路由: /profile</p>
|
||||
</Card>}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import { Card } from "@/components/ui/Card";
|
||||
import { Button } from "@/components/ui/Button";
|
||||
import { EmptyState } from "@/components/ui/EmptyState";
|
||||
import { useTickets } from "@/hooks/useTickets";
|
||||
|
||||
export default function PagePage() {
|
||||
const { data, loading, error, refetch } = useTickets();
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<h1 className="text-xl font-bold text-gray-800">工单归档</h1>
|
||||
<p className="text-sm text-gray-500 mt-1">工单归档</p>
|
||||
</div>
|
||||
<Button onClick={() => setOpen(true)} variant="primary" size="sm">新增</Button>
|
||||
</div>
|
||||
|
||||
{loading ? (
|
||||
<div className="flex justify-center py-12">
|
||||
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-500" />
|
||||
</div>
|
||||
) : error ? (
|
||||
<Card className="text-center py-8">
|
||||
<p className="text-red-500 text-sm">{error}</p>
|
||||
<Button onClick={refetch} variant="secondary" size="sm" className="mt-2">重试</Button>
|
||||
</Card>
|
||||
) : data.length === 0 ? (
|
||||
<EmptyState
|
||||
icon="📭"
|
||||
title="暂无数据"
|
||||
description="还没有任何记录,点击上方按钮开始"
|
||||
action={<Button onClick={() => setOpen(true)} variant="primary" size="sm">创建第一条</Button>}
|
||||
/>
|
||||
) : (
|
||||
<div className="space-y-3">
|
||||
{data.map((item: any) => (
|
||||
<Card key={item.id}>
|
||||
<h3 className="font-medium text-gray-800">{item.title || item.name || `Item ${item.id.slice(0, 8)}`}</h3>
|
||||
<p className="text-xs text-gray-400 mt-1">{item.createdAt || ""}</p>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import { Card } from "@/components/ui/Card";
|
||||
import { Button } from "@/components/ui/Button";
|
||||
import { EmptyState } from "@/components/ui/EmptyState";
|
||||
import { use优先级管理 } from "@/hooks/use优先级管理";
|
||||
|
||||
export default function PagePage() {
|
||||
const { data, loading, error, refetch } = use优先级管理();
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<h1 className="text-xl font-bold text-gray-800">优先级管理</h1>
|
||||
<p className="text-sm text-gray-500 mt-1">优先级管理</p>
|
||||
</div>
|
||||
<Button onClick={() => setOpen(true)} variant="primary" size="sm">新增</Button>
|
||||
</div>
|
||||
|
||||
{loading ? (
|
||||
<div className="flex justify-center py-12">
|
||||
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-500" />
|
||||
</div>
|
||||
) : error ? (
|
||||
<Card className="text-center py-8">
|
||||
<p className="text-red-500 text-sm">{error}</p>
|
||||
<Button onClick={refetch} variant="secondary" size="sm" className="mt-2">重试</Button>
|
||||
</Card>
|
||||
) : data.length === 0 ? (
|
||||
<EmptyState
|
||||
icon="📭"
|
||||
title="暂无数据"
|
||||
description="还没有任何记录,点击上方按钮开始"
|
||||
action={<Button onClick={() => setOpen(true)} variant="primary" size="sm">创建第一条</Button>}
|
||||
/>
|
||||
) : (
|
||||
<div className="space-y-3">
|
||||
{data.map((item: any) => (
|
||||
<Card key={item.id}>
|
||||
<h3 className="font-medium text-gray-800">{item.title || item.name || `Item ${item.id.slice(0, 8)}`}</h3>
|
||||
<p className="text-xs text-gray-400 mt-1">{item.createdAt || ""}</p>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import { Card } from "@/components/ui/Card";
|
||||
import { Button } from "@/components/ui/Button";
|
||||
import { EmptyState } from "@/components/ui/EmptyState";
|
||||
import { use分配 } from "@/hooks/use分配";
|
||||
|
||||
export default function PagePage() {
|
||||
const { data, loading, error, refetch } = use分配();
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<h1 className="text-xl font-bold text-gray-800">分配</h1>
|
||||
<p className="text-sm text-gray-500 mt-1">分配</p>
|
||||
</div>
|
||||
<Button onClick={() => setOpen(true)} variant="primary" size="sm">新增</Button>
|
||||
</div>
|
||||
|
||||
{loading ? (
|
||||
<div className="flex justify-center py-12">
|
||||
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-500" />
|
||||
</div>
|
||||
) : error ? (
|
||||
<Card className="text-center py-8">
|
||||
<p className="text-red-500 text-sm">{error}</p>
|
||||
<Button onClick={refetch} variant="secondary" size="sm" className="mt-2">重试</Button>
|
||||
</Card>
|
||||
) : data.length === 0 ? (
|
||||
<EmptyState
|
||||
icon="📭"
|
||||
title="暂无数据"
|
||||
description="还没有任何记录,点击上方按钮开始"
|
||||
action={<Button onClick={() => setOpen(true)} variant="primary" size="sm">创建第一条</Button>}
|
||||
/>
|
||||
) : (
|
||||
<div className="space-y-3">
|
||||
{data.map((item: any) => (
|
||||
<Card key={item.id}>
|
||||
<h3 className="font-medium text-gray-800">{item.title || item.name || `Item ${item.id.slice(0, 8)}`}</h3>
|
||||
<p className="text-xs text-gray-400 mt-1">{item.createdAt || ""}</p>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import { Card } from "@/components/ui/Card";
|
||||
import { Button } from "@/components/ui/Button";
|
||||
import { EmptyState } from "@/components/ui/EmptyState";
|
||||
import { use处理流程 } from "@/hooks/use处理流程";
|
||||
|
||||
export default function PagePage() {
|
||||
const { data, loading, error, refetch } = use处理流程();
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<h1 className="text-xl font-bold text-gray-800">处理流程</h1>
|
||||
<p className="text-sm text-gray-500 mt-1">处理流程</p>
|
||||
</div>
|
||||
<Button onClick={() => setOpen(true)} variant="primary" size="sm">新增</Button>
|
||||
</div>
|
||||
|
||||
{loading ? (
|
||||
<div className="flex justify-center py-12">
|
||||
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-500" />
|
||||
</div>
|
||||
) : error ? (
|
||||
<Card className="text-center py-8">
|
||||
<p className="text-red-500 text-sm">{error}</p>
|
||||
<Button onClick={refetch} variant="secondary" size="sm" className="mt-2">重试</Button>
|
||||
</Card>
|
||||
) : data.length === 0 ? (
|
||||
<EmptyState
|
||||
icon="📭"
|
||||
title="暂无数据"
|
||||
description="还没有任何记录,点击上方按钮开始"
|
||||
action={<Button onClick={() => setOpen(true)} variant="primary" size="sm">创建第一条</Button>}
|
||||
/>
|
||||
) : (
|
||||
<div className="space-y-3">
|
||||
{data.map((item: any) => (
|
||||
<Card key={item.id}>
|
||||
<h3 className="font-medium text-gray-800">{item.title || item.name || `Item ${item.id.slice(0, 8)}`}</h3>
|
||||
<p className="text-xs text-gray-400 mt-1">{item.createdAt || ""}</p>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import { Card } from "@/components/ui/Card";
|
||||
import { Button } from "@/components/ui/Button";
|
||||
import { EmptyState } from "@/components/ui/EmptyState";
|
||||
import { use工单创建 } from "@/hooks/use工单创建";
|
||||
|
||||
export default function PagePage() {
|
||||
const { data, loading, error, refetch } = use工单创建();
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<h1 className="text-xl font-bold text-gray-800">工单创建</h1>
|
||||
<p className="text-sm text-gray-500 mt-1">工单创建</p>
|
||||
</div>
|
||||
<Button onClick={() => setOpen(true)} variant="primary" size="sm">新增</Button>
|
||||
</div>
|
||||
|
||||
{loading ? (
|
||||
<div className="flex justify-center py-12">
|
||||
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-500" />
|
||||
</div>
|
||||
) : error ? (
|
||||
<Card className="text-center py-8">
|
||||
<p className="text-red-500 text-sm">{error}</p>
|
||||
<Button onClick={refetch} variant="secondary" size="sm" className="mt-2">重试</Button>
|
||||
</Card>
|
||||
) : data.length === 0 ? (
|
||||
<EmptyState
|
||||
icon="📭"
|
||||
title="暂无数据"
|
||||
description="还没有任何记录,点击上方按钮开始"
|
||||
action={<Button onClick={() => setOpen(true)} variant="primary" size="sm">创建第一条</Button>}
|
||||
/>
|
||||
) : (
|
||||
<div className="space-y-3">
|
||||
{data.map((item: any) => (
|
||||
<Card key={item.id}>
|
||||
<h3 className="font-medium text-gray-800">{item.title || item.name || `Item ${item.id.slice(0, 8)}`}</h3>
|
||||
<p className="text-xs text-gray-400 mt-1">{item.createdAt || ""}</p>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import { Card } from "@/components/ui/Card";
|
||||
import { Button } from "@/components/ui/Button";
|
||||
import { EmptyState } from "@/components/ui/EmptyState";
|
||||
|
||||
|
||||
export default function PagePage() {
|
||||
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<h1 className="text-xl font-bold text-gray-800">工单归档</h1>
|
||||
<p className="text-sm text-gray-500 mt-1">工单归档</p>
|
||||
</div>
|
||||
<Button onClick={() => setOpen(true)} variant="primary" size="sm">新增</Button>
|
||||
</div>
|
||||
|
||||
{<Card>
|
||||
<p className="text-gray-500 text-sm">工单归档 页面内容</p>
|
||||
<p className="text-xs text-gray-400 mt-1">路由: /工单归档</p>
|
||||
</Card>}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user