From 827bc97e8e18d7ce9ef796e893a371a936660d5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A6=E8=8D=A3=E8=B6=85?= <302645122@qq.com> Date: Wed, 2 Mar 2022 15:19:48 +0800 Subject: [PATCH] =?UTF-8?q?perf:=20=E5=AF=BC=E5=87=BA=E6=8A=A5=E8=A1=A8?= =?UTF-8?q?=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/Api/ProjectController.php | 62 +++++++++++++++++++ app/Models/Project.php | 7 +++ app/Module/Base.php | 27 ++++++++ .../manage/components/ProjectWorkflow.vue | 18 +++++- .../pages/components/project-workflow.scss | 17 +++++ 5 files changed, 130 insertions(+), 1 deletion(-) diff --git a/app/Http/Controllers/Api/ProjectController.php b/app/Http/Controllers/Api/ProjectController.php index 9e4091492..356c7b7f4 100755 --- a/app/Http/Controllers/Api/ProjectController.php +++ b/app/Http/Controllers/Api/ProjectController.php @@ -13,6 +13,7 @@ use App\Models\ProjectInvite; use App\Models\ProjectLog; use App\Models\ProjectTask; use App\Models\ProjectTaskFile; +use App\Models\ProjectTaskFlowChange; use App\Models\ProjectUser; use App\Models\User; use App\Models\WebSocketDialog; @@ -1028,6 +1029,11 @@ class ProjectController extends AbstractController $headings[] = '结束剩余'; $headings[] = '所属项目'; $headings[] = '父级任务ID'; + $headings[] = '任务计划用时'; + $headings[] = '开发用时'; + $headings[] = '验收/测试用时'; + $headings[] = '任务实际总用时'; + $headings[] = '超时时间'; $datas = []; // $builder = ProjectTask::select(['project_tasks.*', 'project_task_users.userid as ownerid']) @@ -1049,6 +1055,57 @@ class ProjectController extends AbstractController } else { $endSurplus = '-'; } + $developFlowChanges = ProjectTaskFlowChange::whereTaskId($task->id)->get(); + $developTime = 0;//开发时间 + $testTime = 0;//验收/测试时间 + foreach ($developFlowChanges as $change) { + if (strpos($change->before_flow_item_name, 'end') === false) { + $upOne = ProjectTaskFlowChange::where('id', '<', $change->id)->whereTaskId($task->id)->orderByDesc('id')->first(); + if ($upOne) { + if (strpos($change->before_flow_item_name, 'progress') !== false && strpos($change->before_flow_item_name, '进行') !== false) { + $devCtime = Carbon::parse($change->created_at)->timestamp; + $oCtime = Carbon::parse($upOne->created_at)->timestamp; + $minusNum = $devCtime - $oCtime; + $developTime += $minusNum; + } + if (strpos($change->before_flow_item_name, 'test') !== false || strpos($change->before_flow_item_name, '测试') !== false || strpos($change->before_flow_item_name, '验收') !== false) { + $testCtime = Carbon::parse($change->created_at)->timestamp; + $tTime = Carbon::parse($upOne->created_at)->timestamp; + $tMinusNum = $testCtime - $tTime; + $testTime += $tMinusNum; + } + } + } + } + if (!$task->complete_at) { + $lastChange = ProjectTaskFlowChange::whereTaskId($task->id)->orderByDesc('id')->first(); + $nowTime = time(); + $unFinishTime = $nowTime - Carbon::parse($lastChange->created_at)->timestamp; + if (strpos($lastChange->after_flow_item_name, 'progress') !== false || strpos($lastChange->after_flow_item_name, '进行') !== false) { + $developTime += $unFinishTime; + } elseif (strpos($lastChange->after_flow_item_name, 'test') !== false || strpos($lastChange->after_flow_item_name, '测试') !== false || strpos($lastChange->after_flow_item_name, '验收') !== false) { + $testTime += $unFinishTime; + } + } + $firstChange = ProjectTaskFlowChange::whereTaskId($task->id)->orderBy('id')->first(); + if (strpos($firstChange->after_flow_item_name, 'end') !== false) { + $firstDevTime = Carbon::parse($firstChange->created_at)->timestamp - Carbon::parse($task->created_at)->timestamp; + $developTime += $firstDevTime; + } + $totalTime = $developTime + $testTime; //任务总用时 + $planTime = '-';//任务计划用时 + $overTime = '-';//超时时间 + if ($task->end_at) { + $startTime = Carbon::parse($task->start_at)->timestamp; + $endTime = Carbon::parse($task->end_at)->timestamp; + $planTotalTime = $endTime - $startTime; + $residueTime = $planTotalTime - $totalTime; + if ($residueTime < 0) { + $overTime = Base::timeFormat(abs($residueTime)); + } + $planTime = Base::timeDiff($startTime, $endTime); + } + $datas[] = [ $task->id, Base::filterEmoji($task->name), @@ -1063,6 +1120,11 @@ class ProjectController extends AbstractController $endSurplus, Base::filterEmoji($task->project?->name) ?: '-', $task->parent_id ?: '-', + $planTime, + $developTime > 0 ? Base::timeFormat($developTime) : '-', + $testTime > 0 ? Base::timeFormat($testTime) : '-', + $totalTime > 0 ? Base::timeFormat($totalTime) : '-', + $overTime, ]; } }); diff --git a/app/Models/Project.php b/app/Models/Project.php index d4dacc17d..ca47d2f2b 100644 --- a/app/Models/Project.php +++ b/app/Models/Project.php @@ -376,6 +376,7 @@ class Project extends AbstractModel $idc = []; $hasStart = false; $hasEnd = false; + $testNum = 0; $upTaskList = []; foreach ($flows as $item) { $id = intval($item['id']); @@ -416,6 +417,9 @@ class Project extends AbstractModel if ($flow->status == 'end') { $hasEnd = true; } + if ($flow->status == 'test') { + $testNum++; + } if (!$isInsert) { $upTaskList[$flow->id] = $flow->status . "|" . $flow->name; } @@ -424,6 +428,9 @@ class Project extends AbstractModel if (!$hasStart) { throw new ApiException('至少需要1个开始状态'); } + if($testNum > 1){ + throw new ApiException('验收/测试状态只能有1个'); + } if (!$hasEnd) { throw new ApiException('至少需要1个结束状态'); } diff --git a/app/Module/Base.php b/app/Module/Base.php index 5191466fa..7cdc5a125 100755 --- a/app/Module/Base.php +++ b/app/Module/Base.php @@ -1732,6 +1732,33 @@ class Base } } + /** + * 时间秒数格式化 + * @param int $time 时间秒数 + * @return string + */ + public static function timeFormat($time) + { + if ($time > 86400) { + $day = floor($time / 86400); + $hour = ceil(($time - ($day * 86400)) / 3600); + if ($hour > 0) { + return $day . '天' . $hour . '小时'; + } else { + return $day . '天'; + } + } elseif ($time > 3600) { + return ceil($time / 3600) . '小时'; + } elseif ($time > 60) { + return ceil($time / 60) . '分钟'; + } elseif ($time > 1) { + return '1分钟内'; + } else { + return '0秒'; + } + + } + /** * 取ip前3段 * @param $ip diff --git a/resources/assets/js/pages/manage/components/ProjectWorkflow.vue b/resources/assets/js/pages/manage/components/ProjectWorkflow.vue index 7af855d22..a210df9f3 100644 --- a/resources/assets/js/pages/manage/components/ProjectWorkflow.vue +++ b/resources/assets/js/pages/manage/components/ProjectWorkflow.vue @@ -42,6 +42,12 @@
{{$L('可设置多个状态为进行中')}}
+
+
+
{{$L('验收/测试')}}
+
{{$L('只能设置单个状态为验收/测试')}}
+
+
{{$L('结束状态')}}
@@ -113,6 +119,7 @@ +
@@ -295,6 +302,15 @@ export default { }, { "id": -12, + "name": "待测试", + "status": "test", + "turns": [-10, -11, -12, -13], + "userids": [], + "usertype": 'add', + "userlimit": 0, + }, + { + "id": -13, "name": "已完成", "status": "end", "turns": [-10, -11, -12, -13], @@ -303,7 +319,7 @@ export default { "userlimit": 0, }, { - "id": -13, + "id": -14, "name": "已取消", "status": "end", "turns": [-10, -11, -12, -13], diff --git a/resources/assets/sass/pages/components/project-workflow.scss b/resources/assets/sass/pages/components/project-workflow.scss index c7b835e54..92c5bc1a8 100644 --- a/resources/assets/sass/pages/components/project-workflow.scss +++ b/resources/assets/sass/pages/components/project-workflow.scss @@ -70,6 +70,11 @@ border-color: rgba(27, 154, 238, 0.1); color: #0171c2; } + &.test { + background-color: rgba(27, 154, 238, 0.1); + border-color: rgba(27, 154, 238, 0.1); + color: #0171c2; + } &.end { background-color: rgba(21, 173, 49, 0.1); border-color: rgba(21, 173, 49, 0.1); @@ -329,6 +334,13 @@ } } + &.test { + border-color: #ccecff; + &:hover { + border-color: #87d2ff + } + } + &.end { border-color: #cafac8; &:hover { @@ -377,6 +389,11 @@ color: #0171c2 } + &.test { + background: rgba(27,154,238,0.1); + color: #0171c2 + } + &.end { background: rgba(21,173,49,0.1); color: #038a24