mirror of
https://github.com/kuaifan/dootask.git
synced 2025-12-10 18:02:55 +00:00
feat: 管理员系统设置新增:新增邮件设置
This commit is contained in:
parent
ab388f1ef5
commit
cf7e7c1a06
@ -500,4 +500,58 @@ class SystemController extends AbstractController
|
||||
'home_footer' => Base::settingFind('system', 'home_footer')
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @api {get} api/system/emailSetting 14. 获取邮箱设置、保存邮箱设置
|
||||
*
|
||||
* @apiVersion 1.0.0
|
||||
* @apiGroup system
|
||||
* @apiName emailSetting
|
||||
*
|
||||
* @apiParam {String} type
|
||||
* - get: 获取(默认)
|
||||
* - all: 获取所有(需要管理员权限)
|
||||
* - save: 保存设置(参数:smtp_server port account password reg_verify notice task_remind_hours task_remind_hours2)
|
||||
* @apiSuccess {Number} ret 返回状态码(1正确、0错误)
|
||||
* @apiSuccess {String} msg 返回信息(错误描述)
|
||||
* @apiSuccess {Object} data 返回数据
|
||||
*/
|
||||
public function emailSetting()
|
||||
{
|
||||
$type = trim(Request::input('type'));
|
||||
if ($type == 'save') {
|
||||
if (env("SYSTEM_SETTING") == 'disabled') {
|
||||
return Base::retError('当前环境禁止修改');
|
||||
}
|
||||
User::auth('admin');
|
||||
$all = Request::input();
|
||||
foreach ($all as $key => $value) {
|
||||
if (!in_array($key, ['smtp_server', 'port', 'account', 'password', 'reg_verify', 'notice', 'task_remind_hours', 'task_remind_hours2'])) {
|
||||
unset($all[$key]);
|
||||
}
|
||||
}
|
||||
$setting = Base::setting('emailSetting', Base::newTrim($all));
|
||||
} else {
|
||||
$setting = Base::setting('emailSetting');
|
||||
}
|
||||
//
|
||||
if ($type == 'all' || $type == 'save') {
|
||||
User::auth('admin');
|
||||
$setting['reg_invite'] = $setting['reg_invite'] ?: Base::generatePassword(8);
|
||||
} else {
|
||||
if (isset($setting['reg_invite'])) unset($setting['reg_invite']);
|
||||
}
|
||||
//
|
||||
$setting['smtp_server'] = $setting['smtp_server'] ?: '';
|
||||
$setting['port'] = $setting['port'] ?: '';
|
||||
$setting['account'] = $setting['account'] ?: '';
|
||||
$setting['password'] = $setting['password'] ?: '';
|
||||
$setting['reg_verify'] = $setting['reg_verify'] ?: 'close';
|
||||
$setting['notice'] = $setting['notice'] ?: 'open';
|
||||
$setting['task_remind_hours'] = floatval($setting['task_remind_hours']) ?: 0;
|
||||
$setting['task_remind_hours2'] = floatval($setting['task_remind_hours2']) ?: 0;
|
||||
//
|
||||
return Base::retSuccess('success', $setting ?: json_decode('{}'));
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,10 +7,12 @@ use App\Module\Base;
|
||||
use App\Tasks\PushTask;
|
||||
use Arr;
|
||||
use Carbon\Carbon;
|
||||
use Config;
|
||||
use DB;
|
||||
use Exception;
|
||||
use Hhxsv5\LaravelS\Swoole\Task\Task;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Mail;
|
||||
use Request;
|
||||
|
||||
/**
|
||||
@ -1208,4 +1210,33 @@ class ProjectTask extends AbstractModel
|
||||
//
|
||||
return $task;
|
||||
}
|
||||
|
||||
/**
|
||||
* 预超期任务提醒
|
||||
* @param $ownerIds
|
||||
*/
|
||||
public static function overdueRemindEmail($ownerIds)
|
||||
{
|
||||
$users = User::whereIn('userid', $ownerIds)->get();
|
||||
if (!$users) {
|
||||
throw new ApiException("ProjectTask::overdueRemindEmail--没有负责人");
|
||||
}
|
||||
Config::set("mail.mailers.smtp.host", Base::settingFind('emailSetting', 'smtp_server'));
|
||||
Config::set("mail.mailers.smtp.port", Base::settingFind('emailSetting', 'port'));
|
||||
Config::set("mail.mailers.smtp.username", Base::settingFind('emailSetting', 'account'));
|
||||
Config::set("mail.mailers.smtp.password", Base::settingFind('emailSetting', 'password'));
|
||||
foreach ($users as $user) {
|
||||
/** @var User $user */
|
||||
$email = $user->email;
|
||||
try {
|
||||
Mail::send('taskOverdueRemind', ['url' => 'https://www.baidu.com'], function ($m) use ($email) {
|
||||
$m->from(Config::get("mail.mailers.smtp.username"), env('APP_NAME'));
|
||||
$m->to($email);
|
||||
$m->subject("过期任务提醒");
|
||||
});
|
||||
} catch (\Exception $e) {
|
||||
\Log::error($email.'--邮箱发动报错:', [$e->getMessage()]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2982,4 +2982,112 @@ class Base
|
||||
},
|
||||
$str);
|
||||
}
|
||||
//去重复
|
||||
public static function assoc_unique($array, $keyid,$desc=true) {
|
||||
if(empty($array)){
|
||||
return false;
|
||||
}
|
||||
$array = array_values($array);
|
||||
//倒叙排列数
|
||||
if($desc)
|
||||
{
|
||||
$array =(new Self)->array_rsort($array,true);
|
||||
}
|
||||
|
||||
//提取需要判断的项目变成一维数组
|
||||
$a = (new Self)->array_tq($array,$keyid);
|
||||
|
||||
//去除一维数组重复值
|
||||
$a = array_unique($a);
|
||||
//提取二维数组项目值
|
||||
foreach($array[0] AS $key=>$value)
|
||||
{
|
||||
$akey[] = $key;
|
||||
}
|
||||
//重新拼接二维数组
|
||||
foreach($akey AS $key=>$value)
|
||||
{
|
||||
$b = (new Self)->array_tq($array,$value);
|
||||
foreach($a AS $key2=>$value2)
|
||||
{
|
||||
$c[$key2][$value] = $b[$key2];
|
||||
}
|
||||
}
|
||||
|
||||
if($desc)
|
||||
{
|
||||
$c = (new Self)->array_rsort($c,true);
|
||||
}
|
||||
return $c;
|
||||
}
|
||||
|
||||
//提取二维数组项目
|
||||
public static function array_tq($array,$aval="")
|
||||
{
|
||||
foreach($array AS $key=>$value)
|
||||
{
|
||||
$result[] = $value[$aval];
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
public static function array_rsort($arr,$isvalues=false)
|
||||
{
|
||||
if(is_array($arr)){
|
||||
$flag = false;
|
||||
//一维数组
|
||||
if(count($arr) == count($arr,1)){
|
||||
$flag = true;
|
||||
$i = 0;
|
||||
//转换成二维数组
|
||||
foreach($arr AS $key=>$value){
|
||||
$a[$i]["okey"] = $key;
|
||||
$a[$i]["value"] = $value;
|
||||
$i++;
|
||||
}
|
||||
$arr = $a;
|
||||
}
|
||||
//多维数组
|
||||
else
|
||||
{
|
||||
//添加临时key值
|
||||
foreach($arr AS $key=>$value){
|
||||
$value["okey"] = $key;
|
||||
$array[] = $value;
|
||||
}
|
||||
$arr = $array;
|
||||
}
|
||||
|
||||
//倒叙并还原key值
|
||||
$count = count($arr)-1;
|
||||
for($i=0;$i<count($arr);$i++){
|
||||
$b[$arr[$count]["okey"]] = $arr[$count];
|
||||
$count--;
|
||||
}
|
||||
|
||||
//重构一维数组
|
||||
if($flag == true){
|
||||
foreach($b AS $key=>$value){
|
||||
if($isvalues){
|
||||
$c[] = $value["value"];
|
||||
}else{
|
||||
$c[$value["okey"]] = $value["value"];
|
||||
}
|
||||
}
|
||||
}
|
||||
//多维数组去除临时key值
|
||||
else
|
||||
{
|
||||
foreach($b AS $key=>$value) {
|
||||
unset($value["okey"]);
|
||||
if($isvalues){
|
||||
$c[] = $value;
|
||||
}else{
|
||||
$c[$key] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
64
app/Tasks/OverdueRemindEmailTask.php
Normal file
64
app/Tasks/OverdueRemindEmailTask.php
Normal file
@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace App\Tasks;
|
||||
|
||||
|
||||
use App\Models\ProjectTask;
|
||||
use App\Models\ProjectTaskUser;
|
||||
use App\Module\Base;
|
||||
use Carbon\Carbon;
|
||||
|
||||
class OverdueRemindEmailTask extends AbstractTask
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
public function start()
|
||||
{
|
||||
$setting = Base::setting('emailSetting');
|
||||
if ($setting['notice'] === 'open') {
|
||||
$hours = floatval($setting['task_remind_hours']);
|
||||
$hours2 = floatval($setting['task_remind_hours2']);
|
||||
$taskLists1 = [];
|
||||
$taskLists2 = [];
|
||||
$startTime = Carbon::now();
|
||||
if ($hours > 0) {
|
||||
$endTime = Carbon::now()->addHours($hours);
|
||||
$taskLists1 = ProjectTask::whereNull('complete_at')
|
||||
->where('end_at', '>=', $startTime)
|
||||
->where('end_at', '<=', $endTime)
|
||||
->whereNull('archived_at')
|
||||
->take(100)
|
||||
->get()
|
||||
->toArray();
|
||||
}
|
||||
if ($hours2 > 0) {
|
||||
$endTime2 = Carbon::now()->addHours($hours2);
|
||||
$taskLists2 = ProjectTask::whereNull('complete_at')
|
||||
->where('end_at', '>=', $startTime)
|
||||
->where('end_at', '<=', $endTime2)
|
||||
->whereNull('archived_at')
|
||||
->take(100)
|
||||
->get()
|
||||
->toArray();
|
||||
|
||||
}
|
||||
$taskLists = array_merge($taskLists1, $taskLists2);
|
||||
$taskLists = Base::assoc_unique($taskLists, 'id');
|
||||
$ownerIdsArr = [];
|
||||
foreach ($taskLists as &$task) {
|
||||
$ownerIds = ProjectTaskUser::whereTaskId($task['id'])->whereOwner(1)->pluck('userid')->toArray();
|
||||
foreach ($ownerIds as $ownerId) {
|
||||
$ownerIdsArr[] = $ownerId;
|
||||
}
|
||||
}
|
||||
if (!empty($ownerIdsArr)) {
|
||||
ProjectTask::overdueRemindEmail($ownerIdsArr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -36,15 +36,14 @@ return [
|
||||
'mailers' => [
|
||||
'smtp' => [
|
||||
'transport' => 'smtp',
|
||||
'host' => env('MAIL_HOST', 'smtp.mailgun.org'),
|
||||
'port' => env('MAIL_PORT', 587),
|
||||
'encryption' => env('MAIL_ENCRYPTION', 'tls'),
|
||||
'username' => env('MAIL_USERNAME'),
|
||||
'password' => env('MAIL_PASSWORD'),
|
||||
'timeout' => null,
|
||||
'auth_mode' => null,
|
||||
'host' => 'smtp.qq.com',
|
||||
'port' => 465,
|
||||
'encryption' => 'ssl',
|
||||
'username' => '302645122@qq.com',
|
||||
'password' => 'ijncezxbmhrvbhab',
|
||||
'timeout' => 15,
|
||||
],
|
||||
|
||||
|
||||
'ses' => [
|
||||
'transport' => 'ses',
|
||||
],
|
||||
@ -70,6 +69,7 @@ return [
|
||||
'array' => [
|
||||
'transport' => 'array',
|
||||
],
|
||||
|
||||
],
|
||||
|
||||
/*
|
||||
|
||||
117
resources/assets/js/pages/manage/setting/system/emailSetting.vue
Normal file
117
resources/assets/js/pages/manage/setting/system/emailSetting.vue
Normal file
@ -0,0 +1,117 @@
|
||||
<template>
|
||||
<div class="setting-item submit">
|
||||
<Form ref="formData" :model="formData" :rules="ruleData" label-width="auto" @submit.native.prevent>
|
||||
<h3>{{ $L('邮箱服务器设置') }}</h3>
|
||||
<FormItem :label="$L('SMTP服务器')" prop="smtp_server">
|
||||
<Input v-model="formData.smtp_server"/>
|
||||
</FormItem>
|
||||
<FormItem :label="$L('端口')" prop="port">
|
||||
<Input :maxlength="20" v-model="formData.port"/>
|
||||
</FormItem>
|
||||
<FormItem :label="$L('账号')" prop="account">
|
||||
<Input :maxlength="20" v-model="formData.account"/>
|
||||
</FormItem>
|
||||
<FormItem :label="$L('密码')" prop="password">
|
||||
<Input :maxlength="20" v-model="formData.password"/>
|
||||
</FormItem>
|
||||
|
||||
<h3>{{ $L('邮件通知设置') }}</h3>
|
||||
<FormItem :label="$L('开启注册验证')" prop="reg_verify">
|
||||
<RadioGroup v-model="formData.reg_verify">
|
||||
<Radio label="open">{{ $L('开启') }}</Radio>
|
||||
<Radio label="close">{{ $L('关闭') }}</Radio>
|
||||
</RadioGroup>
|
||||
</FormItem>
|
||||
<FormItem :label="$L('开启通知')" prop="notice">
|
||||
<RadioGroup v-model="formData.notice">
|
||||
<Radio label="open">{{ $L('开启') }}</Radio>
|
||||
<Radio label="close">{{ $L('关闭') }}</Radio>
|
||||
</RadioGroup>
|
||||
</FormItem>
|
||||
<template v-if="formData.notice == 'open'">
|
||||
<FormItem :label="$L('任务提醒:')" prop="task_remind_hours">
|
||||
<label>{{ $L('到期前') }}</label>
|
||||
<InputNumber v-model="formData.task_remind_hours"/>
|
||||
<label>{{ $L('小时') }}</label>
|
||||
</FormItem>
|
||||
<FormItem :label="$L('第二次任务提醒:')" prop="task_remind_hours2">
|
||||
<label>{{ $L('到期前') }}</label>
|
||||
<InputNumber v-model="formData.task_remind_hours2"/>
|
||||
<label>{{ $L('小时') }}</label>
|
||||
</FormItem>
|
||||
</template>
|
||||
</Form>
|
||||
<div class="setting-footer">
|
||||
<Button :loading="loadIng > 0" type="primary" @click="submitForm">{{ $L('提交') }}</Button>
|
||||
<Button :loading="loadIng > 0" @click="resetForm" style="margin-left: 8px">{{ $L('重置') }}</Button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "SystemEmailSetting",
|
||||
data() {
|
||||
return {
|
||||
loadIng: 0,
|
||||
formData: {
|
||||
smtp_server: '',
|
||||
port: '',
|
||||
account: '',
|
||||
password: '',
|
||||
reg_verify: 'colse',
|
||||
notice: 'open',
|
||||
task_remind_hours: 0,
|
||||
task_remind_hours2: 0,
|
||||
},
|
||||
ruleData: {},
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.systemSetting();
|
||||
},
|
||||
|
||||
methods: {
|
||||
submitForm() {
|
||||
this.$refs.formData.validate((valid) => {
|
||||
if (valid) {
|
||||
this.systemSetting(true);
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
resetForm() {
|
||||
this.formData = $A.cloneJSON(this.formDatum_bak);
|
||||
},
|
||||
|
||||
formArchived(value) {
|
||||
this.formData = {...this.formData, auto_archived: value};
|
||||
},
|
||||
|
||||
systemSetting(save) {
|
||||
this.loadIng++;
|
||||
this.$store.dispatch("call", {
|
||||
url: 'system/emailSetting?type=' + (save ? 'save' : 'all'),
|
||||
data: this.formData,
|
||||
}).then(({data}) => {
|
||||
if (save) {
|
||||
$A.messageSuccess('修改成功');
|
||||
}
|
||||
this.loadIng--;
|
||||
this.formData = data;
|
||||
this.formDatum_bak = $A.cloneJSON(this.formData);
|
||||
}).catch(({msg}) => {
|
||||
if (save) {
|
||||
$A.modalError(msg);
|
||||
}
|
||||
this.loadIng--;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@ -10,6 +10,9 @@
|
||||
<TabPane :label="$L('项目模板')" name="columnTemplate">
|
||||
<SystemColumnTemplate/>
|
||||
</TabPane>
|
||||
<TabPane :label="$L('邮件设置')" name="emailSetting">
|
||||
<SystemEmailSetting/>
|
||||
</TabPane>
|
||||
</Tabs>
|
||||
</div>
|
||||
</template>
|
||||
@ -18,8 +21,10 @@
|
||||
import SystemSetting from "./setting";
|
||||
import SystemTaskPriority from "./taskPriority";
|
||||
import SystemColumnTemplate from "./columnTemplate";
|
||||
import SystemEmailSetting from "./emailSetting";
|
||||
|
||||
export default {
|
||||
components: {SystemColumnTemplate, SystemTaskPriority, SystemSetting},
|
||||
components: {SystemColumnTemplate, SystemTaskPriority, SystemSetting, SystemEmailSetting},
|
||||
data() {
|
||||
return {
|
||||
tabAction: 'setting',
|
||||
|
||||
17
resources/views/taskOverdueRemind.blade.php
Normal file
17
resources/views/taskOverdueRemind.blade.php
Normal file
@ -0,0 +1,17 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="{{ app()->getLocale() }}">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<p>用户您好, {{env('APP_NAME') }} 任务到期。</p>
|
||||
<p>若需要重新设定账号密码,请点击下方链接:</p>
|
||||
<div style="display: flex; justify-content: left;">
|
||||
<a href="{{$url}}">{{$url}}</a>
|
||||
</div>
|
||||
<p>如果连接无法点击,请复制此URL然后贴入到您浏览器的地址栏中。</p>
|
||||
|
||||
</body>
|
||||
<body>
|
||||
Loading…
x
Reference in New Issue
Block a user