1.优化后台管理员管理页面的权限设置,新增zihuaadmin账号

This commit is contained in:
2026-05-29 17:24:07 +08:00
parent 7c1307e355
commit 54fb283b8d
9 changed files with 287 additions and 438 deletions

View File

@@ -21,7 +21,7 @@ class Admin extends Backend
/**
* 分红比例余量查询(表单提示用)
*/
protected array $noNeedPermission = ['commissionShareRemainder', 'groupMeta'];
protected array $noNeedPermission = ['commissionShareRemainder', 'groupMeta', 'parentMeta'];
protected ?object $model = null;
@@ -114,10 +114,7 @@ class Admin extends Backend
->alias($alias)
->where($where);
$visibleIds = AdminCommissionDistributionService::getVisibleAdminIdsForOperator(
intval($this->auth->id),
$this->auth->isSuperAdmin()
);
$visibleIds = $this->getVisibleAdminIdsForAdminModule();
if ($visibleIds !== []) {
$query->where($adminAlias . '.id', 'in', $visibleIds);
}
@@ -226,7 +223,7 @@ class Admin extends Backend
return $this->error(__('Invalid parameters'));
}
$group = Db::name('admin_group')->where('id', $groupId)->field(['id', 'pid', 'channel_id'])->find();
$group = Db::name('admin_group')->where('id', $groupId)->field(['id', 'pid'])->find();
if (!is_array($group)) {
return $this->error(__('Record not found'));
}
@@ -243,7 +240,45 @@ class Admin extends Backend
return $this->success('', [
'is_top_level' => $pid === 0,
'pid' => $pid,
'channel_id' => $group['channel_id'] ?? null,
]);
}
/**
* 上级代理渠道信息(子代理表单只读展示用)
*/
public function parentMeta(Request $request): Response
{
$response = $this->initializeBackend($request);
if ($response !== null) {
return $response;
}
$parentId = intval($request->get('parent_admin_id', 0));
if ($parentId <= 0) {
return $this->success('', [
'channel_id' => null,
'channel_name' => '',
]);
}
if (!$this->canManageAdminId($parentId) && !$this->auth->isSuperAdmin()) {
return $this->error(__('You have no permission'));
}
$parent = Db::name('admin')->where('id', $parentId)->field(['id', 'channel_id'])->find();
if (!is_array($parent)) {
return $this->error(__('Invalid parent administrator'));
}
$cid = $parent['channel_id'] ?? null;
$channelName = '';
if ($cid !== null && $cid !== '') {
$channelName = (string) (Db::name('channel')->where('id', $cid)->value('name') ?? '');
}
return $this->success('', [
'channel_id' => $cid,
'channel_name' => $channelName,
]);
}
@@ -300,26 +335,14 @@ class Admin extends Backend
$passwd = $data['password'] ?? '';
$data = $this->excludeFields($data);
$creatorChannelId = $this->getCreatorChannelId();
$groupChannelId = $this->resolveChannelIdFromPrimaryGroup($data['group_arr'] ?? []);
if (!$this->auth->isSuperAdmin()) {
$creatorChannelId = $this->getCreatorChannelId();
if ($creatorChannelId === null || $creatorChannelId === '') {
return $this->error(__('You have no permission'));
}
if ($groupChannelId === null || $groupChannelId === '') {
return $this->error(__('Selected role group is not bound to a channel'));
}
if ((string) $groupChannelId !== (string) $creatorChannelId) {
return $this->error(__('Selected role group channel does not match current account'));
}
$data['channel_id'] = $creatorChannelId;
$data['parent_admin_id'] = $this->auth->id;
} else {
$postedChannel = $data['channel_id'] ?? null;
if ($postedChannel === null || $postedChannel === '') {
$data['channel_id'] = ($groupChannelId === null || $groupChannelId === '') ? null : $groupChannelId;
}
}
$parentErr = $this->normalizeParentAndShareFields($data, null, $data['group_arr'] ?? []);
@@ -456,28 +479,13 @@ class Admin extends Backend
$data = $this->excludeFields($data);
unset($data['invite_code'], $data['group_arr'], $data['group_name_arr']);
if (!$isSelfEdit && $editGroupArr !== null) {
$creatorChannelId = $this->getCreatorChannelId();
$groupChannelId = $this->resolveChannelIdFromPrimaryGroup($editGroupArr);
if (!$this->auth->isSuperAdmin()) {
if ($creatorChannelId === null || $creatorChannelId === '') {
return $this->error(__('You have no permission'));
}
if ($groupChannelId === null || $groupChannelId === '') {
return $this->error(__('Selected role group is not bound to a channel'));
}
if ((string) $groupChannelId !== (string) $creatorChannelId) {
return $this->error(__('Selected role group channel does not match current account'));
}
$data['channel_id'] = $creatorChannelId;
} else {
$data['channel_id'] = ($groupChannelId === null || $groupChannelId === '') ? null : $groupChannelId;
}
}
if (!$isSelfEdit) {
if (!$this->auth->isSuperAdmin()) {
unset($data['parent_admin_id']);
unset($data['parent_admin_id'], $data['channel_id']);
$creatorChannelId = $this->getCreatorChannelId();
if ($creatorChannelId !== null && $creatorChannelId !== '') {
$data['channel_id'] = $creatorChannelId;
}
}
$parentErr = $this->normalizeParentAndShareFields($data, intval($id), $editGroupArr ?? []);
if ($parentErr !== null) {
@@ -611,10 +619,7 @@ class Admin extends Backend
->alias($alias)
->where($where);
$visibleIds = AdminCommissionDistributionService::getVisibleAdminIdsForOperator(
intval($this->auth->id),
$this->auth->isSuperAdmin()
);
$visibleIds = $this->getVisibleAdminIdsForAdminModule();
if ($visibleIds !== []) {
$query->where($adminAlias . '.id', 'in', $visibleIds);
}
@@ -628,6 +633,42 @@ class Admin extends Backend
return $rows;
}
/**
* 非超管可见管理员:本人 + 代理树下级 + 角色组管理范围内(本人所在组及下级组)的全部成员。
*
* @return int[] 空数组表示不限制(超管)
*/
private function getVisibleAdminIdsForAdminModule(): array
{
if ($this->auth->isSuperAdmin()) {
return [];
}
$operatorId = intval($this->auth->id);
$ids = AdminCommissionDistributionService::getVisibleAdminIdsForOperator($operatorId, false);
$groupIds = $this->getManageableGroupIds();
if ($groupIds !== []) {
$groupAdminIds = Db::name('admin_group_access')
->where('group_id', 'in', $groupIds)
->column('uid');
foreach ($groupAdminIds as $uid) {
$uidInt = intval($uid);
if ($uidInt > 0) {
$ids[] = $uidInt;
}
}
}
if ($operatorId > 0) {
$ids[] = $operatorId;
}
$ids = array_values(array_unique(array_filter($ids, static fn(int $id): bool => $id > 0)));
return $ids === [] ? [0] : $ids;
}
private function checkGroupAuth(array $groups): ?Response
{
if ($this->auth->isSuperAdmin()) {
@@ -665,22 +706,6 @@ class Admin extends Backend
return null;
}
/**
* @param array<int|string> $groupIds
*/
private function resolveChannelIdFromPrimaryGroup(array $groupIds): mixed
{
if ($groupIds === []) {
return null;
}
$gid = $groupIds[0];
if ($gid === null || $gid === '') {
return null;
}
return Db::name('admin_group')->where('id', $gid)->value('channel_id');
}
private function canManageAdminId(int $adminId): bool
{
if ($this->auth->isSuperAdmin()) {
@@ -689,11 +714,7 @@ class Admin extends Backend
if ($adminId === intval($this->auth->id)) {
return true;
}
$visible = AdminCommissionDistributionService::getVisibleAdminIdsForOperator(
intval($this->auth->id),
false
);
return in_array($adminId, $visible, true);
return in_array($adminId, $this->getVisibleAdminIdsForAdminModule(), true);
}
/**
@@ -721,14 +742,30 @@ class Admin extends Backend
{
if ($this->isPrimaryGroupTopLevel($groupIds)) {
$data['parent_admin_id'] = null;
$channelId = $data['channel_id'] ?? null;
if ($channelId === null || $channelId === '') {
$channelId = $this->resolveChannelIdFromPrimaryGroup($groupIds);
if ($channelId !== null && $channelId !== '') {
$data['channel_id'] = $channelId;
if (!$this->auth->isSuperAdmin()) {
$mayAssignChannel = false;
foreach (['channel/index', 'channel/Index', 'Channel/index', 'Channel/Index'] as $routePath) {
if ($this->auth->check($routePath)) {
$mayAssignChannel = true;
break;
}
}
if (!$mayAssignChannel) {
unset($data['channel_id']);
}
}
$channelId = $data['channel_id'] ?? null;
$channelIdInt = intval($channelId ?? 0);
if ($channelIdInt <= 0) {
$data['channel_id'] = null;
$data['commission_share_rate'] = null;
return null;
}
$exists = Db::name('channel')->where('id', $channelIdInt)->value('id');
if (!$exists) {
return (string) __('Record not found');
}
$shareErr = AdminCommissionDistributionService::validateChannelRootCommissionShareRate(
$channelIdInt,
$data['commission_share_rate'] ?? null,
@@ -752,6 +789,18 @@ class Admin extends Backend
if ($parentId <= 0) {
$data['parent_admin_id'] = null;
$data['commission_share_rate'] = null;
if (!$this->auth->isSuperAdmin()) {
$mayAssignChannel = false;
foreach (['channel/index', 'channel/Index', 'Channel/index', 'Channel/Index'] as $routePath) {
if ($this->auth->check($routePath)) {
$mayAssignChannel = true;
break;
}
}
if (!$mayAssignChannel) {
unset($data['channel_id']);
}
}
return null;
}
@@ -768,12 +817,10 @@ class Admin extends Backend
return (string) __('You have no permission');
}
$channelId = $data['channel_id'] ?? null;
if ($channelId !== null && $channelId !== '' && (string) ($parent['channel_id'] ?? '') !== (string) $channelId) {
return (string) __('Parent administrator must belong to the same channel');
}
if (($channelId === null || $channelId === '') && !empty($parent['channel_id'])) {
if (!empty($parent['channel_id'])) {
$data['channel_id'] = $parent['channel_id'];
} else {
$data['channel_id'] = null;
}
$shareErr = AdminCommissionDistributionService::validateCommissionShareRate(
@@ -893,4 +940,47 @@ class Admin extends Backend
{
return is_array($groups) && count($groups) === 1;
}
/**
* 兼容旧 worker 内存中仍调用本方法的 add/edit新逻辑在 normalizeParentAndShareFields。
*
* @param array<string, mixed> $data
* @param array<int|string> $groupIds
*/
private function applyTopLevelChannelFromOperator(array &$data, array $groupIds): ?string
{
if (!$this->isPrimaryGroupTopLevel($groupIds)) {
return null;
}
$parentId = isset($data['parent_admin_id']) && $data['parent_admin_id'] !== '' && $data['parent_admin_id'] !== null
? intval($data['parent_admin_id'])
: 0;
if ($parentId > 0) {
return null;
}
if (!$this->auth->isSuperAdmin()) {
$mayAssignChannel = false;
foreach (['channel/index', 'channel/Index', 'Channel/index', 'Channel/Index'] as $routePath) {
if ($this->auth->check($routePath)) {
$mayAssignChannel = true;
break;
}
}
if (!$mayAssignChannel) {
unset($data['channel_id']);
}
}
$cid = $data['channel_id'] ?? null;
if ($cid === null || $cid === '') {
$data['channel_id'] = null;
return null;
}
$exists = Db::name('channel')->where('id', $cid)->value('id');
if (!$exists) {
return (string) __('Record not found');
}
return null;
}
}