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)} + /> + +
+ ))} + +
+
+ +
+ +