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('删除')}}
-
-
+
+
+
+ {{$L('升主任务')}}
+
+
+
+
+ {{$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