18 Commits
1.4 ... 1.7.1

Author SHA1 Message Date
net909
3b93ee1203 version 2024-09-17 10:22:45 +08:00
net909
a5145accd6 修改CF优选IP地址 2024-09-17 10:21:27 +08:00
net909
30427a9704 更新CF优选IP接口 2024-09-17 10:11:10 +08:00
net909
4145e282f9 fix 2024-08-30 14:41:29 +08:00
net909
53ec0e12df 修复高版本php 2024-08-28 16:51:51 +08:00
net909
b8addd6d27 新增百度云、火山引擎 2024-08-24 19:42:31 +08:00
net909
0d1d7d3c67 update 2024-08-07 14:05:44 +08:00
net909
8bdf58651c version 2024-08-05 17:10:43 +08:00
net909
350a0bd306 fix 2024-07-25 22:37:41 +08:00
net909
ab074da839 fix 2024-07-25 20:39:21 +08:00
net909
57a237f898 1.6 2024-07-07 15:54:11 +08:00
net909
bf6a091c8d version 2024-07-07 13:39:52 +08:00
net909
14700052b8 修复页面加载错误,支持dnspod国际版 2024-07-07 13:39:27 +08:00
net909
f43f2b196d fix 2024-06-09 10:11:00 +08:00
net909
949b52722a readme 2024-06-08 12:19:20 +08:00
net909
1c504f3b04 解析支持高级搜索 2024-06-07 18:25:31 +08:00
net909
8e4fd32f8c fix 2024-05-24 15:11:28 +08:00
net909
5cd6b108f0 修改syskey存储 2024-05-23 16:26:40 +08:00
46 changed files with 1007 additions and 137 deletions

View File

@@ -2,7 +2,6 @@ APP_DEBUG = false
[APP]
DEFAULT_TIMEZONE = Asia/Shanghai
SYS_KEY = {syskey}
[DATABASE]
TYPE = mysql

View File

@@ -83,6 +83,20 @@ location / {
</IfModule>
```
### Docker部署方法
首先需要安装Docker然后执行以下命令拉取镜像并启动启动后监听8081端口
```
docker run --name dnsmgr -dit -p 8081:80 -v /var/dnsmgr:/app/www netcccyun/dnsmgr
```
访问并安装好后如果容灾切换未自动启动,重启容器即可:
```
docker restart dnsmgr
```
### 版权信息
版权所有Copyright © 2023~2024 by 消失的彩虹海(https://blog.cccyun.cn)

View File

@@ -10,6 +10,7 @@ use think\console\input\Argument;
use think\console\input\Option;
use think\console\Output;
use think\facade\Db;
use think\facade\Config;
use app\lib\TaskRunner;
class Dmtask extends Command
@@ -23,6 +24,9 @@ class Dmtask extends Command
protected function execute(Input $input, Output $output)
{
$res = Db::name('config')->cache('configs',0)->column('value','key');
Config::set($res, 'sys');
config_set('run_error', '');
if(!extension_loaded('swoole')){
$output->writeln('[Error] 未安装Swoole扩展');

View File

@@ -10,6 +10,7 @@ use think\console\input\Argument;
use think\console\input\Option;
use think\console\Output;
use think\facade\Db;
use think\facade\Config;
use app\lib\OptimizeService;
class Opiptask extends Command
@@ -23,6 +24,9 @@ class Opiptask extends Command
protected function execute(Input $input, Output $output)
{
$res = Db::name('config')->cache('configs',0)->column('value','key');
Config::set($res, 'sys');
(new OptimizeService())->execute();
}
}

View File

@@ -47,7 +47,7 @@ class Auth extends BaseController
DB::name('user')->where('id', $user['id'])->update(['lasttime' => date("Y-m-d H:i:s")]);
$session = md5($user['id'].$user['password']);
$expiretime = time()+2562000;
$token = authcode("user\t{$user['id']}\t{$session}\t{$expiretime}", 'ENCODE', env('app.sys_key'));
$token = authcode("user\t{$user['id']}\t{$session}\t{$expiretime}", 'ENCODE', config_get('sys_key'));
cookie('user_token', $token, ['expire' => $expiretime, 'httponly' => true]);
if (file_exists($login_limit_file)) {
unlink($login_limit_file);
@@ -93,7 +93,7 @@ class Auth extends BaseController
if($timestamp < time()-300 || $timestamp > time()+300){
return $this->alert('error', '时间戳无效');
}
if(md5(env('app.sys_key').$domain.$timestamp.$token.env('app.sys_key')) !== $sign){
if(md5(config_get('sys_key').$domain.$timestamp.$token.config_get('sys_key')) !== $sign){
return $this->alert('error', '签名错误');
}
if($token != cache('quicklogin_'.$domain)){
@@ -111,7 +111,7 @@ class Auth extends BaseController
$session = md5($row['id'].$row['name']);
$expiretime = time()+2562000;
$token = authcode("domain\t{$row['id']}\t{$session}\t{$expiretime}", 'ENCODE', env('app.sys_key'));
$token = authcode("domain\t{$row['id']}\t{$session}\t{$expiretime}", 'ENCODE', config_get('sys_key'));
cookie('user_token', $token, ['expire' => $expiretime, 'httponly' => true]);
return redirect('/record/'.$row['id']);
}

View File

@@ -86,6 +86,7 @@ class Dmonitor extends BaseController
'frequency' => input('post.frequency/d'),
'cycle' => input('post.cycle/d'),
'timeout' => input('post.timeout/d'),
'proxy' => input('post.proxy/d'),
'remark' => input('post.remark', null, 'trim'),
'recordinfo' => input('post.recordinfo', null, 'trim'),
'addtime' => time(),
@@ -121,6 +122,7 @@ class Dmonitor extends BaseController
'frequency' => input('post.frequency/d'),
'cycle' => input('post.cycle/d'),
'timeout' => input('post.timeout/d'),
'proxy' => input('post.proxy/d'),
'remark' => input('post.remark', null, 'trim'),
'recordinfo' => input('post.recordinfo', null, 'trim'),
];
@@ -233,6 +235,23 @@ class Dmonitor extends BaseController
return View::fetch();
}
public function proxyset()
{
if(!checkPermission(2)) return $this->alert('error', '无权限');
if(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 mailtest()
{
if(!checkPermission(2)) return $this->alert('error', '无权限');
@@ -246,6 +265,21 @@ class Dmonitor extends BaseController
}
}
public function tgbottest()
{
if(!checkPermission(2)) return $this->alert('error', '无权限');
$tgbot_token = config_get('tgbot_token');
$tgbot_chatid = config_get('tgbot_chatid');
if(empty($tgbot_token) || empty($tgbot_chatid)) return json(['code'=>-1, 'msg'=>'请先保存设置']);
$content = "<strong>消息发送测试</strong>\n\n这是一封测试消息!\n\n来自:".request()->root(true);
$result = \app\lib\MsgNotice::send_telegram_bot($content);
if($result === true){
return json(['code'=>0, 'msg'=>'消息发送成功!']);
}else{
return json(['code'=>-1, 'msg'=>'消息发送失败!'.$result]);
}
}
public function clean()
{
if(!checkPermission(2)) return $this->alert('error', '无权限');

View File

@@ -7,6 +7,7 @@ use think\facade\Db;
use think\facade\View;
use think\facade\Request;
use app\lib\DnsHelper;
use Exception;
class Domain extends BaseController
{
@@ -253,9 +254,9 @@ class Domain extends BaseController
$minTTL = cache('min_ttl_'.$drow['id']);
if(empty($recordLine)){
$dns = DnsHelper::getModel($drow['aid'], $drow['name'], $drow['thirdid']);
if(!$dns) return $this->alert('error', 'DNS模块不存在');
if(!$dns) throw new Exception('DNS模块不存在');
$recordLine = $dns->getRecordLine();
if(!$recordLine) return $this->alert('error', '获取解析线路列表失败,'.$dns->getError());
if(!$recordLine) throw new Exception('获取解析线路列表失败,'.$dns->getError());
cache('record_line_'.$drow['id'], $recordLine, 604800);
$minTTL = $dns->getMinTTL();
if($minTTL){
@@ -291,7 +292,7 @@ class Domain extends BaseController
$token = getSid();
cache('quicklogin_'.$drow['name'], $token, 3600);
$timestamp = time();
$sign = md5(env('app.sys_key').$drow['name'].$timestamp.$token.env('app.sys_key'));
$sign = md5(config_get('sys_key').$drow['name'].$timestamp.$token.config_get('sys_key'));
$drow['loginurl'] = request()->root(true).'/quicklogin?domain='.$drow['name'].'&timestamp='.$timestamp.'&token='.$token.'&sign='.$sign;
}
@@ -329,6 +330,7 @@ class Domain extends BaseController
$id = input('param.id/d');
$keyword = input('post.keyword', null, 'trim');
$subdomain = input('post.subdomain', null, 'trim');
$value = input('post.value', null, 'trim');
$type = input('post.type', null, 'trim');
$line = input('post.line', null, 'trim');
$status = input('post.status', null, 'trim');
@@ -347,10 +349,10 @@ class Domain extends BaseController
if(!checkPermission(0, $drow['name'])) return json(['total'=>0, 'rows'=>[]]);
$dns = DnsHelper::getModel($drow['aid'], $drow['name'], $drow['thirdid']);
$domainRecords = $dns->getDomainRecords($page, $limit, $keyword, $subdomain, $type, $line, $status);
$domainRecords = $dns->getDomainRecords($page, $limit, $keyword, $subdomain, $value, $type, $line, $status);
if(!$domainRecords) return json(['total'=>0, 'rows'=>[]]);
if($domainRecords['total'] != $drow['recordcount']){
if(empty($keyword) && empty($subdomain) && empty($type) && empty($line) && empty($status) && empty($value) && $domainRecords['total'] != $drow['recordcount']){
Db::name('domain')->where('id', $id)->update(['recordcount'=>$domainRecords['total']]);
}
@@ -360,6 +362,11 @@ class Domain extends BaseController
$row['LineName'] = isset($recordLine[$row['Line']]) ? $recordLine[$row['Line']]['name'] : $row['Line'];
}
$dnstype = Db::name('account')->where('id', $drow['aid'])->value('type');
if($dnstype == 'baidu'){
return json($domainRecords['list']);
}
return json(['total'=>$domainRecords['total'], 'rows'=>$domainRecords['list']]);
}

View File

@@ -29,7 +29,7 @@ class Install extends BaseController
}
$configdata = file_get_contents(app()->getRootPath().'.example.env');
$configdata = str_replace(['{syskey}','{dbhost}','{dbname}','{dbuser}','{dbpwd}','{dbport}','{dbprefix}'], [random(16), $mysql_host, $mysql_name, $mysql_user, $mysql_pwd, $mysql_port, $mysql_prefix], $configdata);
$configdata = str_replace(['{dbhost}','{dbname}','{dbuser}','{dbpwd}','{dbport}','{dbprefix}'], [$mysql_host, $mysql_name, $mysql_user, $mysql_pwd, $mysql_port, $mysql_prefix], $configdata);
try{
$DB=new PDO("mysql:host=".$mysql_host.";dbname=".$mysql_name.";port=".$mysql_port,$mysql_user,$mysql_pwd);
@@ -53,6 +53,7 @@ class Install extends BaseController
$sqls=explode(';', $sqls);
$password = password_hash($admin_password, PASSWORD_DEFAULT);
$sqls[]="REPLACE INTO `".$mysql_prefix."config` VALUES ('sys_key', '".random(16)."')";
$sqls[]="INSERT INTO `".$mysql_prefix."user` (`username`,`password`,`level`,`regtime`,`lasttime`,`status`) VALUES ('".addslashes($admin_username)."', '$password', 2, NOW(), NOW(), 1)";
$success=0;$error=0;$errorMsg=null;

View File

@@ -4,7 +4,7 @@ namespace app\lib;
class CheckUtils
{
public static function curl($url, $timeout, $ip = null)
public static function curl($url, $timeout, $ip = null, $proxy = false)
{
$status = true;
$errmsg = null;
@@ -19,6 +19,28 @@ class CheckUtils
}
}
$ch = curl_init();
if($proxy){
$proxy_server = config_get('proxy_server');
$proxy_port = intval(config_get('proxy_port'));
$proxy_userpwd = config_get('proxy_user').':'.config_get('proxy_pwd');
$proxy_type = config_get('proxy_type');
if($proxy_type == 'https'){
$proxy_type = CURLPROXY_HTTPS;
}elseif($proxy_type == 'sock4'){
$proxy_type = CURLPROXY_SOCKS4;
}elseif($proxy_type == 'sock5'){
$proxy_type = CURLPROXY_SOCKS5;
}else{
$proxy_type = CURLPROXY_HTTP;
}
curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_PROXY, $proxy_server);
curl_setopt($ch, CURLOPT_PROXYPORT, $proxy_port);
if($proxy_userpwd != ':'){
curl_setopt($ch, CURLOPT_PROXYUSERPWD, $proxy_userpwd);
}
curl_setopt($ch, CURLOPT_PROXYTYPE, $proxy_type);
}
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);

View File

@@ -39,6 +39,17 @@ class DnsHelper
'redirect' => false,
'log' => false,
],
'baidu' => [
'name' => '百度云',
'config' => [
'ak' => 'AccessKey',
'sk' => 'SecretKey'
],
'remark' => 2,
'status' => false,
'redirect' => false,
'log' => false,
],
'west' => [
'name' => '西部数码',
'config' => [
@@ -50,6 +61,17 @@ class DnsHelper
'redirect' => false,
'log' => false,
],
'huoshan' => [
'name' => '火山引擎',
'config' => [
'ak' => 'AccessKeyId',
'sk' => 'SecretAccessKey'
],
'remark' => 2,
'status' => true,
'redirect' => false,
'log' => false,
],
'dnsla' => [
'name' => 'DNSLA',
'config' => [
@@ -65,7 +87,7 @@ class DnsHelper
'name' => 'Cloudflare',
'config' => [
'ak' => '邮箱地址',
'sk' => 'API密钥'
'sk' => 'API密钥/令牌'
],
'remark' => 2,
'status' => false,

View File

@@ -10,7 +10,7 @@ interface DnsInterface
function getDomainList($KeyWord=null, $PageNumber=1, $PageSize=20);
function getDomainRecords($PageNumber=1, $PageSize=20, $KeyWord = null, $SubDomain = null, $Type = null, $Line = null, $Status = null);
function getDomainRecords($PageNumber=1, $PageSize=20, $KeyWord = null, $SubDomain = null, $Value = null, $Type = null, $Line = null, $Status = null);
function getSubDomainRecords($SubDomain, $PageNumber=1, $PageSize=20, $Type = null, $Line = null);

View File

@@ -41,8 +41,13 @@ class MsgNotice
self::send_mail($mail_name, $mail_title, $mail_content);
}
if(config_get('notice_wxtpl') == 1){
$mail_content = str_replace(['<br/>', '<b>', '</b>'], ["\n\n", '**', '**'], $mail_content);
self::send_wechat_tplmsg($mail_title, $mail_content);
$content = str_replace(['<br/>', '<b>', '</b>'], ["\n\n", '**', '**'], $mail_content);
self::send_wechat_tplmsg($mail_title, $content);
}
if(config_get('notice_tgbot') == 1){
$content = str_replace('<br/>', "\n", $mail_content);
$content = "<strong>".$mail_title."</strong>\n".$content;
self::send_telegram_bot($content);
}
}
@@ -102,4 +107,61 @@ class MsgNotice
return $arr['msg'];
}
}
public static function send_telegram_bot($content){
$tgbot_token = config_get('tgbot_token');
$tgbot_chatid = config_get('tgbot_chatid');
if(!$tgbot_token||!$tgbot_chatid)return false;
$url = 'https://api.telegram.org/bot'.$tgbot_token.'/sendMessage';
$post = ['chat_id'=>$tgbot_chatid, 'text'=>$content, 'parse_mode'=>'HTML'];
$result = self::telegram_curl($url, http_build_query($post));
$arr = json_decode($result, true);
if(isset($arr['ok']) && $arr['ok']==true){
return true;
}else{
return $arr['description'];
}
}
private static function telegram_curl($url, $post){
$ch = curl_init();
if(config_get('tgbot_proxy') == 1){
$proxy_server = config_get('proxy_server');
$proxy_port = intval(config_get('proxy_port'));
$proxy_userpwd = config_get('proxy_user').':'.config_get('proxy_pwd');
$proxy_type = config_get('proxy_type');
if($proxy_type == 'https'){
$proxy_type = CURLPROXY_HTTPS;
}elseif($proxy_type == 'sock4'){
$proxy_type = CURLPROXY_SOCKS4;
}elseif($proxy_type == 'sock5'){
$proxy_type = CURLPROXY_SOCKS5;
}else{
$proxy_type = CURLPROXY_HTTP;
}
curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_PROXY, $proxy_server);
curl_setopt($ch, CURLOPT_PROXYPORT, $proxy_port);
if($proxy_userpwd != ':'){
curl_setopt($ch, CURLOPT_PROXYUSERPWD, $proxy_userpwd);
}
curl_setopt($ch, CURLOPT_PROXYTYPE, $proxy_type);
}
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
$httpheader[] = "Accept: */*";
$httpheader[] = "Accept-Encoding: gzip,deflate,sdch";
$httpheader[] = "Accept-Language: zh-CN,zh;q=0.8";
$httpheader[] = "Connection: close";
curl_setopt($ch, CURLOPT_HTTPHEADER, $httpheader);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Linux; U; Android 4.0.4; es-mx; HTC_One_X Build/IMM76D) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0");
curl_setopt($ch, CURLOPT_ENCODING, "gzip");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$ret = curl_exec($ch);
curl_close($ch);
return $ret;
}
}

View File

@@ -13,6 +13,8 @@ class OptimizeService
'huawei' => ['DEF'=>'default_view', 'CT'=>'Dianxin', 'CU'=>'Liantong', 'CM'=>'Yidong', 'AB'=>'Abroad'],
'west' => ['DEF'=>'', 'CT'=>'LTEL', 'CU'=>'LCNC', 'CM'=>'LMOB', 'AB'=>'LFOR'],
'dnsla' => ['DEF'=>'', 'CT'=>'84613316902921216', 'CU'=>'84613316923892736', 'CM'=>'84613316953252864', 'AB'=>''],
'huoshan' => ['DEF'=>'default', 'CT'=>'telecom', 'CU'=>'unicom', 'CM'=>'mobile', 'AB'=>'oversea'],
'baidu' => ['DEF'=>'default', 'CT'=>'ct', 'CU'=>'cnc', 'CM'=>'cmnet', 'AB'=>''],
];
private $ip_address = [];
@@ -21,10 +23,12 @@ class OptimizeService
private $del_num = 0;
public static function get_license($api, $key){
if($api == 1){
if($api == 2){
throw new Exception('当前接口暂不支持');
}elseif($api == 1){
$url = 'https://api.hostmonit.com/get_license?license='.$key;
}else{
$url = 'https://monitor.gacjie.cn/api/client/get_account_integral?license='.$key;
$url = 'https://www.182682.xyz/api/cf2dns/get_license?license='.$key;
}
$response = get_curl($url);
$arr = json_decode($response, true);
@@ -39,18 +43,24 @@ class OptimizeService
public function get_ip_address($cdn_type = 1, $ip_type = 'v4'){
$api = config_get('optimize_ip_api', 0);
if($api == 1){
if($api == 2){
$url = 'https://api.345673.xyz/get_data';
}elseif($api == 1){
$url = 'https://api.hostmonit.com/get_optimization_ip';
}else{
$url = 'https://monitor.gacjie.cn/api/client/get_ip_address';
$url = 'https://www.182682.xyz/api/cf2dns/';
if($cdn_type == 1){
$url .= 'get_cloudflare_ip';
}elseif($cdn_type == 2){
$url .= 'get_cloudfront_ip';
}elseif($cdn_type == 3){
$url .= 'get_gcore_ip';
}
}
$params = [
'key' => config_get('optimize_ip_key', 'o1zrmHAF'),
'type' => $ip_type,
];
if($api == 0){
$params['cdn_server'] = $cdn_type;
}
$response = get_curl($url, json_encode($params), 0, 0, 0, 0, 0, ['Content-Type: application/json; charset=UTF-8']);
$arr = json_decode($response, true);
if(isset($arr['code']) && $arr['code'] == 200){

View File

@@ -39,7 +39,7 @@ class TaskRunner
}
}else{
if($row['checktype'] == 2){
$result = CheckUtils::curl($row['checkurl'], $row['timeout'], $row['main_value']);
$result = CheckUtils::curl($row['checkurl'], $row['timeout'], $row['main_value'], $row['proxy'] == 1);
}else if($row['checktype'] == 1){
$result = CheckUtils::tcp($row['main_value'], $row['tcpport'], $row['timeout']);
}else{

View File

@@ -49,10 +49,10 @@ class aliyun implements DnsInterface {
}
//获取解析记录列表
public function getDomainRecords($PageNumber=1, $PageSize=20, $KeyWord = null, $SubDomain = null, $Type = null, $Line = null, $Status = null){
public function getDomainRecords($PageNumber=1, $PageSize=20, $KeyWord = null, $SubDomain = null, $Value = null, $Type = null, $Line = null, $Status = null){
$param = ['Action' => 'DescribeDomainRecords', 'DomainName' => $this->domain, 'PageNumber' => $PageNumber, 'PageSize' => $PageSize];
if(!empty($SubDomain) || !empty($Type) || !empty($Line)){
$param += ['SearchMode' => 'ADVANCED', 'RRKeyWord' => $SubDomain, 'ValueKeyWord' => $KeyWord, 'Type' => $Type, 'Line' => $Line, 'ValueKeyWord' => $KeyWord];
if(!empty($SubDomain) || !empty($Type) || !empty($Line) || !empty($Value)){
$param += ['SearchMode' => 'ADVANCED', 'RRKeyWord' => $SubDomain, 'ValueKeyWord' => $Value, 'Type' => $Type, 'Line' => $Line];
}elseif(!empty($KeyWord)){
$param += ['KeyWord' => $KeyWord];
}
@@ -138,7 +138,7 @@ class aliyun implements DnsInterface {
public function addDomainRecord($Name, $Type, $Value, $Line = 'default', $TTL = 600, $MX = null, $Remark = null){
$param = ['Action' => 'AddDomainRecord', 'DomainName' => $this->domain, 'RR' => $Name, 'Type' => $Type, 'Value' => $Value, 'Line' => $this->convertLineCode($Line), 'TTL' => intval($TTL)];
if($MX){
$params['Priority'] = intval($MX);
$param['Priority'] = intval($MX);
}
$data = $this->request($param, true);
if($data){
@@ -151,7 +151,7 @@ class aliyun implements DnsInterface {
public function updateDomainRecord($RecordId, $Name, $Type, $Value, $Line = 'default', $TTL = 600, $MX = null, $Remark = null){
$param = ['Action' => 'UpdateDomainRecord', 'RecordId' => $RecordId, 'RR' => $Name, 'Type' => $Type, 'Value' => $Value, 'Line' => $this->convertLineCode($Line), 'TTL' => intval($TTL)];
if($MX){
$params['Priority'] = intval($MX);
$param['Priority'] = intval($MX);
}
return $this->request($param);
}

View File

@@ -48,11 +48,10 @@ class baidu implements DnsInterface {
}
//获取解析记录列表
public function getDomainRecords($PageNumber=1, $PageSize=20, $KeyWord = null, $SubDomain = null, $Type = null, $Line = null, $Status = null){
$marker = cookie('baidu_record_marker');
public function getDomainRecords($PageNumber=1, $PageSize=20, $KeyWord = null, $SubDomain = null, $Value = null, $Type = null, $Line = null, $Status = null){
$query = ['rr' => $KeyWord];
if(!isNullOrEmpty(($SubDomain))){
$param['rr'] = $SubDomain;
if(!isNullOrEmpty($SubDomain)){
$query['rr'] = $SubDomain;
}
$data = $this->send_reuqest('GET', '/v1/dns/zone/'.$this->domain.'/record', $query);
if($data){
@@ -81,7 +80,7 @@ class baidu implements DnsInterface {
//获取子域名解析记录列表
public function getSubDomainRecords($SubDomain, $PageNumber=1, $PageSize=20, $Type = null, $Line = null){
if($SubDomain == '')$SubDomain='@';
return $this->getDomainRecords($PageNumber, $PageSize, null, $SubDomain, $Type, $Line);
return $this->getDomainRecords($PageNumber, $PageSize, null, $SubDomain, null, $Type, $Line);
}
//获取解析记录详细信息

View File

@@ -48,7 +48,12 @@ class cloudflare implements DnsInterface {
}
//获取解析记录列表
public function getDomainRecords($PageNumber=1, $PageSize=20, $KeyWord = null, $SubDomain = null, $Type = null, $Line = null, $Status = null){
public function getDomainRecords($PageNumber=1, $PageSize=20, $KeyWord = null, $SubDomain = null, $Value = null, $Type = null, $Line = null, $Status = null){
if(!isNullOrEmpty($SubDomain)){
if($SubDomain == '@')$SubDomain=$this->domain;
else $SubDomain .= '.'.$this->domain;
}
if(!isNullOrEmpty($Value)) $KeyWord = $Value;
$param = ['name' => $SubDomain, 'type' => $Type, 'search' => $KeyWord, 'page' => $PageNumber, 'per_page' => $PageSize];
if(!isNullOrEmpty($Line)){
$param['proxied'] = $Line == '1' ? 'true' : 'false';
@@ -67,7 +72,7 @@ class cloudflare implements DnsInterface {
'Line' => $row['proxied'] ? '1' : '0',
'TTL' => $row['ttl'],
'MX' => isset($row['priority']) ? $row['priority'] : null,
'Status' => $row['locked'] ? '0' : '1',
'Status' => '1',
'Weight' => null,
'Remark' => $row['comment'],
'UpdateTime' => $row['modified_on'],
@@ -80,9 +85,7 @@ class cloudflare implements DnsInterface {
//获取子域名解析记录列表
public function getSubDomainRecords($SubDomain, $PageNumber=1, $PageSize=20, $Type = null, $Line = null){
if($SubDomain == '@')$SubDomain=$this->domain;
else $SubDomain .= '.'.$this->domain;
return $this->getDomainRecords($PageNumber, $PageSize, null, $SubDomain, $Type, $Line);
return $this->getDomainRecords($PageNumber, $PageSize, null, $SubDomain, null, $Type, $Line);
}
//获取解析记录详细信息
@@ -99,7 +102,7 @@ class cloudflare implements DnsInterface {
'Line' => $data['result']['proxied'] ? '1' : '0',
'TTL' => $data['result']['ttl'],
'MX' => isset($data['result']['priority']) ? $data['result']['priority'] : null,
'Status' => $data['result']['locked'] ? '0' : '1',
'Status' => '1',
'Weight' => null,
'Remark' => $data['result']['comment'],
'UpdateTime' => $data['result']['modified_on'],
@@ -175,10 +178,16 @@ class cloudflare implements DnsInterface {
private function send_reuqest($method, $path, $params = null){
$url = $this->baseUrl . $path;
$headers = [
'X-Auth-Email: '.$this->Email,
'X-Auth-Key: '.$this->ApiKey,
];
if(preg_match('/^[0-9a-z]+$/i',$this->ApiKey)){
$headers = [
'X-Auth-Email: '.$this->Email,
'X-Auth-Key: '.$this->ApiKey,
];
}else{
$headers = [
'Authorization: Bearer '.$this->ApiKey,
];
}
$body = '';
if ($method == 'GET' || $method == 'DELETE') {

View File

@@ -49,7 +49,7 @@ class dnsla implements DnsInterface {
}
//获取解析记录列表
public function getDomainRecords($PageNumber=1, $PageSize=20, $KeyWord = null, $SubDomain = null, $Type = null, $Line = null, $Status = null){
public function getDomainRecords($PageNumber=1, $PageSize=20, $KeyWord = null, $SubDomain = null, $Value = null, $Type = null, $Line = null, $Status = null){
$param = ['domainId' => $this->domainid, 'pageIndex' => $PageNumber, 'pageSize' => $PageSize];
if(!isNullOrEmpty(($KeyWord))){
$param['host'] = $KeyWord;
@@ -63,6 +63,9 @@ class dnsla implements DnsInterface {
if(!isNullOrEmpty(($SubDomain))){
$param['host'] = $SubDomain;
}
if(!isNullOrEmpty(($Value))){
$param['data'] = $Value;
}
$data = $this->execute('GET', '/api/recordList', $param);
if($data){
$list = [];
@@ -90,7 +93,7 @@ class dnsla implements DnsInterface {
//获取子域名解析记录列表
public function getSubDomainRecords($SubDomain, $PageNumber=1, $PageSize=20, $Type = null, $Line = null){
if($SubDomain == '')$SubDomain='@';
return $this->getDomainRecords($PageNumber, $PageSize, null, $SubDomain, $Type, $Line);
return $this->getDomainRecords($PageNumber, $PageSize, null, $SubDomain, null, $Type, $Line);
}
//获取解析记录详细信息

View File

@@ -12,6 +12,7 @@ class dnspod implements DnsInterface {
private $error;
private $domain;
private $domainid;
private $domainInfo;
function __construct($config){
$this->SecretId = $config['ak'];
@@ -24,7 +25,7 @@ class dnspod implements DnsInterface {
}
public function check(){
if($this->getAccountInfo() != false){
if($this->getDomainList() != false){
return true;
}
return false;
@@ -51,12 +52,18 @@ class dnspod implements DnsInterface {
}
//获取解析记录列表
public function getDomainRecords($PageNumber=1, $PageSize=20, $KeyWord = null, $SubDomain = null, $Type = null, $Line = null, $Status = null){
public function getDomainRecords($PageNumber=1, $PageSize=20, $KeyWord = null, $SubDomain = null, $Value = null, $Type = null, $Line = null, $Status = null){
$offset = ($PageNumber-1)*$PageSize;
if(!isNullOrEmpty($Status)){
if(!isNullOrEmpty($Status) || !isNullOrEmpty($Value)){
$action = 'DescribeRecordFilterList';
$Status = $Status == '1' ? 'ENABLE' : 'DISABLE';
$param = ['Domain' => $this->domain, 'Subdomain' => $SubDomain, 'Keyword' => $KeyWord, 'Offset' => $offset, 'Limit' => $PageSize, 'RecordStatus' => [$Status]];
$param = ['Domain' => $this->domain, 'Offset' => $offset, 'Limit' => $PageSize, 'RecordValue' => $Value];
if(!isNullOrEmpty($SubDomain)) $param['SubDomain'] = $SubDomain;
if(!isNullOrEmpty($KeyWord)) $param['Keyword'] = $KeyWord;
if(!isNullOrEmpty($Value)) $param['RecordValue'] = $Value;
if(!isNullOrEmpty($Status)){
$Status = $Status == '1' ? 'ENABLE' : 'DISABLE';
$param['RecordStatus'] = [$Status];
}
if(!isNullOrEmpty($Type)) $param['RecordType'] = [$this->convertType($Type)];
if(!isNullOrEmpty($Line)) $param['RecordLine'] = [$Line];
}else{
@@ -84,7 +91,7 @@ class dnspod implements DnsInterface {
];
}
return ['total' => $data['RecordCountInfo']['TotalCount'], 'list' => $list];
}elseif($this->error == '记录列表为空。'){
}elseif($this->error == '记录列表为空。' || $this->error == 'No records on the list.'){
return ['total' => 0, 'list' => []];
}
return false;
@@ -93,7 +100,7 @@ class dnspod implements DnsInterface {
//获取子域名解析记录列表
public function getSubDomainRecords($SubDomain, $PageNumber=1, $PageSize=20, $Type = null, $Line = null){
if($SubDomain == '')$SubDomain='@';
return $this->getDomainRecords($PageNumber, $PageSize, null, $SubDomain, $Type, $Line);
return $this->getDomainRecords($PageNumber, $PageSize, null, $SubDomain, null, $Type, $Line);
}
//获取解析记录详细信息
@@ -188,13 +195,23 @@ class dnspod implements DnsInterface {
$list = [];
$this->processLineList($list, $data['LineList'], null);
return $list;
}else{
$data = $this->getRecordLineByGrade();
if($data){
$list = [];
foreach($data as $row){
$list[$row['LineId']] = ['name'=>$row['Name'], 'parent'=>null];
}
return $list;
}
}
return false;
}
private function processLineList(&$list, $line_list, $parent){
foreach($line_list as $row){
if(!isNullOrEmpty($row['LineId']) && $row['Useful'] && !isset($list[$row['LineId']])){
if(isNullOrEmpty($row['LineId'])) $row['LineId'] = 'N.'.$row['LineName'];
if($row['Useful'] && !isset($list[$row['LineId']])){
$list[$row['LineId']] = ['name'=>$row['LineName'], 'parent'=>$parent];
if($row['SubGroup']){
$this->processLineList($list, $row['SubGroup'], $row['LineId']);
@@ -205,11 +222,12 @@ class dnspod implements DnsInterface {
//获取域名概览信息
public function getDomainInfo(){
$action = 'DescribeDomainPreview';
$action = 'DescribeDomain';
$param = ['Domain' => $this->domain];
$data = $this->send_reuqest($action, $param);
if($data){
return $data['Domain'];
$this->domainInfo = $data['DomainInfo'];
return $data['DomainInfo'];
}
return false;
}
@@ -227,16 +245,36 @@ class dnspod implements DnsInterface {
//获取域名最低TTL
public function getMinTTL(){
if($this->domainInfo){
return $this->domainInfo['TTL'];
}
$PurviewList = $this->getDomainPurview();
if($PurviewList){
foreach($PurviewList as $row){
if($row['Name'] == '记录 TTL 最低'){
if($row['Name'] == '记录 TTL 最低' || $row['Name'] == 'Min TTL value'){
return intval($row['Value']);
}
}
}
return false;
}
//获取等级允许的线路
public function getRecordLineByGrade(){
$action = 'DescribeRecordLineList';
$param = ['Domain' => $this->domain, 'DomainGrade' => ''];
$data = $this->send_reuqest($action, $param);
if($data){
$line_list = $data['LineList'];
if(!empty($data['LineGroupList'])){
foreach($data['LineGroupList'] as $row){
$line_list[] = ['Name' => $row['Name'], 'LineId' => $row['LineId']];
}
}
return $line_list;
}
return false;
}
//获取用户信息
public function getAccountInfo(){

View File

@@ -49,10 +49,15 @@ class huawei implements DnsInterface {
}
//获取解析记录列表
public function getDomainRecords($PageNumber=1, $PageSize=20, $KeyWord = null, $SubDomain = null, $Type = null, $Line = null, $Status = null){
public function getDomainRecords($PageNumber=1, $PageSize=20, $KeyWord = null, $SubDomain = null, $Value = null, $Type = null, $Line = null, $Status = null){
$offset = ($PageNumber-1)*$PageSize;
$query = ['type' => $Type, 'line_id' => $Line, 'name' => $KeyWord, 'status' => $Status, 'offset' => $offset, 'limit' => $PageSize];
if(!isNullOrEmpty(($SubDomain))){
$query = ['type' => $Type, 'line_id' => $Line, 'name' => $KeyWord, 'offset' => $offset, 'limit' => $PageSize];
if(!isNullOrEmpty($Status)){
$Status = $Status == '1' ? 'ACTIVE' : 'DISABLE';
$query['status'] = $Status;
}
if(!isNullOrEmpty($SubDomain)){
$SubDomain = $this->getHost($SubDomain);
$query['name'] = $SubDomain;
$query['search_mode'] = 'equal';
}
@@ -83,8 +88,7 @@ class huawei implements DnsInterface {
//获取子域名解析记录列表
public function getSubDomainRecords($SubDomain, $PageNumber=1, $PageSize=20, $Type = null, $Line = null){
$SubDomain = $this->getHost($SubDomain);
return $this->getDomainRecords($PageNumber, $PageSize, null, $SubDomain, $Type, $Line);
return $this->getDomainRecords($PageNumber, $PageSize, null, $SubDomain, null, $Type, $Line);
}
//获取解析记录详细信息
@@ -113,6 +117,7 @@ class huawei implements DnsInterface {
//添加解析记录
public function addDomainRecord($Name, $Type, $Value, $Line = '0', $TTL = 600, $MX = 1, $Remark = null){
$Name = $this->getHost($Name);
if($Type == 'TXT' && substr($Value, 0, 1) != '"') $Value = '"'.$Value.'"';
$records = explode(',', $Value);
$params = ['name' => $Name, 'type' => $this->convertType($Type), 'records' => $records, 'line'=>$Line, 'ttl' => intval($TTL), 'description' => $Remark];
if($Type == 'MX')$param['weight'] = intval($MX);
@@ -123,6 +128,7 @@ class huawei implements DnsInterface {
//修改解析记录
public function updateDomainRecord($RecordId, $Name, $Type, $Value, $Line = '0', $TTL = 600, $MX = 1, $Remark = null){
$Name = $this->getHost($Name);
if($Type == 'TXT' && substr($Value, 0, 1) != '"') $Value = '"'.$Value.'"';
$records = explode(',', $Value);
$params = ['name' => $Name, 'type' => $this->convertType($Type), 'records' => $records, 'line'=>$Line, 'ttl' => intval($TTL), 'description' => $Remark];
if($Type == 'MX')$param['weight'] = intval($MX);

383
app/lib/dns/huoshan.php Normal file
View File

@@ -0,0 +1,383 @@
<?php
namespace app\lib\dns;
use app\lib\DnsInterface;
class huoshan implements DnsInterface {
private $AccessKeyId;
private $SecretAccessKey;
private $endpoint = "open.volcengineapi.com";
private $service = "DNS";
private $version = "2018-08-01";
private $region = "cn-north-1";
private $error;
private $domain;
private $domainid;
private $domainInfo;
private static $trade_code_list = [
'free_inner' => ['level' => 1, 'name' => '免费版', 'ttl' => 600],
'professional_inner' => ['level' => 2, 'name' => '专业版', 'ttl' => 300],
'enterprise_inner' => ['level' => 3, 'name' => '企业版', 'ttl' => 60],
'ultimate_inner' => ['level' => 4, 'name' => '旗舰版', 'ttl' => 1],
'ultimate_exclusive_inner' => ['level' => 5, 'name' => '尊享版', 'ttl' => 1],
];
function __construct($config){
$this->AccessKeyId = $config['ak'];
$this->SecretAccessKey = $config['sk'];
$this->domain = $config['domain'];
$this->domainid = $config['domainid'];
}
public function getError(){
return $this->error;
}
public function check(){
if($this->getDomainList() != false){
return true;
}
return false;
}
//获取域名列表
public function getDomainList($KeyWord=null, $PageNumber=1, $PageSize=20){
$query = ['PageNumber' => $PageNumber, 'PageSize' => $PageSize, 'Key' => $KeyWord];
$data = $this->send_reuqest('GET', 'ListZones', $query);
if($data){
$list = [];
if(!empty($data['Zones'])){
foreach($data['Zones'] as $row){
$list[] = [
'DomainId' => $row['ZID'],
'Domain' => $row['ZoneName'],
'RecordCount' => $row['RecordCount'],
];
}
}
return ['total' => $data['Total'], 'list' => $list];
}
return false;
}
//获取解析记录列表
public function getDomainRecords($PageNumber=1, $PageSize=20, $KeyWord = null, $SubDomain = null, $Value = null, $Type = null, $Line = null, $Status = null){
$query = ['ZID' => intval($this->domainid), 'PageNumber' => $PageNumber, 'PageSize' => $PageSize, 'SearchOrder' => 'desc'];
if(!empty($SubDomain) || !empty($Type) || !empty($Line) || !empty($Value)){
$query += ['Host' => $SubDomain, 'Value' => $Value, 'Type' => $Type, 'Line' => $Line];
}elseif(!empty($KeyWord)){
$query += ['Host' => $KeyWord];
}
$data = $this->send_reuqest('GET', 'ListRecords', $query);
if($data){
$list = [];
foreach($data['Records'] as $row){
$list[] = [
'RecordId' => $row['RecordID'],
'Domain' => $this->domain,
'Name' => $row['Host'],
'Type' => $row['Type'],
'Value' => $row['Value'],
'Line' => $row['Line'],
'TTL' => $row['TTL'],
'MX' => $row['Weight'],
'Status' => $row['Enable'] ? '1' : '0',
'Weight' => $row['Weight'],
'Remark' => $row['Remark'],
'UpdateTime' => $row['UpdatedAt'],
];
}
return ['total' => $data['TotalCount'], 'list' => $list];
}
return false;
}
//获取子域名解析记录列表
public function getSubDomainRecords($SubDomain, $PageNumber=1, $PageSize=20, $Type = null, $Line = null){
return $this->getDomainRecords($PageNumber, $PageSize, null, $SubDomain, null, $Type, $Line);
}
//获取解析记录详细信息
public function getDomainRecordInfo($RecordId){
$data = $this->send_reuqest('GET', 'QueryRecord', ['RecordID' => $RecordId]);
if($data){
if($data['name'] == $data['zone_name']) $data['name'] = '@';
return [
'RecordId' => $data['RecordID'],
'Domain' => $this->domain,
'Name' => $data['Host'],
'Type' => $data['Type'],
'Value' => $data['Value'],
'Line' => $data['Line'],
'TTL' => $data['TTL'],
'MX' => $data['Weight'],
'Status' => $data['Enable'] ? '1' : '0',
'Weight' => $data['Weight'],
'Remark' => $data['Remark'],
'UpdateTime' => $data['UpdatedAt'],
];
}
return false;
}
//添加解析记录
public function addDomainRecord($Name, $Type, $Value, $Line = '0', $TTL = 600, $MX = 1, $Remark = null){
$params = ['ZID' => intval($this->domainid), 'Host' => $Name, 'Type' => $this->convertType($Type), 'Value' => $Value, 'Line'=>$Line, 'TTL' => intval($TTL), 'Remark' => $Remark];
if($Type == 'MX')$param['Weight'] = intval($MX);
$data = $this->send_reuqest('POST', 'CreateRecord', $params);
return is_array($data) ? $data['RecordID'] : false;
}
//修改解析记录
public function updateDomainRecord($RecordId, $Name, $Type, $Value, $Line = '0', $TTL = 600, $MX = 1, $Remark = null){
$params = ['RecordID' => $RecordId, 'Host' => $Name, 'Type' => $this->convertType($Type), 'Value' => $Value, 'Line'=>$Line, 'TTL' => intval($TTL), 'Remark' => $Remark];
if($Type == 'MX')$param['Weight'] = intval($MX);
$data = $this->send_reuqest('POST', 'UpdateRecord', $params);
return is_array($data);
}
//修改解析记录备注
public function updateDomainRecordRemark($RecordId, $Remark){
return false;
}
//删除解析记录
public function deleteDomainRecord($RecordId){
$data = $this->send_reuqest('POST', 'DeleteRecord', ['RecordID' => $RecordId]);
return $data;
}
//设置解析记录状态
public function setDomainRecordStatus($RecordId, $Status){
$params = ['RecordID' => $RecordId, 'Enable' => $Status == '1'];
$data = $this->send_reuqest('POST', 'UpdateRecordStatus', $params);
return is_array($data);
}
//获取解析记录操作日志
public function getDomainRecordLog($PageNumber = 1, $PageSize = 20, $KeyWord = null, $StartDate = null, $endDate = null){
return false;
}
//获取解析线路列表
public function getRecordLine(){
$domainInfo = $this->getDomainInfo();
if(!$domainInfo) return false;
$level = $this->getTradeInfo($domainInfo['TradeCode'])['level'];
$data = $this->send_reuqest('GET', 'ListLines', []);
if($data){
$list = [];
$list['default'] = ['name' => '默认', 'parent' => null];
foreach($data['Lines'] as $row){
if($row['Value'] == 'default') continue;
if($row['Level'] > $level) continue;
$list[$row['Value']] = ['name' => $row['Name'], 'parent' => isset($row['FatherValue']) ? $row['FatherValue'] : null];
}
$data = $this->send_reuqest('GET', 'ListCustomLines', []);
if($data && $data['TotalCount'] > 0){
$list['N.customer_lines'] = ['name' => '自定义线路', 'parent' => null];
foreach($data['CustomerLines'] as $row){
$list[$row['Line']] = ['name' => $row['NameCN'], 'parent' => 'N.customer_lines'];
}
}
return $list;
}
return false;
}
//获取域名概览信息
public function getDomainInfo(){
if(!empty($this->domainInfo)) return $this->domainInfo;
$query = ['ZID' => intval($this->domainid)];
$data = $this->send_reuqest('GET', 'QueryZone', $query);
if($data){
$this->domainInfo = $data;
return $data;
}
return false;
}
//获取域名最低TTL
public function getMinTTL(){
$domainInfo = $this->getDomainInfo();
if($domainInfo){
$ttl = $this->getTradeInfo($domainInfo['TradeCode'])['ttl'];
return $ttl;
}
return false;
}
private function convertType($type){
return $type;
}
private function getTradeInfo($trade_code){
if(array_key_exists($trade_code, self::$trade_code_list)){
$trade_code = $trade_code;
}else{
$trade_code = 'free_inner';
}
return self::$trade_code_list[$trade_code];
}
private function send_reuqest($method, $action, $params = []){
if(!empty($params)){
$params = array_filter($params, function($a){ return $a!==null;});
}
$query = [
'Action' => $action,
'Version' => $this->version,
];
$body = '';
if($method == 'GET'){
$query = array_merge($query, $params);
}else{
$body = !empty($params) ? json_encode($params) : '';
}
$time = time();
$headers = [
'Host' => $this->endpoint,
'X-Date' => gmdate("Ymd\THis\Z", $time),
//'X-Content-Sha256' => hash("sha256", $body),
];
if($body){
$headers['Content-Type'] = 'application/json';
}
$path = '/';
$authorization = $this->generateSign($method, $path, $query, $headers, $body, $time);
$headers['Authorization'] = $authorization;
$url = 'https://'.$this->endpoint.$path.'?'.http_build_query($query);
$header = [];
foreach($headers as $key => $value){
$header[] = $key.': '.$value;
}
return $this->curl($method, $url, $body, $header);
}
private function generateSign($method, $path, $query, $headers, $body, $time){
$algorithm = "HMAC-SHA256";
// step 1: build canonical request string
$httpRequestMethod = $method;
$canonicalUri = $path;
if(substr($canonicalUri, -1) != "/") $canonicalUri .= "/";
$canonicalQueryString = $this->getCanonicalQueryString($query);
[$canonicalHeaders, $signedHeaders] = $this->getCanonicalHeaders($headers);
$hashedRequestPayload = hash("sha256", $body);
$canonicalRequest = $httpRequestMethod."\n"
.$canonicalUri."\n"
.$canonicalQueryString."\n"
.$canonicalHeaders."\n"
.$signedHeaders."\n"
.$hashedRequestPayload;
// step 2: build string to sign
$date = gmdate("Ymd\THis\Z", $time);
$shortDate = substr($date, 0, 8);
$credentialScope = $shortDate . '/' .$this->region . '/' . $this->service . '/request';
$hashedCanonicalRequest = hash("sha256", $canonicalRequest);
$stringToSign = $algorithm."\n"
.$date."\n"
.$credentialScope."\n"
.$hashedCanonicalRequest;
// step 3: sign string
$kDate = hash_hmac("sha256", $shortDate, $this->SecretAccessKey, true);
$kRegion = hash_hmac("sha256", $this->region, $kDate, true);
$kService = hash_hmac("sha256", $this->service, $kRegion, true);
$kSigning = hash_hmac("sha256", "request", $kService, true);
$signature = hash_hmac("sha256", $stringToSign, $kSigning);
// step 4: build authorization
$credential = $this->AccessKeyId . '/' . $shortDate . '/' . $this->region . '/' . $this->service . '/request';
$authorization = $algorithm . ' Credential=' . $credential . ", SignedHeaders=" . $signedHeaders . ", Signature=" . $signature;
return $authorization;
}
private function escape($str)
{
$search = ['+', '*', '%7E'];
$replace = ['%20', '%2A', '~'];
return str_replace($search, $replace, urlencode($str));
}
private function getCanonicalQueryString($parameters)
{
if(empty($parameters)) return '';
ksort($parameters);
$canonicalQueryString = '';
foreach ($parameters as $key => $value) {
$canonicalQueryString .= '&' . $this->escape($key). '=' . $this->escape($value);
}
return substr($canonicalQueryString, 1);
}
private function getCanonicalHeaders($oldheaders){
$headers = array();
foreach ($oldheaders as $key => $value) {
$headers[strtolower($key)] = trim($value);
}
ksort($headers);
$canonicalHeaders = '';
$signedHeaders = '';
foreach ($headers as $key => $value) {
$canonicalHeaders .= $key . ':' . $value . "\n";
$signedHeaders .= $key . ';';
}
$signedHeaders = substr($signedHeaders, 0, -1);
return [$canonicalHeaders, $signedHeaders];
}
private function curl($method, $url, $body, $header){
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
if(!empty($body)){
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
}
$response = curl_exec($ch);
$errno = curl_errno($ch);
if ($errno) {
$this->setError('Curl error: ' . curl_error($ch));
}
curl_close($ch);
if ($errno) return false;
$arr=json_decode($response,true);
if($arr){
if(isset($arr['ResponseMetadata']['Error']['MessageCN'])){
$this->setError($arr['ResponseMetadata']['Error']['MessageCN']);
return false;
}elseif(isset($arr['ResponseMetadata']['Error']['Message'])){
$this->setError($arr['ResponseMetadata']['Error']['Message']);
return false;
}elseif(isset($arr['Result'])){
return $arr['Result'];
}else{
return true;
}
}else{
$this->setError('返回数据解析失败');
return false;
}
}
private function setError($message){
$this->error = $message;
//file_put_contents('logs.txt',date('H:i:s').' '.$message."\r\n", FILE_APPEND);
}
}

View File

@@ -50,8 +50,8 @@ class west implements DnsInterface {
}
//获取解析记录列表
public function getDomainRecords($PageNumber=1, $PageSize=20, $KeyWord = null, $SubDomain = null, $Type = null, $Line = null, $Status = null){
$param = ['act' => 'getdnsrecord', 'domain' => $this->domain, 'type' => $Type, 'line' => $Line, 'host' => $KeyWord, 'pageno' => $PageNumber, 'limit' => $PageSize];
public function getDomainRecords($PageNumber=1, $PageSize=20, $KeyWord = null, $SubDomain = null, $Value = null, $Type = null, $Line = null, $Status = null){
$param = ['act' => 'getdnsrecord', 'domain' => $this->domain, 'type' => $Type, 'line' => $Line, 'host' => $KeyWord, 'value' => $Value, 'pageno' => $PageNumber, 'limit' => $PageSize];
if(!isNullOrEmpty(($SubDomain))){
$param['host'] = $SubDomain;
}
@@ -82,7 +82,7 @@ class west implements DnsInterface {
//获取子域名解析记录列表
public function getSubDomainRecords($SubDomain, $PageNumber=1, $PageSize=20, $Type = null, $Line = null){
if($SubDomain == '')$SubDomain='@';
return $this->getDomainRecords($PageNumber, $PageSize, null, $SubDomain, $Type, $Line);
return $this->getDomainRecords($PageNumber, $PageSize, null, $SubDomain, null, $Type, $Line);
}
//获取解析记录详细信息

View File

@@ -12,8 +12,8 @@ class AuthUser
$islogin = false;
$cookie = cookie('user_token');
$user = null;
if($cookie){
$token=authcode($cookie, 'DECODE', env('app.sys_key'));
if($cookie && config_get('sys_key')){
$token=authcode($cookie, 'DECODE', config_get('sys_key'));
if($token){
list($type, $uid, $sid, $expiretime) = explode("\t", $token);
if($type == 'user'){

View File

@@ -6,6 +6,7 @@ namespace app\middleware;
use Exception;
use think\facade\Db;
use think\facade\Config;
use think\facade\Cache;
class LoadConfig
{
@@ -31,6 +32,11 @@ class LoadConfig
try{
$res = Db::name('config')->cache('configs',0)->column('value','key');
if(empty($res['sys_key']) && !empty(env('app.sys_key'))){
config_set('sys_key', env('app.sys_key'));
Cache::delete('configs');
$res['sys_key'] = env('app.sys_key');
}
Config::set($res, 'sys');
}catch(Exception $e){
if(!strpos($e->getMessage(), 'doesn\'t exist')){

View File

@@ -18,7 +18,7 @@ class ViewOutput
{
View::assign('islogin', $request->islogin);
View::assign('user', $request->user);
View::assign('cdnpublic', '//lib.baomitu.com/');
View::assign('cdnpublic', 'https://s4.zstatic.net/ajax/libs/');
View::assign('skin', getAdminSkin());
return $next($request);
}

View File

@@ -5,7 +5,7 @@ CREATE TABLE `dnsmgr_config` (
PRIMARY KEY (`key`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
INSERT INTO `dnsmgr_config` VALUES ('version', '1007');
INSERT INTO `dnsmgr_config` VALUES ('version', '1011');
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');
@@ -92,6 +92,7 @@ CREATE TABLE `dnsmgr_dmtask` (
`cycle` tinyint(5) NOT NULL DEFAULT 3,
`timeout` tinyint(5) NOT NULL DEFAULT 2,
`remark` varchar(100) DEFAULT NULL,
`proxy` tinyint(1) NOT NULL DEFAULT 0,
`addtime` int(11) NOT NULL DEFAULT 0,
`checktime` int(11) NOT NULL DEFAULT 0,
`checknexttime` int(11) NOT NULL DEFAULT 0,

View File

@@ -62,4 +62,7 @@ CREATE TABLE IF NOT EXISTS `dnsmgr_optimizeip` (
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
ALTER TABLE `dnsmgr_domain`
ADD COLUMN `remark` varchar(100) DEFAULT NULL;
ADD COLUMN `remark` varchar(100) DEFAULT NULL;
ALTER TABLE `dnsmgr_dmtask`
ADD COLUMN `proxy` tinyint(1) NOT NULL DEFAULT 0;

View File

@@ -107,7 +107,7 @@
<a href="/domain"><i class="fa fa-list-ul fa-fw"></i> <span>域名管理</span></a>
</li>
{if request()->user['level'] eq 2}
<li class="treeview {:checkIfActive('overview,task,noticeset,taskinfo,taskform')}">
<li class="treeview {:checkIfActive('overview,task,noticeset,taskinfo,taskform,proxyset')}">
<a href="javascript:;">
<i class="fa fa-heartbeat fa-fw"></i>
<span>容灾切换</span>
@@ -119,6 +119,7 @@
<li><a href="/dmonitor/overview"><i class="fa fa-circle-o"></i> 运行概览</a></li>
<li><a href="/dmonitor/task"><i class="fa fa-circle-o"></i> 切换策略</a></li>
<li><a href="/dmonitor/noticeset"><i class="fa fa-circle-o"></i> 通知设置</a></li>
<li><a href="/dmonitor/proxyset"><i class="fa fa-circle-o"></i> 代理设置</a></li>
</ul>
</li>
<li class="treeview {:checkIfActive('opipset,opiplist,opipform')}">

View File

@@ -15,6 +15,10 @@
<label class="col-sm-3 control-label">微信公众号通知</label>
<div class="col-sm-9"><select class="form-control" name="notice_wxtpl" default="{:config_get('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="notice_tgbot" default="{:config_get('notice_tgbot')}"><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>
@@ -99,6 +103,34 @@
<b>WxPusher</b><a href="https://wxpusher.zjiecode.com/admin/" target="_blank" rel="noopener noreferrer">点此进入</a> ,注册并且创建应用 -> 将appToken填写到上方输入框 -> 扫码关注应用 -> 在用户列表查看自己的UID填写到上方输入框<br/>
</div>
</div>
<div class="panel panel-info">
<div class="panel-heading"><h3 class="panel-title">Telegram机器人接口设置</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">Token</label>
<div class="col-sm-9"><input type="text" name="tgbot_token" value="{:config_get('tgbot_token')}" class="form-control"/></div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">Chat Id</label>
<div class="col-sm-9"><input type="text" name="tgbot_chatid" value="{:config_get('tgbot_chatid')}" class="form-control"/></div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">使用代理服务器</label>
<div class="col-sm-9"><select class="form-control" name="tgbot_proxy" default="{:config_get('tgbot_proxy')}"><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"/>
<a href="javascript:tgbottest()" class="btn btn-default btn-block">发送测试消息</a>
</div>
</div>
</form>
</div>
<div class="panel-footer">
<a href="https://t.me/BotFather" target="_blank" rel="noopener noreferrer">@BotFather</a>对话,使用/newbot命令创建一个新的机器人根据提示输入机器人的名称和用户名可得到Token或使用/mybots命令查看已创建的机器人<a href="https://t.me/getmyid_bot" target="_blank" rel="noopener noreferrer">@getmyid_bot</a>对话可得到Chat Id<br/>
</div>
</div>
</div>
</div>
{/block}
@@ -129,7 +161,7 @@ function saveSetting(obj){
success : function(data) {
layer.close(ii);
if(data.code == 0){
layer.alert('设置保存成功!', {
layer.alert('设置保存成功!<br/>重启检测进程或容器后生效', {
icon: 1,
closeBtn: false
}, function(){
@@ -166,5 +198,25 @@ function mailtest(){
}
});
}
function tgbottest(){
var ii = layer.load(2, {shade:[0.1,'#fff']});
$.ajax({
type : 'GET',
url : '/dmonitor/tgbottest',
dataType : 'json',
success : function(data) {
layer.close(ii);
if(data.code == 0){
layer.alert(data.msg, {icon: 1});
}else{
layer.alert(data.msg, {icon: 2})
}
},
error:function(data){
layer.close(ii);
layer.msg('服务器错误');
}
});
}
</script>
{/block}

View File

@@ -0,0 +1,129 @@
{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">代理服务器设置</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">代理IP</label>
<div class="col-sm-9"><input type="text" name="proxy_server" value="{:config_get('proxy_server')}" class="form-control"/></div>
</div><br/>
<div class="form-group">
<label class="col-sm-3 control-label">代理端口</label>
<div class="col-sm-9"><input type="text" name="proxy_port" value="{:config_get('proxy_port')}" class="form-control"/></div>
</div><br/>
<div class="form-group">
<label class="col-sm-3 control-label">代理账号</label>
<div class="col-sm-9"><input type="text" name="proxy_user" value="{:config_get('proxy_user')}" class="form-control" placeholder="没有请留空"/></div>
</div><br/>
<div class="form-group">
<label class="col-sm-3 control-label">代理密码</label>
<div class="col-sm-9"><input type="text" name="proxy_pwd" value="{:config_get('proxy_pwd')}" class="form-control" placeholder="没有请留空"/></div>
</div><br/>
<div class="form-group">
<label class="col-sm-3 control-label">代理协议</label>
<div class="col-sm-9"><select class="form-control" name="proxy_type" default="{:config_get('proxy_type')}">
<option value="http">HTTP</option>
<option value="https">HTTPS</option>
<option value="sock4">SOCK4</option>
<option value="sock5">SOCK5</option>
</select></div>
</div><br/>
<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>
</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);
}
$("select[name='mail_type']").change(function(){
if($(this).val() == 0){
$("#frame_set1").show();
$("#frame_set2").hide();
}else{
$("#frame_set1").hide();
$("#frame_set2").show();
}
});
$("select[name='mail_type']").change();
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;
}
function mailtest(){
var ii = layer.load(2, {shade:[0.1,'#fff']});
$.ajax({
type : 'GET',
url : '/dmonitor/mailtest',
dataType : 'json',
success : function(data) {
layer.close(ii);
if(data.code == 0){
layer.alert(data.msg, {icon: 1});
}else{
layer.alert(data.msg, {icon: 2})
}
},
error:function(data){
layer.close(ii);
layer.msg('服务器错误');
}
});
}
function tgbottest(){
var ii = layer.load(2, {shade:[0.1,'#fff']});
$.ajax({
type : 'GET',
url : '/dmonitor/tgbottest',
dataType : 'json',
success : function(data) {
layer.close(ii);
if(data.code == 0){
layer.alert(data.msg, {icon: 1});
}else{
layer.alert(data.msg, {icon: 2})
}
},
error:function(data){
layer.close(ii);
layer.msg('服务器错误');
}
});
}
</script>
{/block}

View File

@@ -33,8 +33,8 @@ tbody tr>td:nth-child(2){overflow: hidden;text-overflow: ellipsis;white-space: n
{/block}
{block name="script"}
<script src="{$cdnpublic}layer/3.1.1/layer.js"></script>
<script src="{$cdnpublic}bootstrap-table/1.20.2/bootstrap-table.min.js"></script>
<script src="{$cdnpublic}bootstrap-table/1.20.2/extensions/page-jump-to/bootstrap-table-page-jump-to.min.js"></script>
<script src="{$cdnpublic}bootstrap-table/1.21.4/bootstrap-table.min.js"></script>
<script src="{$cdnpublic}bootstrap-table/1.21.4/extensions/page-jump-to/bootstrap-table-page-jump-to.min.js"></script>
<script src="/static/js/custom.js"></script>
<script>
$(document).ready(function(){

View File

@@ -70,6 +70,17 @@
<input type="text" name="checkurl" v-model="set.checkurl" placeholder="填写以http(s)://开头的完整地址http状态码须为2xx/3xx" class="form-control" data-bv-uri="true" required>
</div>
</div>
<div class="form-group" v-show="set.type<=2&&set.checktype==2">
<label class="col-sm-3 control-label no-padding-right">使用代理请求</label>
<div class="col-sm-6">
<label class="radio-inline">
<input type="radio" name="proxy" value="0" v-model="set.proxy">
</label>
<label class="radio-inline">
<input type="radio" name="proxy" value="1" v-model="set.proxy">
</label>
</div>
</div>
<div class="form-group" v-show="set.type<=2&&set.checktype>0">
<label class="col-sm-3 control-label no-padding-right">最大超时时间</label>
<div class="col-sm-3">
@@ -141,6 +152,7 @@ new Vue({
frequency: 5,
timeout: 2,
cycle: 3,
proxy: 0,
},
recordList: [],
typeList: [

View File

@@ -30,8 +30,8 @@ tbody tr>td:nth-child(4){overflow: hidden;text-overflow: ellipsis;white-space: n
{/block}
{block name="script"}
<script src="{$cdnpublic}layer/3.1.1/layer.js"></script>
<script src="{$cdnpublic}bootstrap-table/1.20.2/bootstrap-table.min.js"></script>
<script src="{$cdnpublic}bootstrap-table/1.20.2/extensions/page-jump-to/bootstrap-table-page-jump-to.min.js"></script>
<script src="{$cdnpublic}bootstrap-table/1.21.4/bootstrap-table.min.js"></script>
<script src="{$cdnpublic}bootstrap-table/1.21.4/extensions/page-jump-to/bootstrap-table-page-jump-to.min.js"></script>
<script src="/static/js/custom.js"></script>
<script>
var action_name = {$info.action_name|json_encode|raw};

View File

@@ -81,8 +81,8 @@
{/block}
{block name="script"}
<script src="{$cdnpublic}layer/3.1.1/layer.js"></script>
<script src="{$cdnpublic}bootstrap-table/1.20.2/bootstrap-table.min.js"></script>
<script src="{$cdnpublic}bootstrap-table/1.20.2/extensions/page-jump-to/bootstrap-table-page-jump-to.min.js"></script>
<script src="{$cdnpublic}bootstrap-table/1.21.4/bootstrap-table.min.js"></script>
<script src="{$cdnpublic}bootstrap-table/1.21.4/extensions/page-jump-to/bootstrap-table-page-jump-to.min.js"></script>
<script src="/static/js/custom.js"></script>
<script>
var dnsconfig = {$dnsconfig|json_encode|raw};
@@ -198,7 +198,7 @@ function save(){
}, function(){
layer.closeAll();
$("#modal-store").modal('hide');
searchSubmit();
searchRefresh();
});
}else{
layer.alert(data.msg, {icon: 2})
@@ -220,7 +220,7 @@ function delItem(id) {
layer.close(ii);
if(data.code == 0){
layer.closeAll();
searchSubmit();
searchRefresh();
}else{
layer.alert(data.msg, {icon: 2});
}

View File

@@ -118,8 +118,8 @@
{/block}
{block name="script"}
<script src="{$cdnpublic}layer/3.1.1/layer.js"></script>
<script src="{$cdnpublic}bootstrap-table/1.20.2/bootstrap-table.min.js"></script>
<script src="{$cdnpublic}bootstrap-table/1.20.2/extensions/page-jump-to/bootstrap-table-page-jump-to.min.js"></script>
<script src="{$cdnpublic}bootstrap-table/1.21.4/bootstrap-table.min.js"></script>
<script src="{$cdnpublic}bootstrap-table/1.21.4/extensions/page-jump-to/bootstrap-table-page-jump-to.min.js"></script>
<script src="{$cdnpublic}select2/4.0.13/js/select2.min.js"></script>
<script src="{$cdnpublic}select2/4.0.13/js/i18n/zh-CN.min.js"></script>
<script src="/static/js/custom.js"></script>
@@ -244,7 +244,7 @@ function saveAdd(){
}, function(){
layer.closeAll();
$("#modal-store").modal('hide');
searchSubmit();
searchRefresh();
});
}else{
layer.alert(data.msg, {icon: 2})
@@ -266,6 +266,7 @@ function editframe(id){
$("#form-store2 input[name=id]").val(data.data.id);
$("#form-store2 select[name=is_hide]").val(data.data.is_hide);
$("#form-store2 select[name=is_sso]").val(data.data.is_sso);
$("#form-store2 input[name=remark]").val(data.data.remark);
}else{
layer.alert(data.msg, {icon: 2})
}
@@ -288,7 +289,7 @@ function saveEdit(){
}, function(){
layer.closeAll();
$("#modal-store2").modal('hide');
searchSubmit();
searchRefresh();
});
}else{
layer.alert(data.msg, {icon: 2})
@@ -310,7 +311,7 @@ function delItem(id) {
layer.close(ii);
if(data.code == 0){
layer.closeAll();
searchSubmit();
searchRefresh();
}else{
layer.alert(data.msg, {icon: 2});
}

View File

@@ -16,8 +16,8 @@
{/block}
{block name="script"}
<script src="{$cdnpublic}layer/3.1.1/layer.js"></script>
<script src="{$cdnpublic}bootstrap-table/1.20.2/bootstrap-table.min.js"></script>
<script src="{$cdnpublic}bootstrap-table/1.20.2/extensions/page-jump-to/bootstrap-table-page-jump-to.min.js"></script>
<script src="{$cdnpublic}bootstrap-table/1.21.4/bootstrap-table.min.js"></script>
<script src="{$cdnpublic}bootstrap-table/1.21.4/extensions/page-jump-to/bootstrap-table-page-jump-to.min.js"></script>
<script src="/static/js/custom.js"></script>
<script>
$(document).ready(function(){

View File

@@ -159,6 +159,7 @@ td{overflow: hidden;text-overflow: ellipsis;white-space: nowrap;max-width:360px;
<div class="panel-body">
<form onsubmit="return searchSubmit()" method="GET" class="form-inline" id="searchToolbar">
<div id="searchbox1">
<div class="form-group">
<label>搜索</label>
<input type="text" class="form-control" name="keyword" placeholder="输入关键字">
@@ -177,6 +178,39 @@ td{overflow: hidden;text-overflow: ellipsis;white-space: nowrap;max-width:360px;
<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="/log?domain={$domainName}">本站日志</a></li>{if $dnsconfig.log}<li><a href="/record/log/{$domainId}">域名日志</a></li>{/if}</ul>
</div>
<a href="javascript:advanceSearch()" class="btn"><i class="fa fa-angle-down"></i> 高级搜索</a>
</div>
<div id="searchbox2" style="display:none">
<div class="form-group">
<select name="type" class="form-control"><option value="">全部类型</option>
<option value="A">A</option>
<option value="CNAME">CNAME</option>
<option value="AAAA">AAAA</option>
<option value="NS">NS</option>
<option value="MX">MX</option>
<option value="SRV">SRV</option>
<option value="TXT">TXT</option>
<option value="CAA">CAA</option>
{if $dnsconfig.redirect}<option value="REDIRECT_URL">显性URL</option>
<option value="FORWARD_URL">隐性URL</option>{/if}
</select>
</div>
<div class="form-group">
<input type="text" class="form-control" name="subdomain" placeholder="输入主机记录">
</div>
<div class="form-group">
<select name="line" class="form-control"><option value="">全部线路</option></select>
</div>
<div class="form-group">
<input type="text" class="form-control" name="value" placeholder="输入记录值">
</div>
<div class="form-group">
<select name="status" class="form-control"><option value="">所有状态</option><option value="1">启用</option><option value="0">暂停</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>
<a href="javascript:advanceSearch()" class="btn"><i class="fa fa-angle-up"></i> 收起</a>
</div>
</form>
<table id="listTable">
@@ -188,14 +222,15 @@ td{overflow: hidden;text-overflow: ellipsis;white-space: nowrap;max-width:360px;
{/block}
{block name="script"}
<script src="{$cdnpublic}layer/3.1.1/layer.js"></script>
<script src="{$cdnpublic}bootstrap-table/1.20.2/bootstrap-table.min.js"></script>
<script src="{$cdnpublic}bootstrap-table/1.20.2/extensions/page-jump-to/bootstrap-table-page-jump-to.min.js"></script>
<script src="{$cdnpublic}bootstrap-table/1.21.4/bootstrap-table.min.js"></script>
<script src="{$cdnpublic}bootstrap-table/1.21.4/extensions/page-jump-to/bootstrap-table-page-jump-to.min.js"></script>
<script src="/static/js/bootstrapValidator.min.js"></script>
<script src="/static/js/custom.js?v=1001"></script>
<script src="/static/js/custom.js?v=1003"></script>
<script>
var recordLine = {$recordLine|json_encode|raw};
var dnsconfig = {$dnsconfig|json_encode|raw};
var defaultLine = recordLine[0].id;
var sidePagination = dnsconfig.type == 'baidu' ? 'client' : 'server';
$(document).ready(function(){
updateToolbar();
let defaultPageSize = getCookie('record_pagesize') ? getCookie('record_pagesize') : 15;
@@ -208,7 +243,7 @@ $(document).ready(function(){
pageSize: pageSize,
classes: 'table table-striped table-hover table-bordered',
uniqueId: 'RecordId',
sidePagination: "{if $dnsconfig.type=='baidu'}client{else}server{/if}",
sidePagination: sidePagination,
columns: [
{
field: '',
@@ -308,6 +343,12 @@ $(document).ready(function(){
$("#form-store").bootstrapValidator();
$("#form-store2").bootstrapValidator();
$.each(recordLine, function(index, item){
if(item.parent == null){
$("#searchToolbar select[name='line']").append('<option value="'+item.id+'">'+item.name+'</option>');
}
})
})
function initLine(option, elem){
option = option || '';
@@ -332,7 +373,7 @@ function changeLine(obj, elem){
if($(obj).find("option:selected").text() == '子集线路(非必填)') return;
var tempLine = recordLine.filter((x) => x.parent == line)
if(tempLine.length > 0){
var option = '<option value="'+line+'">子集线路(非必填)</option>';
var option = line.substr(0,2) == 'N.' ? '' : '<option value="'+line+'">子集线路(非必填)</option>';
$.each(tempLine, function(index, item){
option += '<option value="'+item.id+'">'+item.name+'</option>';
})
@@ -396,7 +437,7 @@ function save(){
}, function(){
layer.closeAll();
$("#modal-store").modal('hide');
searchSubmit();
searchRefresh();
});
}else{
layer.alert(data.msg, {icon: 2})
@@ -416,7 +457,7 @@ function setStatus(recordid, status){
if(data.code == 0){
layer.closeAll();
layer.msg(status=='1'?'开启成功':'暂停成功', {icon: 1, time:500});
searchSubmit();
searchRefresh();
}else{
layer.alert(data.msg, {icon: 2});
}
@@ -438,7 +479,7 @@ function delItem(recordid) {
if(data.code == 0){
layer.closeAll();
layer.msg('删除成功', {icon: 1, time:800});
searchSubmit();
searchRefresh();
}else{
layer.alert(data.msg, {icon: 2});
}
@@ -470,7 +511,7 @@ function setRemark(recordid) {
if(data.code == 0){
layer.closeAll();
layer.msg('保存成功', {icon: 1, time:800});
searchSubmit();
searchRefresh();
}else{
layer.alert(data.msg, {icon:2});
}
@@ -530,7 +571,7 @@ function operation(action){
if(data.code == 0){
layer.closeAll();
layer.alert(data.msg, {icon: 1});
searchSubmit();
searchRefresh();
}else{
layer.alert(data.msg, {icon: 2});
}
@@ -572,7 +613,7 @@ function batch_save(){
}, function(){
layer.closeAll();
$("#modal-store2").modal('hide');
searchSubmit();
searchRefresh();
});
}else{
layer.alert(data.msg, {icon: 2})
@@ -602,7 +643,7 @@ function batch_save_line(){
}, function(){
layer.closeAll();
$("#modal-store3").modal('hide');
searchSubmit();
searchRefresh();
});
}else{
layer.alert(data.msg, {icon: 2})
@@ -633,7 +674,7 @@ function batch_edit_remark(recordids) {
closeBtn: false
}, function(){
layer.closeAll();
searchSubmit();
searchRefresh();
});
},
error:function(data){
@@ -644,5 +685,20 @@ function batch_edit_remark(recordids) {
}
});
}
function advanceSearch(){
$('#searchToolbar').find('input[name]').each(function() {
$(this).val('');
});
$('#searchToolbar').find('select[name]').each(function() {
$(this).find('option:first').prop("selected", 'selected');
});
if($("#searchbox1").is(":visible")){
$("#searchbox1").slideUp();
$("#searchbox2").slideDown();
}else{
$("#searchbox2").slideUp();
$("#searchbox1").slideDown();
}
}
</script>
{/block}

View File

@@ -1,23 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta id="viewport" name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<title>抱歉,出错了</title>
<link href="//res.wx.qq.com/open/libs/weui/0.4.3/weui.css" rel="stylesheet">
<style>.page{position:absolute;top:0;right:0;bottom:0;left:0;overflow-y:auto;-webkit-overflow-scrolling:touch;box-sizing:border-box}</style>
</head>
<body>
<div class="weui_msg">
<div class="weui_icon_area"><i class="weui_icon_info weui_icon_msg"></i></div>
<div class="weui_text_area">
<h4 class="weui_msg_title">{$errmsg}</h4>
</div>
</div>
<script>
document.body.addEventListener('touchmove', function (event) {
event.preventDefault();
},{ passive: false });
</script>
</body>
</html>

View File

@@ -33,8 +33,8 @@ tbody tr>td:nth-child(2){overflow: hidden;text-overflow: ellipsis;white-space: n
{/block}
{block name="script"}
<script src="{$cdnpublic}layer/3.1.1/layer.js"></script>
<script src="{$cdnpublic}bootstrap-table/1.20.2/bootstrap-table.min.js"></script>
<script src="{$cdnpublic}bootstrap-table/1.20.2/extensions/page-jump-to/bootstrap-table-page-jump-to.min.js"></script>
<script src="{$cdnpublic}bootstrap-table/1.21.4/bootstrap-table.min.js"></script>
<script src="{$cdnpublic}bootstrap-table/1.21.4/extensions/page-jump-to/bootstrap-table-page-jump-to.min.js"></script>
<script src="/static/js/custom.js"></script>
<script>
$(document).ready(function(){

View File

@@ -13,7 +13,7 @@
<div class="panel panel-warning">
<div class="panel-heading"><h3 class="panel-title">使用说明</h3></div>
<div class="panel-body">
<p><li>数据接口:<a href="https://monitor.gacjie.cn/" target="_blank" rel="noreferrer">GacJieMonitor</a> 数据接口支持CloudFlare、CloudFront、Gcore<a href="https://hostmonit.com/" target="_blank" rel="noreferrer">HostMonit</a> 只支持CloudFlare。</li></p>
<p><li>数据接口:<a href="https://www.182682.xyz/" target="_blank" rel="noreferrer">182682.xyz</a> 数据接口支持CloudFlare、CloudFront、Gcore<a href="https://stock.hostmonit.com/" target="_blank" rel="noreferrer">HostMonit</a> 只支持CloudFlare<a href="https://345673.xyz/" target="_blank" rel="noreferrer">345673.xyz</a> 只支持CloudFlare。</li></p>
<p><li>接口密钥默认o1zrmHAF为免费KEY可永久免费使用。</li></p>
<p><li>计划任务将以下命令添加到计划任务周期设置为15分钟以上</li></p>
<p><code>cd {:app()->getRootPath()} && php think opiptask</code></p>
@@ -27,7 +27,7 @@
<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"><select class="form-control" name="optimize_ip_api" default="{:config_get('optimize_ip_api')}"><option value="0">GacJieMonitor</option><option value="1">HostMonit</option></select></div>
<div class="col-sm-9"><select class="form-control" name="optimize_ip_api" default="{:config_get('optimize_ip_api')}"><option value="0">182682.xyz</option><option value="1">HostMonit</option><option value="2">345673.xyz</option></select></div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">接口密钥</label>

View File

@@ -27,8 +27,8 @@
{/block}
{block name="script"}
<script src="{$cdnpublic}layer/3.1.1/layer.js"></script>
<script src="{$cdnpublic}bootstrap-table/1.20.2/bootstrap-table.min.js"></script>
<script src="{$cdnpublic}bootstrap-table/1.20.2/extensions/page-jump-to/bootstrap-table-page-jump-to.min.js"></script>
<script src="{$cdnpublic}bootstrap-table/1.21.4/bootstrap-table.min.js"></script>
<script src="{$cdnpublic}bootstrap-table/1.21.4/extensions/page-jump-to/bootstrap-table-page-jump-to.min.js"></script>
<script src="/static/js/custom.js"></script>
<script>
$(document).ready(function(){

View File

@@ -109,8 +109,8 @@
{/block}
{block name="script"}
<script src="{$cdnpublic}layer/3.1.1/layer.js"></script>
<script src="{$cdnpublic}bootstrap-table/1.20.2/bootstrap-table.min.js"></script>
<script src="{$cdnpublic}bootstrap-table/1.20.2/extensions/page-jump-to/bootstrap-table-page-jump-to.min.js"></script>
<script src="{$cdnpublic}bootstrap-table/1.21.4/bootstrap-table.min.js"></script>
<script src="{$cdnpublic}bootstrap-table/1.21.4/extensions/page-jump-to/bootstrap-table-page-jump-to.min.js"></script>
<script src="{$cdnpublic}select2/4.0.13/js/select2.min.js"></script>
<script src="{$cdnpublic}select2/4.0.13/js/i18n/zh-CN.min.js"></script>
<script src="/static/js/custom.js"></script>
@@ -253,7 +253,7 @@ function save(){
}, function(){
layer.closeAll();
$("#modal-store").modal('hide');
searchSubmit();
searchRefresh();
});
}else{
layer.alert(data.msg, {icon: 2})
@@ -271,7 +271,7 @@ function setStatus(id,status) {
success : function(data) {
layer.close(ii);
if(data.code == 0){
searchSubmit();
searchRefresh();
}else{
layer.msg(data.msg, {icon:2, time:1500});
}
@@ -292,7 +292,7 @@ function delItem(id) {
layer.close(ii);
if(data.code == 0){
layer.closeAll();
searchSubmit();
searchRefresh();
}else{
layer.alert(data.msg, {icon: 2});
}

View File

@@ -31,7 +31,7 @@ return [
'show_error_msg' => true,
'exception_tmpl' => \think\facade\App::getAppPath() . 'view/exception.tpl',
'version' => '1007',
'version' => '1015',
'dbversion' => '1007'
'dbversion' => '1011'
];

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

View File

@@ -14,10 +14,18 @@ if (parameter_str !== undefined) {
window.$_GET = [];
}
function searchSubmit(){
function searchRefresh(){
$('#listTable').bootstrapTable('refresh');
return false;
}
function searchSubmit(){
if(typeof sidePagination != 'undefined' && sidePagination == 'client'){
$('#listTable').bootstrapTable('refresh');
}else{
$('#listTable').bootstrapTable('selectPage', 1);
}
return false;
}
function searchClear(){
$('#searchToolbar').find('input[name]').each(function() {
$(this).val('');
@@ -25,7 +33,11 @@ function searchClear(){
$('#searchToolbar').find('select[name]').each(function() {
$(this).find('option:first').prop("selected", 'selected');
});
$('#listTable').bootstrapTable('refresh');
if(typeof sidePagination != 'undefined' && sidePagination == 'client'){
$('#listTable').bootstrapTable('refresh');
}else{
$('#listTable').bootstrapTable('selectPage', 1);
}
}
function updateToolbar(){
$('#searchToolbar').find(':input[name]').each(function() {
@@ -67,6 +79,7 @@ if (typeof $.fn.bootstrapTable !== "undefined") {
queryParamsType: '',
queryParams: function(params) {
$('#searchToolbar').find(':input[name]').each(function() {
if(!$(this).is(":visible")) return;
params[$(this).attr('name')] = $(this).val()
})
updateQueryStr(params);

View File

@@ -69,7 +69,9 @@ Route::group(function () {
Route::any('/dmonitor/task/:action', 'dmonitor/taskform');
Route::get('/dmonitor/task', 'dmonitor/task');
Route::any('/dmonitor/noticeset', 'dmonitor/noticeset');
Route::any('/dmonitor/proxyset', 'dmonitor/proxyset');
Route::get('/dmonitor/mailtest', 'dmonitor/mailtest');
Route::get('/dmonitor/tgbottest', 'dmonitor/tgbottest');
Route::post('/dmonitor/clean', 'dmonitor/clean');
Route::any('/optimizeip/opipset', 'optimizeip/opipset');