feat(roles): role management pages (super-admin)

- /roles — role table with create dialog and a permission-matrix sheet:
  collapsible per-module sections (selected/total counts, role's own
  modules start expanded) and a key/description filter that force-
  expands matches; super-admin role is read-only
- /admin-users — user search (Enter to run) with role assignment
  dialog; editing your own roles is blocked

Both nav items gate on auth:role:* keys, which only super-admin holds.

Co-Authored-By: Claude Fable 5 <[email protected]>
This commit is contained in:
2026-07-12 06:42:51 +08:00
co-authored by Claude Fable 5
parent 46056ae4b0
commit ddfec7258f
5 changed files with 768 additions and 0 deletions
+88
View File
@@ -352,6 +352,94 @@ export interface RetranslateResult {
queued_blocks: number
}
export interface AdminRole {
kind?: string
name: string
permissions: string[]
users_count: number
builtin: boolean
}
/** module → { module, groups: { group → { permissionKey → description } } } */
export type PermissionCatalog = Record<
string,
{ module: string; groups: Record<string, Record<string, string>> }
>
export interface RoleUser {
kind?: string
uid: string
display_name?: string | null
email?: string | null
username?: string | null
roles: string[]
}
export type DimzouDocumentState = 'active' | 'archived' | 'trashed'
export interface DimzouDocumentVersion {
id: number
document_id: number
version_number: number
status: 'draft' | 'published' | 'superseded'
visibility?: 'public' | 'group_only'
structured_title?: unknown
language?: string | null
publication_id?: number | null
published_at?: string | null
frozen_at?: string | null
created_at?: string
updated_at?: string
}
export interface DimzouDocument {
kind?: string
id: number
title?: string | null
owner?: ReportUser | null
category?: { id: string; name?: string | null } | null
state: DimzouDocumentState
versions_count: number
published_version?: number | null
draft_version?: number | null
archived_at?: string | null
deleted_at?: string | null
created_at?: string
updated_at?: string
// detail-only
versions?: DimzouDocumentVersion[]
translations?: Array<{
id: number
language_code: string
status: DimzouTranslationStatus
translated_document_id: number
created_by_uid: string
created_at?: string
}>
pending_revisions_count?: number
pending_join_requests_count?: number
}
export interface DimzouPublication {
kind?: string
id: number
document_id: number
document_version_id: number
version_number: number
visibility: 'public' | 'group_only'
title?: string | null
summary?: string | null
cover_image?: unknown
language?: string | null
keywords?: string[]
feed_card?: unknown
author_headline?: string | null
published_at?: string | null
block_count?: number
author?: ReportUser | null
category?: { id: string; name?: string | null } | null
}
// --- Exc 专长交易(只读监控)---
export interface ExcUser {