From 25e82d690e319bc012180b2f5bfc217d6e3ebfa7 Mon Sep 17 00:00:00 2001 From: kuaifan Date: Wed, 4 Jun 2025 14:52:40 +0800 Subject: [PATCH] =?UTF-8?q?perf:=20=E4=BC=98=E5=8C=96=E5=AF=BC=E5=87=BA?= =?UTF-8?q?=E4=BB=BB=E5=8A=A1=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/Api/ProjectController.php | 253 +++++++++++------- language/original-api.txt | 3 + language/original-web.txt | 3 + resources/assets/js/pages/manage.vue | 6 +- 4 files changed, 164 insertions(+), 101 deletions(-) diff --git a/app/Http/Controllers/Api/ProjectController.php b/app/Http/Controllers/Api/ProjectController.php index 50182bf49..d70d9ecbf 100755 --- a/app/Http/Controllers/Api/ProjectController.php +++ b/app/Http/Controllers/Api/ProjectController.php @@ -1258,7 +1258,7 @@ class ProjectController extends AbstractController $dialog = WebSocketDialog::checkUserDialog($botUser, $user->userid); // go(function () use ($user, $userid, $time, $type, $botUser, $dialog) { - Coroutine::sleep(0.1); + Coroutine::sleep(1); $headings = []; $headings[] = Doo::translate('任务ID'); $headings[] = Doo::translate('父级任务ID'); @@ -1394,7 +1394,7 @@ class ProjectController extends AbstractController 'type' => 'content', 'title' => $content[0]['content'], 'content' => $content, - ], $botUser->userid, false, false, true); + ], $botUser->userid, true, false, true); return; } // @@ -1428,7 +1428,7 @@ class ProjectController extends AbstractController 'type' => 'content', 'title' => $content[0]['content'], 'content' => $content, - ], $botUser->userid, false, false, true); + ], $botUser->userid, true, false, true); return; } // @@ -1455,7 +1455,7 @@ class ProjectController extends AbstractController 'name' => $fileName, 'size' => filesize($zipPath), 'url' => $fileUrl, - ], $botUser->userid, false, false, true); + ], $botUser->userid, true, false, true); } else { $content[] = [ 'content' => "打包失败,请稍后再试...", @@ -1465,9 +1465,15 @@ class ProjectController extends AbstractController 'type' => 'content', 'title' => $content[0]['content'], 'content' => $content, - ], $botUser->userid, false, false, true); + ], $botUser->userid, true, false, true); } }); + // + WebSocketDialogMsg::sendMsg(null, $dialog->id, 'template', [ + 'type' => 'content', + 'content' => '正在导出任务统计,请稍等...', + ], $botUser->userid, true, false, true); + // return Base::retSuccess('success'); } @@ -1487,103 +1493,156 @@ class ProjectController extends AbstractController { $user = User::auth('admin'); // - $headings = []; - $headings[] = Doo::translate('任务ID'); - $headings[] = Doo::translate('父级任务ID'); - $headings[] = Doo::translate('所属项目'); - $headings[] = Doo::translate('任务标题'); - $headings[] = Doo::translate('任务标签'); - $headings[] = Doo::translate('任务开始时间'); - $headings[] = Doo::translate('任务结束时间'); - $headings[] = Doo::translate('任务计划用时'); - $headings[] = Doo::translate('超时时间'); - $headings[] = Doo::translate('负责人'); - $headings[] = Doo::translate('创建人'); - $data = []; + $botUser = User::botGetOrCreate('system-msg'); + if (empty($botUser)) { + return Base::retError('系统机器人不存在'); + } + $dialog = WebSocketDialog::checkUserDialog($botUser, $user->userid); // - ProjectTask::with(['taskTag']) - ->whereNull('complete_at') - ->whereNotNull('end_at') - ->where('end_at', '<=', Carbon::now()) - ->orderBy('end_at') - ->chunk(100, function ($tasks) use (&$data) { - /** @var ProjectTask $task */ - foreach ($tasks as $task) { - $taskStartTime = Carbon::parse($task->start_at ?: $task->created_at)->timestamp; - $totalTime = time() - $taskStartTime; //开发测试总用时 - $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 = Doo::translate(Timer::timeFormat(abs($residueTime))); + go(function () use ($botUser, $dialog, $user) { + Coroutine::sleep(1); + // + $headings = []; + $headings[] = Doo::translate('任务ID'); + $headings[] = Doo::translate('父级任务ID'); + $headings[] = Doo::translate('所属项目'); + $headings[] = Doo::translate('任务标题'); + $headings[] = Doo::translate('任务标签'); + $headings[] = Doo::translate('任务开始时间'); + $headings[] = Doo::translate('任务结束时间'); + $headings[] = Doo::translate('任务计划用时'); + $headings[] = Doo::translate('超时时间'); + $headings[] = Doo::translate('负责人'); + $headings[] = Doo::translate('创建人'); + $data = []; + // + $content = []; + $content[] = [ + 'content' => '导出超期任务已完成', + 'style' => 'font-weight: bold;padding-bottom: 4px;', + ]; + // + ProjectTask::with(['taskTag']) + ->whereNull('complete_at') + ->whereNotNull('end_at') + ->where('end_at', '<=', Carbon::now()) + ->orderBy('end_at') + ->chunk(100, function ($tasks) use (&$data) { + /** @var ProjectTask $task */ + foreach ($tasks as $task) { + $taskStartTime = Carbon::parse($task->start_at ?: $task->created_at)->timestamp; + $totalTime = time() - $taskStartTime; //开发测试总用时 + $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 = Doo::translate(Timer::timeFormat(abs($residueTime))); + } + $planTime = Doo::translate(Timer::timeDiff($startTime, $endTime)); } - $planTime = Doo::translate(Timer::timeDiff($startTime, $endTime)); + $ownerIds = $task->taskUser->where('owner', 1)->pluck('userid')->toArray(); + $ownerNames = []; + foreach ($ownerIds as $ownerId) { + $ownerNames[] = Base::filterEmoji(User::userid2nickname($ownerId)) . " (ID: {$ownerId})"; + } + $data[] = [ + $task->id, + $task->parent_id ?: '-', + Base::filterEmoji($task->project?->name) ?: '-', + Base::filterEmoji($task->name), + $task->taskTag->map(function ($tag) { + return Base::filterEmoji($tag->name); + })->join(', ') ?: '-', + $task->start_at ?: '-', + $task->end_at ?: '-', + $planTime, + $overTime, + implode(', ', $ownerNames), + Base::filterEmoji(User::userid2nickname($task->userid)) . " (ID: {$task->userid})", + ]; } - $ownerIds = $task->taskUser->where('owner', 1)->pluck('userid')->toArray(); - $ownerNames = []; - foreach ($ownerIds as $ownerId) { - $ownerNames[] = Base::filterEmoji(User::userid2nickname($ownerId)) . " (ID: {$ownerId})"; - } - $data[] = [ - $task->id, - $task->parent_id ?: '-', - Base::filterEmoji($task->project?->name) ?: '-', - Base::filterEmoji($task->name), - $task->taskTag->map(function ($tag) { - return Base::filterEmoji($tag->name); - })->join(', ') ?: '-', - $task->start_at ?: '-', - $task->end_at ?: '-', - $planTime, - $overTime, - implode(', ', $ownerNames), - Base::filterEmoji(User::userid2nickname($task->userid)) . " (ID: {$task->userid})", - ]; - } - }); - if (empty($data)) { - return Base::retError('没有任何数据'); - } + }); + if (empty($data)) { + $content[] = [ + 'content' => '没有任何数据', + 'style' => 'color: #ff0000;', + ]; + WebSocketDialogMsg::sendMsg(null, $dialog->id, 'template', [ + 'type' => 'content', + 'title' => $content[0]['content'], + 'content' => $content, + ], $botUser->userid, true, false, true); + return; + } + // + $title = Doo::translate('超期任务'); + $sheets = [ + BillExport::create()->setTitle($title)->setHeadings($headings)->setData($data)->setStyles(["A1:J1" => ["font" => ["bold" => true]]]) + ]; + // + $fileName = $title . '_' . Timer::time() . '.xls'; + $filePath = "temp/task/export/" . date("Ym", Timer::time()); + $export = new BillMultipleExport($sheets); + $res = $export->store($filePath . "/" . $fileName); + if ($res != 1) { + $content[] = [ + 'content' => "导出失败,{$fileName}!", + 'style' => 'color: #ff0000;', + ]; + WebSocketDialogMsg::sendMsg(null, $dialog->id, 'template', [ + 'type' => 'content', + 'title' => $content[0]['content'], + 'content' => $content, + ], $botUser->userid, true, false, true); + return; + } + $xlsPath = storage_path("app/" . $filePath . "/" . $fileName); + $zipFile = "app/" . $filePath . "/" . Base::rightDelete($fileName, '.xls') . ".zip"; + $zipPath = storage_path($zipFile); + if (file_exists($zipPath)) { + Base::deleteDirAndFile($zipPath, true); + } + try { + Madzipper::make($zipPath)->add($xlsPath)->close(); + } catch (\Throwable) { + } + // + if (file_exists($zipPath)) { + $base64 = base64_encode(Base::array2string([ + 'file' => $zipFile, + ])); + $fileUrl = Base::fillUrl('api/project/task/down?key=' . urlencode($base64)); + Session::put('task::export:userid', $user->userid); + WebSocketDialogMsg::sendMsg(null, $dialog->id, 'template', [ + 'type' => 'file_download', + 'title' => '导出超期任务已完成', + 'name' => $fileName, + 'size' => filesize($zipPath), + 'url' => $fileUrl, + ], $botUser->userid, true, false, true); + } else { + $content[] = [ + 'content' => "打包失败,请稍后再试...", + 'style' => 'color: #ff0000;', + ]; + WebSocketDialogMsg::sendMsg(null, $dialog->id, 'template', [ + 'type' => 'content', + 'title' => $content[0]['content'], + 'content' => $content, + ], $botUser->userid, true, false, true); + } + }); // - $title = Doo::translate('超期任务'); - $sheets = [ - BillExport::create()->setTitle($title)->setHeadings($headings)->setData($data)->setStyles(["A1:J1" => ["font" => ["bold" => true]]]) - ]; + WebSocketDialogMsg::sendMsg(null, $dialog->id, 'template', [ + 'type' => 'content', + 'content' => '正在导出超期任务,请稍等...', + ], $botUser->userid, true, false, true); // - $fileName = $title . '_' . Timer::time() . '.xls'; - $filePath = "temp/task/export/" . date("Ym", Timer::time()); - $export = new BillMultipleExport($sheets); - $res = $export->store($filePath . "/" . $fileName); - if ($res != 1) { - return Base::retError('导出失败,' . $fileName . '!'); - } - $xlsPath = storage_path("app/" . $filePath . "/" . $fileName); - $zipFile = "app/" . $filePath . "/" . Base::rightDelete($fileName, '.xls') . ".zip"; - $zipPath = storage_path($zipFile); - if (file_exists($zipPath)) { - Base::deleteDirAndFile($zipPath, true); - } - try { - Madzipper::make($zipPath)->add($xlsPath)->close(); - } catch (\Throwable) { - } - // - if (file_exists($zipPath)) { - $base64 = base64_encode(Base::array2string([ - 'file' => $zipFile, - ])); - Session::put('task::export:userid', $user->userid); - return Base::retSuccess('success', [ - 'size' => Base::twoFloat(filesize($zipPath) / 1024, true), - 'url' => Base::fillUrl('api/project/task/down?key=' . urlencode($base64)), - ]); - } else { - return Base::retError('打包失败,请稍后再试...'); - } + return Base::retSuccess('success'); } /** diff --git a/language/original-api.txt b/language/original-api.txt index a06f44c28..36b07d141 100644 --- a/language/original-api.txt +++ b/language/original-api.txt @@ -87,6 +87,9 @@ 没有任何数据 导出失败,(*)! 打包失败,请稍后再试... +正在导出任务统计,请稍等... +导出超期任务已完成 +正在导出超期任务,请稍等... 任务列表不存在或已被删除 主任务已完成无法添加子任务 子任务不支持此功能 diff --git a/language/original-web.txt b/language/original-web.txt index 4baf1d425..f6aced3dc 100644 --- a/language/original-web.txt +++ b/language/original-web.txt @@ -1639,6 +1639,9 @@ Token 导出任务统计已完成 没有任何数据 打包失败,请稍后再试... +正在导出任务统计,请稍等... +导出超期任务已完成 +正在导出超期任务,请稍等... (*)查看了(*)的联系电话 标记任务未完成 标记任务已完成 diff --git a/resources/assets/js/pages/manage.vue b/resources/assets/js/pages/manage.vue index a238d176c..4ecf2bb9f 100644 --- a/resources/assets/js/pages/manage.vue +++ b/resources/assets/js/pages/manage.vue @@ -844,11 +844,9 @@ export default { return new Promise((resolve, reject) => { this.$store.dispatch("call", { url: 'project/task/exportoverdue', - }).then(({data}) => { + }).then(() => { resolve(); - this.$store.dispatch('downUrl', { - url: data.url - }); + $A.modalSuccess('正在打包,请留意系统消息。'); }).catch(({msg}) => { reject(msg); });