\App\Services\AdminUserConfigService

用户配置服务

职责:用户台账的增删改查、批量启停、导入导出,以及直授角色/任职/个人范围/个人权限 四类授权同步。鉴权(提权拦截、数据范围校验、委派上界)与缓存失效在此收口。

┌────────────────── 分区导航(按此顺序阅读)──────────────────┐ 分区 1 · 构造与依赖 __construct 分区 2 · 查询(读操作) paginate / overview / postUserGroups / deptNames / ledDeptNames memberships / getUserRoleIds / getUserScopes getUserPermissionIds / permissionCatalog 分区 3 · 用户写操作 create / update / batchUpdateStatus / resetPassword destroy / importCsv 分区 4 · 授权同步(写) syncUserRoles / syncMemberships / syncUserScopes / syncUserPermissions 分区 5 · 数据范围与内部 assertTargetVisible / assertOperatorCoversRolePermissions normalizeAvatar / forceLogout / currentOperatorName └────────────────────────────────────────────────────────────┘

Summary

Methods
Properties
Constants
__construct()
paginate()
overview()
postUserGroups()
deptNames()
ledDeptNames()
memberships()
getUserRoleIds()
getUserScopes()
getUserPermissionIds()
permissionCatalog()
create()
update()
batchUpdateStatus()
resetPassword()
destroy()
importCsv()
syncUserRoles()
syncMemberships()
syncUserScopes()
syncUserPermissions()
assertTargetVisible()
No public properties found
No constants found
normalizeStringColumns()
No protected properties found
N/A
currentOperatorName()
assertOperatorCoversRolePermissions()
normalizeAvatar()
forceLogout()
revokeSession()
$cacheService
N/A

Properties

Methods

__construct()

__construct(\App\Services\Admin\PermissionCacheService  $cacheService) : mixed

注入权限缓存服务

Parameters

\App\Services\Admin\PermissionCacheService $cacheService

Returns

mixed —

paginate()

paginate(array  $filters, int  $perPage = 15) : \Illuminate\Contracts\Pagination\LengthAwarePaginator

分页查询用户列表,支持搜索/状态/部门筛选; 列表聚合 roles_summary(直授角色名+icon)与 dept_names(任职部门名),供前端列表直接展示。

Parameters

array $filters
int $perPage

Returns

\Illuminate\Contracts\Pagination\LengthAwarePaginator —

overview()

overview() : array

用户统计概览:总数/启用/停用/超管,供列表页顶部统计卡。

统计口径与列表一致(非豁免操作者只统计自己组织轴可见的用户), 单条 SQL 聚合(PG FILTER 子句)替代 4 次全表 COUNT。

Returns

array —

postUserGroups()

postUserGroups() : array

岗位视角用户分组(岗位表):启用岗位(挂部门)→ 其任职用户(含负责人标记)。 数据范围:非豁免操作者仅见自己可见用户(与用户列表同规)。前端与组织树合并渲染。

Returns

array —

deptNames()

deptNames(\App\Models\SysUser  $user) : string[]

用户任职部门名列表(详情基本信息摘要展示用)。

Parameters

\App\Models\SysUser $user

Returns

string[] —

ledDeptNames()

ledDeptNames(\App\Models\SysUser  $user) : string[]

用户担任负责人的部门名列表(双向并集,详情基本信息摘要展示用): 部门档案负责人(td_sys_dept.leader_id,组织维护部门表单指定)∪ 任职负责人(td_sys_user_dept.is_leader=1,用户职位 Tab 勾选,全见本部门含下级)。

Parameters

\App\Models\SysUser $user

Returns

string[] —

memberships()

memberships(\App\Models\SysUser  $user) : array

用户任职列表(带部门与岗位信息)。

Parameters

\App\Models\SysUser $user

Returns

array —

getUserRoleIds()

getUserRoleIds(\App\Models\SysUser  $user) : int[]

获取用户的直授角色 ID 列表。

Parameters

\App\Models\SysUser $user

Returns

int[] —

getUserScopes()

getUserScopes(\App\Models\SysUser  $user) : \App\Models\SysUserScope[]

用户个人数据范围列表(覆盖式同步后回读用)。

Parameters

\App\Models\SysUser $user

Returns

\App\Models\SysUserScope[] —

getUserPermissionIds()

getUserPermissionIds(\App\Models\SysUser  $user) : int[]

用户个人权限 ID 列表(覆盖式同步后回读用)。

Parameters

\App\Models\SysUser $user

Returns

int[] —

permissionCatalog()

permissionCatalog() : array

个人权限可选目录(V6.3):启用/隐藏菜单树(递归),每个菜单下挂其按钮/接口权限 (type=2/3,status=1)——个人权限 Tab 授权目录(菜单权限不授,页面可见性由角色决定)。 无下挂权限且无有效子级的菜单整体剪枝。低频管理页实时查不缓存(同 MaintainMenuService::tree 带筛选分支的理由)。

Returns

array —

create()

create(array  $data) : \App\Models\SysUser

创建用户。

Parameters

array $data

Throws

\InvalidArgumentException

非超管操作者写入 is_super=1 时抛 403

Returns

\App\Models\SysUser —

update()

update(\App\Models\SysUser  $user, array  $data) : \App\Models\SysUser

更新用户。

停用(status 1→0)或 is_super 变更时,目标用户立即强制下线并清权限/菜单缓存。

Parameters

\App\Models\SysUser $user
array $data

Throws

\InvalidArgumentException

非超管操作者写 is_super=1、操作超管目标、或目标不在数据范围内时抛 403

Returns

\App\Models\SysUser —

batchUpdateStatus()

batchUpdateStatus(int[]  $ids, int  $status) : int

批量启用/停用(事务,逐用户处理)。

停用的用户立即强制下线(杀 Redis token + 清权限/菜单缓存), 避免会话在 token 有效期内(最长 8h)继续可用。

Parameters

int[] $ids
int $status

Returns

int —

resetPassword()

resetPassword(\App\Models\SysUser  $user) : string

重置密码,返回新密码明文。

Parameters

\App\Models\SysUser $user

Throws

\InvalidArgumentException

目标不在操作者数据范围内时抛 403

Returns

string —

destroy()

destroy(\App\Models\SysUser  $user, int  $currentUserId) : void

删除用户(事务内清理任职/直授角色/个人范围关联,避免孤儿数据)。

Parameters

\App\Models\SysUser $user
int $currentUserId

Throws

\InvalidArgumentException

目标是超管而操作者不是时抛 403

importCsv()

importCsv(mixed  $file) : array

从 CSV 文件批量导入用户。

每个用户生成随机初始密码(PasswordHelper::generatePassword),明文只在本次导入响应中返回一次, 库中只存加盐哈希;行内 is_super=是 且操作者非超管时该行跳过(防导入提权)。

Parameters

mixed $file

Returns

array —

syncUserRoles()

syncUserRoles(\App\Models\SysUser  $user, int[]  $roleIds) : void

同步用户直授角色(覆盖式),变更后清该用户权限缓存。

Parameters

\App\Models\SysUser $user
int[] $roleIds

syncMemberships()

syncMemberships(\App\Models\SysUser  $user, array  $items) : void

同步任职(覆盖式,V6.2 起任职仅为归属标记,不再带 scope)。 每条:dept_id + post_id(岗位,须在该部门岗位目录内)+ is_leader。 超级管理员岗位(code=super)特殊:全局岗位 dept_id 必须为 0(不挂部门), 仅超管本人可分配(任职即数据全见),负责人标识强制为 0。

Parameters

\App\Models\SysUser $user
array $items

Throws

\InvalidArgumentException

非超管为任何人任职超级管理员岗位(403)、目标不在数据范围内、 或非豁免操作者自我调整导致范围扩大时抛 403

syncUserScopes()

syncUserScopes(\App\Models\SysUser  $user, array  $items) : void

同步用户个人数据范围(覆盖式)。 每条:company_id(组织)+ dept_id(0=整组织,否则该部门含下级)。 个人范围与岗位范围并集生效(用户可见部门集 = 岗位范围 ∪ 个人范围 ∪ 负责人部门)。

Parameters

\App\Models\SysUser $user
array $items

[{company_id, dept_id}]

Throws

\InvalidArgumentException

目标不在数据范围内(403)、组织/部门不存在或归属不符(400)时抛

syncUserPermissions()

syncUserPermissions(\App\Models\SysUser  $user, int[]  $permissionIds) : void

同步用户个人权限(覆盖式)。 仅按钮/接口权限(type=2/3):菜单页面可见性仍由角色决定(前端安全模型「菜单=全量页面集合」)。 个人权限与角色权限并集生效(与个人数据范围同构)。

Parameters

\App\Models\SysUser $user
int[] $permissionIds

Throws

\InvalidArgumentException

目标不可见(403)、超管只读(403)、越权授予(403)、 权限不存在/停用或含菜单权限(400)时抛

assertTargetVisible()

assertTargetVisible(\App\Models\SysUser  $target) : void

写操作数据范围校验:非豁免操作者只能操作自己组织轴内可见的用户。 目标不在可见集内抛 403(越权访问)。读路径(show/memberships/scopes/permissions)同规复用。

Parameters

\App\Models\SysUser $target

normalizeStringColumns()

normalizeStringColumns(array<string,mixed>  $data, string[]  $columns, array<string,string>  $defaults = [], bool  $fillMissing = false) : array

字符串列归一化:值为 null 的键写入 $defaults 对应默认值(缺省 '')。

Parameters

array $data

待写库数据(按引用字段处理,返回归一化副本)

string[] $columns

参与归一化的列名

array $defaults

列 => 默认值(缺省 '',如 link_target => '_self')

bool $fillMissing

true 时缺失键也补默认值(创建路径全字段落库用);false 只处理已存在的键

Returns

array —

currentOperatorName()

currentOperatorName() : string

当前操作者姓名(密码台账留痕用;无登录上下文——如命令行导入——回落「系统」)

Returns

string —

assertOperatorCoversRolePermissions()

assertOperatorCoversRolePermissions(array  $roleIds) : void

委派上界:授予角色的权限码并集必须 ⊆ 操作者自身权限码(超管豁免)。

Parameters

array $roleIds

Throws

\InvalidArgumentException

角色含操作者未持有的权限码时抛 403

normalizeAvatar()

normalizeAvatar(mixed  $avatar) : string

头像归一与校验(头像 = 文件库文件 id,scene=avatar 上传即登记)。

纯数字 = 文件 id(须存在、图片类、操作者可见或共享);空/0 = 清空;其余非法。

Parameters

mixed $avatar

Throws

\InvalidArgumentException

参数非法/文件不可用

Returns

string —

forceLogout()

forceLogout(\App\Models\SysUser  $user) : void

强制下线:使目标用户当前会话立即失效并清权限/菜单缓存。

仅用于非事务上下文(单用户 update 路径);批量路径见 batchUpdateStatus(提交后统一吊销)。

Parameters

\App\Models\SysUser $user

revokeSession()

revokeSession(?string  $md5Key, ?string  $token) : void

会话吊销的 Redis 副作用:JWT 拉黑 + 删会话/age 键。 必须在事务提交后调用(事务内执行会产生回滚不一致,见 batchUpdateStatus)。

Parameters

?string $md5Key
?string $token