feat(平台端): 园区列表支持 状态显示/禁用启用/级联删除
园区管理每园显示状态(启用/已禁用);可【禁用】(不删,禁止园区端登录/data)【启用】【删除】; 删除为联级:后端 delete_tenant 一并删 企业/知识库/屏幕 + 引擎缓存;禁用后 /park/auth/login 返回 403。 npm run build 通过。
This commit is contained in:
@@ -20,6 +20,8 @@ export const parkApi = {
|
||||
api.put<{ ok: boolean; tenant: Tenant }>(`/park/tenants/${tid}`, body),
|
||||
bindAdmin: (tid: string, username: string) => api.post<{ ok: boolean }>(`/park/tenants/${tid}/bind`, { username }),
|
||||
unbindAdmin: (tid: string) => api.post<{ ok: boolean }>(`/park/tenants/${tid}/unbind`),
|
||||
deleteTenant: (tid: string) => api.del<{ ok: boolean }>(`/park/tenants/${tid}`),
|
||||
setTenantStatus: (tid: string, status: "active" | "disabled") => api.post<{ ok: boolean }>(`/park/tenants/${tid}/status`, { status }),
|
||||
|
||||
// ---- 大屏控制台 ----
|
||||
displayState: (tenantId: string) => api.get<DisplayState>("/park/api/display/state", { tenant_id: tenantId }),
|
||||
|
||||
@@ -47,6 +47,13 @@ export function TenantTab() {
|
||||
if (!window.confirm(`解除「${t.name}」的管理员绑定?`)) return;
|
||||
await parkApi.unbindAdmin(t.id); reload();
|
||||
};
|
||||
const toggle = async (t: Tenant) => {
|
||||
await parkApi.setTenantStatus(t.id, t.status === "disabled" ? "active" : "disabled"); reload();
|
||||
};
|
||||
const remove = async (t: Tenant) => {
|
||||
if (!window.confirm(`确认删除园区「${t.name}」?将一并删除其全部资源(屏幕/企业/知识库/智能体/大屏数据)且不可恢复!`)) return;
|
||||
await parkApi.deleteTenant(t.id); reload();
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
@@ -70,13 +77,16 @@ export function TenantTab() {
|
||||
<div>
|
||||
<span className="font-medium">{t.name}</span>
|
||||
<span className="ml-2 text-xs text-muted-foreground">{t.id}</span>
|
||||
<span className={`ml-2 text-xs ${t.status === "disabled" ? "text-destructive" : "text-emerald-600"}`}>{t.status === "disabled" ? "已禁用" : "启用"}</span>
|
||||
<div className="text-xs text-muted-foreground">管理员:{t.admin_username || "(未绑定)"}</div>
|
||||
<div className="text-xs text-muted-foreground">{(t.intro ?? []).join(" · ")}</div>
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
{t.admin_username
|
||||
? <Button size="sm" variant="ghost" className="text-destructive" onClick={() => unbind(t)}>解除绑定</Button>
|
||||
? <Button size="sm" variant="ghost" onClick={() => unbind(t)}>解除绑定</Button>
|
||||
: <Button size="sm" variant="outline" onClick={() => openBind(t)}>绑定管理员</Button>}
|
||||
<Button size="sm" variant="outline" onClick={() => toggle(t)}>{t.status === "disabled" ? "启用" : "禁用"}</Button>
|
||||
<Button size="sm" variant="ghost" className="text-destructive" onClick={() => remove(t)}>删除</Button>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
|
||||
Reference in New Issue
Block a user