174 lines
4.8 KiB
Dart
174 lines
4.8 KiB
Dart
// 2026-04-11 | test_pic_id_api | 测试API连通性+完整Fallback链
|
||
// 用法: dart scripts/test_pic_id_api.dart
|
||
|
||
import 'dart:convert';
|
||
import 'dart:io';
|
||
import 'dart:typed_data';
|
||
|
||
const String _baseUrl = 'http://eat.wktyl.com/api';
|
||
const String _picBase = 'http://eat.wktyl.com/api/assets/pic';
|
||
|
||
void main() async {
|
||
print('API 连通性 + 完整图片Fallback链测试\n');
|
||
|
||
await testApiConnectivity();
|
||
await testPicIdField();
|
||
await testFullFallbackChain();
|
||
await testMultipleRecipes();
|
||
|
||
print('✅ 全部测试完成');
|
||
}
|
||
|
||
Future<void> testApiConnectivity() async {
|
||
print('📡 [1/4] API 基础连通性');
|
||
|
||
final endpoints = [
|
||
('api.php?act=list&page=1&limit=3', '菜谱列表'),
|
||
('api.php?act=categories&type=recipe', '分类列表'),
|
||
('api.php?act=tags&limit=5', '标签列表'),
|
||
('assets/back.png', '默认图back.png'),
|
||
];
|
||
|
||
for (final (path, name) in endpoints) {
|
||
try {
|
||
final sw = Stopwatch()..start();
|
||
final url = path.startsWith('assets')
|
||
? '$_baseUrl/$path'
|
||
: '$_baseUrl/$path';
|
||
final result = await httpGet(url);
|
||
sw.stop();
|
||
|
||
if (path.startsWith('assets')) {
|
||
print(' ✅ $name (${sw.elapsedMilliseconds}ms, ${result.length}B)');
|
||
} else if (result['code'] == 200) {
|
||
print(' ✅ $name (${sw.elapsedMilliseconds}ms)');
|
||
} else {
|
||
print(' ❌ $name → code=${result['code']}');
|
||
}
|
||
} catch (e) {
|
||
print(' ❌ $name → $e'.substring(0, 50));
|
||
}
|
||
}
|
||
}
|
||
|
||
Future<void> testPicIdField() async {
|
||
print('[2/4] pic_id 字段解析');
|
||
|
||
try {
|
||
final result = await httpGet('$_baseUrl/api.php?act=full&id=32891');
|
||
final data = result['data'];
|
||
if (data == null) {
|
||
print('❌ 无数据');
|
||
return;
|
||
}
|
||
|
||
print('菜谱: ${data['title']} (#${data['id']})');
|
||
print('pic_id: ${data['pic_id']}, recipe_id: ${data['id']}');
|
||
|
||
if (data['pic_id'] != null) {
|
||
print('✅ pic_id 有效');
|
||
} else {
|
||
print('⚠️ pic_id 为null,回退使用 recipe_id');
|
||
}
|
||
} catch (e) {
|
||
print('❌ 异常: $e');
|
||
}
|
||
}
|
||
|
||
Future<void> testFullFallbackChain() async {
|
||
print('[3/4] 完整Fallback链可达性测试 (pic_id=7640)');
|
||
|
||
const int picId = 7640;
|
||
|
||
final chain = [
|
||
('① coverUrl', '', false),
|
||
('② {picId}a.jpg', '$_picBase/${picId}a.jpg', true),
|
||
('③ {picId}b.jpg', '$_picBase/${picId}b.jpg', true),
|
||
('④ {picId}.jpg', '$_picBase/$picId.jpg', true),
|
||
('⑤ back.png', '$_baseUrl/assets/back.png', true),
|
||
('⑥ 本地error.png', 'assets/data/photos/error.png', false),
|
||
('⑦ 空白占位', '', false),
|
||
];
|
||
|
||
for (final (label, url, isNetwork) in chain) {
|
||
if (url.isEmpty) {
|
||
if (label.contains('本地')) {
|
||
final file = File(url);
|
||
if (file.existsSync()) {
|
||
print('✅ $label → 文件存在');
|
||
} else {
|
||
print('❌ $label → 文件不存在');
|
||
}
|
||
}
|
||
continue;
|
||
}
|
||
|
||
try {
|
||
final sw = Stopwatch()..start();
|
||
|
||
Uint8List? bytes;
|
||
int statusCode;
|
||
|
||
if (isNetwork) {
|
||
final client = HttpClient();
|
||
client.connectionTimeout = const Duration(seconds: 6);
|
||
final req = await client.getUrl(Uri.parse(url));
|
||
final resp = await req.close();
|
||
statusCode = resp.statusCode;
|
||
final bb = await resp.fold<BytesBuilder>(
|
||
BytesBuilder(),
|
||
(b, d) => b..add(d),
|
||
);
|
||
bytes = bb.toBytes();
|
||
client.close();
|
||
} else {
|
||
bytes = File(url).readAsBytesSync();
|
||
statusCode = 200;
|
||
}
|
||
|
||
sw.stop();
|
||
|
||
final ok = isNetwork
|
||
? (statusCode == 200 && (bytes?.length ?? 0) > 100)
|
||
: (bytes != null && bytes!.length > 0);
|
||
|
||
if (ok) {
|
||
final sizeKB = ((bytes!.length) / 1024).toStringAsFixed(1);
|
||
print('✅ $label → ${sw.elapsedMilliseconds}ms ($sizeKB KB)');
|
||
} else {
|
||
print('⚠️ $label → HTTP $statusCode (${bytes?.length ?? 0}B)');
|
||
}
|
||
} catch (e) {
|
||
print('❌ $label → 异常');
|
||
}
|
||
}
|
||
}
|
||
|
||
Future<void> testMultipleRecipes() async {
|
||
print('[4/4] 多菜谱 pic_id 对比');
|
||
|
||
for (final id in [32891, 32892, 32893]) {
|
||
try {
|
||
final r = await httpGet('$_baseUrl/api.php?act=full&id=$id');
|
||
final d = r['data'];
|
||
if (d == null) continue;
|
||
|
||
final rid = d['id'];
|
||
final pid = d['pic_id'];
|
||
final diff = (rid == pid) ? '⚠️相同' : '✅不同';
|
||
|
||
print('#$rid pic_id=$pid $diff');
|
||
} catch (_) {}
|
||
}
|
||
}
|
||
|
||
Future<Map<String, dynamic>> httpGet(String url) async {
|
||
final client = HttpClient();
|
||
client.connectionTimeout = const Duration(seconds: 10);
|
||
final request = await client.getUrl(Uri.parse(url));
|
||
final response = await request.close();
|
||
final body = await response.transform(utf8.decoder).join();
|
||
client.close();
|
||
return json.decode(body) as Map<String, dynamic>;
|
||
}
|