lty/qy-lty-admin/components/affinity/affinity-rule-dialog.tsx
2026-03-17 13:17:02 +08:00

322 lines
11 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client"
import type React from "react"
import { useState, useEffect } from "react"
import { Button } from "@/components/ui/button"
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import { Textarea } from "@/components/ui/textarea"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
import { Plus, Loader2, Heart } from "lucide-react"
import { Switch } from "@/components/ui/switch"
// 定义互动规则类型
export type AffinityRule = {
id: string
name: string
type: string
description: string
minChange: number
maxChange: number
singleCap: number
dailyCap: number
isNegative: boolean
isEnabled: boolean
}
type AffinityRuleDialogProps = {
mode?: "create" | "edit"
rule?: AffinityRule
onSave?: (rule: AffinityRule) => void
trigger?: React.ReactNode
}
export function AffinityRuleDialog({ mode = "create", rule, onSave, trigger }: AffinityRuleDialogProps) {
const [open, setOpen] = useState(false)
const [isSubmitting, setIsSubmitting] = useState(false)
// 表单状态
const [name, setName] = useState("")
const [ruleType, setRuleType] = useState("")
const [description, setDescription] = useState("")
const [minChange, setMinChange] = useState("1")
const [maxChange, setMaxChange] = useState("5")
const [singleCap, setSingleCap] = useState("5")
const [dailyCap, setDailyCap] = useState("15")
const [isNegative, setIsNegative] = useState(false)
const [isEnabled, setIsEnabled] = useState(true)
// 当编辑模式且有规则数据时,初始化表单
useEffect(() => {
if (mode === "edit" && rule) {
setName(rule.name)
setRuleType(rule.type)
setDescription(rule.description)
setMinChange(String(rule.minChange))
setMaxChange(String(rule.maxChange))
setSingleCap(String(rule.singleCap))
setDailyCap(String(rule.dailyCap))
setIsNegative(rule.isNegative)
setIsEnabled(rule.isEnabled)
}
}, [mode, rule, open])
// 重置表单
const resetForm = () => {
if (mode === "create") {
setName("")
setRuleType("")
setDescription("")
setMinChange("1")
setMaxChange("5")
setSingleCap("5")
setDailyCap("15")
setIsNegative(false)
setIsEnabled(true)
}
}
const handleSubmit = async () => {
// 表单验证
if (!name || !ruleType || !description) {
alert("请填写所有必填字段!")
return
}
setIsSubmitting(true)
try {
// 构建规则对象
const updatedRule: AffinityRule = {
id: rule?.id || `rule-${Date.now()}`,
name,
type: ruleType,
description,
minChange: Number(minChange),
maxChange: Number(maxChange),
singleCap: Number(singleCap),
dailyCap: Number(dailyCap),
isNegative,
isEnabled,
}
// 模拟API请求
await new Promise((resolve) => setTimeout(resolve, 1500))
// 调用保存回调
if (onSave) {
onSave(updatedRule)
}
// 成功提示
alert(mode === "create" ? "互动规则创建成功!" : "互动规则更新成功!")
setOpen(false)
resetForm()
} catch (error) {
// 错误处理
console.error(mode === "create" ? "创建互动规则失败:" : "更新互动规则失败:", error)
alert(mode === "create" ? "创建互动规则失败,请重试!" : "更新互动规则失败,请重试!")
} finally {
setIsSubmitting(false)
}
}
return (
<Dialog
open={open}
onOpenChange={(newOpen) => {
setOpen(newOpen)
if (!newOpen) resetForm()
}}
>
<DialogTrigger asChild>
{trigger || (
<Button className="bg-gradient-to-r from-pink-500 to-purple-600 hover:from-pink-600 hover:to-purple-700 transition-all duration-300 shadow-md hover:shadow-lg">
<Plus className="mr-2 h-4 w-4" />
</Button>
)}
</DialogTrigger>
<DialogContent className="sm:max-w-[550px]">
<DialogHeader>
<DialogTitle className="text-xl font-bold bg-clip-text text-transparent bg-gradient-to-r from-purple-600 to-pink-600">
{mode === "create" ? "添加互动规则" : "编辑互动规则"}
</DialogTitle>
<DialogDescription>
{mode === "create" ? "设置新的互动行为对好感度的影响规则" : "修改互动行为对好感度的影响规则"}
</DialogDescription>
</DialogHeader>
<div className="grid gap-4 py-4">
<div className="grid grid-cols-2 gap-4">
<div className="space-y-2">
<Label htmlFor="rule-name" className="text-right">
<span className="text-red-500">*</span>
</Label>
<Input
id="rule-name"
placeholder="输入规则名称"
className="border-gray-300 focus-visible:ring-pink-500"
value={name}
onChange={(e) => setName(e.target.value)}
required
/>
</div>
<div className="space-y-2">
<Label htmlFor="rule-type" className="text-right">
<span className="text-red-500">*</span>
</Label>
<Select value={ruleType} onValueChange={setRuleType} required>
<SelectTrigger className="border-gray-300 focus:ring-pink-500">
<SelectValue placeholder="选择互动类型" />
</SelectTrigger>
<SelectContent>
<SelectItem value="card">使<EFBFBD><EFBFBD></SelectItem>
<SelectItem value="chat"></SelectItem>
<SelectItem value="feed"></SelectItem>
<SelectItem value="touch"></SelectItem>
<SelectItem value="dress"></SelectItem>
<SelectItem value="prop">使</SelectItem>
<SelectItem value="gift"></SelectItem>
<SelectItem value="decay"></SelectItem>
<SelectItem value="custom"></SelectItem>
</SelectContent>
</Select>
</div>
</div>
<div className="space-y-2">
<Label htmlFor="description" className="text-right">
<span className="text-red-500">*</span>
</Label>
<Textarea
id="description"
placeholder="输入规则描述"
className="min-h-[80px] border-gray-300 focus-visible:ring-pink-500"
value={description}
onChange={(e) => setDescription(e.target.value)}
required
/>
</div>
<div className="grid grid-cols-2 gap-4">
<div className="space-y-2">
<Label htmlFor="min-change" className="text-right">
<span className="text-red-500">*</span>
</Label>
<div className="flex items-center space-x-2">
<Input
id="min-change"
type="number"
className="border-gray-300 focus-visible:ring-pink-500"
value={minChange}
onChange={(e) => setMinChange(e.target.value)}
required
/>
<span className="text-sm text-gray-500"></span>
</div>
</div>
<div className="space-y-2">
<Label htmlFor="max-change" className="text-right">
<span className="text-red-500">*</span>
</Label>
<div className="flex items-center space-x-2">
<Input
id="max-change"
type="number"
className="border-gray-300 focus-visible:ring-pink-500"
value={maxChange}
onChange={(e) => setMaxChange(e.target.value)}
required
/>
<span className="text-sm text-gray-500"></span>
</div>
</div>
</div>
<div className="grid grid-cols-2 gap-4">
<div className="space-y-2">
<Label htmlFor="single-cap" className="text-right">
<span className="text-red-500">*</span>
</Label>
<div className="flex items-center space-x-2">
<Input
id="single-cap"
type="number"
min="0"
className="border-gray-300 focus-visible:ring-pink-500"
value={singleCap}
onChange={(e) => setSingleCap(e.target.value)}
required
/>
<span className="text-sm text-gray-500"></span>
</div>
</div>
<div className="space-y-2">
<Label htmlFor="daily-cap" className="text-right">
<span className="text-red-500">*</span>
</Label>
<div className="flex items-center space-x-2">
<Input
id="daily-cap"
type="number"
min="0"
className="border-gray-300 focus-visible:ring-pink-500"
value={dailyCap}
onChange={(e) => setDailyCap(e.target.value)}
required
/>
<span className="text-sm text-gray-500"></span>
</div>
</div>
</div>
<div className="flex items-center space-x-2 pt-2">
<Switch id="negative" checked={isNegative} onCheckedChange={setIsNegative} />
<Label htmlFor="negative" className="cursor-pointer">
</Label>
</div>
<div className="flex items-center space-x-2 pt-2">
<Switch id="enable-rule" checked={isEnabled} onCheckedChange={setIsEnabled} />
<Label htmlFor="enable-rule" className="cursor-pointer">
{mode === "create" ? "立即启用此规则" : "启用此规则"}
</Label>
</div>
</div>
<DialogFooter>
<Button variant="outline" onClick={() => setOpen(false)} disabled={isSubmitting}>
</Button>
<Button
className="bg-gradient-to-r from-pink-500 to-purple-600 hover:from-pink-600 hover:to-purple-700"
onClick={handleSubmit}
disabled={isSubmitting}
>
{isSubmitting ? (
<>
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
{mode === "create" ? "创建中..." : "更新中..."}
</>
) : (
<>
<Heart className="mr-2 h-4 w-4" />
{mode === "create" ? "创建规则" : "更新规则"}
</>
)}
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
)
}