mirror of
https://github.com/netcccyun/dnsmgr.git
synced 2026-02-21 15:31:12 +08:00
新增whois查询域名到期时间+到期提醒
This commit is contained in:
parent
76e9adb405
commit
079a142b40
@ -482,4 +482,23 @@ function convertDomainToUtf8($domain) {
|
||||
} else {
|
||||
return $domain;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getDomainDate($domain)
|
||||
{
|
||||
try {
|
||||
$whois = \Iodev\Whois\Factory::get()->createWhois();
|
||||
$info = $whois->loadDomainInfo($domain);
|
||||
if ($info) {
|
||||
if ($info->expirationDate > 0) {
|
||||
return [date('Y-m-d H:i:s', $info->creationDate), date('Y-m-d H:i:s', $info->expirationDate)];
|
||||
} else {
|
||||
throw new Exception('域名到期时间未知');
|
||||
}
|
||||
} else {
|
||||
throw new Exception('域名信息未找到');
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
throw new Exception('查询域名whois失败: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,8 +5,9 @@ namespace app\controller;
|
||||
use app\BaseController;
|
||||
use think\facade\Db;
|
||||
use think\facade\View;
|
||||
use think\facade\Request;
|
||||
use think\facade\Cache;
|
||||
use app\lib\DnsHelper;
|
||||
use app\service\ExpireNoticeService;
|
||||
use Exception;
|
||||
|
||||
class Domain extends BaseController
|
||||
@ -179,6 +180,7 @@ class Domain extends BaseController
|
||||
if (!checkPermission(1)) return json(['total' => 0, 'rows' => []]);
|
||||
$kw = input('post.kw', null, 'trim');
|
||||
$type = input('post.type', null, 'trim');
|
||||
$status = input('post.status', null, 'trim');
|
||||
$offset = input('post.offset/d', 0);
|
||||
$limit = input('post.limit/d', 10);
|
||||
|
||||
@ -192,6 +194,13 @@ class Domain extends BaseController
|
||||
if (request()->user['level'] == 1) {
|
||||
$select->where('is_hide', 0)->where('A.name', 'in', request()->user['permission']);
|
||||
}
|
||||
if (!isNullOrEmpty($status)) {
|
||||
if ($status == '2') {
|
||||
$select->where('A.expiretime', '<=', date('Y-m-d H:i:s'));
|
||||
} elseif ($status == '1') {
|
||||
$select->where('A.expiretime', '<=', date('Y-m-d H:i:s', time() + 86400 * 30))->where('A.expiretime', '>', date('Y-m-d H:i:s'));
|
||||
}
|
||||
}
|
||||
$total = $select->count();
|
||||
$rows = $select->fieldRaw('A.*,B.type,B.remark aremark')->order('A.id', 'desc')->limit($offset, $limit)->select();
|
||||
|
||||
@ -240,11 +249,13 @@ class Domain extends BaseController
|
||||
if (!$row) return json(['code' => -1, 'msg' => '域名不存在']);
|
||||
$is_hide = input('post.is_hide/d');
|
||||
$is_sso = input('post.is_sso/d');
|
||||
$is_notice = input('post.is_notice/d');
|
||||
$remark = input('post.remark', null, 'trim');
|
||||
if (empty($remark)) $remark = null;
|
||||
Db::name('domain')->where('id', $id)->update([
|
||||
'is_hide' => $is_hide,
|
||||
'is_sso' => $is_sso,
|
||||
'is_notice' => $is_notice,
|
||||
'remark' => $remark,
|
||||
]);
|
||||
return json(['code' => 0, 'msg' => '修改域名配置成功!']);
|
||||
@ -280,8 +291,15 @@ class Domain extends BaseController
|
||||
if (empty($ids)) return json(['code' => -1, 'msg' => '参数不能为空']);
|
||||
$remark = input('post.remark', null, 'trim');
|
||||
if (empty($remark)) $remark = null;
|
||||
Db::name('domain')->where('id', 'in', $ids)->update(['remark' => $remark]);
|
||||
return json(['code' => 0, 'msg' => '成功修改' . count($ids) . '个域名!']);
|
||||
$count = Db::name('domain')->where('id', 'in', $ids)->update(['remark' => $remark]);
|
||||
return json(['code' => 0, 'msg' => '成功修改' . $count . '个域名!']);
|
||||
} elseif ($act == 'batchsetnotice') {
|
||||
if (!checkPermission(2)) return $this->alert('error', '无权限');
|
||||
$ids = input('post.ids');
|
||||
$is_notice = input('post.is_notice/d', 0);
|
||||
if (empty($ids)) return json(['code' => -1, 'msg' => '参数不能为空']);
|
||||
$count = Db::name('domain')->where('id', 'in', $ids)->update(['is_notice' => $is_notice]);
|
||||
return json(['code' => 0, 'msg' => '成功修改' . $count . '个域名!']);
|
||||
} elseif ($act == 'batchdel') {
|
||||
if (!checkPermission(2)) return $this->alert('error', '无权限');
|
||||
$ids = input('post.ids');
|
||||
@ -1029,4 +1047,33 @@ class Domain extends BaseController
|
||||
$domainRecords = $dns->getWeightSubDomains($page, $limit, $keyword);
|
||||
return json(['total' => $domainRecords['total'], 'rows' => $domainRecords['list']]);
|
||||
}
|
||||
|
||||
public function expire_notice()
|
||||
{
|
||||
if (!checkPermission(2)) return $this->alert('error', '无权限');
|
||||
if ($this->request->isPost()) {
|
||||
$params = input('post.');
|
||||
foreach ($params as $key => $value) {
|
||||
if (empty($key)) {
|
||||
continue;
|
||||
}
|
||||
config_set($key, $value);
|
||||
Cache::delete('configs');
|
||||
}
|
||||
return json(['code' => 0, 'msg' => 'succ']);
|
||||
}
|
||||
return View::fetch();
|
||||
}
|
||||
|
||||
public function update_date()
|
||||
{
|
||||
$id = input('param.id/d');
|
||||
$drow = Db::name('domain')->where('id', $id)->find();
|
||||
if (!$drow) {
|
||||
return json(['code' => -1, 'msg' => '域名不存在']);
|
||||
}
|
||||
if (!checkPermission(0, $drow['name'])) return json(['code' => -1, 'msg' => '无权限']);
|
||||
$result = (new ExpireNoticeService())->updateDomainDate($id, $drow['name']);
|
||||
return json($result);
|
||||
}
|
||||
}
|
||||
|
||||
@ -890,7 +890,7 @@ class DeployHelper
|
||||
'domain' => [
|
||||
'name' => '绑定的域名',
|
||||
'type' => 'input',
|
||||
'placeholder' => '',
|
||||
'placeholder' => '多个域名可使用,分隔',
|
||||
'show' => 'product==\'cdn\'',
|
||||
'required' => true,
|
||||
],
|
||||
@ -1142,6 +1142,7 @@ class DeployHelper
|
||||
['value'=>'cdn', 'label'=>'内容分发网络CDN'],
|
||||
['value'=>'dcdn', 'label'=>'全站加速DCDN'],
|
||||
['value'=>'clb', 'label'=>'负载均衡CLB'],
|
||||
['value'=>'alb', 'label'=>'应用型负载均衡ALB'],
|
||||
['value'=>'tos', 'label'=>'对象存储TOS'],
|
||||
['value'=>'live', 'label'=>'视频直播'],
|
||||
['value'=>'imagex', 'label'=>'veImageX'],
|
||||
@ -1160,14 +1161,14 @@ class DeployHelper
|
||||
'name' => '绑定的域名',
|
||||
'type' => 'input',
|
||||
'placeholder' => '多个域名可使用,分隔',
|
||||
'show' => 'product!=\'clb\'',
|
||||
'show' => 'product!=\'clb\'&&product!=\'alb\'',
|
||||
'required' => true,
|
||||
],
|
||||
'listener_id' => [
|
||||
'name' => '监听器ID',
|
||||
'type' => 'input',
|
||||
'placeholder' => '',
|
||||
'show' => 'product==\'clb\'',
|
||||
'show' => 'product==\'clb\'||product==\'alb\'',
|
||||
'required' => true,
|
||||
],
|
||||
],
|
||||
|
||||
@ -58,8 +58,10 @@ class huawei implements DeployInterface
|
||||
],
|
||||
],
|
||||
];
|
||||
$client->request('PUT', '/v1.1/cdn/configuration/domains/' . $config['domain'] . '/configs', null, $param);
|
||||
$this->log('CDN域名 ' . $config['domain'] . ' 部署证书成功!');
|
||||
foreach (explode(',', $config['domain']) as $domain) {
|
||||
$client->request('PUT', '/v1.1/cdn/configuration/domains/' . $domain . '/configs', null, $param);
|
||||
$this->log('CDN域名 ' . $domain . ' 部署证书成功!');
|
||||
}
|
||||
}
|
||||
|
||||
private function deploy_elb($fullchain, $privatekey, $config)
|
||||
|
||||
@ -46,6 +46,8 @@ class huoshan implements DeployInterface
|
||||
$this->deploy_imagex($cert_id, $config);
|
||||
} elseif ($config['product'] == 'clb') {
|
||||
$this->deploy_clb($cert_id, $config);
|
||||
} elseif ($config['product'] == 'alb') {
|
||||
$this->deploy_alb($cert_id, $config);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -167,6 +169,19 @@ class huoshan implements DeployInterface
|
||||
$this->log('CLB监听器 ' . $config['listener_id'] . ' 部署证书成功!');
|
||||
}
|
||||
|
||||
private function deploy_alb($cert_id, $config)
|
||||
{
|
||||
if (empty($config['listener_id'])) throw new Exception('监听器ID不能为空');
|
||||
$client = new Volcengine($this->AccessKeyId, $this->SecretAccessKey, 'open.volcengineapi.com', 'alb', '2020-04-01', 'cn-beijing', $this->proxy);
|
||||
$param = [
|
||||
'ListenerId' => $config['listener_id'],
|
||||
'CertificateSource' => 'cert_center',
|
||||
'CertCenterCertificateId' => $cert_id,
|
||||
];
|
||||
$client->request('GET', 'ModifyListenerAttributes', $param);
|
||||
$this->log('ALB监听器 ' . $config['listener_id'] . ' 部署证书成功!');
|
||||
}
|
||||
|
||||
private function get_cert_id($fullchain, $privatekey)
|
||||
{
|
||||
$certInfo = openssl_x509_parse($fullchain, true);
|
||||
|
||||
@ -13,6 +13,7 @@ class CertTaskService
|
||||
{
|
||||
$this->execute_deploy();
|
||||
$this->execute_order();
|
||||
(new ExpireNoticeService())->task();
|
||||
config_set('certtask_time', date("Y-m-d H:i:s"));
|
||||
echo 'done'.PHP_EOL;
|
||||
}
|
||||
|
||||
102
app/service/ExpireNoticeService.php
Normal file
102
app/service/ExpireNoticeService.php
Normal file
@ -0,0 +1,102 @@
|
||||
<?php
|
||||
|
||||
namespace app\service;
|
||||
|
||||
use Exception;
|
||||
use think\facade\Db;
|
||||
use app\utils\MsgNotice;
|
||||
|
||||
/**
|
||||
* 域名到期提醒
|
||||
*/
|
||||
class ExpireNoticeService
|
||||
{
|
||||
|
||||
public function updateDomainDate($id, $domain)
|
||||
{
|
||||
try {
|
||||
[$regTime, $expireTime] = getDomainDate($domain);
|
||||
Db::name('domain')->where('id', $id)->update(['regtime' => $regTime, 'expiretime' => $expireTime, 'checktime' => date('Y-m-d H:i:s'), 'checkstatus' => 1]);
|
||||
return ['code' => 0, 'regTime' => $regTime, 'expireTime' => $expireTime, 'msg' => 'Success'];
|
||||
} catch (Exception $e) {
|
||||
Db::name('domain')->where('id', $id)->update(['checktime' => date('Y-m-d H:i:s'), 'checkstatus' => 2]);
|
||||
return ['code' => -1, 'msg' => $e->getMessage()];
|
||||
}
|
||||
}
|
||||
|
||||
public function task()
|
||||
{
|
||||
$count = $this->refreshDomainList();
|
||||
if ($count > 0) return;
|
||||
|
||||
$days = config_get('expire_noticedays');
|
||||
$max_day = 30;
|
||||
if (!empty($days)) {
|
||||
$days = explode(',', $days);
|
||||
$days = array_map('intval', $days);
|
||||
$max_day = max($days) + 1;
|
||||
}
|
||||
$count = $this->refreshExpiringDomainList($max_day);
|
||||
if ($count > 0) return;
|
||||
|
||||
if (!empty($days) && (config_get('expire_notice_mail') == '1' || config_get('expire_notice_wxtpl') == '1' || config_get('expire_notice_tgbot') == '1' || config_get('expire_notice_webhook') == '1') && date('H') >= 9) {
|
||||
$this->noticeExpiringDomainList($max_day, $days);
|
||||
}
|
||||
}
|
||||
|
||||
private function refreshDomainList()
|
||||
{
|
||||
$domainList = Db::name('domain')->field('id,name')->where('expiretime', null)->where('checkstatus', 0)->select();
|
||||
$count = 0;
|
||||
foreach ($domainList as $domain) {
|
||||
$res = $this->updateDomainDate($domain['id'], $domain['name']);
|
||||
if ($res['code'] == 0) {
|
||||
echo '域名: ' . $domain['name'] . ' 注册时间: ' . $res['regTime'] . ' 到期时间: ' . $res['expireTime'] . PHP_EOL;
|
||||
} else {
|
||||
echo '域名: ' . $domain['name'] . ' 更新失败,' . $res['msg'] . PHP_EOL;
|
||||
}
|
||||
$count++;
|
||||
if ($count >= 5) break;
|
||||
sleep(1);
|
||||
}
|
||||
return $count;
|
||||
}
|
||||
|
||||
private function refreshExpiringDomainList($max_day)
|
||||
{
|
||||
$domainList = Db::name('domain')->field('id,name')->whereRaw('expiretime>=(NOW() - INTERVAL 5 DAY) AND expiretime<=(NOW() + INTERVAL ' . $max_day . ' DAY) AND checktime<=(NOW() - INTERVAL 1 DAY)')->select();
|
||||
$count = 0;
|
||||
foreach ($domainList as $domain) {
|
||||
$res = $this->updateDomainDate($domain['id'], $domain['name']);
|
||||
if ($res['code'] == 0) {
|
||||
echo '域名: ' . $domain['name'] . ' 注册时间: ' . $res['regTime'] . ' 到期时间: ' . $res['expireTime'] . PHP_EOL;
|
||||
} else {
|
||||
echo '域名: ' . $domain['name'] . ' 更新失败,' . $res['msg'] . PHP_EOL;
|
||||
}
|
||||
$count++;
|
||||
if ($count >= 5) break;
|
||||
sleep(1);
|
||||
}
|
||||
return $count;
|
||||
}
|
||||
|
||||
private function noticeExpiringDomainList($max_day, $days)
|
||||
{
|
||||
$domainList = Db::name('domain')->field('id,name,expiretime')->whereRaw('expiretime>=NOW() AND expiretime<=(NOW() + INTERVAL ' . $max_day . ' DAY) AND is_notice=1 AND (noticetime IS NULL OR noticetime<=(NOW() - INTERVAL 20 HOUR))')->order('expiretime', 'asc')->select();
|
||||
$noticeList = [];
|
||||
foreach ($domainList as $domain) {
|
||||
$expireDay = intval((strtotime($domain['expiretime']) - time()) / 86400);
|
||||
if (in_array($expireDay, $days)) {
|
||||
$noticeList[$expireDay][] = ['id' => $domain['id'], 'name' => $domain['name'], 'expiretime' => $domain['expiretime']];
|
||||
}
|
||||
}
|
||||
if (!empty($noticeList)) {
|
||||
foreach ($noticeList as $day => $list) {
|
||||
$ids = array_column($list, 'id');
|
||||
Db::name('domain')->whereIn('id', $ids)->update(['noticetime' => date('Y-m-d H:i:s')]);
|
||||
MsgNotice::expire_notice_send($day, $list);
|
||||
echo '域名到期提醒: ' . $day . '天内到期的' . count($ids) . '个域名已发送' . PHP_EOL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -5,7 +5,7 @@ CREATE TABLE `dnsmgr_config` (
|
||||
PRIMARY KEY (`key`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
INSERT INTO `dnsmgr_config` VALUES ('version', '1028');
|
||||
INSERT INTO `dnsmgr_config` VALUES ('version', '1033');
|
||||
INSERT INTO `dnsmgr_config` VALUES ('notice_mail', '0');
|
||||
INSERT INTO `dnsmgr_config` VALUES ('notice_wxtpl', '0');
|
||||
INSERT INTO `dnsmgr_config` VALUES ('mail_smtp', 'smtp.qq.com');
|
||||
@ -35,6 +35,12 @@ CREATE TABLE `dnsmgr_domain` (
|
||||
`is_sso` tinyint(1) NOT NULL DEFAULT '0',
|
||||
`recordcount` int(1) NOT NULL DEFAULT '0',
|
||||
`remark` varchar(100) DEFAULT NULL,
|
||||
`is_notice` tinyint(1) NOT NULL DEFAULT '0',
|
||||
`regtime` datetime DEFAULT NULL,
|
||||
`expiretime` datetime DEFAULT NULL,
|
||||
`checktime` datetime DEFAULT NULL,
|
||||
`noticetime` datetime DEFAULT NULL,
|
||||
`checkstatus` tinyint(1) NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `name` (`name`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
@ -155,4 +155,12 @@ ALTER TABLE `dnsmgr_account`
|
||||
ADD COLUMN `proxy` tinyint(1) NOT NULL DEFAULT '0';
|
||||
|
||||
ALTER TABLE `dnsmgr_dmtask`
|
||||
ADD COLUMN `cdn` tinyint(1) NOT NULL DEFAULT 0;
|
||||
ADD COLUMN `cdn` tinyint(1) NOT NULL DEFAULT 0;
|
||||
|
||||
ALTER TABLE `dnsmgr_domain`
|
||||
ADD COLUMN `is_notice` tinyint(1) NOT NULL DEFAULT '0',
|
||||
ADD COLUMN `regtime` datetime DEFAULT NULL,
|
||||
ADD COLUMN `expiretime` datetime DEFAULT NULL,
|
||||
ADD COLUMN `checktime` datetime DEFAULT NULL,
|
||||
ADD COLUMN `noticetime` datetime DEFAULT NULL,
|
||||
ADD COLUMN `checkstatus` tinyint(1) NOT NULL DEFAULT '0';
|
||||
@ -133,6 +133,34 @@ class MsgNotice
|
||||
}
|
||||
}
|
||||
|
||||
public static function expire_notice_send($day, $list)
|
||||
{
|
||||
$mail_title = '您有'.count($list).'个域名即将在'.$day.'天后到期';
|
||||
$mail_content = '尊敬的用户,您好:您有'.count($list).'个域名即将在'.$day.'天后到期!<br/><b>域名&到期时间:</b><br/>';
|
||||
foreach ($list as $domain) {
|
||||
$mail_content .= '<b>'.$domain['name'].'</b> - '.$domain['expiretime'].'<br/>';
|
||||
}
|
||||
$mail_content .= '<br/><font color="grey">'.self::$sitename.'</font><br/><font color="grey">'.date('Y-m-d H:i:s').'</font>';
|
||||
|
||||
if (config_get('expire_notice_mail') == 1 || config_get('expire_notice_mail') == 2) {
|
||||
$mail_name = config_get('mail_recv') ? config_get('mail_recv') : config_get('mail_name');
|
||||
self::send_mail($mail_name, $mail_title, $mail_content);
|
||||
}
|
||||
if (config_get('expire_notice_wxtpl') == 1 || config_get('expire_notice_wxtpl') == 2) {
|
||||
$content = str_replace(['<br/>', '<b>', '</b>'], ["\n\n", '**', '**'], $mail_content);
|
||||
self::send_wechat_tplmsg($mail_title, strip_tags($content));
|
||||
}
|
||||
if (config_get('expire_notice_tgbot') == 1 || config_get('expire_notice_tgbot') == 2) {
|
||||
$content = str_replace('<br/>', "\n", $mail_content);
|
||||
$content = "<strong>".$mail_title."</strong>\n".strip_tags($content);
|
||||
self::send_telegram_bot($content);
|
||||
}
|
||||
if (config_get('expire_notice_webhook') == 1) {
|
||||
$content = str_replace(['*', '<br/>', '<b>', '</b>'], ['\*', "\n", '**', '**'], $mail_content);
|
||||
self::send_webhook($mail_title, $content);
|
||||
}
|
||||
}
|
||||
|
||||
public static function send_mail($to, $sub, $msg)
|
||||
{
|
||||
$mail_type = config_get('mail_type');
|
||||
|
||||
@ -103,7 +103,7 @@
|
||||
{if request()->user['type'] eq 'user'}<li class="{:checkIfActive('index')}">
|
||||
<a href="/"><i class="fa fa-home fa-fw"></i> <span>后台首页</span></a>
|
||||
</li>{/if}
|
||||
<li class="{:checkIfActive('domain,record,record_log,record_batch_add,domain_add,weight,record_batch_add2,record_batch_edit2')}">
|
||||
<li class="{:checkIfActive('domain,record,record_log,record_batch_add,domain_add,weight,record_batch_add2,record_batch_edit2,expire_notice')}">
|
||||
<a href="/domain"><i class="fa fa-list-ul fa-fw"></i> <span>域名管理</span></a>
|
||||
</li>
|
||||
{if request()->user['level'] eq 2}
|
||||
|
||||
@ -17,11 +17,16 @@
|
||||
<form onsubmit="return false" method="post" class="form-horizontal" role="form" id="taskform">
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 col-xs-12 control-label no-padding-right">域名选择</label>
|
||||
<div class="col-sm-3 col-xs-5"><input type="text" name="rr" v-model="set.rr" placeholder="主机记录" class="form-control" required></div>
|
||||
<div class="col-sm-3 col-xs-7 dselect"><select name="did" v-model="set.did" class="form-control" required>
|
||||
<option value="">--主域名--</option>
|
||||
<option v-for="option in domainList" :value="option.id">{{option.name}}</option>
|
||||
</select></div>
|
||||
<div class="col-sm-6">
|
||||
<div class="input-group">
|
||||
<input type="text" name="rr" v-model="set.rr" placeholder="主机记录" class="form-control" required>
|
||||
<span class="input-group-addon">.</span>
|
||||
<select name="did" v-model="set.did" class="form-control" required>
|
||||
<option value="">--主域名--</option>
|
||||
<option v-for="option in domainList" :value="option.id">{{option.name}}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label no-padding-right">解析记录</label>
|
||||
|
||||
@ -50,6 +50,18 @@
|
||||
<div class="modal-body">
|
||||
<form class="form-horizontal" id="form-store2">
|
||||
<input type="hidden" name="id"/>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">到期提醒</label>
|
||||
<div class="col-sm-9">
|
||||
<div class="input-group">
|
||||
<select name="is_notice" class="form-control">
|
||||
<option value="0">否</option>
|
||||
<option value="1">是</option>
|
||||
</select>
|
||||
<a tabindex="0" class="input-group-addon" role="button" data-toggle="popover" data-trigger="focus" title="" data-placement="bottom" data-content="域名到期提醒,其他设置在“到期提醒设置”里面" data-original-title="说明"><span class="glyphicon glyphicon-info-sign"></span></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">是否隐藏</label>
|
||||
<div class="col-sm-9">
|
||||
@ -104,13 +116,17 @@
|
||||
<option value="{$k}">{$v}</option>
|
||||
{/foreach}</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<select name="status" class="form-control"><option value="">所有状态</option><option value="1">即将到期</option><option value="2">已到期</option></select>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary"><i class="fa fa-search"></i> 搜索</button>
|
||||
<a href="javascript:searchClear()" class="btn btn-default" title="刷新域名列表"><i class="fa fa-refresh"></i> 刷新</a>
|
||||
{if request()->user['level'] eq 2}<a href="javascript:addframe()" class="btn btn-success"><i class="fa fa-plus"></i> 添加</a>
|
||||
<div class="btn-group" role="group">
|
||||
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">批量操作 <span class="caret"></span></button>
|
||||
<ul class="dropdown-menu"><li><a href="/domain/add">添加域名</a></li><li><a href="javascript:operation('editremark')">修改域名备注</a></li><li><a href="javascript:operation('delete')">删除域名</a></li><li role="separator" class="divider"></li><li><a href="javascript:operation('addrecord')">添加解析</a></li><li><a href="javascript:operation('editrecord')">修改解析</a></li></ul>
|
||||
</div>{/if}
|
||||
<ul class="dropdown-menu"><li><a href="/domain/add">添加域名</a></li><li><a href="javascript:operation('editremark')">修改域名备注</a></li><li><a href="javascript:operation('opennotice')">开启到期提醒</a></li><li><a href="javascript:operation('closenotice')">关闭到期提醒</a></li><li><a href="javascript:operation('delete')">删除域名</a></li><li role="separator" class="divider"></li><li><a href="javascript:operation('addrecord')">添加解析</a></li><li><a href="javascript:operation('editrecord')">修改解析</a></li></ul>
|
||||
</div>
|
||||
<a href="/domain/expirenotice" class="btn btn-default">到期提醒设置</a>{/if}
|
||||
</form>
|
||||
|
||||
<table id="listTable">
|
||||
@ -173,12 +189,61 @@ $(document).ready(function(){
|
||||
title: '添加时间'
|
||||
},
|
||||
{
|
||||
field: 'remark',
|
||||
title: '备注'
|
||||
field: 'regtime',
|
||||
title: '注册时间',
|
||||
visible: false,
|
||||
formatter: function(value, row, index) {
|
||||
var html = '';
|
||||
if(value == null) {
|
||||
if (row.checkstatus == 0) {
|
||||
html = '<font color="#bdbdbd">待查询</font>';
|
||||
} else if (row.checkstatus == 2) {
|
||||
html = '<font color="#bdbdbd">查询失败</font>';
|
||||
}
|
||||
} else {
|
||||
html = value.slice(0,10);
|
||||
}
|
||||
return html;
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'expiretime',
|
||||
title: '到期时间',
|
||||
formatter: function(value, row, index) {
|
||||
var html = '';
|
||||
if(value == null) {
|
||||
if (row.checkstatus == 0) {
|
||||
html = '<font color="#bdbdbd">待查询</font>';
|
||||
} else if (row.checkstatus == 2) {
|
||||
html = '<font color="#bdbdbd">查询失败</font>';
|
||||
}
|
||||
} else {
|
||||
var now = new Date().getTime();
|
||||
var expiretime = new Date(value).getTime();
|
||||
var days = parseInt((expiretime - now) / 1000 / 24 / 60 / 60);
|
||||
if (days > 30) {
|
||||
html += '<span title="还有'+days+'天到期" data-toggle="tooltip" data-placement="bottom">'+value.slice(0,10)+'</span>';
|
||||
} else if (days > 0) {
|
||||
html += '<b><span class="text-yellow" title="还有'+days+'天到期" data-toggle="tooltip" data-placement="bottom">'+value.slice(0,10)+'</span></b>';
|
||||
} else {
|
||||
html += '<b><span class="text-red" title="已到期" data-toggle="tooltip" data-placement="bottom">'+value.slice(0,10)+'</span></b>';
|
||||
}
|
||||
}
|
||||
html += ' <a href="javascript:updateDate('+row.id+')" title="刷新到期时间" class="text-green"><i class="fa fa-refresh"></i></a>';
|
||||
return html;
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'is_notice',
|
||||
title: '到期提醒',
|
||||
formatter: function(value, row, index) {
|
||||
return value==1?'<font color="green">是</font>':'<font color="blue">否</font>';
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'is_hide',
|
||||
title: '是否隐藏',
|
||||
visible: false,
|
||||
formatter: function(value, row, index) {
|
||||
return value==1?'<font color="grey">是</font>':'<font color="blue">否</font>';
|
||||
}
|
||||
@ -186,10 +251,15 @@ $(document).ready(function(){
|
||||
{
|
||||
field: 'is_sso',
|
||||
title: '对接开关',
|
||||
visible: false,
|
||||
formatter: function(value, row, index) {
|
||||
return value==1?'<font color="green">是</font>':'<font color="red">否</font>';
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'remark',
|
||||
title: '备注'
|
||||
},
|
||||
{
|
||||
field: '',
|
||||
title: '操作',
|
||||
@ -202,7 +272,10 @@ $(document).ready(function(){
|
||||
return html;
|
||||
}
|
||||
},
|
||||
]
|
||||
],
|
||||
onLoadSuccess: function(data) {
|
||||
$('[data-toggle="tooltip"]').tooltip()
|
||||
}
|
||||
})
|
||||
|
||||
$("#form-store select[name=aid]").change(function(){
|
||||
@ -259,6 +332,7 @@ function editframe(id){
|
||||
$("#form-store2 input[name=id]").val(row.id);
|
||||
$("#form-store2 select[name=is_hide]").val(row.is_hide);
|
||||
$("#form-store2 select[name=is_sso]").val(row.is_sso);
|
||||
$("#form-store2 select[name=is_notice]").val(row.is_notice);
|
||||
$("#form-store2 input[name=remark]").val(row.remark);
|
||||
}
|
||||
function saveEdit(){
|
||||
@ -369,30 +443,50 @@ function operation(action){
|
||||
sessionStorage.setItem('domains', JSON.stringify(rows));
|
||||
window.location.href = '/record/batchedit';
|
||||
return;
|
||||
}
|
||||
var confirmobj = layer.confirm('确定要删除所选域名吗?', {
|
||||
btn: ['确定','取消']
|
||||
}, function(){
|
||||
var ii = layer.load(2);
|
||||
$.ajax({
|
||||
type : 'POST',
|
||||
url : '/domain/op/act/batchdel',
|
||||
data : {ids: ids},
|
||||
dataType : 'json',
|
||||
success : function(data) {
|
||||
layer.close(ii);
|
||||
if(data.code == 0){
|
||||
layer.closeAll();
|
||||
layer.alert(data.msg, {icon: 1});
|
||||
searchRefresh();
|
||||
}else{
|
||||
layer.alert(data.msg, {icon: 2});
|
||||
}else if(action == 'delete'){
|
||||
var confirmobj = layer.confirm('确定要删除所选域名吗?', {
|
||||
btn: ['确定','取消']
|
||||
}, function(){
|
||||
var ii = layer.load(2);
|
||||
$.ajax({
|
||||
type : 'POST',
|
||||
url : '/domain/op/act/batchdel',
|
||||
data : {ids: ids},
|
||||
dataType : 'json',
|
||||
success : function(data) {
|
||||
layer.close(ii);
|
||||
if(data.code == 0){
|
||||
layer.closeAll();
|
||||
layer.alert(data.msg, {icon: 1});
|
||||
searchRefresh();
|
||||
}else{
|
||||
layer.alert(data.msg, {icon: 2});
|
||||
}
|
||||
}
|
||||
});
|
||||
}, function(){
|
||||
layer.close(confirmobj);
|
||||
});
|
||||
}else{
|
||||
var is_notice = action == 'opennotice' ? 1 : 0;
|
||||
var ii = layer.load(2);
|
||||
$.ajax({
|
||||
type : 'POST',
|
||||
url : '/domain/op/act/batchsetnotice',
|
||||
data : {ids: ids, is_notice: is_notice},
|
||||
dataType : 'json',
|
||||
success : function(data) {
|
||||
layer.close(ii);
|
||||
if(data.code == 0){
|
||||
layer.closeAll();
|
||||
layer.alert(data.msg, {icon: 1});
|
||||
searchRefresh();
|
||||
}else{
|
||||
layer.alert(data.msg, {icon: 2});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}, function(){
|
||||
layer.close(confirmobj);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
function batch_edit_remark(ids) {
|
||||
layer.open({
|
||||
@ -428,6 +522,24 @@ function batch_edit_remark(ids) {
|
||||
}
|
||||
});
|
||||
}
|
||||
function updateDate(id){
|
||||
var ii = layer.load(2);
|
||||
$.ajax({
|
||||
type : 'POST',
|
||||
url : '/domain/updatedate',
|
||||
data : {id: id},
|
||||
dataType : 'json',
|
||||
success : function(data) {
|
||||
layer.close(ii);
|
||||
if(data.code == 0){
|
||||
layer.msg('刷新成功', {icon: 1, time: 600});
|
||||
searchRefresh();
|
||||
}else{
|
||||
layer.alert(data.msg, {icon: 2});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
function loading(){
|
||||
layer.load(2);
|
||||
}
|
||||
|
||||
85
app/view/domain/expire_notice.html
Normal file
85
app/view/domain/expire_notice.html
Normal file
@ -0,0 +1,85 @@
|
||||
{extend name="common/layout" /}
|
||||
{block name="title"}域名到期提醒设置{/block}
|
||||
{block name="main"}
|
||||
<div class="row">
|
||||
<div class="col-xs-12 col-sm-8 col-lg-6 center-block" style="float: none;">
|
||||
|
||||
<div class="panel panel-info">
|
||||
<div class="panel-heading"><h3 class="panel-title"><a href="/domain" class="btn btn-sm btn-default pull-right" style="margin-top:-6px"><i class="fa fa-reply fa-fw"></i> 返回</a>域名到期提醒设置</h3></div>
|
||||
<div class="panel-body">
|
||||
<form onsubmit="return saveSetting(this)" method="post" class="form-horizontal" role="form">
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">到期提醒天数</label>
|
||||
<div class="col-sm-9"><input type="text" name="expire_noticedays" value="{:config_get('expire_noticedays')}" class="form-control" placeholder="留空则不开启到期提醒"/><font color="green">域名到期前多少天发送通知,可填写多个天数,用英文逗号隔开。例如填写7,14则在域名到期前7天与14天分别发送通知。</font></div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">邮件通知</label>
|
||||
<div class="col-sm-9"><select class="form-control" name="expire_notice_mail" default="{:config_get('expire_notice_mail')}"><option value="0">关闭</option><option value="1">开启</option></select></div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">微信公众号通知</label>
|
||||
<div class="col-sm-9"><select class="form-control" name="expire_notice_wxtpl" default="{:config_get('expire_notice_wxtpl')}"><option value="0">关闭</option><option value="1">开启</option></select></div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">Telegram机器人通知</label>
|
||||
<div class="col-sm-9"><select class="form-control" name="expire_notice_tgbot" default="{:config_get('expire_notice_tgbot')}"><option value="0">关闭</option><option value="1">开启</option></select></div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">群机器人Webhook</label>
|
||||
<div class="col-sm-9"><select class="form-control" name="expire_notice_webhook" default="{:config_get('expire_notice_webhook')}"><option value="0">关闭</option><option value="1">开启</option></select></div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-3 col-sm-9">
|
||||
<input type="submit" name="submit" value="保存" class="btn btn-primary btn-block"/>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel panel-warning">
|
||||
<div class="panel-heading"><h3 class="panel-title">计划任务说明</h3></div>
|
||||
<div class="panel-body">
|
||||
<p>支持域名到期提醒+域名列表到期时间自动刷新。与SSL证书共用计划任务,不需要单独添加计划任务。</p><p><a href="/cert/certset">查看计划任务说明</a></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
{/block}
|
||||
{block name="script"}
|
||||
<script src="{$cdnpublic}layer/3.1.1/layer.js"></script>
|
||||
<script>
|
||||
var items = $("select[default]");
|
||||
for (i = 0; i < items.length; i++) {
|
||||
$(items[i]).val($(items[i]).attr("default")||0);
|
||||
}
|
||||
function saveSetting(obj){
|
||||
var ii = layer.load(2, {shade:[0.1,'#fff']});
|
||||
$.ajax({
|
||||
type : 'POST',
|
||||
url : '',
|
||||
data : $(obj).serialize(),
|
||||
dataType : 'json',
|
||||
success : function(data) {
|
||||
layer.close(ii);
|
||||
if(data.code == 0){
|
||||
layer.alert('设置保存成功!', {
|
||||
icon: 1,
|
||||
closeBtn: false
|
||||
}, function(){
|
||||
window.location.reload()
|
||||
});
|
||||
}else{
|
||||
layer.alert(data.msg, {icon: 2})
|
||||
}
|
||||
},
|
||||
error:function(data){
|
||||
layer.close(ii);
|
||||
layer.msg('服务器错误');
|
||||
}
|
||||
});
|
||||
return false;
|
||||
}
|
||||
</script>
|
||||
{/block}
|
||||
@ -16,14 +16,20 @@
|
||||
<div class="panel-body">
|
||||
<form onsubmit="return false" method="post" class="form-horizontal" role="form" id="taskform">
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 col-xs-12 control-label no-padding-right">域名选择</label>
|
||||
<div class="col-sm-3 col-xs-5"><input type="text" name="rr" v-model="set.rr" placeholder="主机记录" class="form-control" required></div>
|
||||
<div class="col-sm-3 col-xs-7 dselect"><select name="did" v-model="set.did" class="form-control" required>
|
||||
<option value="">--主域名--</option>
|
||||
{foreach $domains as $k=>$v}
|
||||
<option value="{$k}">{$v}</option>
|
||||
{/foreach}
|
||||
</select></div>
|
||||
<label class="col-sm-3 control-label no-padding-right">域名选择</label>
|
||||
<div class="col-sm-6">
|
||||
<div class="input-group">
|
||||
<input type="text" name="rr" v-model="set.rr" placeholder="主机记录" class="form-control" required>
|
||||
<span class="input-group-addon">.</span>
|
||||
<select name="did" v-model="set.did" class="form-control" required>
|
||||
<option value="">--主域名--</option>
|
||||
{foreach $domains as $k=>$v}
|
||||
<option value="{$k}">{$v}</option>
|
||||
{/foreach}
|
||||
</select>
|
||||
<a tabindex="0" class="input-group-addon" role="button" data-toggle="popover" data-trigger="focus" title="" data-placement="bottom" data-content="不支持对CloudFlare里的域名添加优选,必须使用其他DNS服务商。" data-original-title="说明"><span class="glyphicon glyphicon-info-sign"></span></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label no-padding-right">CDN服务商</label>
|
||||
@ -142,6 +148,7 @@ new Vue({
|
||||
live: 'submitted',
|
||||
});
|
||||
$('[data-toggle="tooltip"]').tooltip();
|
||||
$('[data-toggle="popover"]').popover()
|
||||
},
|
||||
methods: {
|
||||
submit(){
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
<div class="panel panel-warning">
|
||||
<div class="panel-heading"><h3 class="panel-title">使用说明</h3></div>
|
||||
<div class="panel-body">
|
||||
<p><li>不支持对CloudFlare里的域名添加优选,必须使用其他DNS服务商。需开通Cloudflare for SaaS,且域名使用CNAME的方式解析到CloudFlare。</li></p>
|
||||
<p><li>数据接口:<a href="https://www.wetest.vip/" target="_blank" rel="noreferrer">wetest.vip</a> 数据接口支持CloudFlare、CloudFront、Gcore;<a href="https://stock.hostmonit.com/" target="_blank" rel="noreferrer">HostMonit</a> 只支持CloudFlare。</li></p>
|
||||
<p><li>接口密钥:默认o1zrmHAF为免费KEY可永久免费使用。</li></p>
|
||||
<p><li>计划任务:将以下命令添加到计划任务,周期设置为15分钟以上</li></p>
|
||||
|
||||
@ -48,7 +48,8 @@
|
||||
"topthink/think-view": "^1.0",
|
||||
"cccyun/think-captcha": "^3.0",
|
||||
"symfony/polyfill-intl-idn": "^1.31",
|
||||
"symfony/polyfill-php80": "^1.31"
|
||||
"symfony/polyfill-php80": "^1.31",
|
||||
"cccyun/php-whois": "^1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/var-dumper": "^4.2",
|
||||
|
||||
@ -31,7 +31,7 @@ return [
|
||||
'show_error_msg' => true,
|
||||
'exception_tmpl' => \think\facade\App::getAppPath() . 'view/exception.tpl',
|
||||
|
||||
'version' => '1032',
|
||||
'version' => '1033',
|
||||
|
||||
'dbversion' => '1028'
|
||||
'dbversion' => '1033'
|
||||
];
|
||||
|
||||
@ -49,6 +49,8 @@ Route::group(function () {
|
||||
Route::post('/account/op', 'domain/account_op');
|
||||
Route::get('/account', 'domain/account');
|
||||
|
||||
Route::any('/domain/expirenotice', 'domain/expire_notice');
|
||||
Route::post('/domain/updatedate', 'domain/update_date');
|
||||
Route::post('/domain/data', 'domain/domain_data');
|
||||
Route::post('/domain/op', 'domain/domain_op');
|
||||
Route::post('/domain/list', 'domain/domain_list');
|
||||
|
||||
Loading…
Reference in New Issue
Block a user