实现权限列表与权限渲染组件

This commit is contained in:
2026-03-31 10:56:01 +08:00
parent 2c7970796f
commit 12b60e74df
7 changed files with 94 additions and 3 deletions

View File

@@ -16,7 +16,7 @@ export async function login(params: {
username: string
password: string
remember: boolean
}): Promise<ApiResponse> {
}): Promise<ApiResponse<string[]>> {
const resp = await callByDevice<TokenResp>("/api/auth/token", {
grant_type: "password",
login_type: "password",
@@ -43,7 +43,7 @@ export async function login(params: {
return {
success: true,
data: undefined,
data: data.scope?.split(" ") || [],
}
}

View File

@@ -1,5 +1,6 @@
"use client"
import { zodResolver } from "@hookform/resolvers/zod"
import { useSetAtom } from "jotai"
import { useRouter } from "next/navigation"
import { Controller, useForm } from "react-hook-form"
import { toast } from "sonner"
@@ -16,6 +17,7 @@ import {
FieldLegend,
} from "@/components/ui/field"
import { Input } from "@/components/ui/input"
import { scopesAtom } from "@/lib/stores/scopes"
const schema = z.object({
username: z.string().min(4).max(50),
@@ -36,7 +38,7 @@ export default function LoginPage() {
})
const router = useRouter()
const setScopes = useSetAtom(scopesAtom)
const onSubmit = async (data: Schema) => {
try {
const resp = await login(data)
@@ -45,6 +47,8 @@ export default function LoginPage() {
}
// 登录成功后跳转到首页
console.log("用户权限列表", resp.data)
setScopes(resp.data)
router.push("/")
} catch (e) {
toast.error("登录失败", {

View File

@@ -0,0 +1,13 @@
import { useAtomValue } from "jotai"
import type { ReactNode } from "react"
import { scopesAtom } from "@/lib/stores/scopes"
export function Auth(props: { scope: string; children: ReactNode }) {
const scopes = useAtomValue(scopesAtom)
if (!scopes.length) return props.children
const hasScope = scopes.some(s => props.scope.startsWith(s))
if (!hasScope) return null
return props.children
}

65
src/lib/scopes.ts Normal file
View File

@@ -0,0 +1,65 @@
// 权限
export const ScopePermission = "permission";
export const ScopePermissionRead = "permission:read"; // 读取权限列表
export const ScopePermissionWrite = "permission:write"; // 写入权限
// 管理员角色
export const ScopeAdminRole = "admin_role";
export const ScopeAdminRoleRead = "admin_role:read"; // 读取管理员角色列表
export const ScopeAdminRoleWrite = "admin_role:write"; // 写入管理员角色
// 管理员
export const ScopeAdmin = "admin";
export const ScopeAdminRead = "admin:read"; // 读取管理员列表
export const ScopeAdminWrite = "admin:write"; // 写入管理员
// 产品
export const ScopeProduct = "product";
export const ScopeProductRead = "product:read"; // 读取产品列表
export const ScopeProductWrite = "product:write"; // 写入产品
// 产品套餐
export const ScopeProductSku = "product_sku";
export const ScopeProductSkuRead = "product_sku:read"; // 读取产品套餐列表
export const ScopeProductSkuWrite = "product_sku:write"; // 写入产品套餐
// 折扣
export const ScopeDiscount = "discount";
export const ScopeDiscountRead = "discount:read"; // 读取折扣列表
export const ScopeDiscountWrite = "discount:write"; // 写入折扣
// 用户套餐
export const ScopeResource = "resource";
export const ScopeResourceRead = "resource:read"; // 读取用户套餐列表
export const ScopeResourceWrite = "resource:write"; // 写入用户套餐
// 用户
export const ScopeUser = "user";
export const ScopeUserRead = "user:read"; // 读取用户列表
export const ScopeUserWrite = "user:write"; // 写入用户
export const ScopeUserWriteBalance = "user:write:balance"; // 写入用户余额
// 优惠券
export const ScopeCoupon = "coupon";
export const ScopeCouponRead = "coupon:read"; // 读取优惠券列表
export const ScopeCouponWrite = "coupon:write"; // 写入优惠券
// 批次
export const ScopeBatch = "batch";
export const ScopeBatchRead = "batch:read"; // 读取批次列表
export const ScopeBatchWrite = "batch:write"; // 写入批次
// IP
export const ScopeChannel = "channel";
export const ScopeChannelRead = "channel:read"; // 读取 IP 列表
export const ScopeChannelWrite = "channel:write"; // 写入 IP
// 交易
export const ScopeTrade = "trade";
export const ScopeTradeRead = "trade:read"; // 读取交易列表
export const ScopeTradeWrite = "trade:write"; // 写入交易
// 账单
export const ScopeBill = "bill";
export const ScopeBillRead = "bill:read"; // 读取账单列表
export const ScopeBillWrite = "bill:write"; // 写入账单

5
src/lib/stores/scopes.ts Normal file
View File

@@ -0,0 +1,5 @@
import { atom } from "jotai"
const scopesAtom = atom<string[]>([])
export { scopesAtom }