feat(manage): 部门负责人视角支持项目级可见开关并尊重任务可见性

新增项目级"负责人视角"开关(projects.department_owner_view,默认开启),
项目负责人可关闭,关闭后该项目及其群聊对部门负责人视角隐藏。同时将负责人
只读视角调整为尊重任务可见性:仅"全员可见"任务可被查看/进入任务群,指定
成员可见的任务仅对被指定成员开放。

- 新增 projects.department_owner_view 字段(migration)
- ProjectController::update 支持读写该开关
- UserDepartment::ownerViewContext 过滤已关闭项目,并合并为单次 JOIN 查询
- ProjectTask::findForDepartmentView / task__one / tasks 列表尊重任务可见性
- WebSocketDialog::checkDialog 任务群按可见性放行
- 前端项目设置新增开关(仅系统开启该功能时显示)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
kuaifan
2026-05-21 04:44:51 +00:00
parent 0863e5529a
commit 7f7a82b4b8
10 changed files with 71 additions and 14 deletions

View File

@@ -904,15 +904,19 @@ class WebSocketDialog extends AbstractModel
case 'project':
case 'task':
// 项目群、任务群对话校验是否在项目内
$taskVisibility = 1; // 项目群不涉及任务可见性,按可见处理
if ($dialog->group_type === 'project') {
$projectId = intval(Project::whereDialogId($dialog->id)->value('id'));
} else {
$projectId = intval(ProjectTask::whereDialogId($dialog->id)->value('project_id'));
$taskRow = ProjectTask::select(['project_id', 'visibility'])->whereDialogId($dialog->id)->first();
$projectId = intval($taskRow?->project_id);
$taskVisibility = intval($taskRow?->visibility);
}
if ($projectId > 0 && ProjectUser::whereProjectId($projectId)->whereUserid($userid)->exists()) {
return $dialog;
}
if ($projectId > 0 && $checkOwner === false) {
// 部门负责人只读视角:项目群放行;任务群仅"全员可见"任务放行,指定成员可见任务不放行
if ($projectId > 0 && $checkOwner === false && ($dialog->group_type === 'project' || $taskVisibility === 1)) {
$departmentView = UserDepartment::ownerViewContext(User::auth(), true);
if (UserDepartment::isDepartmentReadonlyProject($departmentView, $projectId)) {
return $dialog;