Files
kitchen/scripts/test_pic_id_api.dart
2026-04-11 22:55:27 +08:00

174 lines
4.8 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 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>;
}