CaiWuXiTong/app/Utilities/SidebarPermissions.php
renshen 813e956df5 应付款终版目录接入独立按表数据
两个「终版」目录(供应商应付(终版)、快递应付(终版))改为独立数据:
保留原有导入、导出、查询、重置、编辑按钮和导入模板,数据初始为空、按表独立存放,
不再借用基础目录的页面与数据。

- 终版目录拥有自己的同名子页面与横向页签
- 新增终版按表数据的独立导入/导出/模板/编辑接口(数据集键 final:<目录>:<页面>)
- 供应商终版 13 个页面、快递终版 4 个页面已接入
- 终版导入模板统一增加“月份”列,记录标识列改为选填
2026-09-29 11:06:41 +08:00

191 lines
6.4 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace App\Utilities;
use App\Models\Auth\User;
use App\Models\Auth\UserAccessGroup;
class SidebarPermissions
{
private const LEGACY_PAGE_KEYS = [
'refunds/small-payment-work-orders' => '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) {
$normalized[] = $finalSectionKey;
} elseif (str_starts_with($normalizedKey, $sectionKey . '/')) {
// 「终版」目录已是独立目录,按同样的子页面粒度跟着授权。
$normalized[] = $finalSectionKey . substr($normalizedKey, strlen($sectionKey));
}
}
if ($key === 'refunds') {
$normalized[] = self::LEGACY_PAGE_KEYS['refunds/small-payment-work-orders'];
}
}
return array_values(array_unique($normalized));
}
}