更新bug

This commit is contained in:
Your Name
2026-08-17 09:06:49 +08:00
parent 2fc8048844
commit c1eee2d28a
48 changed files with 3646 additions and 1016 deletions
@@ -0,0 +1,56 @@
<?php
declare(strict_types=1);
use app\adminapi\logic\auth\AdminLogic;
use app\common\cache\AdminAuthCache;
require dirname(__DIR__) . '/vendor/autoload.php';
function adminMultiRoleExpect(bool $condition, string $message): void
{
if (!$condition) {
throw new RuntimeException($message);
}
}
$adminReflection = new ReflectionClass(AdminLogic::class);
$normalizeRoleIds = $adminReflection->getMethod('normalizeRoleIds');
$roleIdsChanged = $adminReflection->getMethod('roleIdsChanged');
$normalizeRoleIds->setAccessible(true);
$roleIdsChanged->setAccessible(true);
adminMultiRoleExpect(
$normalizeRoleIds->invoke(null, ['7', 2, 7, 0, -1]) === [2, 7],
'Role ids must be normalized, deduplicated and sorted'
);
adminMultiRoleExpect(
$roleIdsChanged->invoke(null, [2], [2, 7]) === true,
'Adding a role must invalidate the existing token'
);
adminMultiRoleExpect(
$roleIdsChanged->invoke(null, [2, 7], [2]) === true,
'Removing a role must invalidate the existing token'
);
adminMultiRoleExpect(
$roleIdsChanged->invoke(null, [2, 7], [7, 2]) === false,
'Changing only role order must not invalidate the token'
);
$cacheMethod = new ReflectionMethod(AdminAuthCache::class, 'clearAuthCache');
$sourceLines = file($cacheMethod->getFileName());
$methodSource = implode('', array_slice(
$sourceLines,
$cacheMethod->getStartLine() - 1,
$cacheMethod->getEndLine() - $cacheMethod->getStartLine() + 1
));
adminMultiRoleExpect(
str_contains($methodSource, 'delete($this->cacheUrlKey)'),
'Single-admin permission cache must delete its concrete cache key'
);
adminMultiRoleExpect(
!str_contains($methodSource, 'tag($this->cacheUrlKey)'),
'Single-admin permission cache must not clear a tag that was never assigned'
);
echo "AdminMultiRoleRegressionTest passed\n";
+50
View File
@@ -0,0 +1,50 @@
<?php
declare(strict_types=1);
use app\common\service\DataScope\DataScopeService;
require dirname(__DIR__) . '/vendor/autoload.php';
function dataScopeMultiRoleExpect(bool $condition, string $message): void
{
if (!$condition) {
throw new RuntimeException($message);
}
}
$mergeRoleScopes = (new ReflectionClass(DataScopeService::class))->getMethod('mergeRoleScopes');
$mergeRoleScopes->setAccessible(true);
$role = static fn (string $name, int $scope): array => ['name' => $name, 'data_scope' => $scope];
dataScopeMultiRoleExpect(
$mergeRoleScopes->invoke(null, [$role('医助', 4)]) === DataScopeService::SCOPE_SELF,
'Single assistant role must remain self-only'
);
dataScopeMultiRoleExpect(
$mergeRoleScopes->invoke(null, [$role('诊室组长', 3), $role('医助', 4)]) === DataScopeService::SCOPE_DEPT,
'Group leader plus assistant must use the group scope'
);
dataScopeMultiRoleExpect(
$mergeRoleScopes->invoke(null, [$role('经理', 2), $role('诊室组长', 3), $role('医助', 4)])
=== DataScopeService::SCOPE_DEPT_AND_CHILD,
'Manager plus narrower roles must use department-and-child scope'
);
dataScopeMultiRoleExpect(
$mergeRoleScopes->invoke(null, [$role('医生', 1), $role('医助', 4)]) === DataScopeService::SCOPE_SELF,
'Legacy all-scope functional role must not widen a bounded role'
);
dataScopeMultiRoleExpect(
$mergeRoleScopes->invoke(null, [$role('管理员', 1), $role('医助', 4)]) === DataScopeService::SCOPE_ALL,
'Explicit administrator role must retain all-data scope'
);
dataScopeMultiRoleExpect(
$mergeRoleScopes->invoke(null, [$role('下单', 1)]) === DataScopeService::SCOPE_ALL,
'A standalone legacy all-scope role must keep its existing behavior'
);
dataScopeMultiRoleExpect(
$mergeRoleScopes->invoke(null, [$role('脏数据', 0)]) === DataScopeService::SCOPE_SELF,
'Invalid role scopes must fail closed to self-only'
);
echo "DataScopeMultiRoleTest passed\n";
@@ -0,0 +1,91 @@
<?php
declare(strict_types=1);
use app\adminapi\logic\firstvisit\FirstVisitConversionLogic;
use app\common\service\DataScope\DataScopeService;
require dirname(__DIR__) . '/vendor/autoload.php';
function conversionRankingExpect(bool $condition, string $message): void
{
if (!$condition) {
throw new RuntimeException($message);
}
}
$reflection = new ReflectionClass(FirstVisitConversionLogic::class);
$rankingKind = $reflection->getMethod('rankingKind');
$rankingRows = $reflection->getMethod('rankingRows');
$topRows = $reflection->getMethod('topRows');
$rankingKind->setAccessible(true);
$rankingRows->setAccessible(true);
$topRows->setAccessible(true);
$member = static fn (int $id, string $name, int $orders, float $amount): array => [
'id' => "M{$id}_11",
'admin_id' => $id,
'name' => $name,
'type' => 'member',
'completed_order_count' => $orders,
'completed_order_amount' => $amount,
'children' => [],
];
$groupRows = [[
'id' => 10,
'name' => '一诊中心',
'children' => [
[
'id' => 11,
'name' => '一组',
'completed_order_count' => 8,
'completed_order_amount' => 800,
'children' => [$member(101, '甲', 5, 500), $member(102, '乙', 3, 300)],
],
[
'id' => 12,
'name' => '二组',
'completed_order_count' => 6,
'completed_order_amount' => 600,
'children' => [$member(103, '丙', 6, 600)],
],
],
]];
conversionRankingExpect(
$rankingKind->invoke(null, DataScopeService::SCOPE_SELF, 0) === 'hidden',
'Self-only data range must hide rankings'
);
conversionRankingExpect(
$rankingRows->invoke(null, $groupRows, 'hidden') === [],
'Hidden ranking mode must not return ranking rows'
);
conversionRankingExpect(
$rankingKind->invoke(null, DataScopeService::SCOPE_DEPT_AND_CHILD, 101) === 'hidden',
'Selecting one employee must switch the ranking to personal mode'
);
$memberRows = $rankingRows->invoke(null, $groupRows, 'member');
conversionRankingExpect(count($memberRows) === 3, 'Member ranking mode must include visible group members');
$rankedMembers = $topRows->invoke(null, $memberRows, 'completed_order_count');
conversionRankingExpect(
array_column($rankedMembers, 'name') === ['丙', '甲', '乙'],
'Member ranking must be ordered by the selected metric'
);
conversionRankingExpect(
$rankedMembers[0]['id'] === 'M103_11',
'Member ranking must preserve its string row key'
);
$teamRows = $rankingRows->invoke(null, $groupRows, 'group');
conversionRankingExpect(
array_column($teamRows, 'name') === ['一组', '二组'],
'Group ranking mode must use direct child departments'
);
conversionRankingExpect(
$rankingKind->invoke(null, DataScopeService::SCOPE_ALL, 0) === 'group',
'All-data range must use the group ranking dimension'
);
echo "FirstVisitConversionRankingTest passed\n";