PA6 补齐权限与审计回归
这个提交包含在:
@@ -2,11 +2,8 @@ import { NavLink } from "react-router-dom";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { fetchWorkflowTasks } from "../../api/workflow";
|
||||
import { useAuth } from "../../auth/AuthContext";
|
||||
import { hasAnyPermission } from "../../auth/permissions";
|
||||
import {
|
||||
MOBILE_APPROVAL_PERMISSIONS,
|
||||
MOBILE_NAV_ITEMS,
|
||||
} from "../../features/mobile/navigation";
|
||||
import { hasAnyPermission, hasBusinessApproverRole } from "../../auth/permissions";
|
||||
import { MOBILE_NAV_ITEMS } from "../../features/mobile/navigation";
|
||||
import { cn } from "../../lib/utils";
|
||||
import { MobileIcon } from "./MobileIcon";
|
||||
|
||||
@@ -18,8 +15,8 @@ function resolveBadgeLabel(count: number) {
|
||||
}
|
||||
|
||||
export function MobileBottomNav() {
|
||||
const { permissions } = useAuth();
|
||||
const canAccessApprovals = hasAnyPermission(permissions, [...MOBILE_APPROVAL_PERMISSIONS]);
|
||||
const { me, permissions } = useAuth();
|
||||
const canAccessApprovals = hasBusinessApproverRole(me?.roleCodes, permissions);
|
||||
|
||||
const pendingCountQuery = useQuery({
|
||||
enabled: canAccessApprovals,
|
||||
@@ -40,7 +37,11 @@ export function MobileBottomNav() {
|
||||
>
|
||||
<div className="relative z-[71] grid grid-cols-4 gap-1">
|
||||
{MOBILE_NAV_ITEMS.map((item) => {
|
||||
const disabled = item.anyOf ? !hasAnyPermission(permissions, [...item.anyOf]) : false;
|
||||
const disabled = item.key === "approvals"
|
||||
? !canAccessApprovals
|
||||
: item.anyOf
|
||||
? !hasAnyPermission(permissions, [...item.anyOf])
|
||||
: false;
|
||||
const badge = item.key === "approvals" && pendingCount > 0 ? resolveBadgeLabel(pendingCount) : null;
|
||||
|
||||
if (disabled) {
|
||||
|
||||
@@ -2,7 +2,7 @@ import { NavLink } from "react-router-dom";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { fetchSystemNavigation, type NavigationItem } from "../../api/workspace";
|
||||
import { useAuth } from "../../auth/AuthContext";
|
||||
import { hasAnyPermission } from "../../auth/permissions";
|
||||
import { hasAnyPermission, hasBusinessApproverRole, hasFinanceRole } from "../../auth/permissions";
|
||||
import {
|
||||
ADMIN_NAV_ORDER,
|
||||
BACKUP_NAV_ORDER,
|
||||
@@ -32,7 +32,7 @@ export const NAV_ITEMS: NavItem[] = [
|
||||
{ to: "/people", label: "人员管理", icon: "group", anyOf: ["system.users", "report.dashboard.view"] },
|
||||
{ to: "/organization", label: "组织架构", icon: "account_tree", anyOf: ["system.users", "report.dashboard.view"] },
|
||||
{ to: "/system/workflow-definitions", label: "流程定义", icon: "schema", anyOf: ["system.settings"] },
|
||||
{ to: "/system/settings", label: "系统设置", icon: "settings", anyOf: ["system.settings", "system.users", "masterdata.view", "masterdata.manage", "notification.channel.manage", "integration.manage"] },
|
||||
{ to: "/system/settings", label: "系统设置", icon: "settings", anyOf: ["system.settings", "system.users", "masterdata.manage", "notification.channel.manage", "integration.manage"] },
|
||||
{ to: "/system/feature-flags", label: "功能开关", icon: "toggle_on", anyOf: ["system.settings"] },
|
||||
{ to: "/audit-logs", label: "审计日志", icon: "manage_search", anyOf: ["system.audit.view"] },
|
||||
{ to: "/workflow/tasks", label: "审批待办", icon: "fact_check", anyOf: ["expense.approve", "leave.approve", "procurement.approve", "travel.approve"] },
|
||||
@@ -136,9 +136,12 @@ function renderBackupSection(items: ResolvedNavItem[], onNavigate?: () => void)
|
||||
);
|
||||
}
|
||||
|
||||
function buildFallbackItems(permissions: string[]) {
|
||||
function buildFallbackItems(permissions: string[], roleCodes: string[]) {
|
||||
const financeOnlyPaths = new Set(["/payment-batches", "/ap-operations", "/invoice-pool"]);
|
||||
const mapItems = (paths: string[]) =>
|
||||
NAV_ITEMS.filter((item) => paths.includes(item.to))
|
||||
.filter((item) => item.to !== "/workflow/tasks" || hasBusinessApproverRole(roleCodes, permissions))
|
||||
.filter((item) => !financeOnlyPaths.has(item.to) || hasFinanceRole(roleCodes, permissions))
|
||||
.filter((item) => !item.anyOf || hasAnyPermission(permissions, item.anyOf))
|
||||
.map((item) => ({ key: item.to, href: item.to, label: item.label, icon: item.icon }));
|
||||
|
||||
@@ -184,7 +187,7 @@ function normalizeSections(sections: { main: NavigationItem[]; admin: Navigation
|
||||
}
|
||||
|
||||
export function NavLinks({ onNavigate }: { onNavigate?: () => void }) {
|
||||
const { permissions } = useAuth();
|
||||
const { me, permissions } = useAuth();
|
||||
const navigationQuery = useQuery({
|
||||
queryKey: ["system-navigation"],
|
||||
queryFn: fetchSystemNavigation,
|
||||
@@ -193,7 +196,7 @@ export function NavLinks({ onNavigate }: { onNavigate?: () => void }) {
|
||||
|
||||
const sections = navigationQuery.data?.sections
|
||||
? normalizeSections(navigationQuery.data.sections)
|
||||
: buildFallbackItems(permissions);
|
||||
: buildFallbackItems(permissions, me?.roleCodes ?? []);
|
||||
|
||||
return (
|
||||
<nav className="space-y-5">
|
||||
|
||||
在新工单中引用
屏蔽一个用户