Files
cunkebao_v3/Cunkebao/app/workspace/auto-like/components/like-rules.tsx

330 lines
13 KiB
TypeScript
Raw Normal View History

2025-03-29 16:50:39 +08:00
"use client"
import { useState } from "react"
2025-04-10 16:40:30 +08:00
import { Card, CardContent } from "@/components/ui/card"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
2025-03-29 16:50:39 +08:00
import { Label } from "@/components/ui/label"
import { Switch } from "@/components/ui/switch"
import { Slider } from "@/components/ui/slider"
import { Checkbox } from "@/components/ui/checkbox"
2025-04-10 16:40:30 +08:00
import { Plus, Trash2, Clock } from "lucide-react"
2025-03-29 16:50:39 +08:00
import { Badge } from "@/components/ui/badge"
2025-04-10 16:40:30 +08:00
import { useViewMode } from "@/app/components/LayoutWrapper"
2025-03-29 16:50:39 +08:00
export interface LikeRulesData {
enableAutoLike: boolean
likeInterval: number
maxLikesPerDay: number
likeOldContent: boolean
contentTypes: string[]
keywordFilters: string[]
friendGroups: string[]
excludedGroups: string[]
2025-04-10 16:40:30 +08:00
timeRanges: { id: string; start: string; end: string }[]
2025-03-29 16:50:39 +08:00
randomizeInterval: boolean
2025-04-10 16:40:30 +08:00
minInterval: number
maxInterval: number
2025-03-29 16:50:39 +08:00
}
interface LikeRulesProps {
2025-04-10 16:40:30 +08:00
initialData: LikeRulesData
2025-03-29 16:50:39 +08:00
onSave: (data: LikeRulesData) => void
}
export function LikeRules({ initialData, onSave }: LikeRulesProps) {
2025-04-10 16:40:30 +08:00
const [formData, setFormData] = useState<LikeRulesData>(initialData)
2025-03-29 16:50:39 +08:00
const [newKeyword, setNewKeyword] = useState("")
2025-04-10 16:40:30 +08:00
const { viewMode } = useViewMode()
2025-03-29 16:50:39 +08:00
2025-04-10 16:40:30 +08:00
const handleContentTypeToggle = (type: string) => {
const updatedTypes = formData.contentTypes.includes(type)
? formData.contentTypes.filter((t) => t !== type)
: [...formData.contentTypes, type]
setFormData({ ...formData, contentTypes: updatedTypes })
2025-03-29 16:50:39 +08:00
}
2025-04-10 16:40:30 +08:00
const addKeywordFilter = () => {
2025-03-29 16:50:39 +08:00
if (newKeyword.trim() && !formData.keywordFilters.includes(newKeyword.trim())) {
setFormData({
...formData,
keywordFilters: [...formData.keywordFilters, newKeyword.trim()],
})
setNewKeyword("")
}
}
2025-04-10 16:40:30 +08:00
const removeKeywordFilter = (keyword: string) => {
2025-03-29 16:50:39 +08:00
setFormData({
...formData,
keywordFilters: formData.keywordFilters.filter((k) => k !== keyword),
})
}
2025-04-10 16:40:30 +08:00
const addTimeRange = () => {
const newId = String(formData.timeRanges.length + 1)
2025-03-29 16:50:39 +08:00
setFormData({
...formData,
2025-04-10 16:40:30 +08:00
timeRanges: [...formData.timeRanges, { id: newId, start: "09:00", end: "18:00" }],
2025-03-29 16:50:39 +08:00
})
}
2025-04-10 16:40:30 +08:00
const updateTimeRange = (id: string, field: "start" | "end", value: string) => {
2025-03-29 16:50:39 +08:00
setFormData({
...formData,
2025-04-10 16:40:30 +08:00
timeRanges: formData.timeRanges.map((range) => (range.id === id ? { ...range, [field]: value } : range)),
2025-03-29 16:50:39 +08:00
})
}
2025-04-10 16:40:30 +08:00
const removeTimeRange = (id: string) => {
if (formData.timeRanges.length > 1) {
setFormData({
...formData,
timeRanges: formData.timeRanges.filter((range) => range.id !== id),
})
}
2025-03-29 16:50:39 +08:00
}
return (
2025-04-10 16:40:30 +08:00
<Card className="mb-6">
<CardContent className="pt-6">
<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"}`}>
2025-03-29 16:50:39 +08:00
<div className="flex items-center justify-between">
2025-04-10 16:40:30 +08:00
<div>
<Label htmlFor="enable-auto-like" className="text-base font-medium">
2025-03-29 16:50:39 +08:00
</Label>
2025-04-10 16:40:30 +08:00
<p className="text-sm text-muted-foreground"></p>
2025-03-29 16:50:39 +08:00
</div>
<Switch
2025-04-10 16:40:30 +08:00
id="enable-auto-like"
2025-03-29 16:50:39 +08:00
checked={formData.enableAutoLike}
onCheckedChange={(checked) => setFormData({ ...formData, enableAutoLike: checked })}
/>
</div>
2025-04-10 16:40:30 +08:00
<div className="space-y-2">
<Label className="text-base font-medium"></Label>
<p className="text-sm text-muted-foreground mb-2"></p>
<div className="flex flex-wrap gap-3">
<div className="flex items-center space-x-2">
<Checkbox
id="text-content"
checked={formData.contentTypes.includes("text")}
onCheckedChange={() => handleContentTypeToggle("text")}
/>
<label htmlFor="text-content" className="text-sm">
</label>
</div>
<div className="flex items-center space-x-2">
<Checkbox
id="image-content"
checked={formData.contentTypes.includes("image")}
onCheckedChange={() => handleContentTypeToggle("image")}
/>
<label htmlFor="image-content" className="text-sm">
</label>
</div>
<div className="flex items-center space-x-2">
<Checkbox
id="video-content"
checked={formData.contentTypes.includes("video")}
onCheckedChange={() => handleContentTypeToggle("video")}
/>
<label htmlFor="video-content" className="text-sm">
</label>
</div>
</div>
</div>
<div className="space-y-2">
<Label htmlFor="max-likes" className="text-base font-medium">
</Label>
<p className="text-sm text-muted-foreground mb-2">100</p>
<div className="flex items-center gap-4">
<Slider
id="max-likes"
value={[formData.maxLikesPerDay]}
min={10}
max={150}
step={5}
onValueChange={(value) => setFormData({ ...formData, maxLikesPerDay: value[0] })}
className="flex-1"
/>
<div className="bg-primary text-primary-foreground rounded-md px-3 py-1 font-medium min-w-[60px] text-center">
{formData.maxLikesPerDay}
</div>
</div>
</div>
<div className="space-y-2">
<Label htmlFor="like-interval" className="text-base font-medium">
</Label>
<p className="text-sm text-muted-foreground mb-2"></p>
<div className="flex items-center gap-4">
<Slider
id="like-interval"
value={[formData.likeInterval]}
min={1}
max={60}
step={1}
onValueChange={(value) => setFormData({ ...formData, likeInterval: value[0] })}
className="flex-1"
/>
<div className="bg-primary text-primary-foreground rounded-md px-3 py-1 font-medium min-w-[60px] text-center">
{formData.likeInterval}
</div>
</div>
</div>
2025-03-29 16:50:39 +08:00
<div className="space-y-2">
<div className="flex items-center justify-between">
2025-04-10 16:40:30 +08:00
<div>
<Label htmlFor="randomize-interval" className="text-base font-medium">
</Label>
<p className="text-sm text-muted-foreground"></p>
</div>
<Switch
id="randomize-interval"
checked={formData.randomizeInterval}
onCheckedChange={(checked) => setFormData({ ...formData, randomizeInterval: checked })}
/>
2025-03-29 16:50:39 +08:00
</div>
2025-04-10 16:40:30 +08:00
{formData.randomizeInterval && (
<div className="grid grid-cols-2 gap-4 mt-3">
<div>
<Label htmlFor="min-interval"></Label>
<Input
id="min-interval"
type="number"
value={formData.minInterval}
onChange={(e) => setFormData({ ...formData, minInterval: Number.parseInt(e.target.value) || 1 })}
2025-03-29 16:50:39 +08:00
min={1}
2025-04-10 16:40:30 +08:00
className="mt-1"
2025-03-29 16:50:39 +08:00
/>
</div>
2025-04-10 16:40:30 +08:00
<div>
<Label htmlFor="max-interval"></Label>
<Input
id="max-interval"
type="number"
value={formData.maxInterval}
onChange={(e) => setFormData({ ...formData, maxInterval: Number.parseInt(e.target.value) || 1 })}
min={formData.minInterval + 1}
className="mt-1"
2025-03-29 16:50:39 +08:00
/>
</div>
</div>
)}
</div>
<div className="space-y-2">
2025-04-10 16:40:30 +08:00
<Label className="text-base font-medium"></Label>
<p className="text-sm text-muted-foreground mb-2"></p>
<div className="space-y-4">
{formData.timeRanges.map((range) => (
<div key={range.id} className="flex items-center space-x-2">
<Clock className="h-4 w-4 text-muted-foreground" />
<Input
type="time"
value={range.start}
onChange={(e) => updateTimeRange(range.id, "start", e.target.value)}
className="w-32"
/>
<span></span>
<Input
type="time"
value={range.end}
onChange={(e) => updateTimeRange(range.id, "end", e.target.value)}
className="w-32"
/>
<Button
variant="ghost"
size="icon"
onClick={() => removeTimeRange(range.id)}
disabled={formData.timeRanges.length <= 1}
className="ml-auto"
>
<Trash2 className="h-4 w-4" />
</Button>
</div>
))}
2025-03-29 16:50:39 +08:00
2025-04-10 16:40:30 +08:00
<Button variant="outline" size="sm" onClick={addTimeRange} className="mt-2">
<Plus className="h-4 w-4 mr-2" />
</Button>
2025-03-29 16:50:39 +08:00
</div>
</div>
2025-04-10 16:40:30 +08:00
<div className="space-y-2">
<Label className="text-base font-medium"></Label>
<p className="text-sm text-muted-foreground mb-2"></p>
<div className="flex space-x-2 mb-2">
<Input
value={newKeyword}
onChange={(e) => setNewKeyword(e.target.value)}
placeholder="输入关键词"
className="flex-1"
onKeyDown={(e) => e.key === "Enter" && addKeywordFilter()}
/>
<Button onClick={addKeywordFilter} variant="secondary">
</Button>
</div>
2025-03-29 16:50:39 +08:00
<div className="flex flex-wrap gap-2 mt-2">
2025-04-10 16:40:30 +08:00
{formData.keywordFilters.length === 0 && (
<span className="text-sm text-muted-foreground"></span>
)}
2025-03-29 16:50:39 +08:00
{formData.keywordFilters.map((keyword) => (
<Badge key={keyword} variant="secondary" className="flex items-center gap-1">
{keyword}
<Button
variant="ghost"
size="icon"
2025-04-10 16:40:30 +08:00
className="h-4 w-4 p-0 ml-1"
onClick={() => removeKeywordFilter(keyword)}
2025-03-29 16:50:39 +08:00
>
<Trash2 className="h-3 w-3" />
</Button>
</Badge>
))}
</div>
</div>
<div className="flex items-center justify-between">
2025-04-10 16:40:30 +08:00
<div>
<Label htmlFor="like-old-content" className="text-base font-medium">
</Label>
<p className="text-sm text-muted-foreground"></p>
</div>
<Switch
id="like-old-content"
checked={formData.likeOldContent}
onCheckedChange={(checked) => setFormData({ ...formData, likeOldContent: checked })}
/>
2025-03-29 16:50:39 +08:00
</div>
</div>
2025-04-10 16:40:30 +08:00
<Button className="w-full" onClick={() => onSave(formData)}>
</Button>
</div>
</CardContent>
</Card>
2025-03-29 16:50:39 +08:00
)
}