添加了快照功能支持,支持定时快照和回滚快照

This commit is contained in:
MengMengCode
2026-06-06 09:24:19 +08:00
parent bb8a646de7
commit a9784539ea
17 changed files with 1352 additions and 40 deletions
@@ -24,6 +24,7 @@ const defaultForm: CreateContainerRequest = {
io_speed_mbps: 0,
extra_ports: [],
port_mapping_count: 2,
snapshot_limit: 3,
assign_ipv6: false,
expires_at: '',
}
@@ -94,7 +95,13 @@ export default function CreateContainerModal({ isOpen, onClose, onSuccess }: Cre
const containers: CreateContainerRequest[] = []
for (let i = 0; i < batchCount; i++) {
const name = batchCount > 1 ? `${boundedForm.name}-${i + 1}` : boundedForm.name
containers.push({ ...boundedForm, name, port_mapping_count: Math.max(2, boundedForm.port_mapping_count || 2), extra_ports: [] })
containers.push({
...boundedForm,
name,
port_mapping_count: Math.max(2, boundedForm.port_mapping_count || 2),
snapshot_limit: Math.max(1, boundedForm.snapshot_limit || 3),
extra_ports: [],
})
}
setLoading(true)
@@ -248,6 +255,15 @@ export default function CreateContainerModal({ isOpen, onClose, onSuccess }: Cre
</div>
</Field>
<Field label="子用户快照上限">
<NumberInput
value={form.snapshot_limit}
min={1}
max={999}
onChange={(value) => setForm({ ...form, snapshot_limit: Math.max(1, Math.round(value || 1)) })}
/>
</Field>
<Field label="到期时间">
<div className="relative">
<CalendarClock className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-gray-400" />
@@ -325,6 +341,7 @@ function clampCreateForm(form: CreateContainerRequest, maxVCPU: number, maxRAMMB
vcpu: clampVCPU(form.vcpu, maxVCPU),
ram_mb: clampInt(form.ram_mb, 128, maxRAMMB, 512),
disk_gb: clampInt(form.disk_gb, 1, maxDiskGB, 10),
snapshot_limit: clampInt(form.snapshot_limit, 1, undefined, 3),
}
}
+14
View File
@@ -3,6 +3,7 @@ import {
ChevronLeft,
ChevronRight,
Code2,
Camera,
LayoutDashboard,
LogOut,
Package,
@@ -31,6 +32,7 @@ export default function Sidebar({ collapsed, onToggle }: SidebarProps) {
const isImagesPage = location.pathname.startsWith('/images')
const isOversellPage = location.pathname.startsWith('/oversell')
const isSnapshotsPage = location.pathname.startsWith('/snapshots')
const isAuditLogsPage = location.pathname.startsWith('/audit-logs')
const isApiIntegrationPage = location.pathname.startsWith('/api-integration')
const isSecurityPage = location.pathname.startsWith('/security')
@@ -136,6 +138,18 @@ export default function Sidebar({ collapsed, onToggle }: SidebarProps) {
{!collapsed && <span></span>}
</button>
<button
onClick={() => navigate('/snapshots')}
className={`w-full flex items-center gap-3 px-3 py-2.5 rounded-md text-sm transition-colors ${
isSnapshotsPage
? 'bg-black text-white'
: 'text-gray-700 hover:bg-gray-100'
}`}
>
<Camera className="w-4 h-4" />
{!collapsed && <span></span>}
</button>
<button
onClick={() => navigate('/audit-logs')}
className={`w-full flex items-center gap-3 px-3 py-2.5 rounded-md text-sm transition-colors ${