perf: 优化任务APP/邮件提醒

This commit is contained in:
kuaifan 2023-01-30 15:12:17 +08:00
parent 31ea53cc15
commit e45804174c
10 changed files with 82 additions and 307 deletions

View File

@ -1459,6 +1459,7 @@ class ProjectController extends AbstractController
$data['new_column'] = $newColumn;
}
$task->pushMsg('add', $data);
$task->taskPush(null, 0);
return Base::retSuccess('添加成功', $data);
}

View File

@ -111,7 +111,7 @@ class SystemController extends AbstractController
*
* @apiParam {String} type
* - get: 获取(默认)
* - save: 保存设置(参数:['smtp_server', 'port', 'account', 'password', 'reg_verify', 'notice', 'task_start_minute', 'task_remind_hours', 'task_remind_hours2', 'notice_msg', 'msg_unread_user_minute', 'msg_unread_group_minute', 'ignore_addr']
* - save: 保存设置(参数:['smtp_server', 'port', 'account', 'password', 'reg_verify', 'notice_msg', 'msg_unread_user_minute', 'msg_unread_group_minute', 'ignore_addr']
* @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述)
* @apiSuccess {Object} data 返回数据
@ -134,10 +134,6 @@ class SystemController extends AbstractController
'account',
'password',
'reg_verify',
'notice',
'task_start_minute',
'task_remind_hours',
'task_remind_hours2',
'notice_msg',
'msg_unread_user_minute',
'msg_unread_group_minute',
@ -156,10 +152,6 @@ class SystemController extends AbstractController
$setting['account'] = $setting['account'] ?: '';
$setting['password'] = $setting['password'] ?: '';
$setting['reg_verify'] = $setting['reg_verify'] ?: 'close';
$setting['notice'] = $setting['notice'] ?: 'close';
$setting['task_start_minute'] = intval($setting['task_start_minute'] ?? -1);
$setting['task_remind_hours'] = floatval($setting['task_remind_hours'] ?? -1);
$setting['task_remind_hours2'] = floatval($setting['task_remind_hours2'] ?? -1);
$setting['notice_msg'] = $setting['notice_msg'] ?: 'close';
$setting['msg_unread_user_minute'] = intval($setting['msg_unread_user_minute'] ?? -1);
$setting['msg_unread_group_minute'] = intval($setting['msg_unread_group_minute'] ?? -1);
@ -281,7 +273,7 @@ class SystemController extends AbstractController
*
* @apiParam {String} type
* - get: 获取(默认)
* - save: 保存设置(参数:['push', 'ios_key', 'ios_secret', 'android_key', 'android_secret', 'push_msg', 'push_task', 'task_start_minute', 'task_remind_hours', 'task_remind_hours2']
* - save: 保存设置(参数:['push', 'ios_key', 'ios_secret', 'android_key', 'android_secret']
* @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述)
* @apiSuccess {Object} data 返回数据
@ -303,11 +295,6 @@ class SystemController extends AbstractController
'ios_secret',
'android_key',
'android_secret',
'push_msg',
'push_task',
'task_start_minute',
'task_remind_hours',
'task_remind_hours2'
])) {
unset($all[$key]);
}
@ -318,11 +305,6 @@ class SystemController extends AbstractController
}
//
$setting['push'] = $setting['push'] ?: 'close';
$setting['push_msg'] = $setting['push_msg'] ?: 'open';
$setting['push_task'] = $setting['push_task'] ?: 'open';
$setting['task_start_minute'] = intval($setting['task_start_minute']);
$setting['task_remind_hours'] = floatval($setting['task_remind_hours']);
$setting['task_remind_hours2'] = floatval($setting['task_remind_hours2']);
//
return Base::retSuccess('success', $setting ?: json_decode('{}'));
}

View File

@ -655,7 +655,7 @@ class ProjectTask extends AbstractModel
}
// 负责人
if (Arr::exists($data, 'owner')) {
$count = $this->taskUser->where('owner', 1)->count();
$older = $this->taskUser->where('owner', 1)->pluck('userid')->toArray();
$array = [];
$owner = is_array($data['owner']) ? $data['owner'] : [$data['owner']];
if (count($owner) > 10) {
@ -679,11 +679,12 @@ class ProjectTask extends AbstractModel
}
}
if ($array) {
if ($count == 0 && count($array) == 1 && $array[0] == User::userid()) {
if (count($older) == 0 && count($array) == 1 && $array[0] == User::userid()) {
$this->addLog("认领{任务}");
} else {
$this->addLog("修改{任务}负责人", ['userid' => $array]);
}
$this->taskPush(array_values(array_diff($array, $older)), 0);
}
$rows = ProjectTaskUser::whereTaskId($this->id)->whereOwner(1)->whereNotIn('userid', $array)->get();
if ($rows->isNotEmpty()) {
@ -1431,6 +1432,55 @@ class ProjectTask extends AbstractModel
}
}
/**
* 任务提醒
* @param $userids
* @param int $type 0-新任务、1-即将超时、2-已超时
* @return void
*/
public function taskPush($userids, int $type)
{
if ($userids === null) {
$userids = $this->taskUser->where('owner', 1)->pluck('userid')->toArray();
}
if (empty($userids)) {
return;
}
$users = User::whereIn('userid', $userids)->whereNull('disable_at')->get();
if (empty($users)) {
return;
}
$botUser = User::botGetOrCreate('task-alert');
if (empty($botUser)) {
return;
}
$text = view('push.task', [
'type' => str_replace([0, 1, 2], ['start', 'before', 'after'], $type),
'task' => $this,
])->render();
/** @var User $user */
foreach ($users as $user) {
$data = [
'type' => $type,
'userid' => $user->userid,
'task_id' => $this->id,
];
$pushLog = ProjectTaskPushLog::where($data)->exists();
if ($pushLog) {
continue;
}
//
$dialog = WebSocketDialog::checkUserDialog($botUser->userid, $data['userid']);
if ($dialog) {
ProjectTaskPushLog::createInstance($data)->save();
WebSocketDialogMsg::sendMsg(null, $dialog->id, 'text', ['text' => $text], $botUser->userid);
}
}
}
/**
* 获取任务
* @param $task_id

View File

@ -3,10 +3,6 @@
namespace App\Tasks;
use App\Models\ProjectTask;
use App\Models\ProjectTaskPushLog;
use App\Models\User;
use App\Models\WebSocketDialog;
use App\Models\WebSocketDialogMsg;
use App\Module\Base;
use Carbon\Carbon;
@ -22,105 +18,35 @@ class AppPushTask extends AbstractTask
public function start()
{
$setting = Base::setting('appPushSetting');
$pushTask = $setting['push'] === 'open' && $setting['push_task'] !== 'close';
if (!$pushTask) {
if ($setting['push'] !== 'open') {
return;
}
$start = intval($setting['task_start_minute']);
$hours = floatval($setting['task_remind_hours']);
$hours2 = floatval($setting['task_remind_hours2']);
if ($start > -1) {
ProjectTask::whereNull("complete_at")
->whereNull("archived_at")
->whereBetween("start_at", [
Carbon::now()->subMinutes($start + 10),
Carbon::now()->subMinutes($start)
])->chunkById(100, function ($tasks) {
/** @var ProjectTask $task */
foreach ($tasks as $task) {
$this->taskPush($task, 0);
}
});
}
if ($hours > -1) {
ProjectTask::whereNull("complete_at")
->whereNull("archived_at")
->whereBetween("end_at", [
Carbon::now()->addMinutes($hours * 60),
Carbon::now()->addMinutes($hours * 60 + 10)
])->chunkById(100, function ($tasks) {
/** @var ProjectTask $task */
foreach ($tasks as $task) {
$this->taskPush($task, 1);
}
});
}
if ($hours2 > -1) {
ProjectTask::whereNull("complete_at")
->whereNull("archived_at")
->whereBetween("end_at", [
Carbon::now()->subMinutes($hours2 * 60 + 10),
Carbon::now()->subMinutes($hours2 * 60)
])->chunkById(100, function ($tasks) {
/** @var ProjectTask $task */
foreach ($tasks as $task) {
$this->taskPush($task, 2);
}
});
}
ProjectTask::whereNull("complete_at")
->whereNull("archived_at")
->whereBetween("end_at", [
Carbon::now()->addMinutes(60),
Carbon::now()->addMinutes(60 + 10)
])->chunkById(100, function ($tasks) {
/** @var ProjectTask $task */
foreach ($tasks as $task) {
$task->taskPush(null, 1);
}
});
ProjectTask::whereNull("complete_at")
->whereNull("archived_at")
->whereBetween("end_at", [
Carbon::now()->subMinutes(60 + 10),
Carbon::now()->subMinutes(60)
])->chunkById(100, function ($tasks) {
/** @var ProjectTask $task */
foreach ($tasks as $task) {
$task->taskPush(null, 2);
}
});
}
public function end()
{
}
/**
* 任务过期前、超期后提醒
* @param ProjectTask $task
* @param int $type
* @return void
*/
private function taskPush(ProjectTask $task, int $type)
{
$userids = $task->taskUser->where('owner', 1)->pluck('userid')->toArray();
if (empty($userids)) {
return;
}
$users = User::whereIn('userid', $userids)->whereNull('disable_at')->get();
if (empty($users)) {
return;
}
$botUser = User::botGetOrCreate('task-alert');
if (empty($botUser)) {
return;
}
$setting = Base::setting('appPushSetting');
$text = view('push.task', [
'type' => str_replace([0, 1, 2], ['start', 'before', 'after'], $type),
'task' => $task,
'setting' => $setting,
])->render();
/** @var User $user */
foreach ($users as $user) {
$data = [
'type' => $type,
'userid' => $user->userid,
'task_id' => $task->id,
];
$pushLog = ProjectTaskPushLog::where($data)->exists();
if ($pushLog) {
continue;
}
//
$dialog = WebSocketDialog::checkUserDialog($botUser->userid, $data['userid']);
if ($dialog) {
ProjectTaskPushLog::createInstance($data)->save();
WebSocketDialogMsg::sendMsg(null, $dialog->id, 'text', ['text' => $text], $botUser->userid); // todo 未能在任务end事件来发送任务
}
}
}
}

View File

@ -25,51 +25,6 @@ class EmailNoticeTask extends AbstractTask
public function start()
{
$setting = Base::setting('emailSetting');
// 任务通知
if ($setting['notice'] === 'open') {
$start = intval($setting['task_start_minute']);
$hours = floatval($setting['task_remind_hours']);
$hours2 = floatval($setting['task_remind_hours2']);
if ($start > -1) {
ProjectTask::whereNull("complete_at")
->whereNull("archived_at")
->whereBetween("start_at", [
Carbon::now()->subMinutes($start + 10),
Carbon::now()->subMinutes($start)
])->chunkById(100, function ($tasks) {
/** @var ProjectTask $task */
foreach ($tasks as $task) {
$this->taskEmail($task, 0);
}
});
}
if ($hours > -1) {
ProjectTask::whereNull("complete_at")
->whereNull("archived_at")
->whereBetween("end_at", [
Carbon::now()->addMinutes($hours * 60),
Carbon::now()->addMinutes($hours * 60 + 10)
])->chunkById(100, function ($tasks) {
/** @var ProjectTask $task */
foreach ($tasks as $task) {
$this->taskEmail($task, 1);
}
});
}
if ($hours2 > -1) {
ProjectTask::whereNull("complete_at")
->whereNull("archived_at")
->whereBetween("end_at", [
Carbon::now()->subMinutes($hours2 * 60 + 10),
Carbon::now()->subMinutes($hours2 * 60)
])->chunkById(100, function ($tasks) {
/** @var ProjectTask $task */
foreach ($tasks as $task) {
$this->taskEmail($task, 2);
}
});
}
}
// 消息通知
if ($setting['notice_msg'] === 'open') {
$userMinute = intval($setting['msg_unread_user_minute']);
@ -114,70 +69,6 @@ class EmailNoticeTask extends AbstractTask
}
/**
* 任务过期前、超期后提醒
* @param ProjectTask $task
* @param int $type
* @return void
*/
private function taskEmail(ProjectTask $task, int $type)
{
$userids = $task->taskUser->where('owner', 1)->pluck('userid')->toArray();
if (empty($userids)) {
return;
}
$users = User::whereIn('userid', $userids)->whereNull('disable_at')->get();
if (empty($users)) {
return;
}
$setting = Base::setting('emailSetting');
/** @var User $user */
foreach ($users as $user) {
$data = [
'type' => $type,
'userid' => $user->userid,
'task_id' => $task->id,
];
$emailLog = ProjectTaskMailLog::where($data)->exists();
if ($emailLog) {
continue;
}
try {
if (!Base::isEmail($user->email)) {
throw new \Exception("User email '{$user->email}' address error");
}
$subject = match ($type) {
1 => "任务提醒",
2 => "任务过期提醒",
default => "任务开始提醒",
};
$content = view('email.task', [
'type' => str_replace([0, 1, 2], ['start', 'before', 'after'], $type),
'user' => $user,
'task' => $task,
'setting' => $setting,
])->render();
Setting::validateAddr($user->email, function($to) use ($content, $subject, $setting) {
Factory::mailer()
->setDsn("smtp://{$setting['account']}:{$setting['password']}@{$setting['smtp_server']}:{$setting['port']}?verify_peer=0")
->setMessage(EmailMessage::create()
->from(env('APP_NAME', 'Task') . " <{$setting['account']}>")
->to($to)
->subject($subject)
->html($content))
->send();
});
$data['is_send'] = 1;
} catch (\Throwable $e) {
$data['send_error'] = $e->getMessage();
}
$data['email'] = $user->email;
ProjectTaskMailLog::createInstance($data)->save();
}
}
/**
* 未读消息通知
* @param $rows

View File

@ -5,7 +5,6 @@ namespace App\Tasks;
@error_reporting(E_ALL & ~E_NOTICE & ~E_WARNING);
use App\Models\User;
use App\Models\UserBot;
use App\Models\WebSocketDialog;
use App\Models\WebSocketDialogMsg;
use App\Models\WebSocketDialogMsgRead;
@ -164,8 +163,7 @@ class WebSocketDialogMsgTask extends AbstractTask
// umeng推送app
if ($umengUserid) {
$setting = Base::setting('appPushSetting');
$pushMsg = $setting['push'] === 'open' && $setting['push_msg'] !== 'close';
if ($pushMsg) {
if ($setting['push'] === 'open') {
$umengTitle = User::userid2nickname($msg->userid);
if ($dialog->type == 'group') {
$umengTitle = "{$dialog->getGroupName()} ($umengTitle)";

View File

@ -24,40 +24,6 @@
<FormItem label="App Master Secret" prop="secret">
<Input :maxlength="255" v-model="formData.android_secret" type="password"/>
</FormItem>
<Divider orientation="left">{{$L('推送内容')}}</Divider>
<FormItem :label="$L('消息提醒')" prop="push_msg">
<RadioGroup v-model="formData.push_msg">
<Radio label="open">{{ $L('开启') }}</Radio>
<Radio label="close">{{ $L('关闭') }}</Radio>
</RadioGroup>
</FormItem>
<FormItem :label="$L('任务提醒')" prop="push_task">
<RadioGroup v-model="formData.push_task">
<Radio label="open">{{ $L('开启') }}</Radio>
<Radio label="close">{{ $L('关闭') }}</Radio>
</RadioGroup>
<Form v-if="formData.push_task == 'open'" @submit.native.prevent>
<FormItem :label="$L('任务开始')" prop="task_start_minute">
<div class="input-number-box">
<InputNumber v-model="formData.task_start_minute" :min="0" :step="1"/>
<label>{{ $L('分钟') }}(m)</label>
</div>
</FormItem>
<FormItem :label="$L('距离到期')" prop="task_remind_hours">
<div class="input-number-box">
<InputNumber v-model="formData.task_remind_hours" :min="0" :step="0.5" @on-change="hoursChange($event, 'task_remind_hours')"/>
<label>{{ $L('小时') }}(h)</label>
</div>
</FormItem>
<FormItem :label="$L('到期超时')" prop="task_remind_hours2">
<div class="input-number-box">
<InputNumber v-model="formData.task_remind_hours2" :min="0" :step="0.5" @on-change="hoursChange($event, 'task_remind_hours2')"/>
<label>{{ $L('小时') }}(h)</label>
</div>
</FormItem>
<div class="form-tip">{{$L('填写-1则不通知误差±10分钟')}}</div>
</Form>
</FormItem>
</template>
</div>
</Form>

View File

@ -35,33 +35,6 @@
{{$L('修改邮箱和删除帐号需要邮箱验证码')}}
</div>
</FormItem>
<FormItem :label="$L('任务提醒')" prop="notice">
<RadioGroup v-model="formData.notice">
<Radio label="open">{{ $L('开启') }}</Radio>
<Radio label="close">{{ $L('关闭') }}</Radio>
</RadioGroup>
<Form v-if="formData.notice == 'open'" @submit.native.prevent>
<FormItem :label="$L('任务开始')" prop="task_start_minute">
<div class="input-number-box">
<InputNumber v-model="formData.task_start_minute" :min="0" :step="1"/>
<label>{{ $L('分钟') }}(m)</label>
</div>
</FormItem>
<FormItem :label="$L('距离到期')" prop="task_remind_hours">
<div class="input-number-box">
<InputNumber v-model="formData.task_remind_hours" :min="0" :step="0.5" @on-change="hoursChange($event, 'task_remind_hours')"/>
<label>{{ $L('小时') }}(h)</label>
</div>
</FormItem>
<FormItem :label="$L('到期超时')" prop="task_remind_hours2">
<div class="input-number-box">
<InputNumber v-model="formData.task_remind_hours2" :min="0" :step="0.5" @on-change="hoursChange($event, 'task_remind_hours2')"/>
<label>{{ $L('小时') }}(h)</label>
</div>
</FormItem>
<div class="form-tip">{{$L('填写-1则不通知误差±10分钟')}}</div>
</Form>
</FormItem>
<FormItem :label="$L('消息提醒')" prop="notice_msg">
<RadioGroup v-model="formData.notice_msg">
<Radio label="open">{{ $L('开启') }}</Radio>
@ -114,10 +87,6 @@ export default {
account: '',
password: '',
reg_verify: 'colse',
notice: 'open',
task_start_minute: -1,
task_remind_hours: -1,
task_remind_hours2: -1,
notice_msg: 'open',
msg_unread_user_minute: -1,
msg_unread_group_minute: -1,

View File

@ -1,8 +0,0 @@
<p>{{ $user->nickname }} 您好:</p>
@if ($type === 'before')
<p>您有一个任务【{{ $task->name }}{{ $setting['task_remind_hours'] > 0 ? "还有{$setting['task_remind_hours']}小时即将超时" : "已超时" }},请及时处理。</p>
@elseif ($type === 'after')
<p>您的任务【{{ $task->name }}】已经超时{{ $setting['task_remind_hours2'] > 0 ? "{$setting['task_remind_hours2']}小时" : "" }},请及时处理。</p>
@else
<p>您有一个新任务【{{ $task->name }}】已开始。</p>
@endif

View File

@ -1,7 +1,7 @@
@if ($type === 'before')
有一个任务 <span class="mention task" data-id="{{ $task->id }}">#{{ $task->name }}</span> {{ $setting['task_remind_hours'] > 0 ? "还有{$setting['task_remind_hours']}小时即将超时" : "已超时" }},请及时处理。
任务 <span class="mention task" data-id="{{ $task->id }}">#{{ $task->name }}</span> 即将超时,请及时处理。
@elseif ($type === 'after')
您的任务 <span class="mention task" data-id="{{ $task->id }}">#{{ $task->name }}</span> 已经超时{{ $setting['task_remind_hours2'] > 0 ? "{$setting['task_remind_hours2']}小时" : "" }},请及时处理。
您的任务 <span class="mention task" data-id="{{ $task->id }}">#{{ $task->name }}</span> 已经超时,请及时处理。
@else
您有一个新任务 <span class="mention task" data-id="{{ $task->id }}">#{{ $task->name }}</span> 已开始
您有一个新任务 <span class="mention task" data-id="{{ $task->id }}">#{{ $task->name }}</span>
@endif