mirror of
https://github.com/kuaifan/dootask.git
synced 2025-12-12 11:19:56 +00:00
perf: 支持手动打卡
This commit is contained in:
parent
29ef080399
commit
fcecccc9b8
@ -3,6 +3,7 @@
|
|||||||
namespace App\Http\Controllers\Api;
|
namespace App\Http\Controllers\Api;
|
||||||
|
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
|
use App\Models\UserBot;
|
||||||
use App\Models\UserCheckinMac;
|
use App\Models\UserCheckinMac;
|
||||||
use App\Models\UserCheckinRecord;
|
use App\Models\UserCheckinRecord;
|
||||||
use App\Models\WebSocketDialog;
|
use App\Models\WebSocketDialog;
|
||||||
@ -89,90 +90,14 @@ class PublicController extends AbstractController
|
|||||||
if ($setting['open'] !== 'open') {
|
if ($setting['open'] !== 'open') {
|
||||||
return 'function off';
|
return 'function off';
|
||||||
}
|
}
|
||||||
|
if (!in_array('auto', $setting['modes'])) {
|
||||||
|
return 'mode off';
|
||||||
|
}
|
||||||
if ($key != $setting['key']) {
|
if ($key != $setting['key']) {
|
||||||
return 'key error';
|
return 'key error';
|
||||||
}
|
}
|
||||||
$times = $setting['time'] ? Base::json2array($setting['time']) : ['09:00', '18:00'];
|
if ($error = UserBot::checkinBotCheckin($mac, $time)) {
|
||||||
$advance = (intval($setting['advance']) ?: 120) * 60;
|
return $error;
|
||||||
$delay = (intval($setting['delay']) ?: 120) * 60;
|
|
||||||
//
|
|
||||||
$nowDate = date("Y-m-d");
|
|
||||||
$nowTime = date("H:i:s");
|
|
||||||
//
|
|
||||||
$timeStart = strtotime("{$nowDate} {$times[0]}");
|
|
||||||
$timeEnd = strtotime("{$nowDate} {$times[1]}");
|
|
||||||
$timeAdvance = max($timeStart - $advance, strtotime($nowDate));
|
|
||||||
$timeDelay = min($timeEnd + $delay, strtotime("{$nowDate} 23:59:59"));
|
|
||||||
if (Base::time() < $timeAdvance || $timeDelay < Base::time()) {
|
|
||||||
return "not in valid time, valid time is " . date("H:i", $timeAdvance) . "-" . date("H:i", $timeDelay);
|
|
||||||
}
|
|
||||||
//
|
|
||||||
$macs = explode(",", $mac);
|
|
||||||
$checkins = [];
|
|
||||||
foreach ($macs as $mac) {
|
|
||||||
$mac = strtoupper($mac);
|
|
||||||
if (Base::isMac($mac) && $UserCheckinMac = UserCheckinMac::whereMac($mac)->first()) {
|
|
||||||
$checkins[] = $UserCheckinMac;
|
|
||||||
$array = [
|
|
||||||
'userid' => $UserCheckinMac->userid,
|
|
||||||
'mac' => $UserCheckinMac->mac,
|
|
||||||
'date' => $nowDate,
|
|
||||||
];
|
|
||||||
$record = UserCheckinRecord::where($array)->first();
|
|
||||||
if (empty($record)) {
|
|
||||||
$record = UserCheckinRecord::createInstance($array);
|
|
||||||
}
|
|
||||||
$record->times = Base::array2json(array_merge($record->times, [$nowTime]));
|
|
||||||
$record->report_time = $time;
|
|
||||||
$record->save();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//
|
|
||||||
if ($checkins && $botUser = User::botGetOrCreate('check-in')) {
|
|
||||||
$getJokeSoup = function($type) {
|
|
||||||
$pre = $type == "up" ? "每日开心:" : "心灵鸡汤:";
|
|
||||||
$key = $type == "up" ? "JokeSoupTask:jokes" : "JokeSoupTask:soups";
|
|
||||||
$array = Base::json2array(Cache::get($key));
|
|
||||||
if ($array) {
|
|
||||||
$item = $array[array_rand($array)];
|
|
||||||
if ($item) {
|
|
||||||
return $pre . $item;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
$sendMsg = function($type, UserCheckinMac $checkin) use ($getJokeSoup, $botUser, $nowDate) {
|
|
||||||
$cacheKey = "Checkin::sendMsg-{$nowDate}-{$type}:" . $checkin->userid;
|
|
||||||
if (Cache::get($cacheKey) === "yes") {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Cache::put($cacheKey, "yes", Carbon::now()->addDay());
|
|
||||||
//
|
|
||||||
$dialog = WebSocketDialog::checkUserDialog($botUser, $checkin->userid);
|
|
||||||
if ($dialog) {
|
|
||||||
$hi = date("H:i");
|
|
||||||
$pre = $type == "up" ? "上班" : "下班";
|
|
||||||
$remark = $checkin->remark ? " ({$checkin->remark})": "";
|
|
||||||
$text = "<p>{$pre}打卡成功,打卡时间: {$hi}{$remark}</p>";
|
|
||||||
$suff = $getJokeSoup($type);
|
|
||||||
if ($suff) {
|
|
||||||
$text = "{$text}<p>----------</p><p>{$suff}</p>";
|
|
||||||
}
|
|
||||||
WebSocketDialogMsg::sendMsg(null, $dialog->id, 'text', ['text' => $text], $botUser->userid, false, false, $type != "up");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if ($timeAdvance <= Base::time() && Base::time() < $timeEnd) {
|
|
||||||
// 上班打卡通知(从最早打卡时间 到 下班打卡时间)
|
|
||||||
foreach ($checkins as $checkin) {
|
|
||||||
$sendMsg('up', $checkin);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ($timeEnd <= Base::time() && Base::time() <= $timeDelay) {
|
|
||||||
// 下班打卡通知(下班打卡时间 到 最晚打卡时间)
|
|
||||||
foreach ($checkins as $checkin) {
|
|
||||||
$sendMsg('down', $checkin);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return 'success';
|
return 'success';
|
||||||
}
|
}
|
||||||
|
|||||||
@ -315,7 +315,7 @@ class SystemController extends AbstractController
|
|||||||
*
|
*
|
||||||
* @apiParam {String} type
|
* @apiParam {String} type
|
||||||
* - get: 获取(默认)
|
* - get: 获取(默认)
|
||||||
* - save: 保存设置(参数:['open', 'time', 'advance', 'delay', 'remindin', 'remindexceed', 'edit', 'key'])
|
* - save: 保存设置(参数:['open', 'time', 'advance', 'delay', 'remindin', 'remindexceed', 'edit', 'modes', 'key'])
|
||||||
* @apiSuccess {Number} ret 返回状态码(1正确、0错误)
|
* @apiSuccess {Number} ret 返回状态码(1正确、0错误)
|
||||||
* @apiSuccess {String} msg 返回信息(错误描述)
|
* @apiSuccess {String} msg 返回信息(错误描述)
|
||||||
* @apiSuccess {Object} data 返回数据
|
* @apiSuccess {Object} data 返回数据
|
||||||
@ -339,6 +339,7 @@ class SystemController extends AbstractController
|
|||||||
'remindin',
|
'remindin',
|
||||||
'remindexceed',
|
'remindexceed',
|
||||||
'edit',
|
'edit',
|
||||||
|
'modes',
|
||||||
'key',
|
'key',
|
||||||
])) {
|
])) {
|
||||||
unset($all[$key]);
|
unset($all[$key]);
|
||||||
@ -347,6 +348,7 @@ class SystemController extends AbstractController
|
|||||||
if ($all['open'] === 'close') {
|
if ($all['open'] === 'close') {
|
||||||
$all['key'] = md5(Base::generatePassword(32));
|
$all['key'] = md5(Base::generatePassword(32));
|
||||||
}
|
}
|
||||||
|
$all['modes'] = array_intersect($all['modes'], ['auto', 'manual', 'location']);
|
||||||
$setting = Base::setting('checkinSetting', Base::newTrim($all));
|
$setting = Base::setting('checkinSetting', Base::newTrim($all));
|
||||||
} else {
|
} else {
|
||||||
$setting = Base::setting('checkinSetting');
|
$setting = Base::setting('checkinSetting');
|
||||||
@ -364,6 +366,7 @@ class SystemController extends AbstractController
|
|||||||
$setting['remindin'] = intval($setting['remindin']) ?: 5;
|
$setting['remindin'] = intval($setting['remindin']) ?: 5;
|
||||||
$setting['remindexceed'] = intval($setting['remindexceed']) ?: 10;
|
$setting['remindexceed'] = intval($setting['remindexceed']) ?: 10;
|
||||||
$setting['edit'] = $setting['edit'] ?: 'close';
|
$setting['edit'] = $setting['edit'] ?: 'close';
|
||||||
|
$setting['modes'] = is_array($setting['modes']) ? $setting['modes'] : [];
|
||||||
$setting['cmd'] = "curl -sSL '" . Base::fillUrl("api/public/checkin/install?key={$setting['key']}") . "' | sh";
|
$setting['cmd'] = "curl -sSL '" . Base::fillUrl("api/public/checkin/install?key={$setting['key']}") . "' | sh";
|
||||||
//
|
//
|
||||||
return Base::retSuccess('success', $setting ?: json_decode('{}'));
|
return Base::retSuccess('success', $setting ?: json_decode('{}'));
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use App\Module\Base;
|
||||||
use App\Module\Doo;
|
use App\Module\Doo;
|
||||||
use App\Module\Extranet;
|
use App\Module\Extranet;
|
||||||
use Cache;
|
use Cache;
|
||||||
@ -71,7 +72,7 @@ class UserBot extends AbstractModel
|
|||||||
'check-in@bot.system' => [
|
'check-in@bot.system' => [
|
||||||
[
|
[
|
||||||
'key' => 'checkin',
|
'key' => 'checkin',
|
||||||
'label' => Doo::translate('我要签到')
|
'label' => Doo::translate('我要打卡')
|
||||||
], [
|
], [
|
||||||
'key' => 'it',
|
'key' => 'it',
|
||||||
'label' => Doo::translate('IT资讯')
|
'label' => Doo::translate('IT资讯')
|
||||||
@ -128,11 +129,139 @@ class UserBot extends AbstractModel
|
|||||||
}
|
}
|
||||||
Cache::put("UserBot::checkinBotQuickMsg:{$userid}", "yes", Carbon::now()->addSecond());
|
Cache::put("UserBot::checkinBotQuickMsg:{$userid}", "yes", Carbon::now()->addSecond());
|
||||||
//
|
//
|
||||||
$text = match ($command) {
|
if ($command === 'checkin') {
|
||||||
"checkin" => "暂未开放手动签到。",
|
$setting = Base::setting('checkinSetting');
|
||||||
default => Extranet::checkinBotQuickMsg($command),
|
if ($setting['open'] !== 'open') {
|
||||||
};
|
return '暂未开启签到功能。';
|
||||||
return $text ?: '维护中...';
|
}
|
||||||
|
if (!in_array('manual', $setting['modes'])) {
|
||||||
|
return '暂未开放手动签到。';
|
||||||
|
}
|
||||||
|
if ($error = UserBot::checkinBotCheckin($userid, Base::time(), true)) {
|
||||||
|
return $error;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return Extranet::checkinBotQuickMsg($command);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 签到机器人签到
|
||||||
|
* @param $mac
|
||||||
|
* @param $time
|
||||||
|
* @param bool $alreadyTip 签到过是否提示
|
||||||
|
* @return string|null 返回string表示错误信息,返回null表示签到成功
|
||||||
|
*/
|
||||||
|
public static function checkinBotCheckin($mac, $time, $alreadyTip = false)
|
||||||
|
{
|
||||||
|
$setting = Base::setting('checkinSetting');
|
||||||
|
$times = $setting['time'] ? Base::json2array($setting['time']) : ['09:00', '18:00'];
|
||||||
|
$advance = (intval($setting['advance']) ?: 120) * 60;
|
||||||
|
$delay = (intval($setting['delay']) ?: 120) * 60;
|
||||||
|
//
|
||||||
|
$nowDate = date("Y-m-d");
|
||||||
|
$nowTime = date("H:i:s");
|
||||||
|
//
|
||||||
|
$timeStart = strtotime("{$nowDate} {$times[0]}");
|
||||||
|
$timeEnd = strtotime("{$nowDate} {$times[1]}");
|
||||||
|
$timeAdvance = max($timeStart - $advance, strtotime($nowDate));
|
||||||
|
$timeDelay = min($timeEnd + $delay, strtotime("{$nowDate} 23:59:59"));
|
||||||
|
if (Base::time() < $timeAdvance || $timeDelay < Base::time()) {
|
||||||
|
return "不在有效时间内,有效时间为:" . date("H:i", $timeAdvance) . "-" . date("H:i", $timeDelay);
|
||||||
|
}
|
||||||
|
//
|
||||||
|
$macs = explode(",", $mac);
|
||||||
|
$checkins = [];
|
||||||
|
foreach ($macs as $mac) {
|
||||||
|
$mac = strtoupper($mac);
|
||||||
|
$array = [];
|
||||||
|
if (Base::isMac($mac)) {
|
||||||
|
if ($UserCheckinMac = UserCheckinMac::whereMac($mac)->first()) {
|
||||||
|
$array = [
|
||||||
|
'userid' => $UserCheckinMac->userid,
|
||||||
|
'mac' => $UserCheckinMac->mac,
|
||||||
|
'date' => $nowDate,
|
||||||
|
];
|
||||||
|
$checkins[] = [
|
||||||
|
'userid' => $UserCheckinMac->userid,
|
||||||
|
'remark' => $UserCheckinMac->remark,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
} elseif (Base::isNumber($mac)) {
|
||||||
|
if ($UserInfo = User::whereUserid($mac)->whereBot(0)->first()) {
|
||||||
|
$array = [
|
||||||
|
'userid' => $UserInfo->userid,
|
||||||
|
'mac' => '00:00:00:00:00:00',
|
||||||
|
'date' => $nowDate,
|
||||||
|
];
|
||||||
|
$checkins[] = [
|
||||||
|
'userid' => $UserInfo->userid,
|
||||||
|
'remark' => '手动签到',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($array) {
|
||||||
|
$record = UserCheckinRecord::where($array)->first();
|
||||||
|
if (empty($record)) {
|
||||||
|
$record = UserCheckinRecord::createInstance($array);
|
||||||
|
}
|
||||||
|
$record->times = Base::array2json(array_merge($record->times, [$nowTime]));
|
||||||
|
$record->report_time = $time;
|
||||||
|
$record->save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//
|
||||||
|
if ($checkins && $botUser = User::botGetOrCreate('check-in')) {
|
||||||
|
$getJokeSoup = function($type) {
|
||||||
|
$pre = $type == "up" ? "每日开心:" : "心灵鸡汤:";
|
||||||
|
$key = $type == "up" ? "JokeSoupTask:jokes" : "JokeSoupTask:soups";
|
||||||
|
$array = Base::json2array(Cache::get($key));
|
||||||
|
if ($array) {
|
||||||
|
$item = $array[array_rand($array)];
|
||||||
|
if ($item) {
|
||||||
|
return $pre . $item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
$sendMsg = function($type, $checkin) use ($alreadyTip, $getJokeSoup, $botUser, $nowDate) {
|
||||||
|
$cacheKey = "Checkin::sendMsg-{$nowDate}-{$type}:" . $checkin['userid'];
|
||||||
|
$typeDesc = $type == "up" ? "上班" : "下班";
|
||||||
|
if (Cache::get($cacheKey) === "yes") {
|
||||||
|
if ($alreadyTip && $dialog = WebSocketDialog::checkUserDialog($botUser, $checkin['userid'])) {
|
||||||
|
$text = "<p>今日已{$typeDesc}打卡,无需重复打卡。</p>";
|
||||||
|
WebSocketDialogMsg::sendMsg(null, $dialog->id, 'text', ['text' => $text], $botUser->userid, false, false, $type != "up");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Cache::put($cacheKey, "yes", Carbon::now()->addDay());
|
||||||
|
//
|
||||||
|
if ($dialog = WebSocketDialog::checkUserDialog($botUser, $checkin['userid'])) {
|
||||||
|
$hi = date("H:i");
|
||||||
|
$remark = $checkin['remark'] ? " ({$checkin['remark']})": "";
|
||||||
|
$text = "<p>{$typeDesc}打卡成功,打卡时间: {$hi}{$remark}</p>";
|
||||||
|
$suff = $getJokeSoup($type);
|
||||||
|
if ($suff) {
|
||||||
|
$text = "{$text}<p>----------</p><p>{$suff}</p>";
|
||||||
|
}
|
||||||
|
WebSocketDialogMsg::sendMsg(null, $dialog->id, 'text', ['text' => $text], $botUser->userid, false, false, $type != "up");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if ($timeAdvance <= Base::time() && Base::time() < $timeEnd) {
|
||||||
|
// 上班打卡通知(从最早打卡时间 到 下班打卡时间)
|
||||||
|
foreach ($checkins as $checkin) {
|
||||||
|
$sendMsg('up', $checkin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($timeEnd <= Base::time() && Base::time() <= $timeDelay) {
|
||||||
|
// 下班打卡通知(下班打卡时间 到 最晚打卡时间)
|
||||||
|
foreach ($checkins as $checkin) {
|
||||||
|
$sendMsg('down', $checkin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Module\Base;
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
|
||||||
|
class SettingCheckinModesValue extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
$setting = Base::setting('checkinSetting');
|
||||||
|
$setting['modes'] = ['auto'];
|
||||||
|
Base::setting('checkinSetting', $setting);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -410,6 +410,7 @@ error
|
|||||||
匿名消息
|
匿名消息
|
||||||
系统管理员
|
系统管理员
|
||||||
我要签到
|
我要签到
|
||||||
|
我要打卡
|
||||||
|
|
||||||
关键词不能为空
|
关键词不能为空
|
||||||
|
|
||||||
|
|||||||
@ -57,11 +57,21 @@
|
|||||||
</RadioGroup>
|
</RadioGroup>
|
||||||
<div class="form-tip">{{$L('允许成员自己修改MAC地址')}}</div>
|
<div class="form-tip">{{$L('允许成员自己修改MAC地址')}}</div>
|
||||||
</FormItem>
|
</FormItem>
|
||||||
|
<FormItem :label="$L('签到方式')" prop="modes">
|
||||||
|
<CheckboxGroup v-model="formData.modes">
|
||||||
|
<Checkbox label="auto">{{$L('自动签到')}}</Checkbox>
|
||||||
|
<Checkbox label="manual">{{$L('手动签到')}}</Checkbox>
|
||||||
|
<Checkbox v-if="false" label="location">{{$L('定位签到')}}</Checkbox>
|
||||||
|
</CheckboxGroup>
|
||||||
|
<div v-if="formData.modes.includes('auto')" class="form-tip">{{$L('自动签到')}}: {{$L('详情看下文安装说明')}}</div>
|
||||||
|
<div v-if="formData.modes.includes('manual')" class="form-tip">{{$L('手动签到')}}: {{$L('通过在签到打卡机器人发送指令签到')}}</div>
|
||||||
|
<div v-if="formData.modes.includes('location')" class="form-tip">{{$L('定位签到')}}: {{$L('通过在签到打卡机器人发送位置签到')}}</div>
|
||||||
|
</FormItem>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<template v-if="formData.open === 'open'">
|
<template v-if="formData.open === 'open' && formData.modes.includes('auto')">
|
||||||
<div class="block-setting-placeholder"></div>
|
<div class="block-setting-placeholder"></div>
|
||||||
<div class="block-setting-box">
|
<div class="block-setting-box">
|
||||||
<h3>{{ $L('自动签到') }}</h3>
|
<h3>{{ $L('自动签到') }}</h3>
|
||||||
@ -111,6 +121,7 @@ export default {
|
|||||||
open: '',
|
open: '',
|
||||||
edit: '',
|
edit: '',
|
||||||
cmd: '',
|
cmd: '',
|
||||||
|
modes: [],
|
||||||
},
|
},
|
||||||
ruleData: {},
|
ruleData: {},
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user