'financial-operations/small-payment-work-orders', ]; private const FINAL_SECTION_KEYS = [ 'supplier-payables' => 'supplier-payables-final', 'courier-payables' => 'courier-payables-final', ]; public static function settings(): array { $value = setting('system.sidebar_permissions', []); if (is_string($value)) { $value = json_decode($value, true) ?: []; } return is_array($value) ? $value : []; } public static function subjectKey(User $user): string { $userKey = 'user_' . $user->id; $settings = self::settings(); if (in_array($userKey, $settings['configured'] ?? [], true)) { return $userKey; } return 'role_' . SystemAccess::roleName($user); } public static function allowedKeys(User $user): ?array { if (SystemAccess::isSuperAdmin($user)) { return null; } $settings = self::settings(); $userSubject = 'user_' . $user->id; if (in_array($userSubject, $settings['configured'] ?? [], true)) { return self::normalizeAllowedKeys((array) ($settings['subjects'][$userSubject] ?? [])); } $groups = UserAccessGroup::forUser($user); if ($groups->isNotEmpty()) { return self::normalizeAllowedKeys( $groups->flatMap(fn ($group) => $group->page_permissions ?? [])->all() ); } $subject = 'role_' . SystemAccess::roleName($user); if (! in_array($subject, $settings['configured'] ?? [], true)) { return null; } return self::normalizeAllowedKeys((array) ($settings['subjects'][$subject] ?? [])); } public static function navigationFor(User $user): array { $navigation = BusinessNavigation::all(); $allowed = self::allowedKeys($user); if ($allowed === null) { return $navigation; } $navigation = array_values(array_filter(array_map(function (array $section) use ($allowed) { $sectionKey = $section['slug']; if (in_array($sectionKey, $allowed, true)) { return $section; } $pages = array_values(array_filter(array_map(function (array $page) use ($allowed, $sectionKey) { $pageKey = $sectionKey . '/' . $page['slug']; if (in_array($pageKey, $allowed, true)) { // 若有 children,保留 children 的精确权限过滤 if (! empty($page['children'])) { $page['children'] = array_values(array_filter($page['children'], function (array $child) use ($allowed, $sectionKey) { return in_array($sectionKey . '/' . $child['slug'], $allowed, true); })); } return $page; } // 子页面可能在 allowed 列表中(独立 URL),父级分组也允许展开 if (! empty($page['children'])) { $visibleChildren = array_values(array_filter($page['children'], function (array $child) use ($allowed, $sectionKey) { return in_array($sectionKey . '/' . $child['slug'], $allowed, true); })); if (! empty($visibleChildren)) { $page['children'] = $visibleChildren; return $page; } } return null; }, $section['pages'] ?? []))); if (! empty($pages)) { $section['pages'] = $pages; return $section; } return null; }, $navigation))); // 新增的公司成本安排与主体经营报表共用公司经营报表权限。 // 对已经保存过精确权限的账号兼容旧配置,避免新增页面被旧权限集合隐藏。 foreach ($navigation as &$section) { if (($section['slug'] ?? null) !== 'company-management') { continue; } $hasSubjectReport = collect($section['pages'] ?? [])->contains('slug', 'subject-operating-report'); $hasCostArrangement = collect($section['pages'] ?? [])->contains('slug', 'company-cost-arrangement'); if ($hasSubjectReport && ! $hasCostArrangement) { $costPage = collect(BusinessNavigation::all()) ->firstWhere('slug', 'company-management')['pages'] ?? []; $costPage = collect($costPage)->firstWhere('slug', 'company-cost-arrangement'); if ($costPage) { $section['pages'][] = $costPage; } } } unset($section); return $navigation; } public static function allKeys(): array { $keys = []; foreach (BusinessNavigation::all() as $section) { $keys[] = $section['slug']; foreach ($section['pages'] ?? [] as $page) { $keys[] = $section['slug'] . '/' . $page['slug']; foreach ($page['children'] ?? [] as $child) { $keys[] = $section['slug'] . '/' . $child['slug']; } } } return $keys; } public static function normalizeAllowedKeys(array $keys): array { $normalized = []; foreach ($keys as $key) { $key = (string) $key; $normalizedKey = self::LEGACY_PAGE_KEYS[$key] ?? $key; $normalized[] = $normalizedKey; foreach (self::FINAL_SECTION_KEYS as $sectionKey => $finalSectionKey) { if ($normalizedKey === $sectionKey || str_starts_with($normalizedKey, $sectionKey . '/')) { $normalized[] = $finalSectionKey; } } if ($key === 'refunds') { $normalized[] = self::LEGACY_PAGE_KEYS['refunds/small-payment-work-orders']; } } return array_values(array_unique($normalized)); } }