mirror of
https://github.com/netcccyun/dnsmgr.git
synced 2026-05-14 00:56:27 +02:00
Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
949b52722a | ||
|
|
1c504f3b04 | ||
|
|
8e4fd32f8c | ||
|
|
5cd6b108f0 | ||
|
|
424d2c8132 | ||
|
|
86bffab357 | ||
|
|
c1edf905f3 | ||
|
|
b252816711 | ||
|
|
7a58292fb9 | ||
|
|
d4b7bcfbf6 |
@@ -2,7 +2,6 @@ APP_DEBUG = false
|
||||
|
||||
[APP]
|
||||
DEFAULT_TIMEZONE = Asia/Shanghai
|
||||
SYS_KEY = {syskey}
|
||||
|
||||
[DATABASE]
|
||||
TYPE = mysql
|
||||
|
||||
14
README.md
14
README.md
@@ -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)
|
||||
|
||||
@@ -232,7 +232,8 @@ function getMillisecond()
|
||||
}
|
||||
|
||||
function getDnsType($value){
|
||||
if(filter_var($value, FILTER_VALIDATE_IP))return 'A';
|
||||
if(filter_var($value, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4))return 'A';
|
||||
else if(filter_var($value, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6))return 'AAAA';
|
||||
else return 'CNAME';
|
||||
}
|
||||
|
||||
|
||||
@@ -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']);
|
||||
}
|
||||
|
||||
@@ -155,7 +155,7 @@ class Domain extends BaseController
|
||||
|
||||
$select = Db::name('domain')->alias('A')->join('account B','A.aid = B.id');
|
||||
if(!empty($kw)){
|
||||
$select->whereLike('name', '%'.$kw.'%');
|
||||
$select->whereLike('name|A.remark', '%'.$kw.'%');
|
||||
}
|
||||
if(!empty($type)){
|
||||
$select->whereLike('B.type', $type);
|
||||
@@ -164,7 +164,7 @@ class Domain extends BaseController
|
||||
$select->where('is_hide', 0)->where('A.name', 'in', request()->user['permission']);
|
||||
}
|
||||
$total = $select->count();
|
||||
$rows = $select->fieldRaw('A.*,B.type,B.remark')->order('A.id','desc')->limit($offset, $limit)->select();
|
||||
$rows = $select->fieldRaw('A.*,B.type,B.remark aremark')->order('A.id','desc')->limit($offset, $limit)->select();
|
||||
|
||||
$list = [];
|
||||
foreach($rows as $row){
|
||||
@@ -210,9 +210,11 @@ 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');
|
||||
$remark = input('post.remark', null, 'trim');
|
||||
Db::name('domain')->where('id', $id)->update([
|
||||
'is_hide' => $is_hide,
|
||||
'is_sso' => $is_sso,
|
||||
'remark' => $remark,
|
||||
]);
|
||||
return json(['code'=>0, 'msg'=>'修改域名配置成功!']);
|
||||
}elseif($act == 'del'){
|
||||
@@ -289,7 +291,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'].'×tamp='.$timestamp.'&token='.$token.'&sign='.$sign;
|
||||
}
|
||||
|
||||
@@ -327,6 +329,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');
|
||||
@@ -345,10 +348,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']]);
|
||||
}
|
||||
|
||||
@@ -534,6 +537,7 @@ class Domain extends BaseController
|
||||
}
|
||||
|
||||
$success = 0;
|
||||
$fail = 0;
|
||||
$dns = DnsHelper::getModel($drow['aid'], $drow['name'], $drow['thirdid']);
|
||||
if($action == 'open'){
|
||||
foreach($recordids as $recordid){
|
||||
@@ -559,10 +563,136 @@ class Domain extends BaseController
|
||||
}
|
||||
}
|
||||
$msg = '成功删除'.$success.'条解析记录';
|
||||
}else if($action == 'remark'){
|
||||
$remark = input('post.remark', null, 'trim');
|
||||
if(empty($remark)) $remark = null;
|
||||
foreach($recordids as $recordid){
|
||||
if($dns->updateDomainRecordRemark($recordid, $remark)){
|
||||
$success++;
|
||||
}else{
|
||||
$fail++;
|
||||
}
|
||||
}
|
||||
$msg = '批量修改备注,成功'.$success.'条,失败'.$fail.'条';
|
||||
}
|
||||
return json(['code'=>0, 'msg'=>$msg]);
|
||||
}
|
||||
|
||||
public function record_batch_edit(){
|
||||
$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 $this->alert('error', '无权限');
|
||||
|
||||
$action = input('post.action', null, 'trim');
|
||||
$recordinfo = input('post.recordinfo', null, 'trim');
|
||||
$recordinfo = json_decode($recordinfo, true);
|
||||
|
||||
if($action == 'value'){
|
||||
$type = input('post.type', null, 'trim');
|
||||
$value = input('post.value', null, 'trim');
|
||||
|
||||
if(empty($recordinfo) || empty($type) || empty($value)){
|
||||
return json(['code'=>-1, 'msg'=>'参数不能为空']);
|
||||
}
|
||||
|
||||
$dns = DnsHelper::getModel($drow['aid'], $drow['name'], $drow['thirdid']);
|
||||
|
||||
$success = 0; $fail = 0;
|
||||
foreach($recordinfo as $record){
|
||||
$recordid = $dns->updateDomainRecord($record['recordid'], $record['name'], $type, $value, $record['line'], $record['ttl'], $record['mx'], $record['remark']);
|
||||
if($recordid){
|
||||
$this->add_log($drow['name'], '修改解析', $type.'记录 '.$record['name'].' '.$value.' (线路:'.$record['line'].' TTL:'.$record['ttl'].')');
|
||||
$success++;
|
||||
}else{
|
||||
$fail++;
|
||||
}
|
||||
}
|
||||
return json(['code'=>0, 'msg'=>'批量修改解析记录,成功'.$success.'条,失败'.$fail.'条']);
|
||||
|
||||
}else if($action == 'line'){
|
||||
$line = input('post.line', null, 'trim');
|
||||
|
||||
if(empty($recordinfo) || empty($line)){
|
||||
return json(['code'=>-1, 'msg'=>'参数不能为空']);
|
||||
}
|
||||
|
||||
$dns = DnsHelper::getModel($drow['aid'], $drow['name'], $drow['thirdid']);
|
||||
|
||||
$success = 0; $fail = 0;
|
||||
foreach($recordinfo as $record){
|
||||
$recordid = $dns->updateDomainRecord($record['recordid'], $record['name'], $record['type'], $record['value'], $line, $record['ttl'], $record['mx'], $record['remark']);
|
||||
if($recordid){
|
||||
$this->add_log($drow['name'], '修改解析', $record['type'].'记录 '.$record['name'].' '.$record['value'].' (线路:'.$line.' TTL:'.$record['ttl'].')');
|
||||
$success++;
|
||||
}else{
|
||||
$fail++;
|
||||
}
|
||||
}
|
||||
return json(['code'=>0, 'msg'=>'批量修改解析线路,成功'.$success.'条,失败'.$fail.'条']);
|
||||
}
|
||||
}
|
||||
|
||||
public function record_batch_add(){
|
||||
$id = input('param.id/d');
|
||||
$drow = Db::name('domain')->where('id', $id)->find();
|
||||
if(!$drow){
|
||||
return $this->alert('error', '域名不存在');
|
||||
}
|
||||
$dnstype = Db::name('account')->where('id', $drow['aid'])->value('type');
|
||||
if(!checkPermission(0, $drow['name'])) return $this->alert('error', '无权限');
|
||||
|
||||
if(request()->isAjax()){
|
||||
$record = input('post.record', null, 'trim');
|
||||
$type = input('post.type', null, 'trim');
|
||||
$line = input('post.line', null, 'trim');
|
||||
$ttl = input('post.ttl/d', 600);
|
||||
$mx = input('post.mx/d', 1);
|
||||
$recordlist = explode("\n", $record);
|
||||
|
||||
if(empty($record) || empty($recordlist)){
|
||||
return json(['code'=>-1, 'msg'=>'参数不能为空']);
|
||||
}
|
||||
|
||||
$dns = DnsHelper::getModel($drow['aid'], $drow['name'], $drow['thirdid']);
|
||||
|
||||
$success = 0; $fail = 0;
|
||||
foreach($recordlist as $record){
|
||||
$record = trim($record);
|
||||
$arr = explode(' ', $record);
|
||||
if(empty($record) || empty($arr[0]) || empty($arr[1])) continue;
|
||||
$thistype = empty($type) ? getDnsType($arr[1]) : $type;
|
||||
$recordid = $dns->addDomainRecord($arr[0], $thistype, $arr[1], $line, $ttl, $mx);
|
||||
if($recordid){
|
||||
$this->add_log($drow['name'], '添加解析', $thistype.'记录 '.$arr[0].' '.$arr[1].' (线路:'.$line.' TTL:'.$ttl.')');
|
||||
$success++;
|
||||
}else{
|
||||
$fail++;
|
||||
}
|
||||
}
|
||||
return json(['code'=>0, 'msg'=>'批量添加解析,成功'.$success.'条,失败'.$fail.'条']);
|
||||
}
|
||||
|
||||
list($recordLine, $minTTL) = $this->get_line_and_ttl($drow);
|
||||
|
||||
$recordLineArr = [];
|
||||
foreach($recordLine as $key=>$item){
|
||||
$recordLineArr[] = ['id'=>strval($key), 'name'=>$item['name'], 'parent'=>$item['parent']];
|
||||
}
|
||||
|
||||
$dnsconfig = DnsHelper::$dns_config[$dnstype];
|
||||
$dnsconfig['type'] = $dnstype;
|
||||
|
||||
View::assign('domainId', $id);
|
||||
View::assign('domainName', $drow['name']);
|
||||
View::assign('recordLine', $recordLineArr);
|
||||
View::assign('minTTL', $minTTL?$minTTL:1);
|
||||
View::assign('dnsconfig', $dnsconfig);
|
||||
return view('batchadd');
|
||||
}
|
||||
|
||||
public function record_log(){
|
||||
$id = input('param.id/d');
|
||||
$drow = Db::name('domain')->where('id', $id)->find();
|
||||
|
||||
@@ -61,7 +61,11 @@ class Index extends BaseController
|
||||
$value=trim($value);
|
||||
if(empty($value))continue;
|
||||
$value = str_replace('dnsmgr_',$mysql_prefix,$value);
|
||||
Db::execute($value);
|
||||
try{
|
||||
Db::execute($value);
|
||||
}catch(Exception $e){
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -69,7 +69,7 @@ class Optimizeip extends BaseController
|
||||
'recordnum' => input('post.recordnum/d'),
|
||||
'ttl' => input('post.ttl/d'),
|
||||
'remark' => input('post.remark', null, 'trim'),
|
||||
'addtime' => time(),
|
||||
'addtime' => date('Y-m-d H:i:s'),
|
||||
'active' => 1
|
||||
];
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ class baidu 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){
|
||||
$marker = cookie('baidu_record_marker');
|
||||
$query = ['rr' => $KeyWord];
|
||||
if(!isNullOrEmpty(($SubDomain))){
|
||||
@@ -81,7 +81,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);
|
||||
}
|
||||
|
||||
//获取解析记录详细信息
|
||||
|
||||
@@ -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';
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
//获取解析记录详细信息
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
//获取解析记录详细信息
|
||||
|
||||
@@ -51,12 +51,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{
|
||||
@@ -93,7 +99,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);
|
||||
}
|
||||
|
||||
//获取解析记录详细信息
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
//获取解析记录详细信息
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
//获取解析记录详细信息
|
||||
|
||||
@@ -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'){
|
||||
|
||||
@@ -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')){
|
||||
|
||||
@@ -5,7 +5,7 @@ CREATE TABLE `dnsmgr_config` (
|
||||
PRIMARY KEY (`key`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
INSERT INTO `dnsmgr_config` VALUES ('version', '1005');
|
||||
INSERT INTO `dnsmgr_config` VALUES ('version', '1007');
|
||||
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');
|
||||
@@ -33,6 +33,7 @@ CREATE TABLE `dnsmgr_domain` (
|
||||
`is_hide` tinyint(1) NOT NULL DEFAULT '0',
|
||||
`is_sso` tinyint(1) NOT NULL DEFAULT '0',
|
||||
`recordcount` int(1) NOT NULL DEFAULT '0',
|
||||
`remark` varchar(100) DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `name` (`name`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
@@ -59,4 +59,7 @@ CREATE TABLE IF NOT EXISTS `dnsmgr_optimizeip` (
|
||||
`errmsg` varchar(100) DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `did` (`did`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
ALTER TABLE `dnsmgr_domain`
|
||||
ADD COLUMN `remark` varchar(100) DEFAULT NULL;
|
||||
@@ -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')}">
|
||||
<li class="{:checkIfActive('domain,record,record_log,record_batch_add')}">
|
||||
<a href="/domain"><i class="fa fa-list-ul fa-fw"></i> <span>域名管理</span></a>
|
||||
</li>
|
||||
{if request()->user['level'] eq 2}
|
||||
|
||||
@@ -147,7 +147,6 @@ new Vue({
|
||||
{value:0, label:'无操作'},
|
||||
{value:1, label:'暂停解析'},
|
||||
{value:2, label:'切换备用解析'},
|
||||
{value:3, label:'条件开启解析'},
|
||||
],
|
||||
checktypeList: [
|
||||
{value:0, label:'PING', disabled: support_ping=='0'},
|
||||
|
||||
139
app/view/domain/batchadd.html
Normal file
139
app/view/domain/batchadd.html
Normal file
@@ -0,0 +1,139 @@
|
||||
{extend name="common/layout" /}
|
||||
{block name="title"}批量添加解析 - {$domainName}{/block}
|
||||
{block name="main"}
|
||||
<div class="row" id="app">
|
||||
<div class="col-xs-12 center-block" style="float: none;">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading"><h3 class="panel-title"><a href="/record/{$domainId}" class="btn btn-sm btn-default pull-right" style="margin-top:-6px"><i class="fa fa-reply fa-fw"></i> 返回</a>批量添加解析 - {$domainName}</h3></div>
|
||||
<div class="panel-body">
|
||||
<form onsubmit="return false" method="post" class="form-horizontal" role="form" id="form-store">
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 col-xs-12 control-label no-padding-right">主机记录&记录值</label>
|
||||
<div class="col-sm-6">
|
||||
<textarea name="record" placeholder="主机记录和记录值用空格隔开,一行一个" class="form-control" rows="8" required></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label no-padding-right">记录类型</label>
|
||||
<div class="col-sm-6">
|
||||
<select name="type" class="form-control">
|
||||
<option value="">A / CNAME / AAAA 自动识别</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>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label no-padding-right">线路类型</label>
|
||||
<div class="col-sm-6" id="line_list">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" style="display:none" id="mx_type">
|
||||
<label class="col-sm-3 control-label no-padding-right">MX优先级</label>
|
||||
<div class="col-sm-6">
|
||||
<input type="text" class="form-control" name="mx" value="10">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label no-padding-right">TTL</label>
|
||||
<div class="col-sm-6">
|
||||
<input type="text" class="form-control" name="ttl" value="600" placeholder="指解析结果在DNS服务器中的缓存时间" required min="{$minTTL}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-3 col-sm-6"><button type="button" class="btn btn-primary" onclick="save()">保存</button></div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{/block}
|
||||
{block name="script"}
|
||||
<script src="{$cdnpublic}layer/3.1.1/layer.js"></script>
|
||||
<script src="/static/js/bootstrapValidator.min.js"></script>
|
||||
<script>
|
||||
var recordLine = {$recordLine|json_encode|raw};
|
||||
var dnsconfig = {$dnsconfig|json_encode|raw};
|
||||
var defaultLine = recordLine[0].id;
|
||||
$(document).ready(function(){
|
||||
$("select[name=type]").change(function(){
|
||||
if($(this).val() == 'MX'){
|
||||
$("#mx_type").show();
|
||||
}else{
|
||||
$("#mx_type").hide();
|
||||
}
|
||||
});
|
||||
|
||||
$("#form-store").bootstrapValidator();
|
||||
initLine();
|
||||
});
|
||||
|
||||
function initLine(option, elem){
|
||||
option = option || '';
|
||||
elem = elem || 'line_list';
|
||||
$("#"+elem).empty();
|
||||
$.each(recordLine, function(index, item){
|
||||
if(item.parent == null){
|
||||
option += '<option value="'+item.id+'">'+item.name+'</option>';
|
||||
}
|
||||
})
|
||||
$("#"+elem).append('<select name="line" class="form-control" onchange="changeLine(this, \''+elem+'\')">'+option+'</select>');
|
||||
}
|
||||
function changeLine(obj, elem){
|
||||
var line = $(obj).val();
|
||||
var flag = false;
|
||||
$("#"+elem).children().each(function(index, elem){
|
||||
if(flag) $(elem).remove()
|
||||
if(obj == elem){
|
||||
flag = true;
|
||||
}
|
||||
})
|
||||
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>';
|
||||
$.each(tempLine, function(index, item){
|
||||
option += '<option value="'+item.id+'">'+item.name+'</option>';
|
||||
})
|
||||
$("#"+elem).append('<select name="line" class="form-control" onchange="changeLine(this, \''+elem+'\')">'+option+'</select>');
|
||||
}
|
||||
}
|
||||
function save(){
|
||||
$("#form-store").data("bootstrapValidator").validate();
|
||||
if(!$("#form-store").data("bootstrapValidator").isValid()){
|
||||
return;
|
||||
}
|
||||
var act = $("#form-store input[name=action]").val();
|
||||
var ii = layer.load(2);
|
||||
$.ajax({
|
||||
type : 'POST',
|
||||
url : '/record/batchadd/{$domainId}',
|
||||
data : $("#form-store").serialize(),
|
||||
dataType : 'json',
|
||||
success : function(data) {
|
||||
layer.close(ii);
|
||||
if(data.code == 0){
|
||||
layer.alert(data.msg,{
|
||||
icon: 1,
|
||||
closeBtn: false
|
||||
}, function(){
|
||||
if(document.referrer.indexOf('/record?') > 0)
|
||||
window.location.href = document.referrer;
|
||||
else
|
||||
window.location.href = '/record/{$domainId}';
|
||||
});
|
||||
}else{
|
||||
layer.alert(data.msg, {icon: 2})
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
{/block}
|
||||
@@ -74,6 +74,12 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label no-padding-right">备注</label>
|
||||
<div class="col-sm-9">
|
||||
<input type="text" class="form-control" name="remark" placeholder="">
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
@@ -91,7 +97,7 @@
|
||||
<form onsubmit="return searchSubmit()" method="GET" class="form-inline" id="searchToolbar">
|
||||
<div class="form-group">
|
||||
<label>搜索</label>
|
||||
<input type="text" class="form-control" name="kw" placeholder="域名">
|
||||
<input type="text" class="form-control" name="kw" placeholder="域名或备注">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<select name="type" class="form-control"><option value="">所有平台</option>{foreach $types as $k=>$v}
|
||||
@@ -139,7 +145,7 @@ $(document).ready(function(){
|
||||
field: 'typename',
|
||||
title: '平台账户',
|
||||
formatter: function(value, row, index) {
|
||||
return '<span title="'+row.remark+'" data-toggle="tooltip" data-placement="right" title="Tooltip on right"><img src="/static/images/'+row.type+'.ico" class="type-logo"></img>'+value+'('+row.aid+')</span>';
|
||||
return '<span title="'+row.aremark+'" data-toggle="tooltip" data-placement="right" title="Tooltip on right"><img src="/static/images/'+row.type+'.ico" class="type-logo"></img>'+value+'('+row.aid+')</span>';
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -157,6 +163,10 @@ $(document).ready(function(){
|
||||
field: 'addtime',
|
||||
title: '添加时间'
|
||||
},
|
||||
{
|
||||
field: 'remark',
|
||||
title: '备注'
|
||||
},
|
||||
{
|
||||
field: 'is_hide',
|
||||
title: '是否隐藏',
|
||||
@@ -256,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})
|
||||
}
|
||||
|
||||
@@ -78,6 +78,78 @@ td{overflow: hidden;text-overflow: ellipsis;white-space: nowrap;max-width:360px;
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal" id="modal-store2" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true" data-backdrop="static">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content animated flipInX">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal"><span
|
||||
aria-hidden="true">×</span><span
|
||||
class="sr-only">Close</span></button>
|
||||
<h4 class="modal-title" id="modal-title">批量修改解析记录</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form class="form-horizontal" id="form-store2">
|
||||
<input type="hidden" name="action" value="value"/>
|
||||
<input type="hidden" name="recordinfo"/>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">记录类型</label>
|
||||
<div class="col-sm-9">
|
||||
<select name="type" class="form-control">
|
||||
<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>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label no-padding-right">记录值</label>
|
||||
<div class="col-sm-9">
|
||||
<input type="text" class="form-control" name="value" placeholder="输入记录值" required>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-white" data-dismiss="modal">关闭</button>
|
||||
<button type="button" class="btn btn-primary" id="store" onclick="batch_save()">保存</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal" id="modal-store3" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true" data-backdrop="static">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content animated flipInX">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal"><span
|
||||
aria-hidden="true">×</span><span
|
||||
class="sr-only">Close</span></button>
|
||||
<h4 class="modal-title" id="modal-title">批量修改解析线路</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form class="form-horizontal" id="form-store3">
|
||||
<input type="hidden" name="action" value="line"/>
|
||||
<input type="hidden" name="recordinfo"/>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">线路类型</label>
|
||||
<div class="col-sm-9" id="line_list3">
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-white" data-dismiss="modal">关闭</button>
|
||||
<button type="button" class="btn btn-primary" id="store" onclick="batch_save_line()">保存</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xs-12 center-block" style="float: none;">
|
||||
<div class="panel panel-default panel-default">
|
||||
@@ -87,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="输入关键字">
|
||||
@@ -99,12 +172,45 @@ td{overflow: hidden;text-overflow: ellipsis;white-space: nowrap;max-width:360px;
|
||||
<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="javascript:operation('open')">启用</a></li><li><a href="javascript:operation('pause')">暂停</a></li><li><a href="javascript:operation('delete')">删除</a></li></ul>
|
||||
<ul class="dropdown-menu"><li><a href="/record/batchadd/{$domainId}">添加</a></li><li><a href="javascript:operation('open')">启用</a></li><li><a href="javascript:operation('pause')">暂停</a></li><li><a href="javascript:operation('edit')">修改记录</a></li><li><a href="javascript:operation('editline')">修改线路</a></li>{if $dnsconfig.remark == 1}<li><a href="javascript:operation('editremark')">修改备注</a></li>{/if}<li><a href="javascript:operation('delete')">删除</a></li></ul>
|
||||
</div>
|
||||
<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="/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">
|
||||
@@ -119,14 +225,14 @@ td{overflow: hidden;text-overflow: ellipsis;white-space: nowrap;max-width:360px;
|
||||
<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="/static/js/bootstrapValidator.min.js"></script>
|
||||
<script src="/static/js/custom.js"></script>
|
||||
<script src="/static/js/custom.js?v=1002"></script>
|
||||
<script>
|
||||
var recordLine = {$recordLine|json_encode|raw};
|
||||
var dnsconfig = {$dnsconfig|json_encode|raw};
|
||||
var defaultLine = recordLine[0].id;
|
||||
$(document).ready(function(){
|
||||
updateToolbar();
|
||||
const defaultPageSize = 15;
|
||||
let defaultPageSize = getCookie('record_pagesize') ? getCookie('record_pagesize') : 15;
|
||||
const pageNumber = typeof window.$_GET['pageNumber'] != 'undefined' ? parseInt(window.$_GET['pageNumber']) : 1;
|
||||
const pageSize = typeof window.$_GET['pageSize'] != 'undefined' ? parseInt(window.$_GET['pageSize']) : defaultPageSize;
|
||||
|
||||
@@ -218,6 +324,12 @@ $(document).ready(function(){
|
||||
}
|
||||
},
|
||||
],
|
||||
onPageChange: function(number, size){
|
||||
if(size != defaultPageSize){
|
||||
defaultPageSize = size;
|
||||
setCookie('record_pagesize', size);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
$("select[name=type]").change(function(){
|
||||
@@ -229,21 +341,29 @@ $(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){
|
||||
function initLine(option, elem){
|
||||
option = option || '';
|
||||
$("#line_list").empty();
|
||||
elem = elem || 'line_list';
|
||||
$("#"+elem).empty();
|
||||
$.each(recordLine, function(index, item){
|
||||
if(item.parent == null){
|
||||
option += '<option value="'+item.id+'">'+item.name+'</option>';
|
||||
}
|
||||
})
|
||||
$("#line_list").append('<select name="line" class="form-control" onchange="changeLine(this)">'+option+'</select>');
|
||||
$("#"+elem).append('<select name="line" class="form-control" onchange="changeLine(this, \''+elem+'\')">'+option+'</select>');
|
||||
}
|
||||
function changeLine(obj){
|
||||
function changeLine(obj, elem){
|
||||
var line = $(obj).val();
|
||||
var flag = false;
|
||||
$("#line_list").children().each(function(index, elem){
|
||||
$("#"+elem).children().each(function(index, elem){
|
||||
if(flag) $(elem).remove()
|
||||
if(obj == elem){
|
||||
flag = true;
|
||||
@@ -256,7 +376,7 @@ function changeLine(obj){
|
||||
$.each(tempLine, function(index, item){
|
||||
option += '<option value="'+item.id+'">'+item.name+'</option>';
|
||||
})
|
||||
$("#line_list").append('<select name="line" class="form-control" onchange="changeLine(this)">'+option+'</select>');
|
||||
$("#"+elem).append('<select name="line" class="form-control" onchange="changeLine(this, \''+elem+'\')">'+option+'</select>');
|
||||
}
|
||||
}
|
||||
function addframe(){
|
||||
@@ -409,6 +529,29 @@ function operation(action){
|
||||
layer.msg('请选择要操作的记录');
|
||||
return;
|
||||
}
|
||||
if(action == 'edit'){
|
||||
var records = [];
|
||||
$.each(rows, function(index, item){
|
||||
records.push({recordid:item.RecordId, name:item.Name, line:item.Line, mx:item.MX, ttl:item.TTL, remark:item.Remark});
|
||||
})
|
||||
batch_edit(records)
|
||||
return;
|
||||
}else if(action == 'editline'){
|
||||
var records = [];
|
||||
$.each(rows, function(index, item){
|
||||
records.push({recordid:item.RecordId, name:item.Name, type:item.Type, value:item.Value, mx:item.MX, ttl:item.TTL, remark:item.Remark});
|
||||
})
|
||||
batch_edit_line(records)
|
||||
return;
|
||||
}else if(action == 'editremark'){
|
||||
var ids = [];
|
||||
$.each(rows, function(index, item){
|
||||
ids.push(item.RecordId);
|
||||
})
|
||||
batch_edit_remark(ids)
|
||||
return;
|
||||
}
|
||||
|
||||
var ids = [];
|
||||
$.each(rows, function(index, item){
|
||||
ids.push(item.RecordId);
|
||||
@@ -437,5 +580,124 @@ function operation(action){
|
||||
layer.close(confirmobj);
|
||||
});
|
||||
}
|
||||
function batch_edit(records){
|
||||
var row = $("#listTable").bootstrapTable('getSelections')[0];
|
||||
$("#batch_num").text(records.length);
|
||||
$("#modal-store2").modal('show');
|
||||
$("#form-store2 input[name=recordinfo]").val(JSON.stringify(records));
|
||||
$("#form-store2 input[name=recordid]").val(row.RecordId);
|
||||
$("#form-store2 input[name=name]").val(row.Name);
|
||||
$("#form-store2 select[name=type]").val(row.Type);
|
||||
$("select[name=type]").change();
|
||||
$("#form-store2 input[name=value]").val(row.Value);
|
||||
$("#form-store2").data("bootstrapValidator").resetForm();
|
||||
}
|
||||
function batch_save(){
|
||||
$("#form-store2").data("bootstrapValidator").validate();
|
||||
if(!$("#form-store2").data("bootstrapValidator").isValid()){
|
||||
return;
|
||||
}
|
||||
var ii = layer.load(2);
|
||||
$.ajax({
|
||||
type : 'POST',
|
||||
url : '/record/batchedit/{$domainId}',
|
||||
data : $("#form-store2").serialize(),
|
||||
dataType : 'json',
|
||||
success : function(data) {
|
||||
layer.close(ii);
|
||||
if(data.code == 0){
|
||||
layer.alert(data.msg,{
|
||||
icon: 1,
|
||||
closeBtn: false
|
||||
}, function(){
|
||||
layer.closeAll();
|
||||
$("#modal-store2").modal('hide');
|
||||
searchSubmit();
|
||||
});
|
||||
}else{
|
||||
layer.alert(data.msg, {icon: 2})
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
function batch_edit_line(records){
|
||||
$("#batch_num").text(records.length);
|
||||
$("#modal-store3").modal('show');
|
||||
$("#form-store3 input[name=recordinfo]").val(JSON.stringify(records));
|
||||
initLine('', 'line_list3');
|
||||
}
|
||||
function batch_save_line(){
|
||||
var ii = layer.load(2);
|
||||
$.ajax({
|
||||
type : 'POST',
|
||||
url : '/record/batchedit/{$domainId}',
|
||||
data : $("#form-store3").serialize(),
|
||||
dataType : 'json',
|
||||
success : function(data) {
|
||||
layer.close(ii);
|
||||
if(data.code == 0){
|
||||
layer.alert(data.msg,{
|
||||
icon: 1,
|
||||
closeBtn: false
|
||||
}, function(){
|
||||
layer.closeAll();
|
||||
$("#modal-store3").modal('hide');
|
||||
searchSubmit();
|
||||
});
|
||||
}else{
|
||||
layer.alert(data.msg, {icon: 2})
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
function batch_edit_remark(recordids) {
|
||||
layer.open({
|
||||
type: 1,
|
||||
area: ['350px'],
|
||||
closeBtn: 2,
|
||||
title: '批量修改备注',
|
||||
content: '<div style="padding:15px"><div class="form-group"><input class="form-control" type="text" name="remark" value="" autocomplete="off" placeholder="备注信息"></div></div>',
|
||||
btn: ['确认', '取消'],
|
||||
yes: function(){
|
||||
var remark = $("input[name='remark']").val();
|
||||
var ii = layer.load(2, {shade:[0.1,'#fff']});
|
||||
$.ajax({
|
||||
type : 'POST',
|
||||
url : '/record/batch/{$domainId}',
|
||||
data : {action:'remark', recordids:recordids, remark:remark},
|
||||
dataType : 'json',
|
||||
success : function(data) {
|
||||
layer.close(ii);
|
||||
layer.alert(data.msg,{
|
||||
icon: 1,
|
||||
closeBtn: false
|
||||
}, function(){
|
||||
layer.closeAll();
|
||||
searchSubmit();
|
||||
});
|
||||
},
|
||||
error:function(data){
|
||||
layer.close(ii);
|
||||
layer.msg('服务器错误');
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
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}
|
||||
@@ -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>
|
||||
@@ -155,7 +155,7 @@ function setActive(id, active){
|
||||
}, 'json');
|
||||
}
|
||||
function delItem(id){
|
||||
layer.confirm('确定要删除此切换策略吗?', {
|
||||
layer.confirm('确定要删除此任务吗?', {
|
||||
btn: ['确定','取消']
|
||||
}, function(){
|
||||
$.post('/optimizeip/opipform/del', {id: id}, function(data){
|
||||
|
||||
@@ -31,7 +31,7 @@ return [
|
||||
'show_error_msg' => true,
|
||||
'exception_tmpl' => \think\facade\App::getAppPath() . 'view/exception.tpl',
|
||||
|
||||
'version' => '1005',
|
||||
'version' => '1009',
|
||||
|
||||
'dbversion' => '1005'
|
||||
'dbversion' => '1007'
|
||||
];
|
||||
|
||||
@@ -15,7 +15,7 @@ if (parameter_str !== undefined) {
|
||||
}
|
||||
|
||||
function searchSubmit(){
|
||||
$('#listTable').bootstrapTable('refresh');
|
||||
$('#listTable').bootstrapTable('selectPage', 1);
|
||||
return false;
|
||||
}
|
||||
function searchClear(){
|
||||
@@ -25,7 +25,7 @@ function searchClear(){
|
||||
$('#searchToolbar').find('select[name]').each(function() {
|
||||
$(this).find('option:first').prop("selected", 'selected');
|
||||
});
|
||||
$('#listTable').bootstrapTable('refresh');
|
||||
$('#listTable').bootstrapTable('selectPage', 1);
|
||||
}
|
||||
function updateToolbar(){
|
||||
$('#searchToolbar').find(':input[name]').each(function() {
|
||||
@@ -67,6 +67,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);
|
||||
@@ -130,4 +131,32 @@ var isMobile = function(){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function setCookie(name,value,expire = null)
|
||||
{
|
||||
var cookie = name + "=" + escape(value);
|
||||
if(expire){
|
||||
var exp = new Date();
|
||||
exp.setTime(exp.getTime() + expire*1000);
|
||||
cookie += ";expires=" + exp.toGMTString();
|
||||
}
|
||||
document.cookie = cookie;
|
||||
}
|
||||
function getCookie(name)
|
||||
{
|
||||
var arr,reg=new RegExp("(^| )"+name+"=([^;]*)(;|$)");
|
||||
if(arr=document.cookie.match(reg))
|
||||
return unescape(arr[2]);
|
||||
else
|
||||
return null;
|
||||
}
|
||||
function delCookie(name)
|
||||
{
|
||||
var exp = new Date();
|
||||
exp.setTime(exp.getTime() - 1);
|
||||
var cval=getCookie(name);
|
||||
if(cval!=null){
|
||||
document.cookie= name + "="+cval+";expires="+exp.toGMTString();
|
||||
}
|
||||
}
|
||||
@@ -56,6 +56,8 @@ Route::group(function () {
|
||||
Route::post('/record/status/:id', 'domain/record_status');
|
||||
Route::post('/record/remark/:id', 'domain/record_remark');
|
||||
Route::post('/record/batch/:id', 'domain/record_batch');
|
||||
Route::post('/record/batchedit/:id', 'domain/record_batch_edit');
|
||||
Route::any('/record/batchadd/:id', 'domain/record_batch_add');
|
||||
Route::any('/record/log/:id', 'domain/record_log');
|
||||
Route::post('/record/list', 'domain/record_list');
|
||||
Route::get('/record/:id', 'domain/record');
|
||||
|
||||
Reference in New Issue
Block a user