\App\Services\AdminSysMessageService

系统信息核心服务

职责:① 公告管理——草稿 CRUD、发布(target 快照展开 + 人数快照)、撤回、 物理删除(级联已读行);② 我的信息——列表(公告/系统通知双页签)、 未读差集、详情即已读、全部已读批量插入;③ 系统事件写入——定向用户、 biz_key 唯一索引幂等(重复事件自动忽略)。

┌────────────────── 分区导航(按此顺序阅读)──────────────────┐ 分区 1 · 管理线 paginate / show / store / update / destroy / publish / revoke 分区 2 · 个人线 myPaginate / myUnreadCount / myShow / myReadAll 分区 3 · 事件写入 sendSystemMessage / workerAlarmWithinWindow / superAdminIds 分区 4 · 内部辅助 applyVisibility / visibleQuery / expandDeptIds / targetCount └────────────────────────────────────────────────────────────┘

Summary

Methods
Properties
Constants
paginate()
show()
store()
update()
destroy()
publish()
revoke()
myPaginate()
myUnreadCount()
myShow()
myReadAll()
sendSystemMessage()
workerAlarmWithinWindow()
superAdminIds()
No public properties found
WORKER_ALARM_WINDOW_MINUTES
No protected methods found
No protected properties found
N/A
doSendSystemMessage()
fillEditable()
visibleQuery()
attachReadFlags()
expandDeptIds()
targetCount()
No private properties found
N/A

Constants

WORKER_ALARM_WINDOW_MINUTES

WORKER_ALARM_WINDOW_MINUTES = 60

worker 告警防重窗口(分钟):窗口内重复失联不再发

Methods

paginate()

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

公告分页列表(含已读/目标统计)。

Parameters

array $filters

{search?: string, status?: int, category?: string}

int $perPage

Returns

\Illuminate\Contracts\Pagination\LengthAwarePaginator —

show()

show(int  $id) : \App\Models\SysMessage

公告详情。

Parameters

int $id

Returns

\App\Models\SysMessage —

store()

store(array  $data, int  $senderId) : \App\Models\SysMessage

新建草稿。

Parameters

array $data

{msg_type, title, content, target_type, target_ids, need_read, expire_time}

int $senderId

Returns

\App\Models\SysMessage —

update()

update(\App\Models\SysMessage  $message, array  $data) : \App\Models\SysMessage

更新草稿(仅草稿可改)。

Parameters

\App\Models\SysMessage $message
array $data

Throws

\InvalidArgumentException

非草稿时 400

Returns

\App\Models\SysMessage —

destroy()

destroy(\App\Models\SysMessage  $message) : void

物理删除(仅草稿/已撤回;事务级联删除已读行)。

Parameters

\App\Models\SysMessage $message

Throws

\InvalidArgumentException

已发布时 400

publish()

publish(\App\Models\SysMessage  $message) : \App\Models\SysMessage

发布:展开 target 快照(dept 子孙)+ 目标人数快照,落已发布态。

Parameters

\App\Models\SysMessage $message

Throws

\InvalidArgumentException

非草稿时 400

Returns

\App\Models\SysMessage —

revoke()

revoke(\App\Models\SysMessage  $message) : \App\Models\SysMessage

撤回(软操作,已读行保留——保留"撤回前多少人看过"的审计价值)。

Parameters

\App\Models\SysMessage $message

Throws

\InvalidArgumentException

非已发布时 400

Returns

\App\Models\SysMessage —

myPaginate()

myPaginate(\App\Models\SysUser  $user, string  $tab, int  $perPage) : \Illuminate\Contracts\Pagination\LengthAwarePaginator

我的消息分页(恒为本人可见集合;tab=announcement 公告 / system 系统通知)。

Parameters

\App\Models\SysUser $user
string $tab

announcement | system

int $perPage

Returns

\Illuminate\Contracts\Pagination\LengthAwarePaginator —

myUnreadCount()

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

我的未读数(总数 + 分类型:公告 / 系统通知;徽标与页签计数数据源)。

Parameters

\App\Models\SysUser $user

Returns

array —

myShow()

myShow(\App\Models\SysUser  $user, int  $id) : array

我的消息详情(need_read=1 时自动标记已读,幂等)。

Parameters

\App\Models\SysUser $user
int $id

Returns

array —

myReadAll()

myReadAll(\App\Models\SysUser  $user) : int

全部已读:批量差集插入(当时可见 need_read 通知全量标记),返回本次新标记数。

Parameters

\App\Models\SysUser $user

Returns

int —

sendSystemMessage()

sendSystemMessage(array|int  $userIds, string  $type, string  $title, string  $content, ?string  $bizKey = null, int  $needRead = SysMessage::NEED_READ_YES) : ?\App\Models\SysMessage

发送系统事件消息(target_type=user,sender_id=0,立即可见)。 needRead 由事件携带(默认 1 跟踪已读;0=仅展示,不参与未读)。 biz_key 撞唯一索引时静默忽略(幂等:同事件只发一次)。

Parameters

array|int $userIds

目标用户 id(可单个或多个)

string $type
string $title
string $content
?string $bizKey
int $needRead

是否需记录已读(SysMessage::NEED_READ_*)

Returns

?\App\Models\SysMessage —

workerAlarmWithinWindow()

workerAlarmWithinWindow() : bool

Worker 告警窗口判定:最近一条 worker 告警在窗口内(重复失联不再发)。

供 WriteMessageNotify 监听器使用(worker 失联事件触发前的去重判断)。

Returns

bool —

superAdminIds()

superAdminIds() : int[]

全部超管用户 id(worker 失联告警目标;监听器侧取)。

Returns

int[] —

doSendSystemMessage()

doSendSystemMessage(array|int  $userIds, string  $type, string  $title, string  $content, ?string  $bizKey = null, int  $needRead = SysMessage::NEED_READ_YES) : ?\App\Models\SysMessage

发送系统事件消息(target_type=user,sender_id=0,立即可见)。 biz_key 撞唯一索引时静默忽略(幂等:同事件只发一次)。

Parameters

array|int $userIds

目标用户 id(可单个或多个)

string $type
string $title
string $content
?string $bizKey
int $needRead

是否需记录已读(SysMessage::NEED_READ_*)

Returns

?\App\Models\SysMessage —

fillEditable()

fillEditable(\App\Models\SysMessage  $message, array  $data) : void

可编辑字段落库(公告与系统事件共用字段白名单;target_ids 归一为数组)。

Parameters

\App\Models\SysMessage $message
array $data

visibleQuery()

visibleQuery(\App\Models\SysUser  $user) : \Illuminate\Database\Eloquent\Builder

我的可见通知查询(含 is_read 派生列,未读排序用)。

可见性实现:先预取本人任职(dept_id/post_id)与角色 id 集合(索引小查询), 再逐 id whereJsonContains 匹配 target_ids(Laravel 生成 PG jsonb @> / sqlite json_each,跨库兼容);无任职/角色的维度自动短路,避免空集合全表命中。

Parameters

\App\Models\SysUser $user

Returns

\Illuminate\Database\Eloquent\Builder —

attachReadFlags()

attachReadFlags(\App\Models\SysUser  $user, \App\Models\SysMessage[]  $items) : void

列表行附加已读标记(一次性批量查询,防 N+1)。

Parameters

\App\Models\SysUser $user
\App\Models\SysMessage[] $items

expandDeptIds()

expandDeptIds(int[]  $ids) : int[]

部门目标展开:目标部门 + 全部子孙部门(ancestors 段匹配,发布时快照)。

Parameters

int[] $ids

Returns

int[] —

targetCount()

targetCount(string  $targetType, int[]  $ids) : int

目标人数快照(发布时 count 一次,统计用;all 取启用用户)。

Parameters

string $targetType
int[] $ids

Returns

int —