将用户管理操作接入职务权限体系

This commit is contained in:
2026-04-21 18:00:02 +08:00
parent a066580014
commit b0028c515f
8 changed files with 462 additions and 85 deletions
+5
View File
@@ -27,6 +27,9 @@
$superLevel = (int) \App\Models\Sysparam::getValue('superlevel', '100');
$myLevel = Auth::user()->user_level;
$positionPermissions = array_keys(array_filter($roomPermissionMap ?? []));
$operatorActivePosition = Auth::user()->activePosition?->load('position.department')->position;
$operatorDepartmentRank = (int) ($operatorActivePosition?->department?->rank ?? 0);
$operatorPositionRank = (int) ($operatorActivePosition?->rank ?? 0);
@endphp
<script>
window.chatContext = {
@@ -84,6 +87,8 @@
$posName = $activePos?->position?->name ?? '';
@endphp
welcomePrefix: "{{ $deptName ? "{$deptName} {$posName} {$user->username}" : $user->username }}",
operatorDepartmentRank: {{ $operatorDepartmentRank }},
operatorPositionRank: {{ $operatorPositionRank }},
myMaxReward: @php
if (Auth::id() === 1) {
// 超级管理员(id=1)无需职务,直接拥有不限量奖励权
@@ -131,6 +131,48 @@
$confirm: (...args) => window.chatDialog.confirm(...args),
$prompt: (...args) => window.chatDialog.prompt(...args),
/**
* 判断当前操作者是否拥有指定的职务权限码。
*/
hasPositionPermission(permissionCode) {
return Boolean(window.chatContext?.positionPermissionMap?.[permissionCode]);
},
/**
* 判断目标用户职务是否严格低于当前操作者。
*
* 规则:
* 1. 先比较部门位阶 rank
* 2. 部门相同再比较职务位阶 rank
* 3. 对方没有在职职务时,视为可处理
* 4. id=1 站长始终可处理
*/
canManageTargetByDuty() {
if (window.chatContext?.isSiteOwner) {
return true;
}
const targetDepartmentRank = Number(this.userInfo.department_rank || 0);
const targetPositionRank = Number(this.userInfo.position_rank || 0);
if (targetDepartmentRank <= 0 && targetPositionRank <= 0) {
return true;
}
const operatorDepartmentRank = Number(window.chatContext?.operatorDepartmentRank || 0);
const operatorPositionRank = Number(window.chatContext?.operatorPositionRank || 0);
if (operatorDepartmentRank > targetDepartmentRank) {
return true;
}
if (operatorDepartmentRank < targetDepartmentRank) {
return false;
}
return operatorPositionRank >= targetPositionRank;
},
/** 切换好友关系(加好友 / 删好友) */
async toggleFriend() {
if (this.friendLoading) return;
@@ -984,11 +1026,15 @@
</div>
{{-- 管理操作 + 职务操作 合并折叠区 --}}
@if (
$myLevel >= $levelWarn ||
$room->master == Auth::user()->username ||
Auth::user()->activePosition ||
$myLevel >= $superLevel)
@php
$canWarnUser = Auth::id() === 1 || (($roomPermissionMap[\App\Support\PositionPermissionRegistry::USER_WARN] ?? false) === true);
$canKickUser = Auth::id() === 1 || (($roomPermissionMap[\App\Support\PositionPermissionRegistry::USER_KICK] ?? false) === true);
$canMuteUser = Auth::id() === 1 || (($roomPermissionMap[\App\Support\PositionPermissionRegistry::USER_MUTE] ?? false) === true);
$canFreezeUser = Auth::id() === 1 || (($roomPermissionMap[\App\Support\PositionPermissionRegistry::USER_FREEZE] ?? false) === true);
$hasUserModerationPermission = $canWarnUser || $canKickUser || $canMuteUser || $canFreezeUser;
$hasPositionActions = Auth::user()->activePosition || $myLevel >= $superLevel;
@endphp
@if ($hasUserModerationPermission || $hasPositionActions)
<div style="padding: 0 16px 12px;" x-show="userInfo.username !== window.chatContext.username">
{{-- 折叠标题 --}}
@@ -1004,31 +1050,31 @@
{{-- 折叠内容 --}}
<div x-show="showAdminPanel" x-transition style="display: none; margin-top: 6px;">
@if ($myLevel >= $levelWarn || $room->master == Auth::user()->username)
<div x-show="userInfo.user_level <= {{ $myLevel }}">
@if ($hasUserModerationPermission)
<div x-show="canManageTargetByDuty()">
<div style="font-size: 10px; color: #9ca3af; margin-bottom: 4px; padding-left: 2px;">
管理员操作
</div>
<div style="display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 8px;">
@if ($myLevel >= $levelWarn)
@if ($canWarnUser)
<button
style="flex:1; padding: 5px; border-radius: 4px; font-size: 11px; background: #fef3c7; border: 1px solid #f59e0b; cursor: pointer;"
x-on:click="warnUser()">⚠️ 警告
</button>
@endif
@if ($myLevel >= $levelKick)
@if ($canKickUser)
<button
style="flex:1; padding: 5px; border-radius: 4px; font-size: 11px; background: #fee2e2; border: 1px solid #ef4444; cursor: pointer;"
x-on:click="kickUser()">🚫 踢出
</button>
@endif
@if ($myLevel >= $levelMute)
@if ($canMuteUser)
<button
style="flex:1; padding: 5px; border-radius: 4px; font-size: 11px; background: #e0e7ff; border: 1px solid #6366f1; cursor: pointer;"
x-on:click="isMuting = !isMuting">🔇 禁言
</button>
@endif
@if ($myLevel >= $levelFreeze)
@if ($canFreezeUser)
<button
style="flex:1; padding: 5px; border-radius: 4px; font-size: 11px; background: #dbeafe; border: 1px solid #3b82f6; cursor: pointer;"
x-on:click="freezeUser()">🧊 冻结
@@ -1036,7 +1082,7 @@
@endif
{{-- 职务奖励金币(凭空产生),仅有在职职务且 max_reward != 0 的人可见 --}}
@if (Auth::user()->activePosition || $myLevel >= $superLevel)
@if ($hasPositionActions)
<button x-show="window.chatContext?.myMaxReward !== 0"
style="flex:1; padding: 5px; border-radius: 4px; font-size: 11px; background: #fef3c7; border: 1px solid #f59e0b; cursor: pointer;"
x-on:click="openRewardModal(userInfo.username)">💰 奖励金币
@@ -1046,7 +1092,7 @@
</div>
@endif
@if (Auth::user()->activePosition || $myLevel >= $superLevel)
@if ($hasPositionActions)
<div>
<div style="font-size: 10px; color: #9ca3af; margin-bottom: 4px; padding-left: 2px;">
职务操作