From 61f5c545953bb4ee20b123bf9671ac35d7f1f3c1 Mon Sep 17 00:00:00 2001 From: "Somhairle H. Marisol" Date: Fri, 18 Sep 2026 12:03:32 +0800 Subject: [变更性质] feat(frontend) [新增功能] round3 页面组件全量迁移 shadcn-svelte(12 页面 + Modal/DatasetWizard/DatasetCard/Status) [实现方案] .btn→Button、.banner→Alert、table.data→Table.Root、.badge→Badge、.tabs→Tabs.Root、.metric-card/form.card→Card.Root;ProjectStrategyTab div 配对修复 [影响范围] src/pages/*.svelte、src/components/*.svelte MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/pages/AdminPage.svelte | 237 +++++++++++++++++++----------------- 1 file changed, 122 insertions(+), 115 deletions(-) (limited to 'frontend/src/pages/AdminPage.svelte') diff --git a/frontend/src/pages/AdminPage.svelte b/frontend/src/pages/AdminPage.svelte index 984962d..d9bea83 100644 --- a/frontend/src/pages/AdminPage.svelte +++ b/frontend/src/pages/AdminPage.svelte @@ -12,11 +12,20 @@ postAdminUserPassword } from '../lib/client'; import { extractStatusMessage } from '../lib/state'; + import { Button } from '$lib/components/ui/button'; + import { Input } from '$lib/components/ui/input'; + import { Alert } from '$lib/components/ui/alert'; + import { Badge } from '$lib/components/ui/badge'; + import { Label } from '$lib/components/ui/label'; + import * as Tabs from '$lib/components/ui/tabs'; + import * as Card from '$lib/components/ui/card'; + import * as Table from '$lib/components/ui/table'; import { fmtDateTime } from '../lib/format'; import type { User, Invitation } from '../lib/types'; let tab = $state<'users' | 'invites' | 'audit'>('users'); + let users: User[] = $state([]); let usersBusy = $state(true); let usersErr = $state(null); @@ -167,39 +176,41 @@ {#snippet actions()} -
- - - -
+ (tab = v as 'users' | 'invites' | 'audit')}> + + 用户 + 邀请与恢复 + 审计日志 + + {/snippet}
{#if tab === 'users'} -
+

用户

{#if !usersBusy && !usersErr && users.length > 0} - - - - - - - - - - - - - + + + + 邮箱 + 姓名 + 角色 + 状态 + AI 权限 + 日回测上限 + 操作 + + + {#each users as u (u.id)} - - - - - - - - - + + {/each} - -
邮箱姓名角色状态AI 权限日回测上限操作
{u.email}{u.name} + + {u.email} + {u.name} + - - {u.active ? '启用' : '停用'} - + + + {u.active ? '启用' : '停用'} + + - - + + void patchUser(u, { daily_run_limit: Number((e.target as HTMLInputElement).value) })} /> - + +
- - + +
-
+ + {/if}

停用账户会立即吊销其会话并阻止其回测与 AI 请求。角色不能作用于他人项目,私阅策略代码不提供。

-
+ {:else if tab === 'invites'} -
+

签发邀请

- - - +
+ + +
+
+ + +
+
{#if newInvite} - + {/if} -
+ -
+

历史邀请

{#if !inviteBusy && !inviteErr && invites.length === 0} {/if} {#if !inviteBusy && invites.length > 0} - - - - - - - - - - - - + + + + 邮箱备注 + 角色 + 创建时间 + 过期 + 状态 + + + + {#each invites as inv (inv.id)} - - - - - - - - + + {/each} - -
邮箱备注角色创建时间过期状态
{inv.email ?? '—'}{inv.role === 'admin' ? '管理员' : '成员'}{fmtDateTime(inv.created_at)}{fmtDateTime(inv.expires_at)} - {#if inv.used_at}已使用 - {:else if inv.revoked}已撤销 - {:else if inv.expires_at && new Date(inv.expires_at) < new Date()}已过期 - {:else}有效 + + {inv.email ?? '—'} + {inv.role === 'admin' ? '管理员' : '成员'} + {fmtDateTime(inv.created_at)} + {fmtDateTime(inv.expires_at)} + + {#if inv.used_at}已使用 + {:else if inv.revoked}已撤销 + {:else if inv.expires_at && new Date(inv.expires_at) < new Date()}已过期 + {:else}有效 {/if} - + + {#if !inv.used_at && !inv.revoked} - + {/if} -
+ + {/if}

恢复链接由“生成恢复”按钮产生,仅出现一次;不会自动发邮件。

-
+ {:else} -
+

安全审计(收尾尾部)

{#if !auditBusy && !auditErr && audit.length === 0} {/if} {#if !auditBusy && audit.length > 0} - - - - - - - - - - - + + + + 时间 + 行为者 + 事件 + 对象 + 结果 + + + {#each audit as e, i (i)} - - - - - - - + + {fmtDateTime(e.time)} + {e.actor ?? '—'} + {e.action} + {e.target ?? '—'} + {e.status} + {/each} - -
时间行为者事件对象结果
{fmtDateTime(e.time)}{e.actor ?? '—'}{e.action}{e.target ?? '—'}{e.status}
+ + {/if}

审计仅记录操作行为与结果,不含密码/密钥/策略代码内容。

-
+ {/if}
{#if resetFor} (resetFor = null)}>
- +

单次有效、限时;重置会吊销对方的全部历史会话。

-- cgit v1.2.3