diff --git a/app/controller/Optimizeip.php b/app/controller/Optimizeip.php index d7b8f9f..ac749f1 100644 --- a/app/controller/Optimizeip.php +++ b/app/controller/Optimizeip.php @@ -85,8 +85,11 @@ class Optimizeip extends BaseController if (empty($task['did']) || empty($task['rr']) || empty($task['ip_type']) || empty($task['recordnum']) || empty($task['ttl'])) { return json(['code' => -1, 'msg' => '必填项不能为空']); } - if ($task['recordnum'] > 5) { - return json(['code' => -1, 'msg' => '解析数量不能超过5个']); + if ($task['recordnum'] < 1) { + return json(['code' => -1, 'msg' => '解析数量不能少于1个']); + } + if ($task['recordnum'] > 50) { + return json(['code' => -1, 'msg' => '解析数量不能超过50个']); } if (Db::name('optimizeip')->where('did', $task['did'])->where('rr', $task['rr'])->find()) { return json(['code' => -1, 'msg' => '当前域名的优选IP任务已存在']); @@ -109,8 +112,11 @@ class Optimizeip extends BaseController if (empty($task['did']) || empty($task['rr']) || empty($task['ip_type']) || empty($task['recordnum']) || empty($task['ttl'])) { return json(['code' => -1, 'msg' => '必填项不能为空']); } - if ($task['recordnum'] > 5) { - return json(['code' => -1, 'msg' => '解析数量不能超过5个']); + if ($task['recordnum'] < 1) { + return json(['code' => -1, 'msg' => '解析数量不能少于1个']); + } + if ($task['recordnum'] > 50) { + return json(['code' => -1, 'msg' => '解析数量不能超过50个']); } if (Db::name('optimizeip')->where('did', $task['did'])->where('rr', $task['rr'])->where('id', '<>', $id)->find()) { return json(['code' => -1, 'msg' => '当前域名的优选IP任务已存在']); diff --git a/app/service/OptimizeService.php b/app/service/OptimizeService.php index bbd84a2..fc07074 100644 --- a/app/service/OptimizeService.php +++ b/app/service/OptimizeService.php @@ -19,7 +19,7 @@ class OptimizeService public static function get_license($api, $key) { if ($api == 2) { - throw new Exception('当前接口暂不支持'); + throw new Exception('xingpingcn.top 接口免费使用,无需密钥,无积分限制'); } elseif ($api == 1) { $url = 'https://api.hostmonit.com/get_license?license='.$key; } else { @@ -39,7 +39,9 @@ class OptimizeService public function get_ip_address($cdn_type = 1, $ip_type = 'v4') { $api = config_get('optimize_ip_api', 0); - if ($api == 1) { + if ($api == 2) { + return $this->get_ip_address_xingpingcn($ip_type); + } elseif ($api == 1) { $url = 'https://api.hostmonit.com/get_optimization_ip'; } else { $url = 'https://www.wetest.vip/api/cf2dns/'; @@ -70,6 +72,59 @@ class OptimizeService } } + /** + * 从 xingpingcn.top 获取优选IP数据 + * @param string $ip_type IP类型 v4/v6 + * @return array + * @throws Exception + */ + private function get_ip_address_xingpingcn($ip_type = 'v4') + { + if ($ip_type == 'v6') { + throw new Exception('xingpingcn.top 接口暂不支持IPv6'); + } + $proxy = config_get('optimize_ip_proxy', ''); + if (!empty($proxy)) { + $proxy = trim($proxy); + if (filter_var($proxy, FILTER_VALIDATE_URL) === false) { + throw new Exception('无效的代理地址配置:URL 格式错误'); + } + $scheme = parse_url($proxy, PHP_URL_SCHEME); + if (!in_array($scheme, ['http', 'https'], true)) { + throw new Exception('无效的代理地址配置:仅支持 http 和 https 协议'); + } + $url = rtrim($proxy, '/') . '/xingpingcn/enhanced-FaaS-in-China/refs/heads/main/Cf.json'; + } else { + $url = 'https://raw.githubusercontent.com/xingpingcn/enhanced-FaaS-in-China/refs/heads/main/Cf.json'; + } + $response = get_curl($url); + if ($response === '') { + throw new Exception('获取优选IP数据失败,网络请求失败,请检查网络连接或代理地址'); + } + $arr = json_decode($response, true); + if (isset($arr['Cf']['result'])) { + $result = $arr['Cf']['result']; + $info = []; + // 转换格式:dianxin->CT, liantong->CU, yidong->CM, default->DEF + if (isset($result['dianxin']) && is_array($result['dianxin'])) { + $info['CT'] = array_map(function($ip) { return ['ip' => $ip]; }, $result['dianxin']); + } + if (isset($result['liantong']) && is_array($result['liantong'])) { + $info['CU'] = array_map(function($ip) { return ['ip' => $ip]; }, $result['liantong']); + } + if (isset($result['yidong']) && is_array($result['yidong'])) { + $info['CM'] = array_map(function($ip) { return ['ip' => $ip]; }, $result['yidong']); + } + // 不使用他的默认线路数据, 因为这真的是默认. 由后续逻辑自己决定是否把CT线路当DEF来用 + // if (isset($result['default']) && is_array($result['default'])) { + // $info['DEF'] = array_map(function($ip) { return ['ip' => $ip]; }, $result['default']); + // } + return $info; + } else { + throw new Exception('获取优选IP数据失败,接口返回数据格式错误'); + } + } + public function get_ip_address2($cdn_type = 1, $ip_type = 'v4') { $key = $cdn_type.'_'.$ip_type; diff --git a/app/view/optimizeip/opipform.html b/app/view/optimizeip/opipform.html index b3158a4..b78e89b 100644 --- a/app/view/optimizeip/opipform.html +++ b/app/view/optimizeip/opipform.html @@ -54,14 +54,14 @@

- +
@@ -110,6 +110,7 @@ new Vue({ el: '#app', data: { action: '{$action}', + optimize_ip_api: '{:config_get("optimize_ip_api", 0)}', set: { id: '', remark: '', @@ -132,8 +133,18 @@ new Vue({ 4:'EdgeOne' }, }, + computed: { + isXingpingcn: function() { + return this.optimize_ip_api == '2'; + } + }, watch: { 'set.ip_type_select': function(val){ + // 如果使用xingpingcn.top接口,自动移除v6 + if(this.isXingpingcn && val.includes('v6')){ + this.set.ip_type_select = val.filter(v => v !== 'v6'); + return; + } this.set.ip_type = val.join(','); } }, @@ -185,4 +196,4 @@ new Vue({ }, }); -{/block} \ No newline at end of file +{/block} diff --git a/app/view/optimizeip/opipset.html b/app/view/optimizeip/opipset.html index f93f4d0..fb7ec2a 100644 --- a/app/view/optimizeip/opipset.html +++ b/app/view/optimizeip/opipset.html @@ -14,8 +14,9 @@

使用说明

  • 不支持对CloudFlare里的域名添加优选,必须使用其他DNS服务商。需开通Cloudflare for SaaS,且域名使用CNAME的方式解析到CloudFlare。
  • -

  • 数据接口:wetest.vip 数据接口支持CloudFlare、CloudFront、EdgeOne;HostMonit 只支持CloudFlare。
  • +

  • 数据接口:wetest.vip 数据接口支持CloudFlare、CloudFront、EdgeOne;HostMonit 只支持CloudFlare;xingpingcn.top 只支持CloudFlare(免费、无需密钥)。
  • 接口密钥:默认o1zrmHAF为免费KEY可永久免费使用。
  • +

  • 代理地址:如 https://ghfast.top/https://raw.githubusercontent.com/ ,留空则直接访问 https://raw.githubusercontent.com/。
  • 自动更新:可查看计划任务设置

  • @@ -24,19 +25,23 @@

    数据接口设置

    -
    +
    -
    +
    -
    +
    + @@ -69,6 +74,25 @@ var items = $("select[default]"); for (i = 0; i < items.length; i++) { $(items[i]).val($(items[i]).attr("default")||0); } +// 切换接口时显示/隐藏对应设置项 +function toggleApiSettings(){ + var api = $("#optimize_ip_api").val(); + if(api == '2'){ + $("#keyGroup").hide(); + $("#proxyGroup").show(); + $("#queryBtn").hide(); + }else{ + $("#keyGroup").show(); + $("#proxyGroup").hide(); + $("#queryBtn").show(); + } +} +$("#optimize_ip_api").change(function(){ + toggleApiSettings(); +}); +// 页面加载时初始化 +toggleApiSettings(); +$('[data-toggle="tooltip"]').tooltip(); function saveSetting(obj){ var ii = layer.load(2, {shade:[0.1,'#fff']}); $.ajax({ @@ -118,4 +142,4 @@ function queryapi(){ }); } -{/block} \ No newline at end of file +{/block}