feat(dialog): 系统设置支持禁止其他人员设置/取消聊天待办

新增系统级开关 todo_set_permission(open=允许默认 / close=禁止)。
开关为禁止时,仅本人、群主/群管理员、项目负责人/项目管理员、任务负责人
可设置或取消聊天消息待办,其他人由后端拦截;默认允许,保持现有行为。

- SystemController::setting 接入开关读写(白名单 + 默认 open)
- WebSocketDialog::checkTodoOwnerPermission 角色判断(复用 isOwner 等)
- WebSocketDialogMsg::toggleTodoMsg 内权限闸门:close 且影响到他人且
  非放行角色时 retError;仅影响自己始终放行;open 时行为零变化
- SystemSetting.vue「消息相关」新增「待办设置权限」开关 UI
- 国际化文案(original-api.txt / original-web.txt)
- TodoSetPermissionTest 覆盖角色判断、闸门决策及真实拦截路径(8 用例)

任务 #124。系统后台 admin 不特殊放行;「完成待办」不在本次范围。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
kuaifan
2026-05-31 15:12:46 +00:00
parent e57736bcc1
commit aa2e0acaba
7 changed files with 300 additions and 0 deletions

View File

@@ -423,6 +423,14 @@ class WebSocketDialogMsg extends AbstractModel
$current = WebSocketDialogMsgTodo::whereMsgId($this->id)->pluck('userid')->toArray();
$cancel = array_diff($current, $userids);
$setup = array_diff($userids, $current);
// 待办操作权限管控(系统开关:禁止其他人员设置/取消待办)
if (Base::settingFind('system', 'todo_set_permission') === 'close') {
$affected = array_unique(array_merge($cancel, $setup)); // 本次真正影响到的用户
$others = array_diff($affected, [$sender]); // 排除"自己"
if ($others && !$dialog->checkTodoOwnerPermission($sender)) {
return Base::retError('仅群主、项目/任务负责人可设置或取消他人待办');
}
}
//
$this->todo = $setup || count($current) > count($cancel) ? $sender : 0;
$this->save();