dootask/app/Observers/ProjectTaskObserver.php
kuaifan 24710289e1 feat(multi-owner): 群/项目/部门支持主+副双负责人体系
- 群组:新增 web_socket_dialog_users.role(1=主、2=副),主可任命/罢免副群主,副可邀请/移出普通成员
- 项目:project_users.owner 扩展为 0/1/2(成员/主/副),主独占转让和删除,副共享日常管理;任务可见性、通知、分配等下游逻辑统一用「主+副」
- 部门:新增 user_department_owners 表存储副负责人;部门群同步副群主,赋予群管理员权限
- 转移用户时副身份不替补、降级为普通成员
- 配套 migration/backfill、API、前端 UI、i18n 词条与三项 Feature 测试
- .gitignore 忽略 .playwright-mcp/
2026-05-03 00:05:31 +00:00

154 lines
5.5 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace App\Observers;
use App\Models\Deleted;
use App\Models\ProjectTask;
use App\Models\ProjectTaskUser;
use App\Models\ProjectTaskVisibilityUser;
use App\Models\ProjectUser;
use App\Tasks\ManticoreSyncTask;
class ProjectTaskObserver extends AbstractObserver
{
/**
* Handle the ProjectTask "created" event.
*
* @param \App\Models\ProjectTask $projectTask
* @return void
*/
public function created(ProjectTask $projectTask)
{
self::taskDeliver(new ManticoreSyncTask('task_sync', $projectTask->toArray()));
}
/**
* Handle the ProjectTask "updated" event.
*
* @param \App\Models\ProjectTask $projectTask
* @return void
*/
public function updated(ProjectTask $projectTask)
{
if ($projectTask->isDirty('visibility')) {
self::visibilityUpdate($projectTask);
}
if ($projectTask->isDirty('archived_at')) {
if ($projectTask->archived_at) {
Deleted::record('projectTask', $projectTask->id, self::userids($projectTask));
} else {
Deleted::forget('projectTask', $projectTask->id, self::userids($projectTask));
}
}
// 检查是否有搜索相关字段变化或权限相关字段变化
// visibility 变化会影响 allowed_users 来源
// parent_id 变化会影响子任务继承
// project_id 变化会影响 visibility=1 的任务权限
$searchableFields = ['name', 'desc', 'archived_at', 'project_id', 'visibility', 'parent_id'];
$isDirty = false;
foreach ($searchableFields as $field) {
if ($projectTask->isDirty($field)) {
$isDirty = true;
break;
}
}
if ($isDirty) {
if ($projectTask->archived_at) {
self::taskDeliver(new ManticoreSyncTask('task_delete', ['task_id' => $projectTask->id]));
} else {
// 重新同步任务(会重新计算 allowed_users
self::taskDeliver(new ManticoreSyncTask('task_sync', $projectTask->toArray()));
}
}
}
/**
* Handle the ProjectTask "deleted" event.
*
* @param \App\Models\ProjectTask $projectTask
* @return void
*/
public function deleted(ProjectTask $projectTask)
{
Deleted::record('projectTask', $projectTask->id, self::userids($projectTask));
self::taskDeliver(new ManticoreSyncTask('task_delete', ['task_id' => $projectTask->id]));
}
/**
* Handle the ProjectTask "restored" event.
*
* @param \App\Models\ProjectTask $projectTask
* @return void
*/
public function restored(ProjectTask $projectTask)
{
Deleted::forget('projectTask', $projectTask->id, self::userids($projectTask));
self::taskDeliver(new ManticoreSyncTask('task_sync', $projectTask->toArray()));
}
/**
* Handle the ProjectTask "force deleted" event.
*
* @param \App\Models\ProjectTask $projectTask
* @return void
*/
public function forceDeleted(ProjectTask $projectTask)
{
self::taskDeliver(new ManticoreSyncTask('task_delete', ['task_id' => $projectTask->id]));
}
/**
* @param ProjectTask $projectTask
* @param string[]|string $dataType
* @return array
*/
public static function userids(ProjectTask $projectTask, array|string $dataType = 'project')
{
if (!is_array($dataType)) {
$dataType = [$dataType];
}
if (in_array('project', $dataType)) {
return ProjectUser::whereProjectId($projectTask->project_id)->pluck('userid')->toArray();
}
if (in_array('projectOwnerUser', $dataType)) {
return ProjectUser::whereProjectId($projectTask->project_id)
->whereIn('owner', [ProjectUser::OWNER_PRIMARY, ProjectUser::OWNER_DEPUTY])
->pluck('userid')->toArray();
}
$array = [];
if (in_array('task', $dataType)) {
$array = array_merge($array, ProjectTaskUser::whereTaskId($projectTask->id)->orWhere('task_pid' ,$projectTask->id)->pluck('userid')->toArray());
}
if (in_array('visibility', $dataType)) {
$array = array_merge($array, ProjectTaskVisibilityUser::whereTaskId($projectTask->id)->pluck('userid')->toArray());
}
return array_values(array_filter(array_unique($array)));
}
/**
* 可见性更新
* @param ProjectTask $projectTask
*/
public static function visibilityUpdate(ProjectTask $projectTask)
{
$projectUserids = self::userids($projectTask);
switch ($projectTask->visibility) {
case 1:
Deleted::forget('projectTask', $projectTask->id, $projectUserids);
break;
case 2:
case 3:
$dataType = $projectTask->visibility == 2 ? ['task'] : ['task', 'visibility'];
$forgetUserids = self::userids($projectTask, $dataType);
$projectOwnerUserIds = self::userids($projectTask, 'projectOwnerUser');
$recordUserids = array_diff($projectUserids, $forgetUserids, $projectOwnerUserIds);
Deleted::record('projectTask', $projectTask->id, $recordUserids);
Deleted::forget('projectTask', $projectTask->id, $forgetUserids);
break;
}
ProjectTask::whereParentId($projectTask->id)->change(['visibility' => $projectTask->visibility]);
}
}