🎉 init: 小龙的工作空间

This commit is contained in:
大海
2026-06-06 10:40:48 +08:00
commit a188ee1426
3201 changed files with 231817 additions and 0 deletions
@@ -0,0 +1,13 @@
"use client";
import { Card } from "@/components/ui/Card";
import { Button } from "@/components/ui/Button";
export default function CartPage() {
return (
<div className="space-y-4">
<h1 className="text-xl font-bold text-gray-800"></h1>
<Card><p className="text-sm text-gray-500">...</p></Card>
<Button variant="primary" className="w-full" size="lg"></Button>
</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 { useInventory } from "@/hooks/useInventory";
export default function PagePage() {
const { data, loading, error, refetch } = useInventory();
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: "ShopApp",
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":"/products","icon":"📋"},{"name":"库存盘点","href":"/stocktaking","icon":"📅"},{"name":"供应商管理","href":"/suppliers","icon":"✏️"},{"name":"库存预警","href":"/stock_alerts","icon":"📸"}] } projectName="ShopApp" />
{/* 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":"/products","icon":"📋"},{"name":"库存盘点","href":"/stocktaking","icon":"📅"},{"name":"供应商管理","href":"/suppliers","icon":"✏️"}] } />
</body>
</html>
);
}
@@ -0,0 +1,12 @@
"use client";
import { Card } from "@/components/ui/Card";
import { EmptyState } from "@/components/ui/EmptyState";
export default function OrderPage() {
return (
<div className="space-y-4">
<h1 className="text-xl font-bold text-gray-800"></h1>
<EmptyState icon="📦" title="暂无订单" description="去逛逛吧" />
</div>
);
}
@@ -0,0 +1,12 @@
"use client";
import { Card } from "@/components/ui/Card";
import { EmptyState } from "@/components/ui/EmptyState";
export default function OrderPage() {
return (
<div className="space-y-4">
<h1 className="text-xl font-bold text-gray-800"></h1>
<EmptyState icon="📦" title="暂无订单" description="去逛逛吧" />
</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">ShopApp</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">使 ShopApp</p>
<p className="text-xs text-gray-400 mt-1"></p>
</div>
<span className="text-3xl">👋</span>
</div>
</div>
</section>
</div>
);
}
@@ -0,0 +1,18 @@
"use client";
import { Button } from "@/components/ui/Button";
export default function ProductDetailPage() {
return (
<div className="space-y-4">
<div className="aspect-square bg-gray-100 rounded-2xl flex items-center justify-center text-6xl">📦</div>
<h1 className="text-xl font-bold"></h1>
<p className="text-2xl font-bold text-red-500">¥99.00</p>
<p className="text-sm text-gray-500"> · 24</p>
<Button variant="primary" className="w-full" size="lg"></Button>
<div className="space-y-2">
<h3 className="font-semibold text-gray-700"></h3>
<p className="text-sm text-gray-500 leading-relaxed">使</p>
</div>
</div>
);
}
@@ -0,0 +1,18 @@
"use client";
import { Button } from "@/components/ui/Button";
export default function ProductDetailPage() {
return (
<div className="space-y-4">
<div className="aspect-square bg-gray-100 rounded-2xl flex items-center justify-center text-6xl">📦</div>
<h1 className="text-xl font-bold"></h1>
<p className="text-2xl font-bold text-red-500">¥99.00</p>
<p className="text-sm text-gray-500"> · 24</p>
<Button variant="primary" className="w-full" size="lg"></Button>
<div className="space-y-2">
<h3 className="font-semibold text-gray-700"></h3>
<p className="text-sm text-gray-500 leading-relaxed">使</p>
</div>
</div>
);
}
@@ -0,0 +1,43 @@
"use client";
import { Card } from "@/components/ui/Card";
import { Button } from "@/components/ui/Button";
const menuItems = [
{ icon: "⚙️", label: "设置", href: "#" },
{ icon: "🔔", label: "通知", href: "#" },
{ icon: "❓", label: "帮助与反馈", href: "#" },
{ icon: "📄", label: "关于我们", href: "#" },
];
export default function ProfilePage() {
return (
<div className="space-y-6">
{/* User Info */}
<div className="bg-gradient-to-br from-blue-500 to-blue-700 rounded-2xl p-6 text-white text-center">
<div className="w-20 h-20 mx-auto rounded-full bg-white/20 flex items-center justify-center text-3xl backdrop-blur">😊</div>
<h1 className="text-xl font-bold mt-3"></h1>
<p className="text-sm text-blue-100">138****1234</p>
<Button variant="ghost" className="mt-3 bg-white/10 text-white hover:bg-white/20" size="sm"></Button>
</div>
{/* Stats */}
<div className="grid grid-cols-3 gap-3">
<Card className="text-center"><p className="text-xl font-bold text-gray-800">0</p><p className="text-xs text-gray-500"></p></Card>
<Card className="text-center"><p className="text-xl font-bold text-gray-800">0</p><p className="text-xs text-gray-500"></p></Card>
<Card className="text-center"><p className="text-xl font-bold text-gray-800">0</p><p className="text-xs text-gray-500"></p></Card>
</div>
{/* Menu */}
<Card className="divide-y divide-gray-50 p-0">
{menuItems.map((item, i) => (
<a key={i} href={item.href} className="flex items-center gap-3 px-4 py-3 hover:bg-gray-50 transition-colors">
<span className="text-lg">{item.icon}</span>
<span className="flex-1 text-sm text-gray-700">{item.label}</span>
<svg className="w-4 h-4 text-gray-300" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" /></svg>
</a>
))}
</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 { useStock_alerts } from "@/hooks/useStock_alerts";
export default function PagePage() {
const { data, loading, error, refetch } = useStock_alerts();
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 { useStocktaking } from "@/hooks/useStocktaking";
export default function PagePage() {
const { data, loading, error, refetch } = useStocktaking();
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 { useSuppliers } from "@/hooks/useSuppliers";
export default function PagePage() {
const { data, loading, error, refetch } = useSuppliers();
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>
);
}