diff --git a/app/controller/Cert.php b/app/controller/Cert.php index bea1528..9838479 100644 --- a/app/controller/Cert.php +++ b/app/controller/Cert.php @@ -43,8 +43,17 @@ class Cert extends BaseController $list = []; foreach ($rows as $row) { - $row['typename'] = $deploy == 1 ? DeployHelper::$deploy_config[$row['type']]['name'] : CertHelper::$cert_config[$row['type']]['name']; - $row['icon'] = $deploy == 1 ? DeployHelper::$deploy_config[$row['type']]['icon'] : CertHelper::$cert_config[$row['type']]['icon']; + if ($deploy == 1) { + if (!empty($row['type']) && isset(DeployHelper::$deploy_config[$row['type']])) { + $row['typename'] = DeployHelper::$deploy_config[$row['type']]['name']; + $row['icon'] = DeployHelper::$deploy_config[$row['type']]['icon']; + } + } else { + if (!empty($row['type']) && isset(CertHelper::$cert_config[$row['type']])) { + $row['typename'] = CertHelper::$cert_config[$row['type']]['name']; + $row['icon'] = CertHelper::$cert_config[$row['type']]['icon']; + } + } $list[] = $row; } @@ -202,6 +211,7 @@ class Cert extends BaseController if (!checkPermission(2)) return $this->alert('error', '无权限'); $domain = $this->request->post('domain', null, 'trim'); $id = input('post.id'); + $aid = input('post.aid', null, 'trim'); $type = input('post.type', null, 'trim'); $status = input('post.status', null, 'trim'); $offset = input('post.offset/d'); @@ -214,6 +224,9 @@ class Cert extends BaseController $oids = Db::name('cert_domain')->where('domain', 'like', '%' . $domain . '%')->column('oid'); $select->whereIn('A.id', $oids); } + if (!empty($aid)) { + $select->where('A.aid', $aid); + } if (!empty($type)) { $select->where('B.type', $type); } @@ -233,7 +246,7 @@ class Cert extends BaseController $list = []; foreach ($rows as $row) { - if (!empty($row['type'])) { + if (!empty($row['type']) && isset(CertHelper::$cert_config[$row['type']])) { $row['typename'] = CertHelper::$cert_config[$row['type']]['name']; $row['icon'] = CertHelper::$cert_config[$row['type']]['icon']; } else { @@ -599,6 +612,7 @@ class Cert extends BaseController $accounts = []; foreach (Db::name('cert_account')->where('deploy', 0)->select() as $row) { + if (empty($row['type']) || !isset(CertHelper::$cert_config[$row['type']])) continue; $accounts[$row['id']] = ['name' => $row['id'] . '_' . CertHelper::$cert_config[$row['type']]['name'], 'type' => $row['type']]; if (!empty($row['remark'])) { $accounts[$row['id']]['name'] .= '(' . $row['remark'] . ')'; @@ -627,19 +641,23 @@ class Cert extends BaseController if (!checkPermission(2)) return $this->alert('error', '无权限'); $domain = $this->request->post('domain', null, 'trim'); $oid = input('post.oid'); + $aid = input('post.aid', null, 'trim'); $type = input('post.type', null, 'trim'); $status = input('post.status', null, 'trim'); $remark = input('post.remark', null, 'trim'); $offset = input('post.offset/d'); $limit = input('post.limit/d'); - $select = Db::name('cert_deploy')->alias('A')->join('cert_account B', 'A.aid = B.id')->join('cert_order C', 'A.oid = C.id')->join('cert_account D', 'C.aid = D.id'); + $select = Db::name('cert_deploy')->alias('A')->leftJoin('cert_account B', 'A.aid = B.id')->leftJoin('cert_order C', 'A.oid = C.id')->leftJoin('cert_account D', 'C.aid = D.id'); if (!empty($oid)) { $select->where('A.oid', $oid); } elseif (!empty($domain)) { $oids = Db::name('cert_domain')->where('domain', 'like', '%' . $domain . '%')->column('oid'); $select->whereIn('oid', $oids); } + if (!empty($aid)) { + $select->where('A.aid', $aid); + } if (!empty($type)) { $select->where('B.type', $type); } @@ -654,9 +672,15 @@ class Cert extends BaseController $list = []; foreach ($rows as $row) { - $row['typename'] = DeployHelper::$deploy_config[$row['type']]['name']; - $row['icon'] = DeployHelper::$deploy_config[$row['type']]['icon']; - $row['certtypename'] = CertHelper::$cert_config[$row['certtype']]['name']; + if (!empty($row['type']) && isset(DeployHelper::$deploy_config[$row['type']])) { + $row['typename'] = DeployHelper::$deploy_config[$row['type']]['name']; + $row['icon'] = DeployHelper::$deploy_config[$row['type']]['icon']; + } + if (!empty($row['certtype']) && isset(CertHelper::$cert_config[$row['certtype']])) { + $row['certtypename'] = CertHelper::$cert_config[$row['certtype']]['name']; + } else { + $row['certtypename'] = '手动续期'; + } $row['domains'] = Db::name('cert_domain')->where('oid', $row['oid'])->order('sort', 'ASC')->column('domain'); if ($row['error']) $row['error'] = htmlspecialchars(str_replace("'", "\\'", $row['error'])); $list[] = $row; @@ -782,6 +806,7 @@ class Cert extends BaseController $accounts = []; foreach (Db::name('cert_account')->where('deploy', 1)->select() as $row) { + if (empty($row['type']) || !isset(DeployHelper::$deploy_config[$row['type']])) continue; $accounts[$row['id']] = ['name' => $row['id'] . '_' . DeployHelper::$deploy_config[$row['type']]['name'], 'type' => $row['type']]; if (!empty($row['remark'])) { $accounts[$row['id']]['name'] .= '(' . $row['remark'] . ')'; @@ -790,10 +815,15 @@ class Cert extends BaseController View::assign('accounts', $accounts); $orders = []; - foreach (Db::name('cert_order')->alias('A')->join('cert_account B', 'A.aid = B.id')->where('status', '<>', 4)->fieldRaw('A.id,A.aid,B.type,B.remark aremark')->order('id', 'desc')->select() as $row) { + foreach (Db::name('cert_order')->alias('A')->leftJoin('cert_account B', 'A.aid = B.id')->where('status', '<>', 4)->fieldRaw('A.id,A.aid,B.type,B.remark aremark')->order('id', 'desc')->select() as $row) { $domains = Db::name('cert_domain')->where('oid', $row['id'])->order('sort', 'ASC')->column('domain'); $domainstr = count($domains) > 2 ? implode('、', array_slice($domains, 0, 2)) . '等' . count($domains) . '个域名' : implode('、', $domains); - $orders[$row['id']] = ['name' => $row['id'] . '_' . $domainstr . '(' . CertHelper::$cert_config[$row['type']]['name'] . ')']; + if ($row['aid'] == 0) { + $name = $row['id'] . '_' . $domainstr . '(手动续期)'; + } else { + $name = $row['id'] . '_' . $domainstr . '(' . CertHelper::$cert_config[$row['type']]['name'] . ')'; + } + $orders[$row['id']] = ['name' => $name]; } View::assign('orders', $orders); @@ -821,7 +851,7 @@ class Cert extends BaseController $offset = input('post.offset/d'); $limit = input('post.limit/d'); - $select = Db::name('cert_cname')->alias('A')->join('domain B', 'A.did = B.id'); + $select = Db::name('cert_cname')->alias('A')->leftJoin('domain B', 'A.did = B.id'); if (!empty($kw)) { $select->whereLike('A.domain', '%' . $kw . '%'); } diff --git a/app/lib/CertHelper.php b/app/lib/CertHelper.php index d2522ed..fa8f3ca 100644 --- a/app/lib/CertHelper.php +++ b/app/lib/CertHelper.php @@ -177,7 +177,7 @@ location / { 'tencent' => [ 'name' => '腾讯云免费SSL', 'class' => 2, - 'icon' => 'tencent.ico', + 'icon' => 'tencent.png', 'wildcard' => false, 'max_domains' => 1, 'cname' => false, @@ -215,7 +215,7 @@ location / { 'aliyun' => [ 'name' => '阿里云免费SSL', 'class' => 2, - 'icon' => 'aliyun.ico', + 'icon' => 'aliyun.png', 'wildcard' => false, 'max_domains' => 1, 'cname' => false, diff --git a/app/lib/DeployHelper.php b/app/lib/DeployHelper.php index 20698df..363afc9 100644 --- a/app/lib/DeployHelper.php +++ b/app/lib/DeployHelper.php @@ -10,7 +10,8 @@ class DeployHelper 'btpanel' => [ 'name' => '宝塔面板', 'class' => 1, - 'icon' => 'bt.ico', + 'icon' => 'bt.png', + 'desc' => '支持部署到宝塔面板搭建的站点、Docker、邮局与面板本身', 'note' => null, 'inputs' => [ 'url' => [ @@ -63,6 +64,7 @@ class DeployHelper 'name' => 'Kangle用户', 'class' => 1, 'icon' => 'host.png', + 'desc' => '支持虚拟主机与CDN站点', 'note' => '以上登录信息为Easypanel用户面板的,非管理员面板。如选网站密码认证类型,则用户面板登录不能开启验证码。', 'inputs' => [ 'url' => [ @@ -136,6 +138,7 @@ class DeployHelper 'name' => 'Kangle管理员', 'class' => 1, 'icon' => 'host.png', + 'desc' => '支持虚拟主机与CDN站点', 'note' => '以上登录地址需填写Easypanel管理员面板地址,非用户面板。', 'inputs' => [ 'url' => [ @@ -202,6 +205,7 @@ class DeployHelper 'name' => '雷池WAF', 'class' => 1, 'icon' => 'safeline.png', + 'desc' => '', 'note' => null, 'tasknote' => '系统会根据关联SSL证书的域名,自动更新对应证书', 'inputs' => [ @@ -233,7 +237,8 @@ class DeployHelper 'btwaf' => [ 'name' => '堡塔云WAF', 'class' => 1, - 'icon' => 'bt.ico', + 'icon' => 'bt.png', + 'desc' => '', 'note' => null, 'tasknote' => '', 'inputs' => [ @@ -273,6 +278,7 @@ class DeployHelper 'name' => 'Cdnfly', 'class' => 1, 'icon' => 'waf.png', + 'desc' => '', 'note' => '登录Cdnfly控制台->账户中心->API密钥,点击开启后获取', 'inputs' => [ 'url' => [ @@ -318,6 +324,7 @@ class DeployHelper 'name' => 'LeCDN', 'class' => 1, 'icon' => 'waf.png', + 'desc' => '', 'note' => null, 'inputs' => [ 'url' => [ @@ -363,6 +370,7 @@ class DeployHelper 'name' => 'GoEdge', 'class' => 1, 'icon' => 'waf.png', + 'desc' => '', 'note' => '需要先开启HTTP API端口', 'tasknote' => '系统会根据关联SSL证书的域名,自动更新对应证书', 'inputs' => [ @@ -421,6 +429,7 @@ class DeployHelper 'name' => '1Panel', 'class' => 1, 'icon' => 'opanel.png', + 'desc' => '更新面板证书管理内的SSL证书', 'note' => null, 'tasknote' => '系统会根据关联SSL证书的域名,自动更新对应证书', 'inputs' => [ @@ -463,6 +472,7 @@ class DeployHelper 'name' => 'MW面板', 'class' => 1, 'icon' => 'mwpanel.ico', + 'desc' => '', 'note' => null, 'tasknote' => '', 'inputs' => [ @@ -520,6 +530,7 @@ class DeployHelper 'name' => '耗子面板', 'class' => 1, 'icon' => 'ratpanel.ico', + 'desc' => '支持耗子面板 v2.5+ 版本使用', 'note' => '支持耗子面板 v2.5+ 版本使用', 'inputs' => [ 'url' => [ @@ -578,6 +589,7 @@ class DeployHelper 'name' => '群晖面板', 'class' => 1, 'icon' => 'synology.png', + 'desc' => '支持群晖DSM 6.x/7.x版本', 'note' => null, 'tasknote' => '', 'inputs' => [ @@ -633,6 +645,7 @@ class DeployHelper 'name' => 'Proxmox VE', 'class' => 1, 'icon' => 'proxmox.ico', + 'desc' => '部署到PVE节点', 'note' => '在“权限->API令牌”添加令牌,不要选特权分离', 'tasknote' => '', 'inputs' => [ @@ -677,8 +690,9 @@ class DeployHelper 'aliyun' => [ 'name' => '阿里云', 'class' => 2, - 'icon' => 'aliyun.ico', - 'note' => '支持部署到阿里云CDN、ESA、SLB、OSS、WAF等服务', + 'icon' => 'aliyun.png', + 'desc' => '支持部署到阿里云CDN、ESA、SLB、OSS、WAF、FC等服务', + 'note' => '支持部署到阿里云CDN、ESA、SLB、OSS、WAF、FC等服务', 'tasknote' => '', 'inputs' => [ 'AccessKeyId' => [ @@ -824,7 +838,8 @@ class DeployHelper 'tencent' => [ 'name' => '腾讯云', 'class' => 2, - 'icon' => 'tencent.ico', + 'icon' => 'tencent.png', + 'desc' => '支持部署到腾讯云CDN、EO、CLB、COS、TKE、SCF等服务', 'note' => '支持部署到腾讯云CDN、EO、CLB、COS、TKE、SCF等服务', 'tasknote' => '', 'inputs' => [ @@ -959,6 +974,7 @@ class DeployHelper 'name' => '华为云', 'class' => 2, 'icon' => 'huawei.ico', + 'desc' => '支持部署到华为云CDN、ELB、WAF等服务', 'note' => '支持部署到华为云CDN、ELB、WAF等服务', 'inputs' => [ 'AccessKeyId' => [ @@ -1031,6 +1047,7 @@ class DeployHelper 'name' => 'UCloud', 'class' => 2, 'icon' => 'ucloud.ico', + 'desc' => '支持部署到UCDN', 'note' => '支持部署到UCDN', 'inputs' => [ 'PublicKey' => [ @@ -1060,6 +1077,7 @@ class DeployHelper 'name' => '七牛云', 'class' => 2, 'icon' => 'qiniu.ico', + 'desc' => '支持部署到七牛云CDN、OSS', 'note' => '支持部署到七牛云CDN、OSS', 'inputs' => [ 'AccessKey' => [ @@ -1115,6 +1133,7 @@ class DeployHelper 'name' => '多吉云', 'class' => 2, 'icon' => 'cloud.png', + 'desc' => '支持部署到多吉云融合CDN', 'note' => '支持部署到多吉云融合CDN', 'inputs' => [ 'AccessKey' => [ @@ -1152,6 +1171,8 @@ class DeployHelper 'name' => '又拍云', 'class' => 2, 'icon' => 'upyun.ico', + 'desc' => '支持部署到又拍云CDN', + 'note' => '支持部署到又拍云CDN', 'tasknote' => '系统会根据关联SSL证书的域名,进行证书的迁移操作', 'inputs' => [ 'username' => [ @@ -1181,6 +1202,7 @@ class DeployHelper 'name' => '百度云', 'class' => 2, 'icon' => 'baidu.ico', + 'desc' => '支持部署到百度云CDN', 'note' => '支持部署到百度云CDN', 'inputs' => [ 'AccessKeyId' => [ @@ -1218,6 +1240,7 @@ class DeployHelper 'name' => '火山引擎', 'class' => 2, 'icon' => 'huoshan.ico', + 'desc' => '支持部署到火山引擎CDN', 'note' => '支持部署到火山引擎CDN', 'inputs' => [ 'AccessKeyId' => [ @@ -1285,6 +1308,7 @@ class DeployHelper 'name' => '西部数码', 'class' => 2, 'icon' => 'west.ico', + 'desc' => '支持部署到西部数码虚拟主机', 'note' => '支持部署到西部数码虚拟主机', 'inputs' => [ 'username' => [ @@ -1322,6 +1346,7 @@ class DeployHelper 'name' => '网宿科技', 'class' => 2, 'icon' => 'wangsu.ico', + 'desc' => '支持部署到网宿CDN', 'note' => '适用产品:网页加速、下载分发、全站加速、点播分发、直播分发、上传加速、移动加速、上网加速、S-P2P、PCDN、应用性能管理、WEB应用防火墙、BotGuard爬虫管理、WSS、DMS、DDoS云清洗、应用加速、应用安全加速解决方案、IPv6一体化解决方案、电商安全加速解决方案、金融安全加速解决方案、政企安全加速解决方案、DDoS云清洗(非网站业务)、区块链安全加速解决方案、IPv6安全加速解决方案、CDN Pro。暂不支持AKSK鉴权。', 'inputs' => [ 'username' => [ @@ -1390,6 +1415,7 @@ class DeployHelper 'name' => '白山云', 'class' => 2, 'icon' => 'waf.png', + 'desc' => '替换白山云证书管理内的证书', 'note' => null, 'inputs' => [ 'account' => [ @@ -1429,7 +1455,8 @@ class DeployHelper 'name' => '天翼云', 'class' => 2, 'icon' => 'ctyun.ico', - 'note' => '支持部署到天翼云CDN', + 'desc' => '支持部署到天翼云CDN、边缘加速', + 'note' => '支持部署到天翼云CDN、边缘加速', 'inputs' => [ 'AccessKeyId' => [ 'name' => 'AccessKeyId', @@ -1477,6 +1504,7 @@ class DeployHelper 'name' => '括彩云', 'class' => 2, 'icon' => 'kuocai.jpg', + 'desc' => '替换括彩云证书管理内的证书', 'note' => '支持括彩云及其代理商,填写控制台登录账号及密码', 'inputs' => [ 'username' => [ @@ -1512,41 +1540,11 @@ class DeployHelper ], ], ], - 'allwaf' => [ - 'name' => 'AllWAF', - 'class' => 2, - 'icon' => 'waf.png', - 'note' => '在ALLWAF访问控制页面创建AccessKey', - 'tasknote' => '系统会根据关联SSL证书的域名,自动更新对应证书', - 'inputs' => [ - 'accessKeyId' => [ - 'name' => 'AccessKey ID', - 'type' => 'input', - 'placeholder' => '', - 'required' => true, - ], - 'accessKey' => [ - 'name' => 'AccessKey密钥', - 'type' => 'input', - 'placeholder' => '', - 'required' => true, - ], - 'proxy' => [ - 'name' => '使用代理服务器', - 'type' => 'radio', - 'options' => [ - '0' => '否', - '1' => '是', - ], - 'value' => '0' - ], - ], - 'taskinputs' => [], - ], 'aws' => [ 'name' => 'AWS', 'class' => 2, - 'icon' => 'aws.ico', + 'icon' => 'aws.png', + 'desc' => '支持部署到Amazon CloudFront、AWS Certificate Manager', 'note' => '支持部署到Amazon CloudFront、AWS Certificate Manager', 'inputs' => [ 'AccessKeyId' => [ @@ -1603,6 +1601,7 @@ class DeployHelper 'name' => 'Gcore', 'class' => 2, 'icon' => 'gcore.ico', + 'desc' => '替换Gcore CDN证书', 'note' => '在 个人资料->API令牌 页面创建API令牌', 'inputs' => [ 'account' => [ @@ -1647,6 +1646,7 @@ class DeployHelper 'name' => 'Cachefly', 'class' => 2, 'icon' => 'cloud.png', + 'desc' => '替换Cachefly CDN证书', 'note' => '在 API Tokens 页面生成 API Token', 'inputs' => [ 'account' => [ @@ -1679,6 +1679,7 @@ class DeployHelper 'name' => 'SSH服务器', 'class' => 3, 'icon' => 'server.png', + 'desc' => '可通过SSH连接到Linux/Windows服务器并部署证书', 'note' => '可通过SSH连接到Linux/Windows服务器并部署证书,php需要安装ssh2扩展', 'tasknote' => '请确保路径存在且有写入权限,路径一定要以/开头(Windows路径请使用/代替\,且需要在最开头加/)', 'inputs' => [ @@ -1805,6 +1806,7 @@ class DeployHelper 'name' => 'FTP服务器', 'class' => 3, 'icon' => 'server.png', + 'desc' => '可将证书上传到FTP服务器', 'note' => '可将证书上传到FTP服务器,php需要安装ftp扩展', 'tasknote' => '请确保路径存在且有写入权限', 'inputs' => [ @@ -1888,6 +1890,7 @@ class DeployHelper 'name' => '复制到本机', 'class' => 3, 'icon' => 'server2.png', + 'desc' => '将证书复制到本机指定路径', 'note' => '将证书复制到本机指定路径', 'tasknote' => '请确保php进程有对证书保存路径的写入权限,宝塔面板需关闭防跨站攻击,如果当前是Docker运行的,则需要做目录映射到宿主机。', 'inputs' => [], diff --git a/app/lib/deploy/allwaf.php b/app/lib/deploy/allwaf.php deleted file mode 100644 index 8d7c82b..0000000 --- a/app/lib/deploy/allwaf.php +++ /dev/null @@ -1,146 +0,0 @@ -accessKeyId = $config['accessKeyId']; - $this->accessKey = $config['accessKey']; - $this->proxy = $config['proxy'] == 1; - } - - public function check() - { - if (empty($this->url) || empty($this->accessKeyId) || empty($this->accessKey)) throw new Exception('必填参数不能为空'); - $this->getAccessToken(); - } - - public function deploy($fullchain, $privatekey, $config, &$info) - { - $domains = $config['domainList']; - if (empty($domains)) throw new Exception('没有设置要部署的域名'); - - $this->getAccessToken(); - - $params = [ - 'domains' => $domains, - 'offset' => 0, - 'size' => 10, - ]; - try { - $data = $this->request('/SSLCertService/listSSLCerts', $params); - } catch (Exception $e) { - throw new Exception('获取证书列表失败:' . $e->getMessage()); - } - $list = json_decode(base64_decode($data['sslCertsJSON']), true); - if (!$list || empty($list)) { - throw new Exception('证书列表为空'); - } - $this->log('获取证书列表成功(total=' . count($list) . ')'); - - $certInfo = openssl_x509_parse($fullchain, true); - $cert_name = str_replace('*.', '', $certInfo['subject']['CN']) . '-' . $certInfo['validFrom_time_t']; - - if (!empty($list)) { - foreach ($list as $row) { - $params = [ - 'sslCertId' => $row['id'], - 'isOn' => true, - 'name' => $row['name'], - 'description' => $row['description'], - 'serverName' => $row['serverName'], - 'isCA' => false, - 'certData' => base64_encode($fullchain), - 'keyData' => base64_encode($privatekey), - 'timeBeginAt' => $certInfo['validFrom_time_t'], - 'timeEndAt' => $certInfo['validTo_time_t'], - 'dnsNames' => $domains, - 'commonNames' => [$certInfo['issuer']['CN']], - ]; - $this->request('/SSLCertService/updateSSLCert', $params); - $this->log('证书ID:' . $row['id'] . '更新成功!'); - } - } else { - $params = [ - 'isOn' => true, - 'name' => $cert_name, - 'description' => $cert_name, - 'serverName' => $certInfo['subject']['CN'], - 'isCA' => false, - 'certData' => base64_encode($fullchain), - 'keyData' => base64_encode($privatekey), - 'timeBeginAt' => $certInfo['validFrom_time_t'], - 'timeEndAt' => $certInfo['validTo_time_t'], - 'dnsNames' => $domains, - 'commonNames' => [$certInfo['issuer']['CN']], - ]; - $result = $this->request('/SSLCertService/createSSLCert', $params); - $this->log('证书ID:' . $result['sslCertId'] . '添加成功!'); - } - } - - private function getAccessToken() - { - $path = '/APIAccessTokenService/getAPIAccessToken'; - $params = [ - 'type' => $this->usertype, - 'accessKeyId' => $this->accessKeyId, - 'accessKey' => $this->accessKey, - ]; - $result = $this->request($path, $params); - if (isset($result['token'])) { - $this->accessToken = $result['token']; - } else { - throw new Exception('登录成功,获取AccessToken失败'); - } - } - - private function request($path, $params = null) - { - $url = $this->url . $path; - $headers = []; - $body = null; - if ($this->accessToken) { - $headers[] = 'X-Cloud-Access-Token: ' . $this->accessToken; - } - if ($params) { - $headers[] = 'Content-Type: application/json'; - $body = json_encode($params); - } - $response = curl_client($url, $body, null, null, $headers, $this->proxy); - $result = json_decode($response['body'], true); - if (isset($result['code']) && $result['code'] == 200) { - return isset($result['data']) ? $result['data'] : null; - } elseif (isset($result['message'])) { - throw new Exception($result['message']); - } else { - if (!empty($response['body'])) $this->log('Response:' . $response['body']); - throw new Exception('返回数据解析失败'); - } - } - - public function setLogger($func) - { - $this->logger = $func; - } - - private function log($txt) - { - if ($this->logger) { - call_user_func($this->logger, $txt); - } - } -} diff --git a/app/service/CertDeployService.php b/app/service/CertDeployService.php index 47c3a86..2791778 100644 --- a/app/service/CertDeployService.php +++ b/app/service/CertDeployService.php @@ -89,6 +89,9 @@ class CertDeployService private function saveResult($status, $error = null, $retrytime = null) { $this->task['status'] = $status; + if (mb_strlen($error) > 300) { + $error = mb_strcut($error, 0, 300); + } $update = ['status' => $status, 'error' => $error, 'retrytime' => $retrytime]; if ($status == 1){ $update['retry'] = 0; diff --git a/app/service/CertOrderService.php b/app/service/CertOrderService.php index d26a2eb..a136949 100644 --- a/app/service/CertOrderService.php +++ b/app/service/CertOrderService.php @@ -178,6 +178,9 @@ class CertOrderService private function saveResult($status, $error = null, $retrytime = null) { $this->order['status'] = $status; + if (mb_strlen($error) > 300) { + $error = mb_strcut($error, 0, 300); + } $update = ['status' => $status, 'error' => $error, '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) { diff --git a/app/view/cert/account_form.html b/app/view/cert/account_form.html index 752f88b..4a443b2 100644 --- a/app/view/cert/account_form.html +++ b/app/view/cert/account_form.html @@ -9,19 +9,104 @@ color: #f56c6c; margin-right: 4px; } +/* 账户类型卡片样式 */ +.account-type-container { + display: flex; + flex-wrap: wrap; + gap: 15px; + margin-bottom: 20px; +} +.account-type-category { + width: 100%; + margin-bottom: 10px; + font-size: 18px; + font-weight: bold; + color: #333; + border-bottom: 1px solid #eee; + padding-bottom: 5px; +} +.account-type-card { + width: calc(25% - 15px); + min-width: 200px; + padding: 10px; + border: 1px solid #ddd; + border-radius: 5px; + cursor: pointer; + transition: all 0.3s; + background: #fff; + height: 100px; + overflow: hidden; +} +.account-type-card:hover { + border-color: #409EFF; + box-shadow: 0 2px 12px 0 rgba(0,0,0,0.1); +} +.account-type-card .icon { + width: 30px; + margin: 11px 8px; + float: left; +} +.account-type-card .content { + margin-left: 38px; +} +.account-type-card .title { + font-size: 14px; + font-weight: bold; + margin-bottom: 3px; + color: #333; +} +.account-type-card .desc { + font-size: 12px; + color: #999; + line-height: 1.4; + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; + text-overflow: ellipsis; +} +@media (max-width: 768px) { + .account-type-card { + width: calc(50% - 15px); + } +} +@media (max-width: 480px) { + .account-type-card { + width: 100%; + } +}

返回{if $action=='edit'}编辑{else}添加{/if}{$title}

-
+ +
+
+ + +
+
+ + +
- +
+ {{ typeList[set.type].name }} + 重新选择 +
+
@@ -104,6 +189,7 @@ new Vue({ el: '#app', data: { action: '{$action}', + selectedType: false, set: { deploy: '{$deploy}', id: '', @@ -140,16 +226,24 @@ new Vue({ } } }, - mounted() { - this.typeOption = Object.keys(classList).map((key) => { - var tempList = []; - Object.keys(typeList).forEach((key2) => { - if(typeList[key2].class == key){ - tempList.push({label: typeList[key2].name, value: key2}) - } + computed: { + groupedTypes() { + return Object.keys(classList).map((key) => { + var tempList = []; + Object.keys(typeList).forEach((key2) => { + if(typeList[key2].class == key){ + tempList.push({label: typeList[key2].name, value: key2}) + } + }) + return {label: classList[key], types: tempList} }) - return {label: classList[key], children: tempList} - }) + } + }, + mounted() { + this.typeOption = this.groupedTypes; + if(this.action == 'edit') { + this.selectedType = true; + } if(this.action == 'edit'){ Object.keys(info).forEach((key) => { this.set[key] = info[key] @@ -181,6 +275,10 @@ new Vue({ }) }, methods: { + selectType(type) { + this.set.type = type; + this.selectedType = true; + }, submit(){ var that=this; Object.keys(this.config).forEach((key) => { @@ -235,4 +333,4 @@ new Vue({ }, }); -{/block} \ No newline at end of file +{/block} diff --git a/app/view/cert/certaccount.html b/app/view/cert/certaccount.html index dcfb725..3759a1e 100644 --- a/app/view/cert/certaccount.html +++ b/app/view/cert/certaccount.html @@ -68,7 +68,7 @@ $(document).ready(function(){ field: '', title: '操作', formatter: function(value, row, index) { - var html = '编辑 删除'; + var html = '编辑 删除 订单'; return html; } }, @@ -79,12 +79,12 @@ function delItem(id){ layer.confirm('确定要删除此账户吗?', { btn: ['确定','取消'] }, function(){ - $.post('/cert/account/del?deploy=0', {id: id}, function(data){ + $.post('/cert/account/del', {id: id, deploy: 0}, function(data){ if(data.code == 0) { layer.msg('删除成功', {icon: 1, time:800}); $('#listTable').bootstrapTable('refresh'); } else { - layer.msg(data.msg, {icon: 2}); + layer.alert(data.msg, {icon: 2}); } }, 'json'); }); diff --git a/app/view/cert/certorder.html b/app/view/cert/certorder.html index 6c11ea8..c6cdd82 100644 --- a/app/view/cert/certorder.html +++ b/app/view/cert/certorder.html @@ -16,6 +16,7 @@ pre.pre-log{height: 330px;overflow-y: auto;width: 100%;background-color: rgba(51 +
diff --git a/app/view/cert/deployaccount.html b/app/view/cert/deployaccount.html index a392d80..c7d1e0c 100644 --- a/app/view/cert/deployaccount.html +++ b/app/view/cert/deployaccount.html @@ -68,7 +68,7 @@ $(document).ready(function(){ field: '', title: '操作', formatter: function(value, row, index) { - var html = '编辑 删除'; + var html = '编辑 删除 任务'; return html; } }, @@ -79,12 +79,12 @@ function delItem(id){ layer.confirm('确定要删除此账户吗?', { btn: ['确定','取消'] }, function(){ - $.post('/cert/account/del?deploy=1', {id: id}, function(data){ + $.post('/cert/account/del', {id: id, deploy: 1}, function(data){ if(data.code == 0) { layer.msg('删除成功', {icon: 1, time:800}); $('#listTable').bootstrapTable('refresh'); } else { - layer.msg(data.msg, {icon: 2}); + layer.alert(data.msg, {icon: 2}); } }, 'json'); }); diff --git a/app/view/cert/deploytask.html b/app/view/cert/deploytask.html index 481e490..709eb48 100644 --- a/app/view/cert/deploytask.html +++ b/app/view/cert/deploytask.html @@ -12,6 +12,7 @@ pre.pre-log{height: 330px;overflow-y: auto;width: 100%;background-color: rgba(51
+
@@ -80,6 +81,7 @@ $(document).ready(function(){ field: 'typename', title: '自动部署账户', formatter: function(value, row, index) { + if(!value) return '已被删除' return ''+(row.aremark?row.aremark:value+'('+row.aid+')')+''; } }, diff --git a/public/static/images/aliyun.png b/public/static/images/aliyun.png new file mode 100644 index 0000000..f519fbb Binary files /dev/null and b/public/static/images/aliyun.png differ diff --git a/public/static/images/aws.png b/public/static/images/aws.png new file mode 100644 index 0000000..0c132f7 Binary files /dev/null and b/public/static/images/aws.png differ diff --git a/public/static/images/bt.ico b/public/static/images/bt.ico deleted file mode 100644 index 0a5d0ea..0000000 Binary files a/public/static/images/bt.ico and /dev/null differ diff --git a/public/static/images/bt.png b/public/static/images/bt.png new file mode 100644 index 0000000..6e0eec3 Binary files /dev/null and b/public/static/images/bt.png differ diff --git a/public/static/images/huawei.ico b/public/static/images/huawei.ico index 32085d8..bd9490b 100644 Binary files a/public/static/images/huawei.ico and b/public/static/images/huawei.ico differ diff --git a/public/static/images/maoyun.png b/public/static/images/maoyun.png new file mode 100644 index 0000000..2ef8410 Binary files /dev/null and b/public/static/images/maoyun.png differ diff --git a/public/static/images/tencent.ico b/public/static/images/tencent.ico deleted file mode 100644 index 1e94a78..0000000 Binary files a/public/static/images/tencent.ico and /dev/null differ diff --git a/public/static/images/tencent.png b/public/static/images/tencent.png new file mode 100644 index 0000000..9d26cf5 Binary files /dev/null and b/public/static/images/tencent.png differ