"use client" import * as React from "react" import { useState, useEffect, useRef } 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, X, CheckCircle2 } from "lucide-react" import Link from "next/link" import { toast, Toaster } from "sonner" import Image from "next/image" import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter } from "@/components/ui/dialog" import { apiRequest } from "@/lib/api-utils" // 为React.use添加类型声明 declare module 'react' { function use(promise: Promise): T; function use(value: T): T; } interface Device { id: number memo: string imei: string phone: string model: string brand: string alive: number createTime: number } interface Project { id: number name: string memo: string companyId: number createTime: string account: string phone: string | null deviceCount: number friendCount: number userCount: number username: string status: number s2_accountId?: number devices?: Device[] } export default function EditProjectPage({ params }: { params: { id: string } }) { const router = useRouter() const [isSubmitting, setIsSubmitting] = useState(false) const [isLoading, setIsLoading] = useState(true) const [project, setProject] = useState(null) const [password, setPassword] = useState("") const [confirmPassword, setConfirmPassword] = useState("") const [isModalOpen, setIsModalOpen] = useState(false) const [qrCodeData, setQrCodeData] = useState("") const [isAddingDevice, setIsAddingDevice] = useState(false) const [isPolling, setIsPolling] = useState(false) const [pollingStatus, setPollingStatus] = useState<"waiting" | "polling" | "success" | "error">("waiting") const [addedDevice, setAddedDevice] = useState(null) const [isQrCodeBroken, setIsQrCodeBroken] = useState(false) const pollingTimerRef = useRef(null) const pollingCountRef = useRef(0) const MAX_POLLING_COUNT = 120; // 2分钟 * 60秒 = 120次 const { id } = React.use(params) useEffect(() => { const fetchProject = async () => { setIsLoading(true) try { const result = await apiRequest(`/company/detail/${id}`) if (result.code === 200) { setProject(result.data) } else { toast.error(result.msg || "获取项目信息失败") } } catch (error) { toast.error("网络错误,请稍后重试") } finally { setIsLoading(false) } } fetchProject() }, [id]) const handleSubmit = async (e: React.FormEvent) => { e.preventDefault() setIsSubmitting(true) try { const result = await apiRequest('/company/update', 'POST', { id: id, name: project?.name, account: project?.account, password: password, memo: project?.memo, phone: project?.phone, username: project?.username, status: project?.status.toString(), }) if (result.code === 200) { toast.success("项目更新成功") router.push("/dashboard/projects") } else { toast.error(result.msg || "更新失败") } } catch (error) { toast.error("网络错误,请稍后重试") } finally { setIsSubmitting(false) } } const handleAddDevice = async () => { if (!project?.s2_accountId) { toast.error("无法添加设备,未找到账号ID") return } setIsAddingDevice(true) // 重置轮询状态 setPollingStatus("waiting") setIsPolling(false) setAddedDevice(null) setIsQrCodeBroken(false) pollingCountRef.current = 0; try { const result = await apiRequest('/v1/api/device/add', 'POST', { accountId: project.s2_accountId }) if (result.code === 200 && result.data?.qrCode) { setQrCodeData(result.data.qrCode) setIsModalOpen(true) // 五秒后开始轮询 setTimeout(() => { startPolling(); }, 5000); } else { toast.error(result.msg || "获取设备二维码失败") } } catch (error) { toast.error("网络错误,请稍后重试") } finally { setIsAddingDevice(false) } } const startPolling = () => { setIsPolling(true); setPollingStatus("polling"); // 清除可能存在的旧定时器 if (pollingTimerRef.current) { clearInterval(pollingTimerRef.current); } // 设置轮询定时器 pollingTimerRef.current = setInterval(() => { pollAddResult(); pollingCountRef.current += 1; // 如果达到最大轮询次数,停止轮询 if (pollingCountRef.current >= MAX_POLLING_COUNT) { stopPolling(); } }, 1000); } const pollAddResult = async () => { if (!project?.s2_accountId) { console.error("未找到账号ID,无法轮询"); return; } try { const result = await apiRequest(`/devices/add-results?accountId=${project.s2_accountId}`) if (result.code === 200) { // 检查是否最后一次轮询且设备未添加 if (pollingCountRef.current >= MAX_POLLING_COUNT && !result.data.added) { setPollingStatus("error"); setIsQrCodeBroken(true); stopPolling(); return; } // 检查设备是否已添加成功 if (result.data.added) { setPollingStatus("success"); setAddedDevice(result.data.device); stopPolling(); // 刷新设备列表 refreshProjectData(); toast.success("设备添加成功"); } } else { // 请求失败但继续轮询 console.error("轮询请求失败:", result.msg); } } catch (error) { console.error("轮询请求出错:", error); // 不要因为单次错误停止轮询 } } // 刷新项目数据的方法 const refreshProjectData = async () => { try { const result = await apiRequest(`/company/detail/${id}`) if (result.code === 200) { setProject(result.data) } else { toast.error(result.msg || "刷新项目信息失败") } } catch (error) { toast.error("网络错误,请稍后重试") } } const stopPolling = () => { if (pollingTimerRef.current) { clearInterval(pollingTimerRef.current); pollingTimerRef.current = null; } setIsPolling(false); } const closeModal = () => { stopPolling(); setIsModalOpen(false) setQrCodeData("") setPollingStatus("waiting"); setAddedDevice(null); setIsQrCodeBroken(false); } // 组件卸载时清除定时器 useEffect(() => { return () => { if (pollingTimerRef.current) { clearInterval(pollingTimerRef.current); } }; }, []); if (isLoading) { return
加载中...
} return (

编辑项目

项目基本信息 编辑项目的名称、手机号等基础信息
setProject({ ...project, name: e.target.value })} placeholder="请输入项目名称" required />
setProject({ ...project, account: e.target.value })} placeholder="请输入登录的账号" required />
setProject({ ...project, username: e.target.value })} placeholder="用于账号登录后显示的用户名,可以填真实姓名" required />
setProject({ ...project, phone: e.target.value as string })} placeholder="手机号可用于登录" required />
setPassword(e.target.value)} placeholder="不修改请留空" />
setConfirmPassword(e.target.value)} placeholder="不修改请留空" />
{project && project.devices && project.devices.length > 0 && (
{project.devices.map((device) => ( ))}
设备名称 IMEI 手机号 型号 品牌 状态 添加时间
{device.memo} {device.imei || '-'} {device.phone || '-'} {device.model || '-'} {device.brand || '-'} {device.alive === 1 ? '在线' : '离线'} {device.createTime || '-'}
)}