- 新增壁纸图库相关组件(WallpaperGalleryView/WallpaperSearchBar等) - 优化编辑器主题服务和系统UI管理 - 新增虚线边框和拖拽描边风格支持 - 完善今日诗词服务和阅读报告功能 - 修复多个UI问题和空指针异常 - 更新依赖库版本和SVG资源 - 优化交互动画和状态管理 - 补充文档和API测试脚本
197 lines
6.6 KiB
Dart
197 lines
6.6 KiB
Dart
// ============================================================
|
|
// 闲言APP — 接口连通性验证脚本
|
|
// 创建时间: 2026-05-02
|
|
// 更新时间: 2026-05-02
|
|
// 作用: 验证壁纸API + 今日诗词SDK的连通性和性能
|
|
// 上次更新: 初始创建
|
|
// ============================================================
|
|
|
|
// 使用方法: dart run scripts/api_verify.dart
|
|
|
|
import 'dart:convert';
|
|
import 'dart:io';
|
|
|
|
void main() async {
|
|
print('═══════════════════════════════════════════');
|
|
print(' 闲言APP — 接口连通性验证');
|
|
print(' ${DateTime.now().toIso8601String()}');
|
|
print('═══════════════════════════════════════════\n');
|
|
|
|
// 1. 壁纸 API
|
|
await _verifyWallpaperApi();
|
|
|
|
// 2. 今日诗词 SDK
|
|
await _verifyJinrishiciSdk();
|
|
|
|
print('\n═══════════════════════════════════════════');
|
|
print(' 验证完成');
|
|
print('═══════════════════════════════════════════');
|
|
}
|
|
|
|
Future<void> _verifyWallpaperApi() async {
|
|
print('┌─────────────────────────────────────────┐');
|
|
print('│ 🖼️ 壁纸 API 验证 │');
|
|
print('└─────────────────────────────────────────┘\n');
|
|
|
|
final baseUrl = 'http://bz.wktyl.com';
|
|
final endpoints = [
|
|
{
|
|
'name': 'Unsplash',
|
|
'path': '/api_unsplash.php',
|
|
'params': 'limit=5&page=1',
|
|
},
|
|
{
|
|
'name': '360壁纸',
|
|
'path': '/api_360_bing.php',
|
|
'params': 'limit=5&page=1&source=360',
|
|
},
|
|
{
|
|
'name': '必应壁纸',
|
|
'path': '/api_360_bing.php',
|
|
'params': 'limit=5&page=1&source=bing',
|
|
},
|
|
{'name': 'Pexels', 'path': '/api_pexels.php', 'params': 'limit=5&page=1'},
|
|
{'name': 'Pixabay', 'path': '/api_pixabay.php', 'params': 'limit=5&page=1'},
|
|
{
|
|
'name': 'WallSt',
|
|
'path': '/api_wallstreet.php',
|
|
'params': 'limit=5&page=1',
|
|
},
|
|
];
|
|
|
|
for (final ep in endpoints) {
|
|
final url = '$baseUrl${ep['path']}?${ep['params']}';
|
|
await _testEndpoint(ep['name']!, url);
|
|
}
|
|
}
|
|
|
|
Future<void> _verifyJinrishiciSdk() async {
|
|
print('\n┌─────────────────────────────────────────┐');
|
|
print('│ 📜 今日诗词 SDK 验证 │');
|
|
print('└─────────────────────────────────────────┘\n');
|
|
|
|
// Step 1: Token
|
|
final tokenUrl = 'https://v2.jinrishici.com/token';
|
|
String? token;
|
|
|
|
final tokenResult = await _testEndpoint('Token 获取', tokenUrl);
|
|
if (tokenResult != null) {
|
|
try {
|
|
final data = jsonDecode(tokenResult) as Map<String, dynamic>;
|
|
token = data['data'] as String?;
|
|
if (token != null) {
|
|
print(' ✅ Token: ${token.substring(0, 20)}...');
|
|
}
|
|
} catch (e) {
|
|
print(' ⚠️ Token 解析失败: $e');
|
|
}
|
|
}
|
|
|
|
// Step 2: Sentence
|
|
final sentenceUrl = 'https://v2.jinrishici.com/sentence';
|
|
final headers = token != null ? {'X-User-Token': token} : <String, String>{};
|
|
final sentenceResult = await _testEndpoint(
|
|
'每日诗词',
|
|
sentenceUrl,
|
|
headers: headers,
|
|
);
|
|
|
|
if (sentenceResult != null) {
|
|
try {
|
|
final data = jsonDecode(sentenceResult) as Map<String, dynamic>;
|
|
final content = data['data']?['content'] as String?;
|
|
final origin = data['data']?['origin'] as Map<String, dynamic>?;
|
|
final title = origin?['title'] as String?;
|
|
final author = origin?['author'] as String?;
|
|
final dynasty = origin?['dynasty'] as String?;
|
|
print(' 📝 内容: $content');
|
|
print(' 📖 来源: 《$title》${dynasty ?? ''}·${author ?? ''}');
|
|
} catch (e) {
|
|
print(' ⚠️ 诗词解析失败: $e');
|
|
}
|
|
}
|
|
|
|
// Step 3: Info (天气数据)
|
|
final infoUrl = 'https://v2.jinrishici.com/info';
|
|
final infoResult = await _testEndpoint('用户信息+天气', infoUrl, headers: headers);
|
|
|
|
if (infoResult != null) {
|
|
try {
|
|
final data = jsonDecode(infoResult) as Map<String, dynamic>;
|
|
final infoData = data['data'] as Map<String, dynamic>?;
|
|
final region = infoData?['region'] as String?;
|
|
final weatherData = infoData?['weatherData'] as Map<String, dynamic>?;
|
|
print(' 📍 地区: $region');
|
|
if (weatherData != null) {
|
|
print(' 🌡️ 温度: ${weatherData['temperature']}°C');
|
|
print(' 🌤️ 天气: ${weatherData['weather']}');
|
|
print(' 💧 湿度: ${weatherData['humidity']}%');
|
|
print(' 🌬️ 风向: ${weatherData['windDirection']}');
|
|
print(' 💨 风力: ${weatherData['windPower']}级');
|
|
if (weatherData['pm25'] != null) {
|
|
print(' 🫁 PM2.5: ${weatherData['pm25']}');
|
|
}
|
|
}
|
|
} catch (e) {
|
|
print(' ⚠️ 信息解析失败: $e');
|
|
}
|
|
}
|
|
}
|
|
|
|
Future<String?> _testEndpoint(
|
|
String name,
|
|
String url, {
|
|
Map<String, String>? headers,
|
|
}) async {
|
|
final sw = Stopwatch()..start();
|
|
try {
|
|
final client = HttpClient();
|
|
client.connectionTimeout = const Duration(seconds: 10);
|
|
|
|
final request = await client.getUrl(Uri.parse(url));
|
|
headers?.forEach((k, v) => request.headers.set(k, v));
|
|
|
|
final response = await request.close();
|
|
final body = await response.transform(utf8.decoder).join();
|
|
sw.stop();
|
|
|
|
final status = response.statusCode;
|
|
final ms = sw.elapsedMilliseconds;
|
|
final size = body.length;
|
|
|
|
final statusIcon = status == 200 ? '✅' : '❌';
|
|
final perfIcon = ms < 500
|
|
? '🟢'
|
|
: ms < 2000
|
|
? '🟡'
|
|
: '🔴';
|
|
|
|
print(' $statusIcon $name');
|
|
print(' URL: $url');
|
|
print(
|
|
' 状态码: $status | 响应时间: ${ms}ms $perfIcon | 大小: ${_formatSize(size)}',
|
|
);
|
|
|
|
if (status != 200) {
|
|
print(
|
|
' 响应: ${body.substring(0, body.length > 200 ? 200 : body.length)}',
|
|
);
|
|
}
|
|
|
|
client.close();
|
|
return status == 200 ? body : null;
|
|
} catch (e) {
|
|
sw.stop();
|
|
print(' ❌ $name');
|
|
print(' URL: $url');
|
|
print(' 错误: $e (${sw.elapsedMilliseconds}ms)');
|
|
return null;
|
|
}
|
|
}
|
|
|
|
String _formatSize(int bytes) {
|
|
if (bytes < 1024) return '$bytes B';
|
|
if (bytes < 1024 * 1024) return '${(bytes / 1024).toStringAsFixed(1)} KB';
|
|
return '${(bytes / (1024 * 1024)).toStringAsFixed(1)} MB';
|
|
}
|