diff --git a/app/Http/Controllers/Api/SystemController.php b/app/Http/Controllers/Api/SystemController.php index 310457c99..01c6f26be 100755 --- a/app/Http/Controllers/Api/SystemController.php +++ b/app/Http/Controllers/Api/SystemController.php @@ -3,6 +3,8 @@ namespace App\Http\Controllers\Api; use App\Models\UserDevice; +use App\Models\WebSocketDialog; +use App\Models\WebSocketDialogMsg; use Request; use Session; use Response; @@ -22,6 +24,7 @@ use App\Module\Apps; use App\Module\BillMultipleExport; use LdapRecord\LdapRecordException; use Guanguans\Notify\Messages\EmailMessage; +use Swoole\Coroutine; /** * @apiDefine system @@ -1264,7 +1267,7 @@ class SystemController extends AbstractController */ public function checkin__export() { - User::auth('admin'); + $user = User::auth('admin'); // $setting = Base::setting('checkinSetting'); if ($setting['open'] !== 'open') { @@ -1294,126 +1297,179 @@ class SystemController extends AbstractController $secondStart = strtotime("2000-01-01 {$time[0]}") - strtotime("2000-01-01 00:00:00"); $secondEnd = strtotime("2000-01-01 {$time[1]}") - strtotime("2000-01-01 00:00:00"); // - $headings = []; - $headings[] = Doo::translate('签到人'); - $headings[] = Doo::translate('签到日期'); - $headings[] = Doo::translate('班次时间'); - $headings[] = Doo::translate('首次签到时间'); - $headings[] = Doo::translate('首次签到结果'); - $headings[] = Doo::translate('最后签到时间'); - $headings[] = Doo::translate('最后签到结果'); - $headings[] = Doo::translate('参数数据'); + $botUser = User::botGetOrCreate('system-msg'); + if (empty($botUser)) { + return Base::retError('系统机器人不存在'); + } + $dialog = WebSocketDialog::checkUserDialog($botUser, $user->userid); // - $sheets = []; - $startD = Carbon::parse($date[0])->startOfDay(); - $endD = Carbon::parse($date[1])->endOfDay(); - $users = User::whereIn('userid', $userid)->take(100)->get(); - /** @var User $user */ - foreach ($users as $user) { - $recordTimes = UserCheckinRecord::getTimes($user->userid, [$startD, $endD]); + go(function () use ($secondStart, $secondEnd, $time, $userid, $date, $user, $botUser, $dialog) { + Coroutine::sleep(1); // - $nickname = Base::filterEmoji($user->nickname); - $styles = ["A1:H1" => ["font" => ["bold" => true]]]; - $datas = []; - $startT = $startD->timestamp; - $endT = $endD->timestamp; - $index = 1; - while ($startT < $endT) { - $index++; - $sameDate = date("Y-m-d", $startT); - $sameTimes = $recordTimes[$sameDate] ?? []; - $sameCollect = UserCheckinRecord::atCollect($sameDate, $sameTimes); - $firstBetween = [Carbon::createFromTimestamp($startT), Carbon::createFromTimestamp($startT + $secondEnd - 1)]; - $lastBetween = [Carbon::createFromTimestamp($startT + $secondStart + 1), Carbon::createFromTimestamp($startT + 86400)]; - $firstRecord = $sameCollect?->whereBetween("datetime", $firstBetween)->first(); - $lastRecord = $sameCollect?->whereBetween("datetime", $lastBetween)->last(); - $firstTimestamp = $firstRecord['timestamp'] ?: 0; - $lastTimestamp = $lastRecord['timestamp'] ?: 0; - if (Timer::time() < $startT + $secondStart) { - $firstResult = "-"; - } else { - $firstResult = Doo::translate("正常"); - if (empty($firstTimestamp)) { - $firstResult = Doo::translate("缺卡"); - $styles["E{$index}"] = ["font" => ["color" => ["rgb" => "ff0000"]]]; - } elseif ($firstTimestamp > $startT + $secondStart) { - $firstResult = Doo::translate("迟到"); - $styles["E{$index}"] = ["font" => ["color" => ["rgb" => "436FF6"]]]; + $headings = []; + $headings[] = Doo::translate('签到人'); + $headings[] = Doo::translate('签到日期'); + $headings[] = Doo::translate('班次时间'); + $headings[] = Doo::translate('首次签到时间'); + $headings[] = Doo::translate('首次签到结果'); + $headings[] = Doo::translate('最后签到时间'); + $headings[] = Doo::translate('最后签到结果'); + $headings[] = Doo::translate('参数数据'); + // + $content = []; + $content[] = [ + 'content' => '导出签到数据已完成', + 'style' => 'font-weight: bold;padding-bottom: 4px;', + ]; + // + $sheets = []; + $startD = Carbon::parse($date[0])->startOfDay(); + $endD = Carbon::parse($date[1])->endOfDay(); + $users = User::whereIn('userid', $userid)->take(100)->get(); + /** @var User $user */ + foreach ($users as $user) { + $recordTimes = UserCheckinRecord::getTimes($user->userid, [$startD, $endD]); + // + $nickname = Base::filterEmoji($user->nickname); + $styles = ["A1:H1" => ["font" => ["bold" => true]]]; + $datas = []; + $startT = $startD->timestamp; + $endT = $endD->timestamp; + $index = 1; + while ($startT < $endT) { + $index++; + $sameDate = date("Y-m-d", $startT); + $sameTimes = $recordTimes[$sameDate] ?? []; + $sameCollect = UserCheckinRecord::atCollect($sameDate, $sameTimes); + $firstBetween = [Carbon::createFromTimestamp($startT), Carbon::createFromTimestamp($startT + $secondEnd - 1)]; + $lastBetween = [Carbon::createFromTimestamp($startT + $secondStart + 1), Carbon::createFromTimestamp($startT + 86400)]; + $firstRecord = $sameCollect?->whereBetween("datetime", $firstBetween)->first(); + $lastRecord = $sameCollect?->whereBetween("datetime", $lastBetween)->last(); + $firstTimestamp = $firstRecord['timestamp'] ?: 0; + $lastTimestamp = $lastRecord['timestamp'] ?: 0; + if (Timer::time() < $startT + $secondStart) { + $firstResult = "-"; + } else { + $firstResult = Doo::translate("正常"); + if (empty($firstTimestamp)) { + $firstResult = Doo::translate("缺卡"); + $styles["E{$index}"] = ["font" => ["color" => ["rgb" => "ff0000"]]]; + } elseif ($firstTimestamp > $startT + $secondStart) { + $firstResult = Doo::translate("迟到"); + $styles["E{$index}"] = ["font" => ["color" => ["rgb" => "436FF6"]]]; + } } - } - if (Timer::time() < $startT + $secondEnd) { - $lastResult = "-"; - $lastTimestamp = 0; - } else { - $lastResult = Doo::translate("正常"); - if (empty($lastTimestamp) || $lastTimestamp === $firstTimestamp) { - $lastResult = Doo::translate("缺卡"); - $styles["G{$index}"] = ["font" => ["color" => ["rgb" => "ff0000"]]]; - } elseif ($lastTimestamp < $startT + $secondEnd) { - $lastResult = Doo::translate("早退"); - $styles["G{$index}"] = ["font" => ["color" => ["rgb" => "436FF6"]]]; + if (Timer::time() < $startT + $secondEnd) { + $lastResult = "-"; + $lastTimestamp = 0; + } else { + $lastResult = Doo::translate("正常"); + if (empty($lastTimestamp) || $lastTimestamp === $firstTimestamp) { + $lastResult = Doo::translate("缺卡"); + $styles["G{$index}"] = ["font" => ["color" => ["rgb" => "ff0000"]]]; + } elseif ($lastTimestamp < $startT + $secondEnd) { + $lastResult = Doo::translate("早退"); + $styles["G{$index}"] = ["font" => ["color" => ["rgb" => "436FF6"]]]; + } } + $firstTimestamp = $firstTimestamp ? date("H:i", $firstTimestamp) : "-"; + $lastTimestamp = $lastTimestamp ? date("H:i", $lastTimestamp) : "-"; + $section = array_map(function($item) { + return $item[0] . "-" . ($item[1] ?: "None"); + }, UserCheckinRecord::atSection($sameTimes)); + $datas[] = [ + "{$nickname} (ID: {$user->userid})", + $sameDate, + implode("-", $time), + $firstTimestamp, + $firstResult, + $lastTimestamp, + $lastResult, + implode(", ", $section), + ]; + $startT += 86400; } - $firstTimestamp = $firstTimestamp ? date("H:i", $firstTimestamp) : "-"; - $lastTimestamp = $lastTimestamp ? date("H:i", $lastTimestamp) : "-"; - $section = array_map(function($item) { - return $item[0] . "-" . ($item[1] ?: "None"); - }, UserCheckinRecord::atSection($sameTimes)); - $datas[] = [ - "{$nickname} (ID: {$user->userid})", - $sameDate, - implode("-", $time), - $firstTimestamp, - $firstResult, - $lastTimestamp, - $lastResult, - implode(", ", $section), - ]; - $startT += 86400; + $title = (count($sheets) + 1) . "." . ($nickname ?: $user->userid); + $sheets[] = BillExport::create()->setTitle($title)->setHeadings($headings)->setData($datas)->setStyles($styles); } - $title = (count($sheets) + 1) . "." . ($nickname ?: $user->userid); - $sheets[] = BillExport::create()->setTitle($title)->setHeadings($headings)->setData($datas)->setStyles($styles); - } - if (empty($sheets)) { - return Base::retError('没有任何数据'); - } + if (empty($sheets)) { + $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; + } + // + $fileName = $users[0]->nickname; + if (count($users) > 1) { + $fileName .= "等" . count($userid) . "位成员的签到记录"; + } else { + $fileName .= '的签到记录'; + } + $fileName = Doo::translate($fileName) . '_' . Timer::time() . '.xlsx'; + $filePath = "temp/checkin/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, '.xlsx') . ".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/system/checkin/down?key=' . urlencode($base64)); + Session::put('checkin::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); + } + }); // - $fileName = $users[0]->nickname; - if (count($users) > 1) { - $fileName .= "等" . count($userid) . "位成员的签到记录"; - } else { - $fileName .= '的签到记录'; - } - $fileName = Doo::translate($fileName) . '_' . Timer::time() . '.xlsx'; - $filePath = "temp/checkin/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, '.xlsx') . ".zip"; - $zipPath = storage_path($zipFile); - if (file_exists($zipPath)) { - Base::deleteDirAndFile($zipPath, true); - } - try { - Madzipper::make($zipPath)->add($xlsPath)->close(); - } catch (\Throwable) { - } + WebSocketDialogMsg::sendMsg(null, $dialog->id, 'template', [ + 'type' => 'content', + 'content' => '正在导出签到数据,请稍等...', + ], $botUser->userid, true, false, true); // - if (file_exists($zipPath)) { - $base64 = base64_encode(Base::array2string([ - 'file' => $zipFile, - ])); - Session::put('checkin::export:userid', $user->userid); - return Base::retSuccess('success', [ - 'size' => Base::twoFloat(filesize($zipPath) / 1024, true), - 'url' => Base::fillUrl('api/system/checkin/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 297f90246..78059eb71 100644 --- a/language/original-api.txt +++ b/language/original-api.txt @@ -92,6 +92,8 @@ 正在导出超期任务,请稍等... 导出审批数据已完成 正在导出审批数据,请稍等... +导出签到数据已完成 +正在导出签到数据,请稍等... 任务列表不存在或已被删除 主任务已完成无法添加子任务 子任务不支持此功能 diff --git a/language/original-web.txt b/language/original-web.txt index bfbaa19c1..b3dcc0f99 100644 --- a/language/original-web.txt +++ b/language/original-web.txt @@ -1644,6 +1644,8 @@ Token 正在导出超期任务,请稍等... 导出审批数据已完成 正在导出审批数据,请稍等... +导出签到数据已完成 +正在导出签到数据,请稍等... (*)查看了(*)的联系电话 标记任务未完成 标记任务已完成 diff --git a/resources/assets/js/pages/manage/components/CheckinExport.vue b/resources/assets/js/pages/manage/components/CheckinExport.vue index 946e71156..cff3cb139 100644 --- a/resources/assets/js/pages/manage/components/CheckinExport.vue +++ b/resources/assets/js/pages/manage/components/CheckinExport.vue @@ -103,11 +103,9 @@ export default { this.$store.dispatch("call", { url: 'system/checkin/export', data: this.formData, - }).then(({data}) => { + }).then(() => { this.show = false; - this.$store.dispatch('downUrl', { - url: data.url - }); + $A.modalSuccess('正在打包,请留意系统消息。'); }).catch(({msg}) => { $A.modalError(msg); }).finally(_ => {