feat(shared): update permissions system, i18n, hooks, and components
- Update permission-bitmap.ts, permissions.ts, resolve-action-error.ts - Update types/permissions.ts - Update rbac i18n messages (en, zh-CN) - Update locale-switcher.tsx - Update use-action-with-toast.ts hook
This commit is contained in:
@@ -4,7 +4,7 @@ import * as React from "react"
|
||||
import { useTransition } from "react"
|
||||
import { useLocale, useTranslations } from "next-intl"
|
||||
import { Check, Globe } from "lucide-react"
|
||||
import { toast } from "sonner"
|
||||
import { notify } from "@/shared/lib/notify"
|
||||
|
||||
import { Button } from "@/shared/components/ui/button"
|
||||
import {
|
||||
@@ -35,9 +35,9 @@ export function LocaleSwitcher({ compact = false }: { compact?: boolean }) {
|
||||
startTransition(async () => {
|
||||
const result = await setLocaleAction(next)
|
||||
if (result.success) {
|
||||
toast.success(t("switch"))
|
||||
notify.success(t("switch"))
|
||||
} else {
|
||||
toast.error(t("switch"))
|
||||
notify.error(t("switch"))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"use client"
|
||||
|
||||
import { useTransition } from "react"
|
||||
import { toast } from "sonner"
|
||||
import { notify } from "@/shared/lib/notify"
|
||||
import type { ActionState } from "@/shared/types/action-state"
|
||||
|
||||
export function useActionWithToast<T>() {
|
||||
@@ -11,9 +11,9 @@ export function useActionWithToast<T>() {
|
||||
startTransition(async () => {
|
||||
const result = await action()
|
||||
if (result.success) {
|
||||
toast.success(result.message || "操作成功")
|
||||
notify.success(result.message || "操作成功")
|
||||
} else {
|
||||
toast.error(result.message || "操作失败")
|
||||
notify.error(result.message || "操作失败")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -173,7 +173,11 @@
|
||||
},
|
||||
"audit": {
|
||||
"read": "Read Audit Logs",
|
||||
"readDesc": "Allows viewing system audit logs"
|
||||
"readDesc": "Allows viewing system audit logs",
|
||||
"purge": "Purge Audit Logs",
|
||||
"purgeDesc": "Physically delete expired audit logs (destructive, admin only)",
|
||||
"retentionManage": "Manage Audit Retention",
|
||||
"retentionManageDesc": "Configure audit log retention days and auto-cleanup rules"
|
||||
},
|
||||
"announcement": {
|
||||
"manage": "Manage Announcements",
|
||||
|
||||
@@ -173,7 +173,11 @@
|
||||
},
|
||||
"audit": {
|
||||
"read": "查看审计日志",
|
||||
"readDesc": "允许查看系统审计日志"
|
||||
"readDesc": "允许查看系统审计日志",
|
||||
"purge": "清理审计日志",
|
||||
"purgeDesc": "物理删除过期审计日志(破坏性操作,仅管理员)",
|
||||
"retentionManage": "管理审计保留策略",
|
||||
"retentionManageDesc": "配置审计日志保留天数与自动清理规则"
|
||||
},
|
||||
"announcement": {
|
||||
"manage": "管理公告",
|
||||
|
||||
@@ -91,6 +91,8 @@ export const PERMISSION_BITMAP_ORDER: readonly Permission[] = [
|
||||
Permissions.SETTINGS_ADMIN,
|
||||
// Audit
|
||||
Permissions.AUDIT_LOG_READ,
|
||||
Permissions.AUDIT_LOG_PURGE,
|
||||
Permissions.AUDIT_RETENTION_MANAGE,
|
||||
// Announcement
|
||||
Permissions.ANNOUNCEMENT_MANAGE,
|
||||
Permissions.ANNOUNCEMENT_READ,
|
||||
|
||||
@@ -48,6 +48,8 @@ export const ROLE_PERMISSIONS_SEED: Record<BuiltinRole, Permission[]> = {
|
||||
Permissions.AI_CONFIGURE,
|
||||
Permissions.SETTINGS_ADMIN,
|
||||
Permissions.AUDIT_LOG_READ,
|
||||
Permissions.AUDIT_LOG_PURGE,
|
||||
Permissions.AUDIT_RETENTION_MANAGE,
|
||||
Permissions.ANNOUNCEMENT_MANAGE,
|
||||
Permissions.ANNOUNCEMENT_READ,
|
||||
Permissions.GRADE_RECORD_MANAGE,
|
||||
|
||||
@@ -15,7 +15,7 @@ import type { ActionState } from "@/shared/types/action-state"
|
||||
* ```tsx
|
||||
* const t = useTranslations("attendance")
|
||||
* const msg = resolveActionError(result, t, t("errors.unexpected"))
|
||||
* toast.error(msg)
|
||||
* notify.error(msg)
|
||||
* ```
|
||||
*/
|
||||
export function resolveActionError<T>(
|
||||
|
||||
@@ -110,6 +110,10 @@ export const Permissions = {
|
||||
|
||||
// Audit
|
||||
AUDIT_LOG_READ: "audit_log:read",
|
||||
/** 审计日志清理(物理删除)—— 破坏性操作,仅 admin */
|
||||
AUDIT_LOG_PURGE: "audit_log:purge",
|
||||
/** 审计日志保留策略管理(配置保留天数、自动清理规则) */
|
||||
AUDIT_RETENTION_MANAGE: "audit_retention:manage",
|
||||
|
||||
// Announcement
|
||||
ANNOUNCEMENT_MANAGE: "announcement:manage",
|
||||
@@ -210,6 +214,17 @@ export const Permissions = {
|
||||
|
||||
export type Permission = (typeof Permissions)[keyof typeof Permissions]
|
||||
|
||||
/** 所有合法的权限值列表(用于运行时校验) */
|
||||
const PERMISSION_VALUES = Object.values(Permissions) as readonly string[]
|
||||
|
||||
/**
|
||||
* 类型守卫:判断值是否为合法的 Permission。
|
||||
* 用于从 string[] 安全收窄到 Permission[],替代 `as Permission[]` 断言。
|
||||
*/
|
||||
export function isPermission(value: unknown): value is Permission {
|
||||
return typeof value === "string" && PERMISSION_VALUES.includes(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* Data scope for row-level security.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user