From 780e01ce4f0159e4d2cc867c3df1f215dd8b82a5 Mon Sep 17 00:00:00 2001 From: net909 Date: Fri, 27 Feb 2026 18:36:56 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=85=BE=E8=AE=AF=E4=BA=91DN?= =?UTF-8?q?S=E5=9F=9F=E5=90=8D=E5=88=AB=E5=90=8D=E7=AE=A1=E7=90=86?= =?UTF-8?q?=E3=80=81=E4=BF=AE=E5=A4=8D=E4=B8=BB=E5=9F=9F=E5=90=8D=E5=88=A4?= =?UTF-8?q?=E6=96=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/common.php | 4 +- app/controller/Cert.php | 9 +- app/controller/Domain.php | 80 ++++++++++++++++++ app/lib/deploy/aliyun.php | 14 ++-- app/lib/dns/dnspod.php | 38 +++++++++ app/lib/dns/huawei.php | 4 - app/service/CertDeployService.php | 2 +- app/service/CertOrderService.php | 21 ++++- app/sql/install.sql | 10 +++ app/sql/update.sql | 11 ++- app/view/domain/alias.html | 132 ++++++++++++++++++++++++++++++ app/view/domain/domain_add.html | 1 + app/view/domain/record.html | 7 +- route/app.php | 1 + 14 files changed, 313 insertions(+), 21 deletions(-) create mode 100644 app/view/domain/alias.html diff --git a/app/common.php b/app/common.php index 9828954..c87ae35 100644 --- a/app/common.php +++ b/app/common.php @@ -302,10 +302,12 @@ function getMainDomain($host) $domains = config('temp.domains'); if (!$domains) { $domains = Db::name('domain')->column('name'); + $domains_alias = Db::name('domain_alias')->column('name'); + $domains = array_merge($domains, $domains_alias); config(['domains'=>$domains], 'temp'); } foreach ($domains as $domain) { - if (str_ends_with($host, $domain)) { + if ($host === $domain || str_ends_with($host, '.' . $domain)) { return $domain; } } diff --git a/app/controller/Cert.php b/app/controller/Cert.php index 1693395..451d70d 100644 --- a/app/controller/Cert.php +++ b/app/controller/Cert.php @@ -505,9 +505,12 @@ class Cert extends BaseController $mainDomain = getMainDomain($domain); $drow = Db::name('domain')->where('name', $mainDomain)->find(); if (!$drow) { - if (substr($domain, 0, 2) == '*.') $domain = substr($domain, 2); - if (!$cname || !Db::name('cert_cname')->where('domain', $domain)->where('status', 1)->find()) { - return ['code' => -1, 'msg' => '域名' . $domain . '未在本系统添加']; + $drow = Db::name('domain_alias')->alias('A')->join('domain B', 'A.did = B.id')->where('A.name', $mainDomain)->find(); + if (!$drow) { + if (substr($domain, 0, 2) == '*.') $domain = substr($domain, 2); + if (!$cname || !Db::name('cert_cname')->where('domain', $domain)->where('status', 1)->find()) { + return ['code' => -1, 'msg' => '域名' . $domain . '未在本系统添加']; + } } } } diff --git a/app/controller/Domain.php b/app/controller/Domain.php index 7bb3381..c5fdd74 100644 --- a/app/controller/Domain.php +++ b/app/controller/Domain.php @@ -305,6 +305,7 @@ class Domain extends BaseController if (!checkPermission(2)) return $this->alert('error', '无权限'); $id = input('post.id/d'); Db::name('domain')->where('id', $id)->delete(); + Db::name('domain_alias')->where('did', $id)->delete(); Db::name('dmtask')->where('did', $id)->delete(); Db::name('optimizeip')->where('did', $id)->delete(); Db::name('sctask')->where('did', $id)->delete(); @@ -1106,8 +1107,87 @@ class Domain extends BaseController $dns = DnsHelper::getModel($drow['aid'], $drow['name'], $drow['thirdid']); $domainRecords = $dns->getWeightSubDomains($page, $limit, $keyword); + if (!$domainRecords) return json(['total' => 0, 'rows' => []]); return json(['total' => $domainRecords['total'], 'rows' => $domainRecords['list']]); } + + public function alias() + { + $id = input('param.id/d'); + $drow = Db::name('domain')->where('id', $id)->find(); + if (!$drow) { + return $this->alert('error', '域名不存在'); + } + if (!checkPermission(0, $drow['name'])) return $this->alert('error', '无权限'); + if (request()->isAjax()) { + $act = input('param.act'); + if ($act == 'add') { + $alias = input('post.alias', null, 'trim'); + if (empty($alias)) { + return json(['code' => -1, 'msg' => '参数不能为空']); + } + $dns = DnsHelper::getModel($drow['aid'], $drow['name'], $drow['thirdid']); + if ($dns->addDomainAlias($alias)) { + return json(['code' => 0, 'msg' => '添加域名别名成功']); + } else { + return json(['code' => -1, 'msg' => '添加域名别名失败,' . $dns->getError()]); + } + } elseif ($act == 'delete') { + $alias_id = input('post.alias_id/d'); + if (empty($alias_id)) { + return json(['code' => -1, 'msg' => '参数不能为空']); + } + $dns = DnsHelper::getModel($drow['aid'], $drow['name'], $drow['thirdid']); + if ($dns->deleteDomainAlias($alias_id)) { + return json(['code' => 0, 'msg' => '删除域名别名成功']); + } else { + return json(['code' => -1, 'msg' => '删除域名别名失败,' . $dns->getError()]); + } + } + } + + $dns = DnsHelper::getModel($drow['aid'], $drow['name'], $drow['thirdid']); + $domainAliasList = $dns->domainAliasList() ?? []; + + $this->updateAliasList($id, $domainAliasList); + + View::assign('domainId', $id); + View::assign('domainName', $drow['name']); + View::assign('domainAliasList', $domainAliasList); + return view(); + } + + private function updateAliasList($id, $domainAliasList) + { + $domainAliases = array_column($domainAliasList, 'DomainAlias'); + $addList = []; + $deleteList = []; + $existList = Db::name('domain_alias')->where('did', $id)->select()->toArray(); + $existAliases = array_column($existList, 'name'); + foreach ($existList as $item) { + if (!in_array($item['name'], $domainAliases)) { + $deleteList[] = $item['id']; + } + } + foreach ($domainAliases as $item) { + if (!in_array($item, $existAliases)) { + $addList[] = $item; + } + } + if (!empty($deleteList)) { + Db::name('domain_alias')->where('id', 'in', $deleteList)->delete(); + } + if (!empty($addList)) { + $dataList = []; + foreach ($addList as $item) { + $dataList[] = [ + 'did' => $id, + 'name' => $item, + ]; + } + Db::name('domain_alias')->insertAll($dataList); + } + } public function expire_notice() { diff --git a/app/lib/deploy/aliyun.php b/app/lib/deploy/aliyun.php index 901c2e9..18b1954 100644 --- a/app/lib/deploy/aliyun.php +++ b/app/lib/deploy/aliyun.php @@ -66,11 +66,11 @@ class aliyun implements DeployInterface $this->deploy_alb($cert_id, $config); } elseif ($config['product'] == 'nlb') { $this->deploy_nlb($cert_id, $config); - } elseif($config['product'] == 'esa_saas'){ + } elseif ($config['product'] == 'esa_saas') { $this->deploy_esa_saas($cert_id, $config); } elseif ($config['product'] == 'ga') { $this->deploy_ga($cert_id, $config); - }elseif ($config['product'] == 'upload') { + } elseif ($config['product'] == 'upload') { } else { throw new Exception('未知的产品类型'); } @@ -196,7 +196,7 @@ class aliyun implements DeployInterface $this->log('成功查询到' . $data['TotalCount'] . '个ESA站点'); $site_id = $data['Sites'][0]['SiteId']; // 查询对应的saas域名 - $param =[ + $param = [ 'Action' => 'ListCustomHostnames', 'SiteName' => $saas_sitename, 'SiteId' => $site_id, @@ -212,18 +212,18 @@ class aliyun implements DeployInterface $param = [ 'Action' => 'UpdateCustomHostname', - 'HostnameId'=> $saas_hostname_id, + 'HostnameId' => $saas_hostname_id, 'SslFlag' => 'on', 'CertType' => 'cas', 'CasId' => $cas_id, 'CasRegion' => $config['region'], ]; $this->log('ESA SAAS站点部署参数 ' . json_encode($param)); - try{ + try { $saas_deploy_result = $client->request($param); $this->log('ESA SAAS站点部署结果 ' . json_encode($saas_deploy_result)); - }catch(Exception $e){ - throw new Exception('部署失败:' . $e->getMessage()); + } catch (Exception $e) { + throw new Exception('部署失败:' . $e->getMessage()); } $this->log('ESA SAAS站点 ' . $saas_sitename . ' 证书添加成功!'); } diff --git a/app/lib/dns/dnspod.php b/app/lib/dns/dnspod.php index a2ef75c..61eee98 100644 --- a/app/lib/dns/dnspod.php +++ b/app/lib/dns/dnspod.php @@ -327,6 +327,44 @@ class dnspod implements DnsInterface return false; } + //域名别名列表 + public function domainAliasList() + { + $action = 'DescribeDomainAliasList'; + $param = [ + 'Domain' => $this->domain, + ]; + $data = $this->send_request($action, $param); + if ($data) { + return $data['DomainAliasList']; + } + return false; + } + + //添加域名别名 + public function addDomainAlias($alias) + { + $action = 'CreateDomainAlias'; + $param = [ + 'Domain' => $this->domain, + 'DomainAlias' => $alias, + ]; + $data = $this->send_request($action, $param); + return is_array($data); + } + + //删除域名别名 + public function deleteDomainAlias($id) + { + $action = 'DeleteDomainAlias'; + $param = [ + 'Domain' => $this->domain, + 'DomainAliasId' => $id, + ]; + $data = $this->send_request($action, $param); + return is_array($data); + } + private function convertLineCode($line) { $convert_dict = ['default' => '0', 'unicom' => '10=1', 'telecom' => '10=0', 'mobile' => '10=3', 'edu' => '10=2', 'oversea' => '3=0', 'btvn' => '10=22', 'search' => '80=0', 'internal' => '7=0']; diff --git a/app/lib/dns/huawei.php b/app/lib/dns/huawei.php index 0d55884..812b68b 100644 --- a/app/lib/dns/huawei.php +++ b/app/lib/dns/huawei.php @@ -79,7 +79,6 @@ class huawei implements DnsInterface foreach ($data['recordsets'] as $row) { $name = substr($row['name'], 0, -(strlen($row['zone_name']) + 1)); if ($name == '') $name = '@'; - if ($row['type'] == 'MX') list($row['mx'], $row['records']) = explode(' ', $row['records'][0]); $list[] = [ 'RecordId' => $row['id'], 'Domain' => rtrim($row['zone_name'], '.'), @@ -113,7 +112,6 @@ class huawei implements DnsInterface if ($data) { $name = substr($data['name'], 0, -(strlen($data['zone_name']) + 1)); if ($name == '') $name = '@'; - if ($data['type'] == 'MX') list($data['mx'], $data['records']) = explode(' ', $data['records'][0]); return [ 'RecordId' => $data['id'], 'Domain' => rtrim($data['zone_name'], '.'), @@ -139,7 +137,6 @@ class huawei implements DnsInterface if ($Type == 'TXT' && substr($Value, 0, 1) != '"') $Value = '"' . $Value . '"'; $records = array_reverse(explode(',', $Value)); $params = ['name' => $Name, 'type' => $this->convertType($Type), 'records' => $records, 'line' => $Line, 'ttl' => intval($TTL), 'description' => $Remark]; - if ($Type == 'MX') $params['records'][0] = intval($MX) . ' ' . $Value; if ($Weight > 0) $params['weight'] = intval($Weight); $data = $this->send_request('POST', '/v2.1/zones/'.$this->domainid.'/recordsets', null, $params); return is_array($data) ? $data['id'] : false; @@ -152,7 +149,6 @@ class huawei implements DnsInterface if ($Type == 'TXT' && substr($Value, 0, 1) != '"') $Value = '"' . $Value . '"'; $records = array_reverse(explode(',', $Value)); $params = ['name' => $Name, 'type' => $this->convertType($Type), 'records' => $records, 'line' => $Line, 'ttl' => intval($TTL), 'description' => $Remark]; - if ($Type == 'MX') $params['records'][0] = intval($MX) . ' ' . $Value; if ($Weight > 0) $params['weight'] = intval($Weight); $data = $this->send_request('PUT', '/v2.1/zones/'.$this->domainid.'/recordsets/'.$RecordId, null, $params); return is_array($data); diff --git a/app/service/CertDeployService.php b/app/service/CertDeployService.php index 275f165..f5da0f2 100644 --- a/app/service/CertDeployService.php +++ b/app/service/CertDeployService.php @@ -99,7 +99,7 @@ class CertDeployService if (!empty($error) && strlen($error) > 300) { $error = mb_strcut($error, 0, 300); } - $update = ['status' => $status, 'error' => $error, 'retrytime' => $retrytime]; + $update = ['status' => $status, 'error' => $error ? str_replace(["\r", "\n"], '', $error) : null, 'retrytime' => $retrytime]; if ($status == 1){ $update['retry'] = 0; $update['lasttime'] = date('Y-m-d H:i:s'); diff --git a/app/service/CertOrderService.php b/app/service/CertOrderService.php index 0935ec4..4c7ddd1 100644 --- a/app/service/CertOrderService.php +++ b/app/service/CertOrderService.php @@ -22,6 +22,7 @@ class CertOrderService private $dnsList; private $domainList; private $cnameDomainList = []; + private $domainsAliasList = []; // 订单状态:0:待提交 1:待验证 2:正在验证 3:已签发 4:已吊销 -1:购买证书失败 -2:创建订单失败 -3:添加DNS失败 -4:验证DNS失败 -5:验证订单失败 -6:订单验证未通过 -7:签发证书失败 public function __construct($oid) @@ -72,6 +73,12 @@ class CertOrderService if (!$drow && preg_match('/^xn--/', $mainDomain)) { $drow = Db::name('domain')->where('name', idn_to_utf8($mainDomain))->find(); } + if (!$drow) { + $drow = Db::name('domain_alias')->alias('A')->join('domain B', 'A.did = B.id')->where('A.name', $mainDomain)->field('A.name as alias,B.name as maindomain')->find(); + if ($drow) { + $this->domainsAliasList[$drow['alias']] = $drow['maindomain']; + } + } if (!$drow) { if (substr($domain, 0, 2) == '*.') $domain = substr($domain, 2); $cname_row = Db::name('cert_cname')->where('domain', $domain)->where('status', 1)->find(); @@ -181,7 +188,7 @@ class CertOrderService if (!empty($error) && strlen($error) > 300) { $error = mb_strcut($error, 0, 300); } - $update = ['status' => $status, 'error' => $error, 'updatetime' => date('Y-m-d H:i:s'), 'retrytime' => $retrytime]; + $update = ['status' => $status, 'error' => $error ? str_replace(["\r", "\n"], '', $error) : null, 'updatetime' => date('Y-m-d H:i:s'), 'retrytime' => $retrytime]; $res = Db::name('cert_order')->where('id', $this->order['id'])->data($update); if ($status < 0 || $retrytime) { $this->order['retry']++; @@ -261,6 +268,18 @@ class CertOrderService $this->saveResult(-2, $e->getMessage()); throw $e; } + + foreach ($this->domainsAliasList as $alias => $mainDomain) { + if (isset($this->dnsList[$alias])) { + if (!isset($this->dnsList[$mainDomain])) { + $this->dnsList[$mainDomain] = $this->dnsList[$alias]; + } else { + $this->dnsList[$mainDomain] = array_merge($this->dnsList[$mainDomain], $this->dnsList[$alias]); + } + unset($this->dnsList[$alias]); + } + } + Db::name('cert_order')->where('id', $this->order['id'])->update(['info' => json_encode($this->info), 'dns' => json_encode($this->dnsList)]); if (!empty($this->dnsList)) { diff --git a/app/sql/install.sql b/app/sql/install.sql index b37415d..37dd8c9 100644 --- a/app/sql/install.sql +++ b/app/sql/install.sql @@ -251,4 +251,14 @@ CREATE TABLE `dnsmgr_sctask` ( `remark` varchar(100) DEFAULT NULL, PRIMARY KEY (`id`), KEY `did` (`did`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +DROP TABLE IF EXISTS `dnsmgr_domain_alias`; +CREATE TABLE `dnsmgr_domain_alias` ( + `id` int(11) unsigned NOT NULL auto_increment, + `did` int(11) unsigned NOT NULL, + `name` varchar(255) NOT NULL, + PRIMARY KEY (`id`), + KEY `did` (`did`), + KEY `name` (`name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; \ No newline at end of file diff --git a/app/sql/update.sql b/app/sql/update.sql index b69eda9..69ce7f3 100644 --- a/app/sql/update.sql +++ b/app/sql/update.sql @@ -189,4 +189,13 @@ CREATE TABLE IF NOT EXISTS `dnsmgr_sctask` ( ALTER TABLE `dnsmgr_account` ADD COLUMN `config` text DEFAULT NULL, -CHANGE COLUMN `ak` `name` varchar(255) NOT NULL; \ No newline at end of file +CHANGE COLUMN `ak` `name` varchar(255) NOT NULL; + +CREATE TABLE IF NOT EXISTS `dnsmgr_domain_alias` ( + `id` int(11) unsigned NOT NULL auto_increment, + `did` int(11) unsigned NOT NULL, + `name` varchar(255) NOT NULL, + PRIMARY KEY (`id`), + KEY `did` (`did`), + KEY `name` (`name`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; \ No newline at end of file diff --git a/app/view/domain/alias.html b/app/view/domain/alias.html new file mode 100644 index 0000000..59ed41b --- /dev/null +++ b/app/view/domain/alias.html @@ -0,0 +1,132 @@ +{extend name="common/layout" /} +{block name="title"}域名别名 - {$domainName}{/block} +{block name="main"} + +
+
+
+

返回域名别名 - {$domainName}

+
+ +
+ 域名别名使用完全相同的解析记录,免除重复操作,仅支持专业版及以上套餐 +
+ +
+
+ +
+ +
+ +
+ + + + + + + + + + + {volist name="domainAliasList" id="item"} + + + + + + {/volist} + {empty name="domainAliasList"} + + {/empty} + +
域名别名域名状态操作
{$item.DomainAlias} + {if isset($item.Status)} + {if $item.Status == '2'} + 正常 + {elseif $item.Status == '3'} + 封禁 + {else/} + DNS不正确 + {/if} + {else/} + - + {/if} + + 删除 +
暂无域名别名
+
+
+
+
+{/block} +{block name="script"} + + + +{/block} diff --git a/app/view/domain/domain_add.html b/app/view/domain/domain_add.html index 854f194..27e2b04 100644 --- a/app/view/domain/domain_add.html +++ b/app/view/domain/domain_add.html @@ -95,6 +95,7 @@ new Vue({ }, async getDomainList(){ this.domainList = []; + this.page = 1; while(true){ try{ layer.msg('正在获取第'+this.page+'页域名', {icon: 16, shade: 0.01}); diff --git a/app/view/domain/record.html b/app/view/domain/record.html index e013e5d..a0fa50c 100644 --- a/app/view/domain/record.html +++ b/app/view/domain/record.html @@ -55,12 +55,12 @@ td{overflow: hidden;text-overflow: ellipsis;white-space: nowrap;max-width:360px; - {/if}
@@ -184,6 +184,7 @@ td{overflow: hidden;text-overflow: ellipsis;white-space: nowrap;max-width:360px; 刷新 添加记录 {if $dnsconfig.type=='aliyun'}权重配置{/if} + {if $dnsconfig.type=='dnspod'}域名别名{/if}
@@ -291,7 +292,7 @@ $(document).ready(function(){ title: '记录值', formatter: function(value, row, index) { var copyId = 'copy-value-' + row.RecordId; - if(row.Type == 'MX') { + if(row.Type == 'MX' && dnsconfig.type!='huawei') { return ''+value+'' + '' + ' | '+row.MX+''; diff --git a/route/app.php b/route/app.php index 09efa14..d549a1b 100644 --- a/route/app.php +++ b/route/app.php @@ -74,6 +74,7 @@ Route::group(function () { Route::post('/record/list', 'domain/record_list'); Route::post('/record/weight/data/:id', 'domain/weight_data'); Route::any('/record/weight/:id', 'domain/weight'); + Route::any('/record/alias/:id', 'domain/alias'); Route::get('/record/:id', 'domain/record'); Route::get('/dmonitor/overview', 'dmonitor/overview');