diff --git a/app/Http/Controllers/Api/ProjectController.php b/app/Http/Controllers/Api/ProjectController.php
index bb4242856..1db3a301a 100755
--- a/app/Http/Controllers/Api/ProjectController.php
+++ b/app/Http/Controllers/Api/ProjectController.php
@@ -16,6 +16,7 @@ use App\Models\ProjectLog;
use App\Models\ProjectTask;
use App\Models\ProjectTaskFile;
use App\Models\ProjectTaskFlowChange;
+use App\Models\ProjectTaskUser;
use App\Models\ProjectUser;
use App\Models\User;
use App\Models\WebSocketDialog;
@@ -880,8 +881,17 @@ class ProjectController extends AbstractController
public function task__lists()
{
$user = User::auth();
- //
+
+ // 任务可见性
+ $project_ids = Project::whereUserid($user->userid)->pluck('id')->toArray(); // 负责人项目ids
+ $main_task_ids = ProjectTask::whereIn('project_id', $project_ids)->pluck('id')->toArray(); // 负责人项目任务ids
+ $other_task_ids = ProjectTaskUser::whereUserid($user->userid)->whereColumn('task_id', '=', 'task_pid')->whereNotIn('project_id', $project_ids)->pluck('task_id')->toArray(); // 非负责人项目任务ids
+ $all_visible_task_ids = ProjectTask::whereIsAllVisible(1)->pluck('id')->toArray(); // 所有人可见项目ids
+ $one_task_ids = array_merge($main_task_ids, $other_task_ids);
+ $visibility_task_ids = array_merge($one_task_ids, $all_visible_task_ids);
+
$builder = ProjectTask::with(['taskUser', 'taskTag']);
+ $builder->whereIn("project_tasks.id", $visibility_task_ids);
//
$parent_id = intval(Request::input('parent_id'));
$project_id = intval(Request::input('project_id'));
@@ -1326,17 +1336,26 @@ class ProjectController extends AbstractController
*/
public function task__one()
{
- User::auth();
+ $user = User::auth();
//
$task_id = intval(Request::input('task_id'));
$archived = Request::input('archived', 'no');
//
$isArchived = str_replace(['all', 'yes', 'no'], [null, false, true], $archived);
$task = ProjectTask::userTask($task_id, $isArchived, true, false, ['taskUser', 'taskTag']);
+ // 项目可见性
+ $project_userid = Project::whereId($task->project_id)->value('userid'); // 项目负责人
+ if ($task->is_all_visible != 1 && $user->userid != $project_userid) {
+ $visibleUserids = ProjectTaskUser::whereTaskId($task_id)->pluck('userid')->toArray();
+ if (!in_array($user->userid, $visibleUserids)) {
+ return Base::retError('无任务权限');
+ }
+ }
//
$data = $task->toArray();
$data['project_name'] = $task->project?->name;
$data['column_name'] = $task->projectColumn?->name;
+ $data['visibility_appointor'] = $task->is_all_visible==1 ? [0] : ProjectTaskUser::whereTaskId($task_id)->whereOwner(2)->pluck('userid');
return Base::retSuccess('success', $data);
}
@@ -1542,7 +1561,7 @@ class ProjectController extends AbstractController
*/
public function task__add()
{
- User::auth();
+ $user = User::auth();
//
$data = Request::input();
$project_id = intval($data['project_id']);
@@ -1587,6 +1606,17 @@ class ProjectController extends AbstractController
$data = $data->toArray();
$data['new_column'] = $newColumn;
}
+
+
+ if ($data['is_all_visible'] == 1) {
+ $data['is_visible'] = 1;
+ } else {
+ $projectOwner = Project::whereId($data['project_id'])->pluck('userid')->toArray(); // 项目负责人
+ $taskOwnerAndAssists = ProjectTaskUser::select(['userid', 'owner'])->whereTaskId($data['id'])->pluck('userid')->toArray();
+ $visibleIds = array_merge($projectOwner, $taskOwnerAndAssists);
+ $data['is_visible'] = in_array($user->userid, $visibleIds) ? 1 : 0;
+ }
+
$task->pushMsg('add', $data);
$task->taskPush(null, 0);
return Base::retSuccess('添加成功', $data);
@@ -1648,6 +1678,7 @@ class ProjectController extends AbstractController
* @apiParam {String} [content] 任务详情(子任务不支持)
* @apiParam {String} [color] 背景色(子任务不支持)
* @apiParam {Array} [assist] 修改协助人员(子任务不支持)
+ * @apiParam {Array} [visibility_appointor] 修改可见性人员
*
* @apiParam {Number} [p_level] 优先级相关(子任务不支持)
* @apiParam {String} [p_name] 优先级相关(子任务不支持)
@@ -1664,17 +1695,31 @@ class ProjectController extends AbstractController
{
User::auth();
//
- $data = Request::input();
- $task_id = intval($data['task_id']);
+ $param = Request::input();
+ $task_id = intval($param['task_id']);
//
$task = ProjectTask::userTask($task_id, true, true, 2);
// 更新任务
$updateMarking = [];
- $task->updateTask($data, $updateMarking);
+ $task->updateTask($param, $updateMarking);
//
$data = ProjectTask::oneTask($task->id)->toArray();
$data['update_marking'] = $updateMarking ?: json_decode('{}');
+ $data['visibility_appointor'] = $data['is_all_visible'] == 1 ? [0] : ProjectTaskUser::whereTaskId($task->id)->whereOwner(2)->pluck('userid');
$task->pushMsg('update', $data);
+ // 可见性推送
+ if (Arr::exists($param, 'visibility_appointor')) {
+ if ($data['is_all_visible'] == 1) {
+ $task->pushMsgVisibleAdd($data);
+ }
+ if ($data['is_all_visible'] == 0) {
+ if ($param['visibility_appointor']) {
+ $task->pushMsgVisibleUpdate($data);
+ } else {
+ $task->pushMsgVisibleRemove();
+ }
+ }
+ }
//
return Base::retSuccess('修改成功', $data);
}
diff --git a/app/Models/ProjectTask.php b/app/Models/ProjectTask.php
index 6b319bfa5..3ac4e0e62 100644
--- a/app/Models/ProjectTask.php
+++ b/app/Models/ProjectTask.php
@@ -370,6 +370,18 @@ class ProjectTask extends AbstractModel
$p_color = $data['p_color'];
$top = intval($data['top']);
$userid = User::userid();
+ $visibility_appoint = $data['visibility_appoint'];
+ $visibility_appointor = $data['visibility_appointor'];
+ // 可见性
+ $visibility_userids = [];
+ $is_all_visible = 0;
+ if ($visibility_appoint) {
+ if (in_array(0, $visibility_appointor)) {
+ $is_all_visible = 1;
+ } else {
+ $visibility_userids = $visibility_appointor;
+ }
+ }
//
if (ProjectTask::whereProjectId($project_id)
->whereNull('project_tasks.complete_at')
@@ -398,6 +410,7 @@ class ProjectTask extends AbstractModel
'p_level' => $p_level,
'p_name' => $p_name,
'p_color' => $p_color,
+ 'is_all_visible' => $is_all_visible
]);
if ($content) {
$task->desc = Base::getHtml($content, 100);
@@ -462,7 +475,7 @@ class ProjectTask extends AbstractModel
}
}
//
- return AbstractModel::transaction(function() use ($assist, $times, $subtasks, $content, $owner, $task) {
+ return AbstractModel::transaction(function() use ($assist, $times, $subtasks, $content, $owner, $task, $visibility_userids) {
$task->save();
$owner = array_values(array_unique($owner));
foreach ($owner as $uid) {
@@ -484,6 +497,17 @@ class ProjectTask extends AbstractModel
'owner' => 0,
])->save();
}
+
+ foreach ($visibility_userids as $uid) {
+ ProjectTaskUser::createInstance([
+ 'project_id' => $task->project_id,
+ 'task_id' => $task->id,
+ 'task_pid' => $task->parent_id ?: $task->id,
+ 'userid' => $uid,
+ 'owner' => 2,
+ ])->save();
+ }
+
if ($content) {
ProjectTaskContent::createInstance([
'project_id' => $task->project_id,
@@ -691,6 +715,26 @@ class ProjectTask extends AbstractModel
$updateMarking['is_update_project'] = true;
$this->syncDialogUser();
}
+ // 可见性
+ if (Arr::exists($data, 'visibility_appointor')) {
+ if (in_array(0, $data['visibility_appointor'])) {
+ ProjectTask::whereId($data['task_id'])->update(['is_all_visible' => 1]);
+ } else {
+ ProjectTask::whereId($data['task_id'])->update(['is_all_visible' => 0]);
+ // 覆盖
+ ProjectTaskUser::whereTaskId($data['task_id'])->whereOwner(2)->delete();
+ foreach ($data['visibility_appointor'] as $uid) {
+ ProjectTaskUser::createInstance([
+ 'project_id' => $this->project_id,
+ 'task_id' => $this->id,
+ 'task_pid' => $this->parent_id ?: $this->id,
+ 'userid' => $uid,
+ 'owner' => 2,
+ ])->save();
+ }
+
+ }
+ }
// 计划时间(原则:子任务时间在主任务时间内)
if (Arr::exists($data, 'times')) {
$oldAt = [Carbon::parse($this->start_at), Carbon::parse($this->end_at)];
@@ -1372,6 +1416,8 @@ class ProjectTask extends AbstractModel
$userids = $this->project->relationUserids();
} elseif (!is_array($userid)) {
$userids = [$userid];
+ } elseif (is_array($userid)) {
+ $userids = $userid;
}
//
$array = [];
@@ -1391,8 +1437,10 @@ class ProjectTask extends AbstractModel
];
}
// 协助人
- $assists = $taskUser->pluck('userid')->toArray();
- $assists = array_intersect($userids, array_diff($assists, $owners));
+// $assists = $taskUser->pluck('userid')->toArray();
+// $assists = array_intersect($userids, array_diff($assists, $owners));
+ $assists = $taskUser->where('owner', 0)->pluck('userid')->toArray();
+ $assists = array_intersect($userids, $assists);
if ($assists) {
$array[] = [
'userid' => array_values($assists),
@@ -1403,13 +1451,21 @@ class ProjectTask extends AbstractModel
];
}
// 项目成员(其他人)
- $userids = array_diff($userids, $owners, $assists);
+ if ($data['is_all_visible'] == 1) {
+ // 全部可见
+ $userids = array_diff($userids, $owners, $assists);
+ } else {
+ // 指定可见
+ $visible = $taskUser->where('owner', 2)->pluck('userid')->toArray();
+ $userids = $visible;
+ }
$data = array_merge($data, [
'owner' => 0,
'assist' => 0,
]);
}
}
+ //
$array[] = [
'userid' => array_values($userids),
'data' => $data
@@ -1430,6 +1486,116 @@ class ProjectTask extends AbstractModel
}
}
+ /**
+ * 添加可见性任务 推送
+ * @param array|self $data 发送内容,默认为[id, parent_id, project_id, column_id, dialog_id]
+ */
+ public function pushMsgVisibleAdd($data = null)
+ {
+ if (!$this->project) {
+ return;
+ }
+ if ($data === null) {
+ $data = [
+ 'id' => $this->id,
+ 'parent_id' => $this->parent_id,
+ 'project_id' => $this->project_id,
+ 'column_id' => $this->column_id,
+ 'dialog_id' => $this->dialog_id,
+ ];
+ } elseif ($data instanceof self) {
+ $data = $data->toArray();
+ }
+ //
+ $array = [];
+ if ($this->is_all_visible == 0) {
+ $userids = ProjectTaskUser::select(['userid', 'owner'])->whereTaskId($this->id)->pluck('userid')->toArray();
+ } else {
+ $userids = ProjectUser::whereProjectId($this->project_id)->pluck('userid')->toArray(); // 项目成员
+ }
+ //
+ $array[] = [
+ 'userid' => array_values($userids),
+ 'data' => $data
+ ];
+ //
+ foreach ($array as $item) {
+ $params = [
+// 'ignoreFd' => Request::header('fd'),
+ 'ignoreFd' => '0',
+ 'userid' => array_values($item),
+ 'msg' => [
+ 'type' => 'projectTask',
+ 'action' => 'add',
+ 'data' => $item['data'],
+ ]
+ ];
+ $task = new PushTask($params, false);
+ Task::deliver($task);
+ }
+ }
+
+ /**
+ * 删除可见性任务 推送
+ * @param string $action
+ * @param array|self $data 发送内容,默认为[id, parent_id, project_id, column_id, dialog_id]
+ */
+ public function pushMsgVisibleRemove($data = null)
+ {
+ if (!$this->project) {
+ return;
+ }
+ if ($data === null) {
+ $data = [
+ 'id' => $this->id,
+ 'parent_id' => $this->parent_id,
+ 'project_id' => $this->project_id,
+ 'column_id' => $this->column_id,
+ 'dialog_id' => $this->dialog_id,
+ ];
+ } elseif ($data instanceof self) {
+ $data = $data->toArray();
+ }
+ //
+ $array = [];
+ // 项目成员 与 项目负责人,任务负责人、协助人的差集
+ $projectUserids = ProjectUser::whereProjectId($this->project_id)->pluck('userid')->toArray(); // 项目成员
+ $projectOwner = Project::whereId($this->project_id)->pluck('userid')->toArray(); // 项目负责人
+ $taskOwnerAndAssists = ProjectTaskUser::select(['userid', 'owner'])->whereIn('owner', [0, 1])->whereTaskId($this->id)->pluck('userid')->toArray();
+ $userids = array_diff($projectUserids, $projectOwner, $taskOwnerAndAssists);
+ //
+ $array[] = [
+ 'userid' => array_values($userids),
+ 'data' => $data
+ ];
+ //
+ foreach ($array as $item) {
+ $params = [
+// 'ignoreFd' => Request::header('fd'),
+ 'ignoreFd' => '0',
+ 'userid' => array_values($item),
+ 'msg' => [
+ 'type' => 'projectTask',
+ 'action' => 'delete',
+ 'data' => $item['data'],
+ ]
+ ];
+ $task = new PushTask($params, false);
+ Task::deliver($task);
+ }
+ }
+
+ /**
+ * 更新可见性任务 推送
+ * @param array|self $data 发送内容,默认为[id, parent_id, project_id, column_id, dialog_id]
+ */
+ public function pushMsgVisibleUpdate($data)
+ {
+ $this->pushMsgVisibleRemove();
+ usleep(300);
+ $this->pushMsgVisibleAdd($data);
+ }
+
/**
* 任务提醒
* @param $userids
diff --git a/app/Tasks/PushTask.php b/app/Tasks/PushTask.php
index 6f506f734..2e02d0acf 100644
--- a/app/Tasks/PushTask.php
+++ b/app/Tasks/PushTask.php
@@ -149,7 +149,7 @@ class PushTask extends AbstractTask
if (!is_array($userid)) {
$userid = [$userid];
}
- foreach ($userid as $uid) {
+ foreach ($userid[0] as $uid) {
$row = WebSocket::select(['fd'])->whereUserid($uid)->pluck('fd');
if ($row->isNotEmpty()) {
$array = array_merge($array, $row->toArray());
@@ -162,6 +162,8 @@ class PushTask extends AbstractTask
$ignoreFd = is_array($ignoreFd) ? $ignoreFd : [$ignoreFd];
}
// 开始发送
+ \Log::info('fd');
+ \Log::info($array);
foreach ($array as $fid) {
if ($ignoreFd) {
if (in_array($fid, $ignoreFd)) continue;
diff --git a/database/migrations/2023_06_15_093619_add_project_tasks_is_all_visible.php b/database/migrations/2023_06_15_093619_add_project_tasks_is_all_visible.php
new file mode 100644
index 000000000..ac95cf314
--- /dev/null
+++ b/database/migrations/2023_06_15_093619_add_project_tasks_is_all_visible.php
@@ -0,0 +1,36 @@
+tinyInteger('is_all_visible')->nullable()->default(1)->after('is_default')->comment('是否所有人可见');
+ }
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ //
+ Schema::table('project_tasks', function (Blueprint $table) {
+ $table->dropColumn("avatar");
+ });
+ }
+}
diff --git a/resources/assets/js/pages/manage/components/TaskAdd.vue b/resources/assets/js/pages/manage/components/TaskAdd.vue
index 8062266e2..0d61dc532 100644
--- a/resources/assets/js/pages/manage/components/TaskAdd.vue
+++ b/resources/assets/js/pages/manage/components/TaskAdd.vue
@@ -92,6 +92,25 @@
+