diff --git a/Cunkebao/app/components/DeviceSelector.tsx b/Cunkebao/app/components/DeviceSelector.tsx
index cc876b071..ebd1ba62c 100755
--- a/Cunkebao/app/components/DeviceSelector.tsx
+++ b/Cunkebao/app/components/DeviceSelector.tsx
@@ -18,6 +18,7 @@ import {
PaginationNext,
PaginationPrevious,
} from "@/components/ui/pagination"
+import { ImeiDisplay } from "@/components/ImeiDisplay"
interface WechatAccount {
wechatId: string
@@ -169,7 +170,10 @@ export function DeviceSelector({
{device.status === "online" ? "在线" : "离线"}
-
{device.wechatAccounts.map((account) => (
diff --git a/Cunkebao/app/components/device-grid.tsx b/Cunkebao/app/components/device-grid.tsx
index 9b5a5fe8e..028119a71 100755
--- a/Cunkebao/app/components/device-grid.tsx
+++ b/Cunkebao/app/components/device-grid.tsx
@@ -6,6 +6,7 @@ import { Badge } from "@/components/ui/badge"
import { Checkbox } from "@/components/ui/checkbox"
import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@/components/ui/dialog"
import { Battery, Smartphone, MessageCircle, Users, Clock } from "lucide-react"
+import { ImeiDisplay } from "@/components/ImeiDisplay"
export interface Device {
id: string
@@ -88,11 +89,15 @@ export function DeviceGrid({
/>
)}
-
-
{device.name}
-
- {device.status === "online" ? "在线" : "离线"}
-
+
+
+
{device.name}
+
+
+ {device.status === "online" ? "在线" : "离线"}
+
+
+
@@ -142,10 +147,13 @@ export function DeviceGrid({
{selectedDevice.name}
-
IMEI: {selectedDevice.imei}
+
+ IMEI:
+
+
-
+
{selectedDevice.status === "online" ? "在线" : "离线"}
diff --git a/Cunkebao/app/components/device-selection-dialog.tsx b/Cunkebao/app/components/device-selection-dialog.tsx
index 9e434c81b..e467984f2 100755
--- a/Cunkebao/app/components/device-selection-dialog.tsx
+++ b/Cunkebao/app/components/device-selection-dialog.tsx
@@ -11,6 +11,7 @@ import { Card } from "@/components/ui/card"
import { Badge } from "@/components/ui/badge"
import { ScrollArea } from "@/components/ui/scroll-area"
import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs"
+import { ImeiDisplay } from "@/components/ImeiDisplay"
interface WechatAccount {
wechatId: string
@@ -278,7 +279,10 @@ export function DeviceSelectionDialog({
{device.status === "online" ? "在线" : "离线"}
-
diff --git a/Cunkebao/app/devices/[id]/page.tsx b/Cunkebao/app/devices/[id]/page.tsx
index 521741eb9..9a2596d11 100755
--- a/Cunkebao/app/devices/[id]/page.tsx
+++ b/Cunkebao/app/devices/[id]/page.tsx
@@ -12,6 +12,7 @@ import { Label } from "@/components/ui/label"
import { ScrollArea } from "@/components/ui/scroll-area"
import { fetchDeviceDetail, fetchDeviceRelatedAccounts, updateDeviceTaskConfig, fetchDeviceHandleLogs } from "@/api/devices"
import { toast } from "sonner"
+import { ImeiDisplay } from "@/components/ImeiDisplay"
interface WechatAccount {
id: string
@@ -439,7 +440,10 @@ export default function DeviceDetailPage() {
{device.status === "online" ? "在线" : "离线"}
-
好友数: {device.totalFriend}
diff --git a/Cunkebao/app/workspace/moments-sync/components/device-selection-dialog.tsx b/Cunkebao/app/workspace/moments-sync/components/device-selection-dialog.tsx
index d87bb3d5a..f4b9cfe30 100755
--- a/Cunkebao/app/workspace/moments-sync/components/device-selection-dialog.tsx
+++ b/Cunkebao/app/workspace/moments-sync/components/device-selection-dialog.tsx
@@ -9,6 +9,7 @@ import { Search, RefreshCw } from "lucide-react"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
import { ScrollArea } from "@/components/ui/scroll-area"
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"
+import { ImeiDisplay } from "@/components/ImeiDisplay"
interface Device {
id: string
@@ -123,12 +124,15 @@ export function DeviceSelectionDialog({ open, onOpenChange, selectedDevices, onS
{device.name}
-
+
{device.status === "online" ? "在线" : "离线"}
-
IMEI: {device.imei}
+
+ IMEI:
+
+
微信号: {device.wxid}
{device.usedInPlans > 0 && (
diff --git a/Cunkebao/app/workspace/moments-sync/new/steps/DeviceSelector.tsx b/Cunkebao/app/workspace/moments-sync/new/steps/DeviceSelector.tsx
index 2a0c9ce6d..f5e2e0b52 100755
--- a/Cunkebao/app/workspace/moments-sync/new/steps/DeviceSelector.tsx
+++ b/Cunkebao/app/workspace/moments-sync/new/steps/DeviceSelector.tsx
@@ -4,7 +4,7 @@ import { useState, useEffect } from "react"
import { Card } from "@/components/ui/card"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
-import { Search, RefreshCw, X } from "lucide-react"
+import { Search, RefreshCw, X, ChevronLeft, ChevronRight } from "lucide-react"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
import { Checkbox } from "@/components/ui/checkbox"
import { toast } from "@/components/ui/use-toast"
@@ -17,6 +17,7 @@ import {
PaginationNext,
PaginationPrevious,
} from "@/components/ui/pagination"
+import { ImeiDisplay } from "@/components/ImeiDisplay"
// 定义类型,避免导入错误
interface Device {
@@ -148,6 +149,16 @@ export function DeviceSelector({ formData, onChange, onNext, onPrev }: DeviceSel
}
}
+ const handlePrevPage = () => {
+ setCurrentPage((prev) => Math.max(1, prev - 1))
+ }
+
+ const handleNextPage = () => {
+ setCurrentPage((prev) => Math.min(Math.ceil(filteredDevices.length / itemsPerPage), prev + 1))
+ }
+
+ const isLastPage = currentPage === Math.ceil(filteredDevices.length / itemsPerPage)
+
return (
@@ -193,15 +204,14 @@ export function DeviceSelector({ formData, onChange, onNext, onPrev }: DeviceSel
{device.name}
-
+
{device.status === "online" ? "在线" : "离线"}
-
+
+
+
+ IMEI:
+
-
IMEI: {device.imei}
微信号: {device.wechatId}
{device.usedInPlans > 0 && (
已用于 {device.usedInPlans} 个计划
@@ -211,24 +221,25 @@ export function DeviceSelector({ formData, onChange, onNext, onPrev }: DeviceSel
))}
-
+
setCurrentPage((prev) => Math.max(1, prev - 1))}
+ onClick={handlePrevPage}
disabled={currentPage === 1}
/>
- {Array.from({ length: Math.ceil(filteredDevices.length / itemsPerPage) }, (_, i) => i + 1).map((page) => (
-
- setCurrentPage(page)} isActive={currentPage === page}>
- {page}
+ {Array.from({ length: Math.ceil(filteredDevices.length / itemsPerPage) }).map((_, index) => (
+
+ setCurrentPage(index + 1)}
+ isActive={currentPage === index + 1}
+ >
+ {index + 1}
))}
- setCurrentPage((prev) => Math.min(Math.ceil(filteredDevices.length / itemsPerPage), prev + 1))
- }
- disabled={currentPage === Math.ceil(filteredDevices.length / itemsPerPage)}
+ onClick={handleNextPage}
+ disabled={isLastPage}
/>
@@ -268,6 +279,30 @@ export function DeviceSelector({ formData, onChange, onNext, onPrev }: DeviceSel
下一步
+
+
+
+
+
+ {currentPage} / {Math.ceil(filteredDevices.length / itemsPerPage)}
+
+
+
+
)
diff --git a/Cunkebao/components/ImeiDisplay.tsx b/Cunkebao/components/ImeiDisplay.tsx
new file mode 100644
index 000000000..ef95a33e3
--- /dev/null
+++ b/Cunkebao/components/ImeiDisplay.tsx
@@ -0,0 +1,121 @@
+"use client"
+
+import { useState, useEffect } from "react"
+import {
+ Dialog,
+ DialogContent,
+ DialogHeader,
+ DialogTitle,
+ DialogDescription
+} from "@/components/ui/dialog"
+import { Button } from "@/components/ui/button"
+import { Copy } from "lucide-react"
+import { toast } from "@/components/ui/use-toast"
+
+interface ImeiDisplayProps {
+ imei: string
+ className?: string
+ containerWidth?: string | number // 可以接受字符串或数字类型的容器宽度配置
+}
+
+export function ImeiDisplay({ imei, className = "", containerWidth = "max-w-[calc(100%-40px)]" }: ImeiDisplayProps) {
+ // 初始状态设为false,确保服务端渲染和客户端水合时状态一致
+ const [open, setOpen] = useState(false)
+ const [mounted, setMounted] = useState(false)
+
+ // 确保只在客户端执行的初始化逻辑
+ useEffect(() => {
+ setMounted(true)
+ }, [])
+
+ const handleCopy = () => {
+ // 只在客户端执行
+ if (typeof navigator === 'undefined') return
+
+ try {
+ if (navigator.clipboard) {
+ navigator.clipboard.writeText(imei)
+ toast({
+ title: "已复制",
+ description: "IMEI已复制到剪贴板",
+ })
+ } else {
+ // 备用复制方法
+ const textArea = document.createElement("textarea")
+ textArea.value = imei
+ document.body.appendChild(textArea)
+ textArea.focus()
+ textArea.select()
+
+ try {
+ document.execCommand('copy')
+ toast({
+ title: "已复制",
+ description: "IMEI已复制到剪贴板",
+ })
+ } catch (err) {
+ toast({
+ title: "复制失败",
+ description: "您的浏览器不支持自动复制",
+ variant: "destructive"
+ })
+ }
+
+ document.body.removeChild(textArea)
+ }
+ } catch (err) {
+ toast({
+ title: "复制失败",
+ description: "您的浏览器不支持自动复制",
+ variant: "destructive"
+ })
+ }
+ }
+
+ // 处理containerWidth为数字的情况
+ const widthStyle = typeof containerWidth === 'number'
+ ? `max-w-[${containerWidth}px]`
+ : containerWidth
+
+ // 服务端渲染时,仅返回静态内容
+ if (!mounted) {
+ return
{imei}
+ }
+
+ return (
+ <>
+
{
+ e.stopPropagation()
+ setOpen(true)
+ }}
+ title={imei}
+ >
+ {imei}
+
+
+
+ >
+ )
+}
\ No newline at end of file
diff --git a/Cunkebao/components/device-grid.tsx b/Cunkebao/components/device-grid.tsx
index 8688f88f8..6b93ac490 100755
--- a/Cunkebao/components/device-grid.tsx
+++ b/Cunkebao/components/device-grid.tsx
@@ -2,8 +2,9 @@
import { Card } from "@/components/ui/card"
import { Badge } from "@/components/ui/badge"
-import { Smartphone, Battery, Users, MessageCircle } from "lucide-react"
+import { Smartphone, Battery, Users, MessageCircle, Clock } from "lucide-react"
import { Checkbox } from "@/components/ui/checkbox"
+import { ImeiDisplay } from "@/components/ImeiDisplay"
export interface Device {
id: string
@@ -54,7 +55,7 @@ export function DeviceGrid({ devices, selectable, selectedDevices, onSelect, dev
)}
-
+
{currentStatus.status === "online" ? "在线" : "离线"}
@@ -68,7 +69,10 @@ export function DeviceGrid({ devices, selectable, selectedDevices, onSelect, dev
{device.name}
-
IMEI-{device.imei}
+
+ IMEI:
+
+
{device.remark && 备注: {device.remark}
}
@@ -90,7 +94,7 @@ export function DeviceGrid({ devices, selectable, selectedDevices, onSelect, dev
今日添加:{device.todayAdded}
加友状态:
-
+
{device.addFriendStatus === "normal" ? "正常" : "异常"}