完善PR审查后出现的问题

This commit is contained in:
2026-05-31 10:13:36 +08:00
parent 61ad85f6fc
commit 5ee6ba1e28
4 changed files with 161 additions and 50 deletions
@@ -7,6 +7,7 @@ import 'package:http/http.dart' as http;
import 'package:url_launcher/url_launcher.dart';
import '../../widgets/desktop_constrained.dart';
import '../../widgets/toast_helper.dart';
enum _NetworkTestTab { network, service, custom }
@@ -20,6 +21,13 @@ class NetworkTestPage extends StatefulWidget {
class _NetworkTestPageState extends State<NetworkTestPage> {
static final _panUri = Uri.parse('https://pan.gongyun.org');
static final _infoUri = Uri.parse('https://www.gongyun.org/appnetinfo.html');
static final _primaryIpLookupUri = Uri.parse('https://ipwho.is/');
static final _secondaryIpLookupUri = Uri.parse('https://ipapi.co/json/');
static const _probeHeaders = {'Cache-Control': 'no-cache'};
static const _probeGetFallbackHeaders = {
'Cache-Control': 'no-cache',
'Range': 'bytes=0-0',
};
_NetworkTestTab _tab = _NetworkTestTab.network;
bool _networkLoading = false;
@@ -44,8 +52,7 @@ class _NetworkTestPageState extends State<NetworkTestPage> {
IconButton(
tooltip: '说明',
icon: const Icon(Icons.info_outline),
onPressed: () =>
launchUrl(_infoUri, mode: LaunchMode.externalApplication),
onPressed: () => _openExternalUrl(_infoUri),
),
],
),
@@ -71,7 +78,7 @@ class _NetworkTestPageState extends State<NetworkTestPage> {
ButtonSegment(
value: _NetworkTestTab.custom,
icon: Icon(Icons.route_outlined),
label: Text('自定义'),
label: Text('自定义线路'),
),
],
selected: {_tab},
@@ -129,7 +136,7 @@ class _NetworkTestPageState extends State<NetworkTestPage> {
context: context,
builder: (dialogContext) => AlertDialog(
title: const Text('自定义线路'),
content: const Text('此功能暂不可用'),
content: const Text('自定义线路为会员功能,当前版本暂未开放。'),
actions: [
FilledButton(
onPressed: () => Navigator.of(dialogContext).pop(),
@@ -140,7 +147,20 @@ class _NetworkTestPageState extends State<NetworkTestPage> {
);
}
Future<void> _openExternalUrl(Uri uri) async {
try {
final opened = await launchUrl(uri, mode: LaunchMode.externalApplication);
if (!opened) {
ToastHelper.failure('无法打开链接: $uri');
}
} catch (e) {
ToastHelper.failure('无法打开链接: $e');
}
}
Future<void> _runNetworkTest() async {
if (_networkLoading) return;
setState(() {
_networkLoading = true;
_networkError = null;
@@ -171,6 +191,8 @@ class _NetworkTestPageState extends State<NetworkTestPage> {
}
Future<void> _runServiceTest() async {
if (_serviceLoading) return;
setState(() {
_serviceLoading = true;
_serviceError = null;
@@ -246,7 +268,7 @@ class _NetworkTestPageState extends State<NetworkTestPage> {
Future<_IpInfo> _fetchIpInfo() async {
try {
final response = await http
.get(Uri.parse('https://ipwho.is/'))
.get(_primaryIpLookupUri)
.timeout(const Duration(seconds: 8));
if (response.statusCode >= 200 && response.statusCode < 300) {
final data = jsonDecode(response.body) as Map<String, dynamic>;
@@ -270,7 +292,7 @@ class _NetworkTestPageState extends State<NetworkTestPage> {
try {
final response = await http
.get(Uri.parse('https://ipapi.co/json/'))
.get(_secondaryIpLookupUri)
.timeout(const Duration(seconds: 8));
if (response.statusCode >= 200 && response.statusCode < 300) {
final data = jsonDecode(response.body) as Map<String, dynamic>;
@@ -307,7 +329,7 @@ class _NetworkTestPageState extends State<NetworkTestPage> {
final response = await http
.get(
Uri.parse('https://status.gongyun.org/api/monitor?pageId=$pageId'),
headers: const {'Cache-Control': 'no-cache'},
headers: _probeHeaders,
)
.timeout(const Duration(seconds: 10));
if (response.statusCode < 200 || response.statusCode >= 300) {
@@ -367,13 +389,19 @@ class _NetworkTestPageState extends State<NetworkTestPage> {
}) async {
final stopwatch = Stopwatch()..start();
try {
final response = await http
.get(uri, headers: const {'Cache-Control': 'no-cache'})
var response = await http
.head(uri, headers: _probeHeaders)
.timeout(const Duration(seconds: 8));
if (_shouldRetryProbeWithGet(response.statusCode)) {
response = await http
.get(uri, headers: _probeGetFallbackHeaders)
.timeout(const Duration(seconds: 8));
}
stopwatch.stop();
final isHealthy = healthyStatusCodes.isEmpty
? response.statusCode >= 200 && response.statusCode < 500
: healthyStatusCodes.contains(response.statusCode);
final isHealthy = _isHealthyStatus(
response.statusCode,
healthyStatusCodes,
);
return _ProbeResult(
reachable: isHealthy,
latencyMs: stopwatch.elapsedMilliseconds,
@@ -384,6 +412,17 @@ class _NetworkTestPageState extends State<NetworkTestPage> {
}
}
bool _shouldRetryProbeWithGet(int statusCode) {
return statusCode == 403 || statusCode == 405 || statusCode == 501;
}
bool _isHealthyStatus(int statusCode, Set<int> healthyStatusCodes) {
if (healthyStatusCodes.isNotEmpty) {
return healthyStatusCodes.contains(statusCode);
}
return statusCode >= 200 && statusCode < 500;
}
Future<_StabilityResult> _testStability(Uri uri) async {
final latencies = <int>[];
var successCount = 0;
@@ -438,7 +477,7 @@ class _NetworkPanel extends StatelessWidget {
if (loading) const LinearProgressIndicator(),
if (error != null) _ErrorText(error!),
_InfoRow(
label: '公云存储网访问测试',
label: '公云存储网访问测试',
value: data == null ? '检测中' : (data.panReachable ? '正常' : '离线'),
valueColor: _statusColor(context, data?.panReachable),
),
@@ -463,11 +502,14 @@ class _NetworkPanel extends StatelessWidget {
title: '说明',
children: const [
_DescriptionLine('公云存储作为国际化云存储产品,已接入Cloudflare CDN作为全球加速引擎。'),
_DescriptionLine(
'当前网络 IP 地址、AS 与运营商信息通过第三方服务 ipwho.is 查询;如该服务不可用,将使用 ipapi.co 作为备用查询。',
),
_DescriptionLine(
'由于部分国家/地区有法律法规限制与审查,可能会出现包括但不限于网络波动、网络丢包以及网络连接不稳定现象',
),
_DescriptionLine(
'出现网络连接问题您可将本页面内容向公云存储团队进行报告,团队会根据相关诊断线索进行排查与优化。',
'出现网络连接问题您可将本页面内容向公云存储团队报告,团队会根据相关诊断线索进行排查与优化。',
),
],
),