【操盘手端】自动点赞提交
This commit is contained in:
@@ -5,6 +5,7 @@ import { Button } from "@/components/ui/button"
|
||||
import { Switch } from "@/components/ui/switch"
|
||||
import { Plus, Minus, Clock, HelpCircle } from "lucide-react"
|
||||
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip"
|
||||
import { useViewMode } from "@/app/components/LayoutWrapper"
|
||||
|
||||
interface BasicSettingsProps {
|
||||
formData: {
|
||||
@@ -20,132 +21,136 @@ interface BasicSettingsProps {
|
||||
}
|
||||
|
||||
export function BasicSettings({ formData, onChange, onNext }: BasicSettingsProps) {
|
||||
const { viewMode } = useViewMode()
|
||||
|
||||
return (
|
||||
<div className="space-y-8 px-6">
|
||||
<div>
|
||||
<div className="text-base font-medium mb-2">任务名称</div>
|
||||
<Input
|
||||
value={formData.taskName}
|
||||
onChange={(e) => onChange({ taskName: e.target.value })}
|
||||
placeholder="请输入任务名称"
|
||||
className="h-12 border-0 border-b border-gray-200 rounded-none focus-visible:ring-0 focus-visible:border-blue-600 px-0 text-base"
|
||||
/>
|
||||
</div>
|
||||
<div className={`space-y-6 ${viewMode === "desktop" ? "p-6" : "p-4"}`}>
|
||||
<div className={`grid ${viewMode === "desktop" ? "grid-cols-2 gap-8" : "grid-cols-1 gap-4"}`}>
|
||||
<div>
|
||||
<div className="text-base font-medium mb-2">任务名称</div>
|
||||
<Input
|
||||
value={formData.taskName}
|
||||
onChange={(e) => onChange({ taskName: e.target.value })}
|
||||
placeholder="请输入任务名称"
|
||||
className="h-12 border-0 border-b border-gray-200 rounded-none focus-visible:ring-0 focus-visible:border-blue-600 px-0 text-base"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div className="text-base font-medium mb-2">允许发布时间段</div>
|
||||
<div className="flex items-center space-x-4">
|
||||
<div className="relative flex-1">
|
||||
<Input
|
||||
type="time"
|
||||
value={formData.startTime}
|
||||
onChange={(e) => onChange({ startTime: e.target.value })}
|
||||
className="h-12 pl-10 rounded-xl border-gray-200 text-base"
|
||||
/>
|
||||
<Clock className="absolute left-3 top-4 h-4 w-4 text-gray-400" />
|
||||
</div>
|
||||
<span className="text-gray-500">至</span>
|
||||
<div className="relative flex-1">
|
||||
<Input
|
||||
type="time"
|
||||
value={formData.endTime}
|
||||
onChange={(e) => onChange({ endTime: e.target.value })}
|
||||
className="h-12 pl-10 rounded-xl border-gray-200 text-base"
|
||||
/>
|
||||
<Clock className="absolute left-3 top-4 h-4 w-4 text-gray-400" />
|
||||
<div>
|
||||
<div className="text-base font-medium mb-2">允许发布时间段</div>
|
||||
<div className="flex items-center space-x-4">
|
||||
<div className="relative flex-1">
|
||||
<Input
|
||||
type="time"
|
||||
value={formData.startTime}
|
||||
onChange={(e) => onChange({ startTime: e.target.value })}
|
||||
className="h-12 pl-10 rounded-xl border-gray-200 text-base"
|
||||
/>
|
||||
<Clock className="absolute left-3 top-4 h-4 w-4 text-gray-400" />
|
||||
</div>
|
||||
<span className="text-gray-500">至</span>
|
||||
<div className="relative flex-1">
|
||||
<Input
|
||||
type="time"
|
||||
value={formData.endTime}
|
||||
onChange={(e) => onChange({ endTime: e.target.value })}
|
||||
className="h-12 pl-10 rounded-xl border-gray-200 text-base"
|
||||
/>
|
||||
<Clock className="absolute left-3 top-4 h-4 w-4 text-gray-400" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div className="text-base font-medium mb-2">每日同步数量</div>
|
||||
<div className="flex items-center space-x-5">
|
||||
<Button
|
||||
variant="outline"
|
||||
size="lg"
|
||||
onClick={() => onChange({ syncCount: Math.max(1, formData.syncCount - 1) })}
|
||||
className="h-12 w-12 rounded-xl"
|
||||
>
|
||||
<Minus className="h-5 w-5" />
|
||||
</Button>
|
||||
<span className="w-8 text-center text-lg font-medium">{formData.syncCount}</span>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="lg"
|
||||
onClick={() => onChange({ syncCount: formData.syncCount + 1 })}
|
||||
className="h-12 w-12 rounded-xl"
|
||||
>
|
||||
<Plus className="h-5 w-5" />
|
||||
</Button>
|
||||
<span className="text-gray-500">条朋友圈</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div className="text-base font-medium mb-2">账号类型</div>
|
||||
<div className="flex space-x-4">
|
||||
<div className="flex-1 relative">
|
||||
<TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button
|
||||
variant="ghost"
|
||||
onClick={() => onChange({ accountType: "business" })}
|
||||
className={`w-full h-12 justify-between rounded-lg ${
|
||||
formData.accountType === "business"
|
||||
? "bg-blue-600 hover:bg-blue-600 text-white"
|
||||
: "bg-white hover:bg-gray-50"
|
||||
}`}
|
||||
>
|
||||
业务号
|
||||
<HelpCircle
|
||||
className={`h-4 w-4 ${formData.accountType === "business" ? "text-white/70" : "text-gray-400"}`}
|
||||
/>
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent className="max-w-[300px]">
|
||||
<p>
|
||||
业务号能够循环推送内容库中的内容。当内容库所有内容循环推送完毕后,若有新内容则优先推送新内容,若无新内容则继续循环推送。
|
||||
</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
</div>
|
||||
<div className="flex-1 relative">
|
||||
<TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button
|
||||
variant="ghost"
|
||||
onClick={() => onChange({ accountType: "personal" })}
|
||||
className={`w-full h-12 justify-between rounded-lg ${
|
||||
formData.accountType === "personal"
|
||||
? "bg-blue-600 hover:bg-blue-600 text-white"
|
||||
: "bg-white hover:bg-gray-50"
|
||||
}`}
|
||||
>
|
||||
人设号
|
||||
<HelpCircle
|
||||
className={`h-4 w-4 ${formData.accountType === "personal" ? "text-white/70" : "text-gray-400"}`}
|
||||
/>
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
<p>用于实时更新同步,有新动态时进行同步,无动态则不同步。</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
<div>
|
||||
<div className="text-base font-medium mb-2">每日同步数量</div>
|
||||
<div className="flex items-center space-x-5">
|
||||
<Button
|
||||
variant="outline"
|
||||
size="lg"
|
||||
onClick={() => onChange({ syncCount: Math.max(1, formData.syncCount - 1) })}
|
||||
className="h-12 w-12 rounded-xl bg-white border-gray-200"
|
||||
>
|
||||
<Minus className="h-5 w-5" />
|
||||
</Button>
|
||||
<span className="w-8 text-center text-lg font-medium">{formData.syncCount}</span>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="lg"
|
||||
onClick={() => onChange({ syncCount: formData.syncCount + 1 })}
|
||||
className="h-12 w-12 rounded-xl bg-white border-gray-200"
|
||||
>
|
||||
<Plus className="h-5 w-5" />
|
||||
</Button>
|
||||
<span className="text-gray-500">条朋友圈</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-between py-2">
|
||||
<span className="text-base font-medium">是否启用</span>
|
||||
<Switch
|
||||
checked={formData.enabled}
|
||||
onCheckedChange={(checked) => onChange({ enabled: checked })}
|
||||
className="data-[state=checked]:bg-blue-600 h-7 w-12"
|
||||
/>
|
||||
<div>
|
||||
<div className="text-base font-medium mb-2">账号类型</div>
|
||||
<div className="flex space-x-4">
|
||||
<div className="flex-1 relative">
|
||||
<TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button
|
||||
variant="ghost"
|
||||
onClick={() => onChange({ accountType: "business" })}
|
||||
className={`w-full h-12 justify-between rounded-lg ${
|
||||
formData.accountType === "business"
|
||||
? "bg-blue-600 hover:bg-blue-600 text-white"
|
||||
: "bg-white hover:bg-gray-50"
|
||||
}`}
|
||||
>
|
||||
业务号
|
||||
<HelpCircle
|
||||
className={`h-4 w-4 ${formData.accountType === "business" ? "text-white/70" : "text-gray-400"}`}
|
||||
/>
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent className="max-w-[300px]">
|
||||
<p>
|
||||
业务号能够循环推送内容库中的内容。当内容库所有内容循环推送完毕后,若有新内容则优先推送新内容,若无新内容则继续循环推送。
|
||||
</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
</div>
|
||||
<div className="flex-1 relative">
|
||||
<TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button
|
||||
variant="ghost"
|
||||
onClick={() => onChange({ accountType: "personal" })}
|
||||
className={`w-full h-12 justify-between rounded-lg ${
|
||||
formData.accountType === "personal"
|
||||
? "bg-blue-600 hover:bg-blue-600 text-white"
|
||||
: "bg-white hover:bg-gray-50"
|
||||
}`}
|
||||
>
|
||||
人设号
|
||||
<HelpCircle
|
||||
className={`h-4 w-4 ${formData.accountType === "personal" ? "text-white/70" : "text-gray-400"}`}
|
||||
/>
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
<p>用于实时更新同步,有新动态时进行同步,无动态则不同步。</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-between py-2">
|
||||
<span className="text-base font-medium">是否启用</span>
|
||||
<Switch
|
||||
checked={formData.enabled}
|
||||
onCheckedChange={(checked) => onChange({ enabled: checked })}
|
||||
className="data-[state=checked]:bg-blue-600 h-7 w-12"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Button
|
||||
@@ -157,4 +162,3 @@ export function BasicSettings({ formData, onChange, onNext }: BasicSettingsProps
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@ 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
|
||||
@@ -124,15 +123,12 @@ export function DeviceSelectionDialog({ open, onOpenChange, selectedDevices, onS
|
||||
<div className="flex-1">
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="font-medium">{device.name}</span>
|
||||
<Badge variant={device.status === "online" ? "default" : "secondary"}>
|
||||
<Badge variant={device.status === "online" ? "success" : "secondary"}>
|
||||
{device.status === "online" ? "在线" : "离线"}
|
||||
</Badge>
|
||||
</div>
|
||||
<div className="text-sm text-gray-500 mt-1">
|
||||
<div className="flex items-center">
|
||||
<span className="mr-1">IMEI:</span>
|
||||
<ImeiDisplay imei={device.imei} containerWidth={160} />
|
||||
</div>
|
||||
<div>IMEI: {device.imei}</div>
|
||||
<div>微信号: {device.wxid}</div>
|
||||
</div>
|
||||
{device.usedInPlans > 0 && (
|
||||
@@ -147,4 +143,3 @@ export function DeviceSelectionDialog({ open, onOpenChange, selectedDevices, onS
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -61,7 +61,9 @@ export function BasicSettings({ formData, onChange, onNext }: BasicSettingsProps
|
||||
>
|
||||
<Minus className="h-4 w-4" />
|
||||
</Button>
|
||||
<span className="w-12 text-center">{formData.syncCount}</span>
|
||||
<span className="w-12 text-center bg-primary text-primary-foreground rounded-md px-3 py-1 font-medium">
|
||||
{formData.syncCount}
|
||||
</span>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
@@ -135,4 +137,3 @@ export function BasicSettings({ formData, onChange, onNext }: BasicSettingsProps
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -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, ChevronLeft, ChevronRight } from "lucide-react"
|
||||
import { Search, RefreshCw, X } 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,7 +17,6 @@ import {
|
||||
PaginationNext,
|
||||
PaginationPrevious,
|
||||
} from "@/components/ui/pagination"
|
||||
import { ImeiDisplay } from "@/components/ImeiDisplay"
|
||||
|
||||
// 定义类型,避免导入错误
|
||||
interface Device {
|
||||
@@ -149,16 +148,6 @@ 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 (
|
||||
<Card className="p-6">
|
||||
<div className="space-y-4">
|
||||
@@ -204,14 +193,15 @@ export function DeviceSelector({ formData, onChange, onNext, onPrev }: DeviceSel
|
||||
<div className="flex-1 min-w-0">
|
||||
<div className="flex items-center justify-between mb-1">
|
||||
<div className="font-medium truncate">{device.name}</div>
|
||||
<Badge variant={device.status === "online" ? "default" : "secondary"}>
|
||||
<div
|
||||
className={`px-2 py-1 rounded-full text-xs ${
|
||||
device.status === "online" ? "bg-green-100 text-green-800" : "bg-gray-100 text-gray-800"
|
||||
}`}
|
||||
>
|
||||
{device.status === "online" ? "在线" : "离线"}
|
||||
</Badge>
|
||||
</div>
|
||||
<div className="text-sm text-gray-500 flex items-center">
|
||||
<span className="mr-1">IMEI:</span>
|
||||
<ImeiDisplay imei={device.imei} containerWidth={160} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-sm text-gray-500">IMEI: {device.imei}</div>
|
||||
<div className="text-sm text-gray-500">微信号: {device.wechatId}</div>
|
||||
{device.usedInPlans > 0 && (
|
||||
<div className="text-sm text-orange-500">已用于 {device.usedInPlans} 个计划</div>
|
||||
@@ -221,25 +211,24 @@ export function DeviceSelector({ formData, onChange, onNext, onPrev }: DeviceSel
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
<Pagination className="mt-4">
|
||||
<Pagination>
|
||||
<PaginationContent>
|
||||
<PaginationPrevious
|
||||
onClick={handlePrevPage}
|
||||
onClick={() => setCurrentPage((prev) => Math.max(1, prev - 1))}
|
||||
disabled={currentPage === 1}
|
||||
/>
|
||||
{Array.from({ length: Math.ceil(filteredDevices.length / itemsPerPage) }).map((_, index) => (
|
||||
<PaginationItem key={index}>
|
||||
<PaginationLink
|
||||
onClick={() => setCurrentPage(index + 1)}
|
||||
isActive={currentPage === index + 1}
|
||||
>
|
||||
{index + 1}
|
||||
{Array.from({ length: Math.ceil(filteredDevices.length / itemsPerPage) }, (_, i) => i + 1).map((page) => (
|
||||
<PaginationItem key={page}>
|
||||
<PaginationLink onClick={() => setCurrentPage(page)} isActive={currentPage === page}>
|
||||
{page}
|
||||
</PaginationLink>
|
||||
</PaginationItem>
|
||||
))}
|
||||
<PaginationNext
|
||||
onClick={handleNextPage}
|
||||
disabled={isLastPage}
|
||||
onClick={() =>
|
||||
setCurrentPage((prev) => Math.min(Math.ceil(filteredDevices.length / itemsPerPage), prev + 1))
|
||||
}
|
||||
disabled={currentPage === Math.ceil(filteredDevices.length / itemsPerPage)}
|
||||
/>
|
||||
</PaginationContent>
|
||||
</Pagination>
|
||||
@@ -279,32 +268,7 @@ export function DeviceSelector({ formData, onChange, onNext, onPrev }: DeviceSel
|
||||
下一步
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-center items-center space-x-2 mt-4">
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
onClick={handlePrevPage}
|
||||
disabled={currentPage === 1}
|
||||
>
|
||||
<ChevronLeft className="h-4 w-4" />
|
||||
</Button>
|
||||
|
||||
<div className="text-sm text-gray-500">
|
||||
{currentPage} / {Math.ceil(filteredDevices.length / itemsPerPage)}
|
||||
</div>
|
||||
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
onClick={handleNextPage}
|
||||
disabled={isLastPage}
|
||||
>
|
||||
<ChevronRight className="h-4 w-4" />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user