From 3a01dc897ad41ee3c6351baf4ac1dbfade128a80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9F=B3=E6=B8=85=E7=88=BD?= Date: Wed, 9 Apr 2025 09:45:06 +0800 Subject: [PATCH] =?UTF-8?q?=E8=B6=85=E7=BA=A7=E7=AE=A1=E7=90=86=E5=91=98?= =?UTF-8?q?=E5=90=8E=E5=8F=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../plan/controller/TrafficPool.php | 4 - SuperAdmin/.gitignore | 27 + .../app/dashboard/admins/[id]/edit/page.tsx | 137 ++++ SuperAdmin/app/dashboard/admins/loading.tsx | 4 + SuperAdmin/app/dashboard/admins/new/page.tsx | 115 +++ SuperAdmin/app/dashboard/admins/page.tsx | 154 ++++ .../app/dashboard/customers/[id]/page.tsx | 202 +++++ .../app/dashboard/customers/loading.tsx | 4 + SuperAdmin/app/dashboard/customers/page.tsx | 310 +++++++ SuperAdmin/app/dashboard/layout.tsx | 101 +++ SuperAdmin/app/dashboard/page.tsx | 47 ++ .../app/dashboard/projects/[id]/edit/page.tsx | 159 ++++ .../app/dashboard/projects/[id]/page.tsx | 179 ++++ SuperAdmin/app/dashboard/projects/loading.tsx | 4 + .../app/dashboard/projects/new/page.tsx | 129 +++ SuperAdmin/app/dashboard/projects/page.tsx | 147 ++++ SuperAdmin/app/globals.css | 87 ++ SuperAdmin/app/layout.tsx | 33 + SuperAdmin/app/login/page.tsx | 70 ++ SuperAdmin/components.json | 21 + SuperAdmin/components/theme-provider.tsx | 11 + SuperAdmin/components/ui/accordion.tsx | 58 ++ SuperAdmin/components/ui/alert-dialog.tsx | 141 ++++ SuperAdmin/components/ui/alert.tsx | 59 ++ SuperAdmin/components/ui/aspect-ratio.tsx | 7 + SuperAdmin/components/ui/avatar.tsx | 50 ++ SuperAdmin/components/ui/badge.tsx | 31 + SuperAdmin/components/ui/breadcrumb.tsx | 115 +++ SuperAdmin/components/ui/button.tsx | 56 ++ SuperAdmin/components/ui/calendar.tsx | 66 ++ SuperAdmin/components/ui/card.tsx | 79 ++ SuperAdmin/components/ui/carousel.tsx | 262 ++++++ SuperAdmin/components/ui/chart.tsx | 365 +++++++++ SuperAdmin/components/ui/checkbox.tsx | 30 + SuperAdmin/components/ui/collapsible.tsx | 11 + SuperAdmin/components/ui/command.tsx | 153 ++++ SuperAdmin/components/ui/context-menu.tsx | 200 +++++ SuperAdmin/components/ui/dialog.tsx | 122 +++ SuperAdmin/components/ui/drawer.tsx | 118 +++ SuperAdmin/components/ui/dropdown-menu.tsx | 200 +++++ SuperAdmin/components/ui/form.tsx | 178 ++++ SuperAdmin/components/ui/hover-card.tsx | 29 + SuperAdmin/components/ui/input-otp.tsx | 71 ++ SuperAdmin/components/ui/input.tsx | 22 + SuperAdmin/components/ui/label.tsx | 26 + SuperAdmin/components/ui/menubar.tsx | 236 ++++++ SuperAdmin/components/ui/navigation-menu.tsx | 128 +++ SuperAdmin/components/ui/pagination.tsx | 117 +++ SuperAdmin/components/ui/popover.tsx | 31 + SuperAdmin/components/ui/progress.tsx | 28 + SuperAdmin/components/ui/radio-group.tsx | 44 + SuperAdmin/components/ui/resizable.tsx | 45 ++ SuperAdmin/components/ui/scroll-area.tsx | 48 ++ SuperAdmin/components/ui/select.tsx | 160 ++++ SuperAdmin/components/ui/separator.tsx | 31 + SuperAdmin/components/ui/sheet.tsx | 140 ++++ SuperAdmin/components/ui/sidebar.tsx | 763 ++++++++++++++++++ SuperAdmin/components/ui/skeleton.tsx | 15 + SuperAdmin/components/ui/slider.tsx | 28 + SuperAdmin/components/ui/sonner.tsx | 31 + SuperAdmin/components/ui/switch.tsx | 29 + SuperAdmin/components/ui/table.tsx | 117 +++ SuperAdmin/components/ui/tabs.tsx | 55 ++ SuperAdmin/components/ui/textarea.tsx | 22 + SuperAdmin/components/ui/toast.tsx | 129 +++ SuperAdmin/components/ui/toaster.tsx | 35 + SuperAdmin/components/ui/toggle-group.tsx | 61 ++ SuperAdmin/components/ui/toggle.tsx | 45 ++ SuperAdmin/components/ui/tooltip.tsx | 30 + SuperAdmin/components/ui/use-mobile.tsx | 19 + SuperAdmin/components/ui/use-toast.ts | 194 +++++ SuperAdmin/hooks/use-mobile.tsx | 19 + SuperAdmin/hooks/use-toast.ts | 194 +++++ SuperAdmin/lib/utils.ts | 6 + SuperAdmin/next.config.mjs | 51 ++ SuperAdmin/package.json | 70 ++ SuperAdmin/pnpm-lock.yaml | 5 + SuperAdmin/postcss.config.mjs | 8 + SuperAdmin/public/placeholder-logo.png | Bin 0 -> 958 bytes SuperAdmin/public/placeholder-logo.svg | 1 + SuperAdmin/public/placeholder-user.jpg | Bin 0 -> 2615 bytes SuperAdmin/public/placeholder.jpg | Bin 0 -> 1596 bytes SuperAdmin/public/placeholder.svg | 1 + SuperAdmin/styles/globals.css | 94 +++ SuperAdmin/tailwind.config.ts | 88 ++ SuperAdmin/tsconfig.json | 27 + 86 files changed, 7535 insertions(+), 4 deletions(-) create mode 100644 SuperAdmin/.gitignore create mode 100644 SuperAdmin/app/dashboard/admins/[id]/edit/page.tsx create mode 100644 SuperAdmin/app/dashboard/admins/loading.tsx create mode 100644 SuperAdmin/app/dashboard/admins/new/page.tsx create mode 100644 SuperAdmin/app/dashboard/admins/page.tsx create mode 100644 SuperAdmin/app/dashboard/customers/[id]/page.tsx create mode 100644 SuperAdmin/app/dashboard/customers/loading.tsx create mode 100644 SuperAdmin/app/dashboard/customers/page.tsx create mode 100644 SuperAdmin/app/dashboard/layout.tsx create mode 100644 SuperAdmin/app/dashboard/page.tsx create mode 100644 SuperAdmin/app/dashboard/projects/[id]/edit/page.tsx create mode 100644 SuperAdmin/app/dashboard/projects/[id]/page.tsx create mode 100644 SuperAdmin/app/dashboard/projects/loading.tsx create mode 100644 SuperAdmin/app/dashboard/projects/new/page.tsx create mode 100644 SuperAdmin/app/dashboard/projects/page.tsx create mode 100644 SuperAdmin/app/globals.css create mode 100644 SuperAdmin/app/layout.tsx create mode 100644 SuperAdmin/app/login/page.tsx create mode 100644 SuperAdmin/components.json create mode 100644 SuperAdmin/components/theme-provider.tsx create mode 100644 SuperAdmin/components/ui/accordion.tsx create mode 100644 SuperAdmin/components/ui/alert-dialog.tsx create mode 100644 SuperAdmin/components/ui/alert.tsx create mode 100644 SuperAdmin/components/ui/aspect-ratio.tsx create mode 100644 SuperAdmin/components/ui/avatar.tsx create mode 100644 SuperAdmin/components/ui/badge.tsx create mode 100644 SuperAdmin/components/ui/breadcrumb.tsx create mode 100644 SuperAdmin/components/ui/button.tsx create mode 100644 SuperAdmin/components/ui/calendar.tsx create mode 100644 SuperAdmin/components/ui/card.tsx create mode 100644 SuperAdmin/components/ui/carousel.tsx create mode 100644 SuperAdmin/components/ui/chart.tsx create mode 100644 SuperAdmin/components/ui/checkbox.tsx create mode 100644 SuperAdmin/components/ui/collapsible.tsx create mode 100644 SuperAdmin/components/ui/command.tsx create mode 100644 SuperAdmin/components/ui/context-menu.tsx create mode 100644 SuperAdmin/components/ui/dialog.tsx create mode 100644 SuperAdmin/components/ui/drawer.tsx create mode 100644 SuperAdmin/components/ui/dropdown-menu.tsx create mode 100644 SuperAdmin/components/ui/form.tsx create mode 100644 SuperAdmin/components/ui/hover-card.tsx create mode 100644 SuperAdmin/components/ui/input-otp.tsx create mode 100644 SuperAdmin/components/ui/input.tsx create mode 100644 SuperAdmin/components/ui/label.tsx create mode 100644 SuperAdmin/components/ui/menubar.tsx create mode 100644 SuperAdmin/components/ui/navigation-menu.tsx create mode 100644 SuperAdmin/components/ui/pagination.tsx create mode 100644 SuperAdmin/components/ui/popover.tsx create mode 100644 SuperAdmin/components/ui/progress.tsx create mode 100644 SuperAdmin/components/ui/radio-group.tsx create mode 100644 SuperAdmin/components/ui/resizable.tsx create mode 100644 SuperAdmin/components/ui/scroll-area.tsx create mode 100644 SuperAdmin/components/ui/select.tsx create mode 100644 SuperAdmin/components/ui/separator.tsx create mode 100644 SuperAdmin/components/ui/sheet.tsx create mode 100644 SuperAdmin/components/ui/sidebar.tsx create mode 100644 SuperAdmin/components/ui/skeleton.tsx create mode 100644 SuperAdmin/components/ui/slider.tsx create mode 100644 SuperAdmin/components/ui/sonner.tsx create mode 100644 SuperAdmin/components/ui/switch.tsx create mode 100644 SuperAdmin/components/ui/table.tsx create mode 100644 SuperAdmin/components/ui/tabs.tsx create mode 100644 SuperAdmin/components/ui/textarea.tsx create mode 100644 SuperAdmin/components/ui/toast.tsx create mode 100644 SuperAdmin/components/ui/toaster.tsx create mode 100644 SuperAdmin/components/ui/toggle-group.tsx create mode 100644 SuperAdmin/components/ui/toggle.tsx create mode 100644 SuperAdmin/components/ui/tooltip.tsx create mode 100644 SuperAdmin/components/ui/use-mobile.tsx create mode 100644 SuperAdmin/components/ui/use-toast.ts create mode 100644 SuperAdmin/hooks/use-mobile.tsx create mode 100644 SuperAdmin/hooks/use-toast.ts create mode 100644 SuperAdmin/lib/utils.ts create mode 100644 SuperAdmin/next.config.mjs create mode 100644 SuperAdmin/package.json create mode 100644 SuperAdmin/pnpm-lock.yaml create mode 100644 SuperAdmin/postcss.config.mjs create mode 100644 SuperAdmin/public/placeholder-logo.png create mode 100644 SuperAdmin/public/placeholder-logo.svg create mode 100644 SuperAdmin/public/placeholder-user.jpg create mode 100644 SuperAdmin/public/placeholder.jpg create mode 100644 SuperAdmin/public/placeholder.svg create mode 100644 SuperAdmin/styles/globals.css create mode 100644 SuperAdmin/tailwind.config.ts create mode 100644 SuperAdmin/tsconfig.json diff --git a/Server/application/plan/controller/TrafficPool.php b/Server/application/plan/controller/TrafficPool.php index d6120c71..a655f936 100644 --- a/Server/application/plan/controller/TrafficPool.php +++ b/Server/application/plan/controller/TrafficPool.php @@ -3,8 +3,6 @@ namespace app\plan\controller; use think\Controller; use think\facade\Request; -use app\plan\model\TrafficPool as TrafficPoolModel; -use app\plan\model\TrafficSource; /** * 流量池控制器 @@ -50,8 +48,6 @@ class TrafficPool extends Controller ]; } - new - return json([ 'code' => 200, 'msg' => '导入完成', diff --git a/SuperAdmin/.gitignore b/SuperAdmin/.gitignore new file mode 100644 index 00000000..f650315f --- /dev/null +++ b/SuperAdmin/.gitignore @@ -0,0 +1,27 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules + +# next.js +/.next/ +/out/ + +# production +/build + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.pnpm-debug.log* + +# env files +.env* + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts \ No newline at end of file diff --git a/SuperAdmin/app/dashboard/admins/[id]/edit/page.tsx b/SuperAdmin/app/dashboard/admins/[id]/edit/page.tsx new file mode 100644 index 00000000..7cc8de27 --- /dev/null +++ b/SuperAdmin/app/dashboard/admins/[id]/edit/page.tsx @@ -0,0 +1,137 @@ +"use client" + +import type React from "react" + +import { useState } from "react" +import { useRouter } from "next/navigation" +import { Button } from "@/components/ui/button" +import { Input } from "@/components/ui/input" +import { Label } from "@/components/ui/label" +import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card" +import { ArrowLeft } from "lucide-react" +import Link from "next/link" +import { Checkbox } from "@/components/ui/checkbox" + +// Sample admin data for editing +const adminData = { + id: "2", + username: "admin_li", + name: "李管理", + permissions: ["project_management", "customer_pool"], +} + +export default function EditAdminPage({ params }: { params: { id: string } }) { + const router = useRouter() + const [isSubmitting, setIsSubmitting] = useState(false) + const [username, setUsername] = useState(adminData.username) + const [name, setName] = useState(adminData.name) + + const permissions = [ + { id: "project_management", label: "项目管理" }, + { id: "customer_pool", label: "客户池" }, + { id: "admin_management", label: "管理员权限" }, + ] + + const [selectedPermissions, setSelectedPermissions] = useState(adminData.permissions) + + const togglePermission = (permissionId: string) => { + setSelectedPermissions((prev) => + prev.includes(permissionId) ? prev.filter((id) => id !== permissionId) : [...prev, permissionId], + ) + } + + const handleSubmit = (e: React.FormEvent) => { + e.preventDefault() + setIsSubmitting(true) + + // Simulate API call + setTimeout(() => { + setIsSubmitting(false) + router.push("/dashboard/admins") + }, 1500) + } + + return ( +
+
+ +

编辑管理员

+
+ +
+ + + 管理员信息 + 编辑管理员账号信息和权限 + + +
+
+ + setUsername(e.target.value)} + placeholder="请输入账号" + required + /> +
+ +
+ + setName(e.target.value)} + placeholder="请输入姓名" + required + /> +
+ +
+ + +
+ +
+ + +
+
+ +
+ +
+ {permissions.map((permission) => ( +
+ togglePermission(permission.id)} + /> + +
+ ))} +
+
+
+ + + + +
+
+
+ ) +} + diff --git a/SuperAdmin/app/dashboard/admins/loading.tsx b/SuperAdmin/app/dashboard/admins/loading.tsx new file mode 100644 index 00000000..cec067bd --- /dev/null +++ b/SuperAdmin/app/dashboard/admins/loading.tsx @@ -0,0 +1,4 @@ +export default function Loading() { + return null +} + diff --git a/SuperAdmin/app/dashboard/admins/new/page.tsx b/SuperAdmin/app/dashboard/admins/new/page.tsx new file mode 100644 index 00000000..4ef3fa3d --- /dev/null +++ b/SuperAdmin/app/dashboard/admins/new/page.tsx @@ -0,0 +1,115 @@ +"use client" + +import type React from "react" + +import { useState } from "react" +import { useRouter } from "next/navigation" +import { Button } from "@/components/ui/button" +import { Input } from "@/components/ui/input" +import { Label } from "@/components/ui/label" +import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card" +import { ArrowLeft } from "lucide-react" +import Link from "next/link" +import { Checkbox } from "@/components/ui/checkbox" + +export default function NewAdminPage() { + const router = useRouter() + const [isSubmitting, setIsSubmitting] = useState(false) + + const permissions = [ + { id: "project_management", label: "项目管理" }, + { id: "customer_pool", label: "客户池" }, + { id: "admin_management", label: "管理员权限" }, + ] + + const [selectedPermissions, setSelectedPermissions] = useState([]) + + const togglePermission = (permissionId: string) => { + setSelectedPermissions((prev) => + prev.includes(permissionId) ? prev.filter((id) => id !== permissionId) : [...prev, permissionId], + ) + } + + const handleSubmit = (e: React.FormEvent) => { + e.preventDefault() + setIsSubmitting(true) + + // Simulate API call + setTimeout(() => { + setIsSubmitting(false) + router.push("/dashboard/admins") + }, 1500) + } + + return ( +
+
+ +

新增管理员

+
+ +
+ + + 管理员信息 + 创建新管理员账号并设置权限 + + +
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+ +
+ +
+ {permissions.map((permission) => ( +
+ togglePermission(permission.id)} + /> + +
+ ))} +
+
+
+ + + + +
+
+
+ ) +} + diff --git a/SuperAdmin/app/dashboard/admins/page.tsx b/SuperAdmin/app/dashboard/admins/page.tsx new file mode 100644 index 00000000..1713c62a --- /dev/null +++ b/SuperAdmin/app/dashboard/admins/page.tsx @@ -0,0 +1,154 @@ +"use client" + +import { useState } from "react" +import Link from "next/link" +import { Button } from "@/components/ui/button" +import { Input } from "@/components/ui/input" +import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table" +import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu" +import { Search, MoreHorizontal, Edit, Trash, UserPlus } from "lucide-react" +import { Badge } from "@/components/ui/badge" + +// Sample admin data +const adminsData = [ + { + id: "1", + username: "admin_zhang", + name: "张管理", + role: "超级管理员", + permissions: ["项目管理", "客户池", "管理员权限"], + createdAt: "2023-05-01", + lastLogin: "2023-06-28 09:15", + }, + { + id: "2", + username: "admin_li", + name: "李管理", + role: "项目管理员", + permissions: ["项目管理", "客户池"], + createdAt: "2023-05-10", + lastLogin: "2023-06-27 14:30", + }, + { + id: "3", + username: "admin_wang", + name: "王管理", + role: "客户管理员", + permissions: ["客户池"], + createdAt: "2023-05-15", + lastLogin: "2023-06-28 11:45", + }, + { + id: "4", + username: "admin_zhao", + name: "赵管理", + role: "项目管理员", + permissions: ["项目管理"], + createdAt: "2023-05-20", + lastLogin: "2023-06-26 16:20", + }, +] + +export default function AdminsPage() { + const [searchTerm, setSearchTerm] = useState("") + + const filteredAdmins = adminsData.filter( + (admin) => + admin.username.toLowerCase().includes(searchTerm.toLowerCase()) || + admin.name.toLowerCase().includes(searchTerm.toLowerCase()) || + admin.role.toLowerCase().includes(searchTerm.toLowerCase()), + ) + + return ( +
+
+

管理员列表

+ +
+ +
+
+ + setSearchTerm(e.target.value)} + /> +
+
+ +
+ + + + 账号 + 姓名 + 角色 + 权限 + 创建时间 + 最后登录 + 操作 + + + + {filteredAdmins.length > 0 ? ( + filteredAdmins.map((admin) => ( + + {admin.username} + {admin.name} + + {admin.role} + + +
+ {admin.permissions.map((permission) => ( + + {permission} + + ))} +
+
+ {admin.createdAt} + {admin.lastLogin} + + + + + + + + + 编辑管理员 + + + + 删除管理员 + + + + +
+ )) + ) : ( + + + 未找到管理员 + + + )} +
+
+
+
+ ) +} + diff --git a/SuperAdmin/app/dashboard/customers/[id]/page.tsx b/SuperAdmin/app/dashboard/customers/[id]/page.tsx new file mode 100644 index 00000000..ff6243f5 --- /dev/null +++ b/SuperAdmin/app/dashboard/customers/[id]/page.tsx @@ -0,0 +1,202 @@ +"use client" + +import Link from "next/link" +import { Button } from "@/components/ui/button" +import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card" +import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs" +import { Badge } from "@/components/ui/badge" +import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar" +import { ArrowLeft, MessageSquare, Phone, UserPlus } from "lucide-react" + +// Sample customer data +const customerData = { + id: "1", + name: "张三", + avatar: "/placeholder.svg?height=100&width=100", + wechatId: "zhangsan123", + gender: "男", + region: "北京", + source: "微信搜索", + tags: ["潜在客户", "高消费"], + projectName: "电商平台项目", + addedDate: "2023-06-10", + devices: [ + { id: "d1", name: "iPhone 13 Pro", addedDate: "2023-06-10" }, + { id: "d2", name: "MacBook Pro", addedDate: "2023-06-12" }, + ], + interactions: [ + { + id: "i1", + type: "消息", + content: "您好,我对您的产品很感兴趣,能详细介绍一下吗?", + date: "2023-06-15 14:30", + }, + { + id: "i2", + type: "电话", + content: "讨论产品细节和价格", + duration: "15分钟", + date: "2023-06-16 10:45", + }, + { + id: "i3", + type: "消息", + content: "谢谢您的详细介绍,我考虑一下再联系您。", + date: "2023-06-16 16:20", + }, + { + id: "i4", + type: "消息", + content: "我决定购买您的产品,请问如何下单?", + date: "2023-06-18 09:15", + }, + ], + transactions: [ + { + id: "t1", + product: "高级会员套餐", + amount: "¥1,299", + status: "已完成", + date: "2023-06-20", + }, + ], +} + +export default function CustomerDetailPage({ params }: { params: { id: string } }) { + return ( +
+
+
+ +

客户详情

+
+ +
+ +
+ + + 基本信息 + + + + + {customerData.name.slice(0, 2)} + +

{customerData.name}

+

{customerData.wechatId}

+ +
+ {customerData.tags.map((tag) => ( + + {tag} + + ))} +
+ +
+
+ 性别 + {customerData.gender} +
+
+ 地区 + {customerData.region} +
+
+ 来源 + {customerData.source} +
+
+ 所属项目 + {customerData.projectName} +
+
+ 添加时间 + {customerData.addedDate} +
+
+
+
+ + + + 详细信息 + + + + + 互动记录 + 关联设备 + 交易记录 + + + + {customerData.interactions.map((interaction) => ( +
+
+ {interaction.type === "消息" ? ( + + ) : ( + + )} +
+
+
+

{interaction.type}

+

{interaction.date}

+
+

{interaction.content}

+ {interaction.duration && ( +

通话时长: {interaction.duration}

+ )} +
+
+ ))} +
+ + + {customerData.devices.map((device) => ( +
+
+

{device.name}

+

添加时间: {device.addedDate}

+
+
+ ))} +
+ + + {customerData.transactions.length > 0 ? ( + customerData.transactions.map((transaction) => ( +
+
+

{transaction.product}

+

交易日期: {transaction.date}

+
+
+

{transaction.amount}

+ + {transaction.status} + +
+
+ )) + ) : ( +

暂无交易记录

+ )} +
+
+
+
+
+
+ ) +} + diff --git a/SuperAdmin/app/dashboard/customers/loading.tsx b/SuperAdmin/app/dashboard/customers/loading.tsx new file mode 100644 index 00000000..cec067bd --- /dev/null +++ b/SuperAdmin/app/dashboard/customers/loading.tsx @@ -0,0 +1,4 @@ +export default function Loading() { + return null +} + diff --git a/SuperAdmin/app/dashboard/customers/page.tsx b/SuperAdmin/app/dashboard/customers/page.tsx new file mode 100644 index 00000000..63acc780 --- /dev/null +++ b/SuperAdmin/app/dashboard/customers/page.tsx @@ -0,0 +1,310 @@ +"use client" + +import { useState } from "react" +import Link from "next/link" +import { Button } from "@/components/ui/button" +import { Input } from "@/components/ui/input" +import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table" +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger, + DropdownMenuSeparator, +} from "@/components/ui/dropdown-menu" +import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select" +import { Search, MoreHorizontal, Eye, UserPlus, Filter } from "lucide-react" +import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar" +import { Badge } from "@/components/ui/badge" + +// Sample customer data +const customersData = [ + { + id: "1", + name: "张三", + avatar: "/placeholder.svg?height=40&width=40", + wechatId: "zhangsan123", + gender: "男", + region: "北京", + source: "微信搜索", + tags: ["潜在客户", "高消费"], + projectName: "电商平台项目", + addedDate: "2023-06-10", + }, + { + id: "2", + name: "李四", + avatar: "/placeholder.svg?height=40&width=40", + wechatId: "lisi456", + gender: "男", + region: "上海", + source: "朋友推荐", + tags: ["活跃用户"], + projectName: "社交媒体营销", + addedDate: "2023-06-12", + }, + { + id: "3", + name: "王五", + avatar: "/placeholder.svg?height=40&width=40", + wechatId: "wangwu789", + gender: "男", + region: "广州", + source: "广告点击", + tags: ["新用户"], + projectName: "企业官网推广", + addedDate: "2023-06-15", + }, + { + id: "4", + name: "赵六", + avatar: "/placeholder.svg?height=40&width=40", + wechatId: "zhaoliu321", + gender: "男", + region: "深圳", + source: "线下活动", + tags: ["高消费", "忠诚客户"], + projectName: "教育平台项目", + addedDate: "2023-06-18", + }, + { + id: "5", + name: "钱七", + avatar: "/placeholder.svg?height=40&width=40", + wechatId: "qianqi654", + gender: "女", + region: "成都", + source: "微信群", + tags: ["潜在客户"], + projectName: "金融服务推广", + addedDate: "2023-06-20", + }, + { + id: "6", + name: "孙八", + avatar: "/placeholder.svg?height=40&width=40", + wechatId: "sunba987", + gender: "女", + region: "武汉", + source: "微信搜索", + tags: ["活跃用户", "高消费"], + projectName: "电商平台项目", + addedDate: "2023-06-22", + }, + { + id: "7", + name: "周九", + avatar: "/placeholder.svg?height=40&width=40", + wechatId: "zhoujiu135", + gender: "女", + region: "杭州", + source: "朋友推荐", + tags: ["新用户"], + projectName: "社交媒体营销", + addedDate: "2023-06-25", + }, +] + +export default function CustomersPage() { + const [searchTerm, setSearchTerm] = useState("") + const [selectedRegion, setSelectedRegion] = useState("") + const [selectedGender, setSelectedGender] = useState("") + const [selectedSource, setSelectedSource] = useState("") + const [selectedProject, setSelectedProject] = useState("") + + // Filter customers based on search and filters + const filteredCustomers = customersData.filter((customer) => { + const matchesSearch = + customer.name.toLowerCase().includes(searchTerm.toLowerCase()) || + customer.wechatId.toLowerCase().includes(searchTerm.toLowerCase()) + + const matchesRegion = selectedRegion ? customer.region === selectedRegion : true + const matchesGender = selectedGender ? customer.gender === selectedGender : true + const matchesSource = selectedSource ? customer.source === selectedSource : true + const matchesProject = selectedProject ? customer.projectName === selectedProject : true + + return matchesSearch && matchesRegion && matchesGender && matchesSource && matchesProject + }) + + // Get unique values for filters + const regions = [...new Set(customersData.map((c) => c.region))] + const sources = [...new Set(customersData.map((c) => c.source))] + const projects = [...new Set(customersData.map((c) => c.projectName))] + + return ( +
+
+

客户池

+ +
+ +
+
+
+ + setSearchTerm(e.target.value)} + /> +
+ + + + + +
+

地区

+ +
+ +
+

性别

+ +
+ +
+

来源

+ +
+ +
+

所属项目

+ +
+
+
+
+ +
+ + + + 客户信息 + 微信ID + 标签 + 地区 + 来源 + 所属项目 + 添加时间 + 操作 + + + + {filteredCustomers.length > 0 ? ( + filteredCustomers.map((customer) => ( + + +
+ + + {customer.name.slice(0, 2)} + +
+
{customer.name}
+
{customer.gender}
+
+
+
+ {customer.wechatId} + +
+ {customer.tags.map((tag) => ( + + {tag} + + ))} +
+
+ {customer.region} + {customer.source} + {customer.projectName} + {customer.addedDate} + + + + + + + + + 查看详情 + + + + 分发客户 + + + + +
+ )) + ) : ( + + + 未找到客户 + + + )} +
+
+
+
+
+ ) +} + diff --git a/SuperAdmin/app/dashboard/layout.tsx b/SuperAdmin/app/dashboard/layout.tsx new file mode 100644 index 00000000..b44afd4e --- /dev/null +++ b/SuperAdmin/app/dashboard/layout.tsx @@ -0,0 +1,101 @@ +"use client" + +import type React from "react" + +import { useState } from "react" +import Link from "next/link" +import { usePathname } from "next/navigation" +import { Button } from "@/components/ui/button" +import { LayoutDashboard, Users, Settings, LogOut, Menu, X } from "lucide-react" + +export default function DashboardLayout({ + children, +}: { + children: React.ReactNode +}) { + const [sidebarOpen, setSidebarOpen] = useState(true) + const pathname = usePathname() + + const navItems = [ + { + title: "项目管理", + href: "/dashboard/projects", + icon: , + }, + { + title: "客户池", + href: "/dashboard/customers", + icon: , + }, + { + title: "管理员权限", + href: "/dashboard/admins", + icon: , + }, + ] + + return ( +
+ {/* Mobile sidebar toggle */} +
+ +
+ + {/* Sidebar */} +
+
+
+

超级管理员后台

+
+ +
+ +
+
+
+ + {/* Main content */} +
+
+

+ {navItems.find((item) => pathname.startsWith(item.href))?.title || "仪表盘"} +

+
+
{children}
+
+
+ ) +} + diff --git a/SuperAdmin/app/dashboard/page.tsx b/SuperAdmin/app/dashboard/page.tsx new file mode 100644 index 00000000..dfe14b45 --- /dev/null +++ b/SuperAdmin/app/dashboard/page.tsx @@ -0,0 +1,47 @@ +import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card" +import { Users, FolderKanban, UserCog } from "lucide-react" + +export default function DashboardPage() { + return ( +
+

欢迎使用超级管理员后台

+

通过此平台,您可以管理项目、客户和管理员权限。

+ +
+ + + 项目总数 + + + +
24
+

较上月增长 12%

+
+
+ + + + 客户总数 + + + +
1,284
+

较上月增长 8%

+
+
+ + + + 管理员数量 + + + +
8
+

较上月增长 2 人

+
+
+
+
+ ) +} + diff --git a/SuperAdmin/app/dashboard/projects/[id]/edit/page.tsx b/SuperAdmin/app/dashboard/projects/[id]/edit/page.tsx new file mode 100644 index 00000000..fcd2f406 --- /dev/null +++ b/SuperAdmin/app/dashboard/projects/[id]/edit/page.tsx @@ -0,0 +1,159 @@ +"use client" + +import type React from "react" + +import { useState } from "react" +import { useRouter } from "next/navigation" +import { Button } from "@/components/ui/button" +import { Input } from "@/components/ui/input" +import { Textarea } from "@/components/ui/textarea" +import { Label } from "@/components/ui/label" +import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card" +import { ArrowLeft, Plus, Trash } from "lucide-react" +import Link from "next/link" + +// Sample project data for editing +const projectData = { + id: "1", + name: "电商平台项目", + phone: "13800138000", + account: "ecommerce_admin", + description: "这是一个电商平台推广项目,主要针对年轻用户群体,通过微信社交渠道进行产品推广和销售转化。", + devices: [ + { id: "d1", name: "iPhone 13 Pro" }, + { id: "d2", name: "Huawei P40" }, + { id: "d3", name: "Samsung S21" }, + ], +} + +export default function EditProjectPage({ params }: { params: { id: string } }) { + const router = useRouter() + const [isSubmitting, setIsSubmitting] = useState(false) + const [projectName, setProjectName] = useState(projectData.name) + const [phone, setPhone] = useState(projectData.phone) + const [account, setAccount] = useState(projectData.account) + const [description, setDescription] = useState(projectData.description) + const [devices, setDevices] = useState(projectData.devices) + + const handleAddDevice = () => { + setDevices([...devices, { id: Date.now().toString(), name: "" }]) + } + + const handleRemoveDevice = (id: string) => { + setDevices(devices.filter((device) => device.id !== id)) + } + + const handleDeviceChange = (id: string, value: string) => { + setDevices(devices.map((device) => (device.id === id ? { ...device, name: value } : device))) + } + + const handleSubmit = (e: React.FormEvent) => { + e.preventDefault() + setIsSubmitting(true) + + // Simulate API call + setTimeout(() => { + setIsSubmitting(false) + router.push(`/dashboard/projects/${params.id}`) + }, 1500) + } + + return ( +
+
+ +

编辑项目

+
+ +
+ + + 项目基本信息 + 编辑项目的名称、手机号等基础信息 + + +
+ + setProjectName(e.target.value)} + placeholder="请输入项目名称" + required + /> +
+ +
+
+ + setPhone(e.target.value)} + placeholder="请输入手机号" + required + /> +
+ +
+ + setAccount(e.target.value)} + placeholder="请输入账号" + required + /> +
+
+ +
+ +
+ {devices.map((device, index) => ( +
+ handleDeviceChange(device.id, e.target.value)} + /> + +
+ ))} + +
+
+ +
+ +