补充个人中心下的页面
This commit is contained in:
@@ -1,5 +1,127 @@
|
||||
import { Lock, Trash2, Unlock } from "lucide-react"
|
||||
import { useState } from "react"
|
||||
import DataTable from "@/components/data-table"
|
||||
import Page from "@/components/page"
|
||||
import { Badge } from "@/components/ui/badge"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Input } from "@/components/ui/input"
|
||||
import type { WhiteIpItem } from "@/lib/models/whitelist"
|
||||
|
||||
// TODO: 后端白名单接口就绪后,将 saveWhiteIp/fetchWhiteList 接入(见 src/api/whitelist.ts)
|
||||
|
||||
export default function WhitelistPage() {
|
||||
return <Page>白名单</Page>
|
||||
const [ip, setIp] = useState("")
|
||||
const [list, setList] = useState<WhiteIpItem[]>([])
|
||||
|
||||
const handleSave = () => {
|
||||
const value = ip.trim()
|
||||
if (!value) return
|
||||
// TODO: await saveWhiteIp(value)
|
||||
setList(prev => [
|
||||
{ id: Date.now(), ip: value, createTime: "", isLocked: "未锁定" },
|
||||
...prev,
|
||||
])
|
||||
setIp("")
|
||||
}
|
||||
|
||||
return (
|
||||
<Page>
|
||||
<div className="bg-white rounded-lg p-4">
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center gap-3">
|
||||
<Input
|
||||
value={ip}
|
||||
onChange={e => setIp(e.target.value)}
|
||||
onKeyDown={e => e.key === "Enter" && handleSave()}
|
||||
placeholder="请输入IP地址并点击保存白名单"
|
||||
className="max-w-sm"
|
||||
/>
|
||||
<Button onClick={handleSave}>保存</Button>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-3">
|
||||
<h3 className="font-semibold text-lg">当前白名单列表</h3>
|
||||
<Badge variant="secondary" className="text-yellow-600">
|
||||
当前仅允许保留白名单数量:5个
|
||||
</Badge>
|
||||
</div>
|
||||
|
||||
<DataTable<WhiteIpItem>
|
||||
data={list}
|
||||
status="done"
|
||||
columns={[
|
||||
{
|
||||
accessorKey: "ip",
|
||||
header: "IP地址",
|
||||
},
|
||||
{
|
||||
accessorKey: "createTime",
|
||||
header: "设置时间",
|
||||
},
|
||||
{
|
||||
accessorKey: "isLocked",
|
||||
header: "锁定状态",
|
||||
cell: ({ row }) => {
|
||||
const isLocked = row.original.isLocked === "已锁定"
|
||||
return (
|
||||
<Badge variant={isLocked ? "destructive" : "outline"}>
|
||||
{row.original.isLocked}
|
||||
</Badge>
|
||||
)
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "actions",
|
||||
header: "操作",
|
||||
cell: ({ row }) => {
|
||||
const item = row.original
|
||||
// TODO: 接入 lockWhiteIp / deleteWhiteIp
|
||||
return (
|
||||
<div className="flex gap-2">
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() =>
|
||||
setList(prev =>
|
||||
prev.map(i =>
|
||||
i.id === item.id
|
||||
? {
|
||||
...i,
|
||||
isLocked:
|
||||
i.isLocked === "未锁定"
|
||||
? "已锁定"
|
||||
: "未锁定",
|
||||
}
|
||||
: i,
|
||||
),
|
||||
)
|
||||
}
|
||||
>
|
||||
{item.isLocked === "未锁定" ? (
|
||||
<Lock className="mr-1 h-3 w-3" />
|
||||
) : (
|
||||
<Unlock className="mr-1 h-3 w-3" />
|
||||
)}
|
||||
{item.isLocked === "未锁定" ? "锁定" : "解锁"}
|
||||
</Button>
|
||||
<Button
|
||||
variant="destructive"
|
||||
size="sm"
|
||||
onClick={() =>
|
||||
setList(prev => prev.filter(i => i.id !== item.id))
|
||||
}
|
||||
>
|
||||
<Trash2 className="mr-1 h-3 w-3" />
|
||||
删除
|
||||
</Button>
|
||||
</div>
|
||||
)
|
||||
},
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</Page>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user