朋友圈自动同步

This commit is contained in:
wong
2025-04-11 16:15:48 +08:00
parent 2411bb6d05
commit 0cd689e6ae
20 changed files with 1862 additions and 207 deletions

View File

@@ -0,0 +1,235 @@
"use client"
import { useState, useEffect } from "react"
import { useRouter } from "next/navigation"
import { ChevronLeft, Search } from "lucide-react"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { StepIndicator } from "../../components/step-indicator"
import { BasicSettings } from "../../components/basic-settings"
import { DeviceSelectionDialog } from "../../components/device-selection-dialog"
import { TagSelector } from "../../components/tag-selector"
import { api, ApiResponse } from "@/lib/api"
import { showToast } from "@/lib/toast"
interface TaskConfig {
id: number
workbenchId: number
interval: number
maxLikes: number
startTime: string
endTime: string
contentTypes: string[]
devices: number[]
targetGroups: string[]
tagOperator: number
createTime: string
updateTime: string
}
interface Task {
id: number
name: string
type: number
status: number
autoStart: number
createTime: string
updateTime: string
config: TaskConfig
}
export default function EditAutoLikePage({ params }: { params: { id: string } }) {
const router = useRouter()
const [currentStep, setCurrentStep] = useState(1)
const [deviceDialogOpen, setDeviceDialogOpen] = useState(false)
const [loading, setLoading] = useState(true)
const [formData, setFormData] = useState({
taskName: "",
likeInterval: 5,
maxLikesPerDay: 200,
timeRange: { start: "08:00", end: "22:00" },
contentTypes: ["text", "image", "video"],
enabled: true,
selectedDevices: [] as number[],
selectedTags: [] as string[],
tagOperator: "and" as "and" | "or",
})
useEffect(() => {
fetchTaskDetail()
}, [])
const fetchTaskDetail = async () => {
const loadingToast = showToast("正在加载任务信息...", "loading", true);
try {
const response = await api.get<{code: number, msg: string, data: Task}>(`/v1/workbench/detail?id=${params.id}`)
if (response.code === 200 && response.data) {
const task = response.data
setFormData({
taskName: task.name,
likeInterval: task.config.interval,
maxLikesPerDay: task.config.maxLikes,
timeRange: {
start: task.config.startTime,
end: task.config.endTime
},
contentTypes: task.config.contentTypes,
enabled: task.status === 1,
selectedDevices: task.config.devices,
selectedTags: task.config.targetGroups,
tagOperator: task.config.tagOperator === 1 ? "and" : "or"
})
} else {
showToast(response.msg || "获取任务信息失败", "error")
router.back()
}
} catch (error: any) {
console.error("获取任务详情失败:", error)
showToast(error?.message || "请检查网络连接", "error")
router.back()
} finally {
loadingToast.remove()
setLoading(false)
}
}
const handleUpdateFormData = (data: Partial<typeof formData>) => {
setFormData((prev) => ({ ...prev, ...data }))
}
const handleNext = () => {
setCurrentStep((prev) => Math.min(prev + 1, 3))
}
const handlePrev = () => {
setCurrentStep((prev) => Math.max(prev - 1, 1))
}
const handleComplete = async () => {
const loadingToast = showToast("正在更新任务...", "loading", true);
try {
const response = await api.post<ApiResponse>('/v1/workbench/update', {
id: params.id,
type: 1,
name: formData.taskName,
interval: formData.likeInterval,
maxLikes: formData.maxLikesPerDay,
startTime: formData.timeRange.start,
endTime: formData.timeRange.end,
contentTypes: formData.contentTypes,
enabled: formData.enabled,
devices: formData.selectedDevices,
targetGroups: formData.selectedTags,
tagOperator: formData.tagOperator === 'and' ? 1 : 2
});
if (response.code === 200) {
loadingToast.remove();
showToast(response.msg || "更新成功", "success");
router.push("/workspace/auto-like");
} else {
loadingToast.remove();
showToast(response.msg || "请稍后再试", "error");
}
} catch (error: any) {
console.error("更新自动点赞任务失败:", error);
loadingToast.remove();
showToast(error?.message || "请检查网络连接或稍后再试", "error");
}
};
if (loading) {
return null;
}
return (
<div className="min-h-screen bg-[#F8F9FA] pb-20">
<header className="sticky top-0 z-10 bg-white">
<div className="flex items-center h-14 px-4">
<Button variant="ghost" size="icon" onClick={() => router.back()} className="hover:bg-gray-50">
<ChevronLeft className="h-6 w-6" />
</Button>
<h1 className="ml-2 text-lg font-medium"></h1>
</div>
</header>
<div className="mt-8">
<StepIndicator currentStep={currentStep} />
<div className="mt-8">
{currentStep === 1 && (
<BasicSettings formData={formData} onChange={handleUpdateFormData} onNext={handleNext} />
)}
{currentStep === 2 && (
<div className="space-y-6 px-6">
<div className="relative">
<Search className="absolute left-3 top-4 h-5 w-5 text-gray-400" />
<Input
placeholder="选择设备"
className="h-12 pl-11 rounded-xl border-gray-200 text-base"
onClick={() => setDeviceDialogOpen(true)}
readOnly
value={formData.selectedDevices.length > 0 ? `已选择 ${formData.selectedDevices.length} 个设备` : ""}
/>
</div>
{formData.selectedDevices.length > 0 && (
<div className="text-base text-gray-500">{formData.selectedDevices.length} </div>
)}
<div className="flex space-x-4 pt-4">
<Button variant="outline" onClick={handlePrev} className="flex-1 h-12 rounded-xl text-base">
</Button>
<Button
onClick={handleNext}
className="flex-1 h-12 bg-blue-600 hover:bg-blue-700 rounded-xl text-base shadow-sm"
disabled={formData.selectedDevices.length === 0}
>
</Button>
</div>
<DeviceSelectionDialog
open={deviceDialogOpen}
onOpenChange={setDeviceDialogOpen}
selectedDevices={formData.selectedDevices}
onSelect={(devices) => {
handleUpdateFormData({ selectedDevices: devices })
setDeviceDialogOpen(false)
}}
/>
</div>
)}
{currentStep === 3 && (
<div className="px-6">
<TagSelector
selectedTags={formData.selectedTags}
tagOperator={formData.tagOperator}
onTagsChange={(tags) => handleUpdateFormData({ selectedTags: tags })}
onOperatorChange={(operator) => handleUpdateFormData({ tagOperator: operator })}
onBack={handlePrev}
onComplete={handleComplete}
/>
<div className="flex space-x-4 pt-4">
<Button variant="outline" onClick={handlePrev} className="flex-1 h-12 rounded-xl text-base">
</Button>
<Button
onClick={handleComplete}
className="flex-1 h-12 bg-blue-600 hover:bg-blue-700 rounded-xl text-base shadow-sm"
>
</Button>
</div>
</div>
)}
</div>
</div>
</div>
)
}

View File

@@ -294,7 +294,11 @@ export default function AutoLikePage() {
<div className="grid grid-cols-2 gap-4 mb-4">
<div className="text-sm text-gray-500">
<div>{task.config.devices.length} </div>
<div>{task.config.targetGroups.join(', ')}</div>
<div>{
task.config.targetGroups.length > 2
? `${task.config.targetGroups[0]}${task.config.targetGroups.length - 1}个标签`
: task.config.targetGroups.join(', ')
}</div>
</div>
<div className="text-sm text-gray-500">
<div>{task.config.interval} </div>