plan pages

This commit is contained in:
xavier
2025-06-03 16:37:39 +08:00
parent 0d33ba7e34
commit 1f2a1dab00
62 changed files with 12508 additions and 1984 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -5,15 +5,13 @@ import { Card } from "@/components/ui/card"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import { HelpCircle, MessageSquare, AlertCircle, RefreshCw } from "lucide-react"
import { HelpCircle, MessageSquare, AlertCircle } from "lucide-react"
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@/components/ui/dialog"
import { Alert, AlertDescription } from "@/components/ui/alert"
import { ChevronsUpDown } from "lucide-react"
import { Checkbox } from "@/components/ui/checkbox"
import { fetchDeviceList } from "@/api/devices"
import type { ServerDevice } from "@/types/device"
interface FriendRequestSettingsProps {
formData: any
@@ -38,15 +36,20 @@ const remarkTypes = [
{ value: "source", label: "来源" },
]
// 模拟设备数据
const mockDevices = [
{ id: "1", name: "iPhone 13 Pro", status: "online" },
{ id: "2", name: "Xiaomi 12", status: "online" },
{ id: "3", name: "Huawei P40", status: "offline" },
{ id: "4", name: "OPPO Find X3", status: "online" },
{ id: "5", name: "Samsung S21", status: "online" },
]
export function FriendRequestSettings({ formData, onChange, onNext, onPrev }: FriendRequestSettingsProps) {
const [isTemplateDialogOpen, setIsTemplateDialogOpen] = useState(false)
const [hasWarnings, setHasWarnings] = useState(false)
const [isDeviceSelectorOpen, setIsDeviceSelectorOpen] = useState(false)
const [selectedDevices, setSelectedDevices] = useState<ServerDevice[]>(formData.selectedDevices || [])
const [devices, setDevices] = useState<ServerDevice[]>([])
const [loadingDevices, setLoadingDevices] = useState(false)
const [deviceError, setDeviceError] = useState<string | null>(null)
const [searchKeyword, setSearchKeyword] = useState("")
const [selectedDevices, setSelectedDevices] = useState<any[]>(formData.selectedDevices || [])
// 获取场景标题
const getScenarioTitle = () => {
@@ -64,33 +67,6 @@ export function FriendRequestSettings({ formData, onChange, onNext, onPrev }: Fr
}
}
// 加载设备列表
const loadDevices = async () => {
try {
setLoadingDevices(true)
setDeviceError(null)
const response = await fetchDeviceList(1, 100, searchKeyword)
if (response.code === 200 && response.data?.list) {
setDevices(response.data.list)
} else {
setDeviceError(response.msg || "获取设备列表失败")
console.error("获取设备列表失败:", response.msg)
}
} catch (err) {
console.error("获取设备列表失败:", err)
setDeviceError("获取设备列表失败,请稍后重试")
} finally {
setLoadingDevices(false)
}
}
// 初始化时加载设备列表
useEffect(() => {
loadDevices()
}, [])
// 使用useEffect设置默认值
useEffect(() => {
if (!formData.greeting) {
@@ -120,7 +96,7 @@ export function FriendRequestSettings({ formData, onChange, onNext, onPrev }: Fr
onNext()
}
const toggleDeviceSelection = (device: ServerDevice) => {
const toggleDeviceSelection = (device: any) => {
const isSelected = selectedDevices.some((d) => d.id === device.id)
let newSelectedDevices
@@ -134,13 +110,8 @@ export function FriendRequestSettings({ formData, onChange, onNext, onPrev }: Fr
onChange({ ...formData, selectedDevices: newSelectedDevices })
}
// 根据关键词搜索设备
const handleSearch = () => {
loadDevices()
}
return (
<div className="w-full p-4 bg-gray-50">
<Card className="p-6">
<div className="space-y-6">
<div>
<Label className="text-base"></Label>
@@ -157,77 +128,31 @@ export function FriendRequestSettings({ formData, onChange, onNext, onPrev }: Fr
{isDeviceSelectorOpen && (
<div className="absolute z-10 w-full mt-1 bg-white border rounded-md shadow-lg">
<div className="p-2">
<div className="flex gap-2 mb-2">
<Input
placeholder="搜索设备..."
value={searchKeyword}
onChange={(e) => setSearchKeyword(e.target.value)}
onKeyDown={(e) => e.key === 'Enter' && handleSearch()}
/>
<Button variant="outline" size="icon" onClick={handleSearch}>
<RefreshCw className="h-4 w-4" />
</Button>
</div>
{loadingDevices ? (
<div className="flex justify-center items-center py-4">
<div className="animate-spin h-5 w-5 border-2 border-blue-500 rounded-full border-t-transparent"></div>
</div>
) : deviceError ? (
<div className="text-center text-red-500 py-4">
{deviceError}
<Button variant="outline" size="sm" onClick={loadDevices} className="ml-2">
</Button>
</div>
) : devices.length === 0 ? (
<div className="text-center text-gray-500 py-4">
</div>
) : (
<div className="max-h-60 overflow-auto">
{devices.map((device) => (
<div
key={device.id}
className="flex items-center justify-between p-2 hover:bg-gray-100 cursor-pointer"
onClick={() => toggleDeviceSelection(device)}
>
<div className="flex items-center space-x-2">
<Checkbox
checked={selectedDevices.some((d) => d.id === device.id)}
onCheckedChange={() => toggleDeviceSelection(device)}
/>
<span>{device.memo}</span>
</div>
<span className={`text-xs ${device.alive === 1 ? "text-green-500" : "text-gray-400"}`}>
{device.alive === 1 ? "在线" : "离线"}
</span>
<Input placeholder="搜索设备..." className="mb-2" />
<div className="max-h-60 overflow-auto">
{mockDevices.map((device) => (
<div
key={device.id}
className="flex items-center justify-between p-2 hover:bg-gray-100 cursor-pointer"
onClick={() => toggleDeviceSelection(device)}
>
<div className="flex items-center space-x-2">
<Checkbox
checked={selectedDevices.some((d) => d.id === device.id)}
onCheckedChange={() => toggleDeviceSelection(device)}
/>
<span>{device.name}</span>
</div>
))}
</div>
)}
<span className={`text-xs ${device.status === "online" ? "text-green-500" : "text-gray-400"}`}>
{device.status === "online" ? "在线" : "离线"}
</span>
</div>
))}
</div>
</div>
</div>
)}
</div>
{selectedDevices.length > 0 && (
<div className="mt-2 flex flex-wrap gap-2">
{selectedDevices.map((device) => (
<div key={device.id} className="flex items-center bg-gray-100 rounded-full px-3 py-1">
<span className="text-sm">{device.memo}</span>
<Button
variant="ghost"
size="sm"
className="ml-2 p-0"
onClick={() => toggleDeviceSelection(device)}
>
<AlertCircle className="h-4 w-4" />
</Button>
</div>
))}
</div>
)}
</div>
<div>
@@ -314,7 +239,7 @@ export function FriendRequestSettings({ formData, onChange, onNext, onPrev }: Fr
</div>
{hasWarnings && (
<Alert variant="destructive" className="bg-amber-50 border-amber-200">
<Alert variant="warning" className="bg-amber-50 border-amber-200">
<AlertCircle className="h-4 w-4 text-amber-500" />
<AlertDescription></AlertDescription>
</Alert>
@@ -347,7 +272,6 @@ export function FriendRequestSettings({ formData, onChange, onNext, onPrev }: Fr
</div>
</DialogContent>
</Dialog>
</div>
</Card>
)
}

View File

@@ -82,7 +82,7 @@ export function MessageSettings({ formData, onChange, onNext, onPrev }: MessageS
type: "text",
content: "",
sendInterval: 5,
intervalUnit: "minutes",
intervalUnit: "seconds", // 默认改为秒
},
],
},
@@ -103,7 +103,7 @@ export function MessageSettings({ formData, onChange, onNext, onPrev }: MessageS
if (dayPlans[dayIndex].day === 0) {
// 即时消息使用间隔设置
newMessage.sendInterval = 5
newMessage.intervalUnit = "minutes"
newMessage.intervalUnit = "seconds" // 默认改为秒
} else {
// 非即时消息使用具体时间设置
newMessage.scheduledTime = {
@@ -192,7 +192,7 @@ export function MessageSettings({ formData, onChange, onNext, onPrev }: MessageS
}
return (
<div className="w-full p-4 bg-gray-50">
<Card className="p-6">
<div className="space-y-6">
<div className="flex items-center justify-between">
<h2 className="text-lg font-semibold"></h2>
@@ -549,7 +549,6 @@ export function MessageSettings({ formData, onChange, onNext, onPrev }: MessageS
</DialogFooter>
</DialogContent>
</Dialog>
</div>
</Card>
)
}