diff --git a/app/Http/Controllers/Api/ProjectController.php b/app/Http/Controllers/Api/ProjectController.php index 8256d61cb..baf771cc6 100755 --- a/app/Http/Controllers/Api/ProjectController.php +++ b/app/Http/Controllers/Api/ProjectController.php @@ -45,6 +45,7 @@ use App\Models\ProjectTaskVisibilityUser; use App\Models\ProjectTaskTemplate; use App\Models\ProjectTag; use App\Models\ProjectTaskRelation; +use App\Observers\ProjectTaskObserver; /** * @apiDefine project @@ -2230,6 +2231,131 @@ class ProjectController extends AbstractController return Base::retSuccess('添加成功', $data); } + /** + * @api {get} api/project/task/upgrade 36. 子任务升级为主任务 + * + * @apiDescription 需要token身份(限:项目、任务负责人) + * @apiVersion 1.0.0 + * @apiGroup project + * @apiName task__upgrade + * + * @apiParam {Number} task_id 子任务ID + * + * @apiSuccess {Number} ret 返回状态码(1正确、0错误) + * @apiSuccess {String} msg 返回信息(错误描述) + * @apiSuccess {Object} data 返回数据 + */ + public function task__upgrade() + { + $user = User::auth(); + // + $task_id = intval(Request::input('task_id')); + // + $task = ProjectTask::userTask($task_id, true, true, ['taskUser']); + if ($task->parent_id == 0) { + return Base::retError('当前任务已是主任务'); + } + // + $project = Project::userProject($task->project_id); + ProjectPermission::userTaskPermission($project, ProjectPermission::TASK_MOVE, $task); + // + $parentTask = ProjectTask::withTrashed()->find($task->parent_id); + $visibilityUserids = []; + if ($task->visibility == 3) { + $visibilityUserids = ProjectTaskVisibilityUser::whereTaskId($task->id)->pluck('userid')->toArray(); + if (empty($visibilityUserids) && $parentTask) { + $visibilityUserids = ProjectTaskVisibilityUser::whereTaskId($parentTask->id)->pluck('userid')->toArray(); + } + } + // + DB::transaction(function () use ($task, $parentTask, $visibilityUserids) { + $task->lockForUpdate(); + $task->parent_id = 0; + if ($parentTask) { + $task->p_level = $parentTask->p_level; + $task->p_name = $parentTask->p_name; + $task->p_color = $parentTask->p_color; + } + $task->save(); + ProjectTaskUser::whereTaskId($task->id)->update(['task_pid' => $task->id]); + if ($task->visibility == 3 && !empty($visibilityUserids)) { + ProjectTaskVisibilityUser::whereTaskId($task->id)->delete(); + foreach (array_unique($visibilityUserids) as $userid) { + if (!$userid) { + continue; + } + ProjectTaskVisibilityUser::createInstance([ + 'project_id' => $task->project_id, + 'task_id' => $task->id, + 'userid' => $userid, + ])->save(); + } + } + if ($parentTask) { + $parentTask->addLog("子任务升级为主任务", [ + 'subtask' => [ + 'id' => $task->id, + 'name' => $task->name, + ], + ]); + } + $task->addLog("升级为主任务"); + }); + // + $task->refresh()->loadMissing(['project', 'taskUser']); + if ($task->visibility != 1) { + ProjectTaskObserver::visibilityUpdate($task); + } + $taskData = ProjectTask::oneTask($task->id); + $parentData = null; + if ($parentTask && !$parentTask->trashed()) { + $parentTask->refresh()->loadMissing(['project', 'taskUser']); + $parentData = ProjectTask::oneTask($parentTask->id); + } + // + $taskArray = $taskData ? $taskData->toArray() : []; + $parentArray = $parentData ? $parentData->toArray() : null; + if ($taskArray) { + $task->pushMsg('update', $taskArray); + } + if ($parentArray && $parentTask) { + $parentTask->pushMsg('update', $parentArray); + } + if ($parentTask && !$parentTask->trashed()) { + $mentionRelation = ProjectTaskRelation::updateOrCreate( + [ + 'task_id' => $task->id, + 'related_task_id' => $parentTask->id, + 'direction' => ProjectTaskRelation::DIRECTION_MENTIONED_BY, + ], + [ + 'userid' => $user->userid ?? null, + ] + ); + $mentionedByRelation = ProjectTaskRelation::updateOrCreate( + [ + 'task_id' => $parentTask->id, + 'related_task_id' => $task->id, + 'direction' => ProjectTaskRelation::DIRECTION_MENTION, + ], + [ + 'userid' => $user->userid ?? null, + ] + ); + if ($mentionRelation->wasRecentlyCreated || $mentionRelation->wasChanged()) { + $task->pushMsg('relation', null, null, false); + } + if ($mentionedByRelation->wasRecentlyCreated || $mentionedByRelation->wasChanged()) { + $parentTask->pushMsg('relation', null, null, false); + } + } + // + return Base::retSuccess('操作成功', [ + 'task' => $taskArray, + 'parent' => $parentArray, + ]); + } + /** * @api {post} api/project/task/update 35. 修改任务、子任务 * diff --git a/language/original-api.txt b/language/original-api.txt index 6c0ee24ff..fe9a5d2c1 100644 --- a/language/original-api.txt +++ b/language/original-api.txt @@ -920,4 +920,8 @@ URL格式不正确 收藏记录不存在 修改备注成功 请输入修改备注 -备注最多支持(*)个字符 \ No newline at end of file +备注最多支持(*)个字符 + +当前任务已是主任务 +子任务升级为主任务 +升级为主任务 \ No newline at end of file diff --git a/language/original-web.txt b/language/original-web.txt index 62f530867..dd7d3c08a 100644 --- a/language/original-web.txt +++ b/language/original-web.txt @@ -2214,3 +2214,8 @@ AI 未生成内容 暂无共同群组 (*)个 查看更多... + +子任务升级为主任务 +升级为主任务 +升主任务 +你确定要将子任务【(*)】升级为主任务吗? \ No newline at end of file diff --git a/resources/assets/js/pages/manage/components/TaskOperation.vue b/resources/assets/js/pages/manage/components/TaskOperation.vue index 878224a0e..c377092a0 100644 --- a/resources/assets/js/pages/manage/components/TaskOperation.vue +++ b/resources/assets/js/pages/manage/components/TaskOperation.vue @@ -86,11 +86,18 @@ - -
- {{$L('删除')}} -
-
+ @@ -342,6 +349,10 @@ export default { this.$refs.forwarder.onSelection() break; + case 'upgrade': + this.upgradeSubtask(); + break; + case 'archived': case 'remove': this.archivedOrRemoveTask(command); @@ -391,6 +402,33 @@ export default { }) }, + upgradeSubtask() { + if (this.loadIng) { + return; + } + $A.modalConfirm({ + title: '升级为主任务', + content: `你确定要将子任务【${this.task.name}】升级为主任务吗?`, + loading: true, + onOk: () => { + if (this.loadIng) { + return; + } + return new Promise((resolve, reject) => { + this.$store.dispatch("taskConvertToMain", this.task.id).then(({data, msg}) => { + $A.messageSuccess(msg); + this.hide(); + this.$store.dispatch("openTask", data?.task?.id || this.task.id); + resolve(); + }).catch(({msg}) => { + $A.modalError(msg); + reject(); + }); + }) + } + }); + }, + archivedOrRemoveTask(type) { let typeDispatch = 'removeTask'; let typeName = '删除'; diff --git a/resources/assets/js/store/actions.js b/resources/assets/js/store/actions.js index 755aea120..0b6b9959f 100644 --- a/resources/assets/js/store/actions.js +++ b/resources/assets/js/store/actions.js @@ -2276,6 +2276,47 @@ export default { }); }, + /** + * 子任务升级为主任务 + * @param dispatch + * @param data Number|JSONObject{task_id} + * @returns {Promise} + */ + taskConvertToMain({dispatch}, data) { + return new Promise(function (resolve, reject) { + if (/^\d+$/.test(data)) { + data = {task_id: data} + } + if ($A.runNum(data.task_id) === 0) { + reject({msg: 'Parameter error'}); + return; + } + dispatch("setLoad", { + key: `task-${data.task_id}`, + delay: 300 + }) + dispatch("call", { + url: 'project/task/upgrade', + data, + }).then(result => { + const {task, parent} = result.data || {}; + if (task) { + dispatch("saveTask", task); + } + if (parent) { + dispatch("saveTask", parent); + } + resolve(result) + }).catch(e => { + console.warn(e); + dispatch("getTaskOne", data.task_id).catch(() => {}) + reject(e) + }).finally(_ => { + dispatch("cancelLoad", `task-${data.task_id}`) + }); + }); + }, + /** * 获取任务详细描述 * @param state