瀑布流
This commit is contained in:
100
scripts/test_detail_cache.dart
Normal file
100
scripts/test_detail_cache.dart
Normal file
@@ -0,0 +1,100 @@
|
||||
// 2026-04-13 | test_detail_cache.dart | 详情页缓存测试 | 验证304缓存响应问题
|
||||
// 运行: dart run scripts/test_detail_cache.dart
|
||||
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
const String baseUrl = 'https://eat.wktyl.com/api';
|
||||
|
||||
Future<void> main() async {
|
||||
print('=== 详情页缓存测试 ===\n');
|
||||
|
||||
// 测试ID
|
||||
const testId = 27295;
|
||||
|
||||
// 测试1: 正常请求(不带刷新)
|
||||
print('📡 测试1: 正常请求 (id=$testId, 无刷新)');
|
||||
await testRequest(testId, forceRefresh: false);
|
||||
|
||||
// 等待一下
|
||||
await Future.delayed(const Duration(seconds: 1));
|
||||
|
||||
// 测试2: 强制刷新
|
||||
print('\n📡 测试2: 强制刷新 (id=$testId, _refresh=1)');
|
||||
await testRequest(testId, forceRefresh: true);
|
||||
|
||||
// 测试3: 使用另一个ID
|
||||
print('\n📡 测试3: 测试另一个ID (id=46518)');
|
||||
await testRequest(46518, forceRefresh: false);
|
||||
|
||||
print('\n=== 测试完成 ===');
|
||||
}
|
||||
|
||||
Future<void> testRequest(int id, {required bool forceRefresh}) async {
|
||||
final client = HttpClient();
|
||||
try {
|
||||
var url = '$baseUrl/api.php?act=full&id=$id';
|
||||
if (forceRefresh) {
|
||||
url += '&_refresh=1';
|
||||
}
|
||||
|
||||
print(' 请求URL: $url');
|
||||
|
||||
final uri = Uri.parse(url);
|
||||
final request = await client.getUrl(uri);
|
||||
|
||||
// 添加请求头
|
||||
request.headers.set('Accept', 'application/json');
|
||||
request.headers.set('User-Agent', 'MomKitchen/1.0');
|
||||
|
||||
final response = await request.close();
|
||||
|
||||
print(' 状态码: ${response.statusCode}');
|
||||
print(' 响应头:');
|
||||
response.headers.forEach((key, value) {
|
||||
if (key.toLowerCase().contains('cache') ||
|
||||
key.toLowerCase().contains('etag') ||
|
||||
key.toLowerCase().contains('last-modified')) {
|
||||
print(' $key: $value');
|
||||
}
|
||||
});
|
||||
|
||||
final body = await response.transform(utf8.decoder).join();
|
||||
|
||||
if (response.statusCode == 304) {
|
||||
print(' ⚠️ 收到304缓存响应');
|
||||
print(' 响应体长度: ${body.length}');
|
||||
if (body.isEmpty) {
|
||||
print(' ❌ 缓存响应体为空!这就是问题所在');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (body.isEmpty) {
|
||||
print(' ❌ 响应体为空');
|
||||
return;
|
||||
}
|
||||
|
||||
final json = jsonDecode(body) as Map<String, dynamic>;
|
||||
print(' code: ${json['code']}');
|
||||
print(' message: ${json['message']}');
|
||||
print(' _cached: ${json['_cached']}');
|
||||
|
||||
final data = json['data'] as Map<String, dynamic>?;
|
||||
if (data == null) {
|
||||
print(' ❌ data字段为null');
|
||||
return;
|
||||
}
|
||||
|
||||
print(' ✅ 数据加载成功');
|
||||
print(' id: ${data['id']}');
|
||||
print(' title: ${data['title']}');
|
||||
print(' pic_id: ${data['pic_id']}');
|
||||
print(' cover: ${data['cover']}');
|
||||
} catch (e, stackTrace) {
|
||||
print(' ❌ 请求错误: $e');
|
||||
print(' 堆栈: $stackTrace');
|
||||
} finally {
|
||||
client.close();
|
||||
}
|
||||
}
|
||||
64
scripts/test_detail_id.dart
Normal file
64
scripts/test_detail_id.dart
Normal file
@@ -0,0 +1,64 @@
|
||||
// 2026-04-13 | test_detail_id.dart | 详情页ID测试 | 验证详情页API返回数据
|
||||
// 运行: dart run scripts/test_detail_id.dart
|
||||
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
const String baseUrl = 'https://eat.wktyl.com/api';
|
||||
|
||||
Future<void> main() async {
|
||||
print('=== 详情页ID测试 ===\n');
|
||||
|
||||
// 测试ID 32390(从日志中获取)
|
||||
const testId = 32390;
|
||||
|
||||
print('📡 测试ID: $testId');
|
||||
await testDetailApi(testId);
|
||||
|
||||
// 再测试一个有效的ID
|
||||
print('\n📡 测试另一个ID: 46518');
|
||||
await testDetailApi(46518);
|
||||
}
|
||||
|
||||
Future<void> testDetailApi(int id) async {
|
||||
final client = HttpClient();
|
||||
try {
|
||||
final url = Uri.parse('$baseUrl/api.php?act=full&id=$id&_refresh=1');
|
||||
print(' 请求URL: $url');
|
||||
|
||||
final request = await client.getUrl(url);
|
||||
request.headers.set('Accept', 'application/json');
|
||||
|
||||
final response = await request.close();
|
||||
final body = await response.transform(utf8.decoder).join();
|
||||
|
||||
print(' 状态码: ${response.statusCode}');
|
||||
print(' 响应长度: ${body.length}');
|
||||
|
||||
if (body.isEmpty) {
|
||||
print(' ❌ 响应体为空');
|
||||
return;
|
||||
}
|
||||
|
||||
final json = jsonDecode(body) as Map<String, dynamic>;
|
||||
print(' code: ${json['code']}');
|
||||
print(' message: ${json['message']}');
|
||||
|
||||
final data = json['data'] as Map<String, dynamic>?;
|
||||
if (data == null) {
|
||||
print(' ❌ data字段为null');
|
||||
return;
|
||||
}
|
||||
|
||||
print(' ✅ 数据加载成功');
|
||||
print(' id: ${data['id']}');
|
||||
print(' title: ${data['title']}');
|
||||
print(' pic_id: ${data['pic_id']}');
|
||||
print(' cover: ${data['cover']}');
|
||||
print(' intro: ${(data['intro'] as String?)?.substring(0, (data['intro'] as String?)?.length.clamp(0, 50) ?? 0)}...');
|
||||
} catch (e) {
|
||||
print(' ❌ 请求错误: $e');
|
||||
} finally {
|
||||
client.close();
|
||||
}
|
||||
}
|
||||
135
scripts/test_discover_api.dart
Normal file
135
scripts/test_discover_api.dart
Normal file
@@ -0,0 +1,135 @@
|
||||
// 2026-04-13 | test_discover_api.dart | API测试脚本 | 验证发现页API返回数据
|
||||
// 运行: dart run scripts/test_discover_api.dart
|
||||
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
const String baseUrl = 'https://eat.wktyl.com/api';
|
||||
|
||||
Future<void> main() async {
|
||||
print('=== 发现页API测试 ===\n');
|
||||
|
||||
// 测试1: 获取初始数据
|
||||
print('📡 测试1: 获取初始数据 (total=50)');
|
||||
final data1 = await fetchDiscover(50);
|
||||
print(' 返回项目数: ${data1['items_count']}');
|
||||
print(' recipes: ${data1['recipes_count']}');
|
||||
print(' ingredients: ${data1['ingredients_count']}');
|
||||
print(' categories: ${data1['categories_count']}');
|
||||
print(' tags: ${data1['tags_count']}');
|
||||
print(' meal_times: ${data1['meal_times_count']}');
|
||||
|
||||
// 测试2: 再次获取数据,检查是否是新的随机数据
|
||||
print('\n📡 测试2: 再次获取数据 (total=50)');
|
||||
final data2 = await fetchDiscover(50);
|
||||
print(' 返回项目数: ${data2['items_count']}');
|
||||
|
||||
// 测试3: 检查两次数据是否相同
|
||||
final ids1 = data1['recipe_ids'] as List<int>;
|
||||
final ids2 = data2['recipe_ids'] as List<int>;
|
||||
final sameIds = ids1.where((id) => ids2.contains(id)).length;
|
||||
print(' 两次请求相同的recipe ID数量: $sameIds / ${ids1.length}');
|
||||
|
||||
// 测试4: 获取详情页数据
|
||||
if (ids1.isNotEmpty) {
|
||||
final testId = ids1.first;
|
||||
print('\n📡 测试3: 获取详情页数据 (id=$testId)');
|
||||
await testRecipeDetail(testId);
|
||||
}
|
||||
|
||||
// 测试5: 检查API返回的recipe结构
|
||||
print('\n📡 测试4: 检查recipe数据结构');
|
||||
if (data1['recipes'] != null && (data1['recipes'] as List).isNotEmpty) {
|
||||
final recipe = (data1['recipes'] as List).first;
|
||||
print(' recipe字段: ${recipe.keys.toList()}');
|
||||
print(' id: ${recipe['id']}');
|
||||
print(' title: ${recipe['title']}');
|
||||
print(' cover: ${recipe['cover']}');
|
||||
print(' category: ${recipe['category']}');
|
||||
print(' rating: ${recipe['rating']}');
|
||||
print(' views: ${recipe['views']}');
|
||||
}
|
||||
|
||||
print('\n=== 测试完成 ===');
|
||||
}
|
||||
|
||||
Future<Map<String, dynamic>> fetchDiscover(int total) async {
|
||||
final client = HttpClient();
|
||||
try {
|
||||
final uri = Uri.parse(
|
||||
'$baseUrl/api_discover.php?total=$total'
|
||||
'&recipe=${(total * 0.35).round()}'
|
||||
'&ingredient=${(total * 0.15).round()}'
|
||||
'&category=${(total * 0.12).round()}'
|
||||
'&tag=${(total * 0.18).round()}'
|
||||
'&nutrition=${(total * 0.1).round()}'
|
||||
'&meal_time=${(total * 0.1).round()}',
|
||||
);
|
||||
|
||||
final request = await client.getUrl(uri);
|
||||
final response = await request.close();
|
||||
final body = await response.transform(utf8.decoder).join();
|
||||
final json = jsonDecode(body) as Map<String, dynamic>;
|
||||
|
||||
if (json['code'] != 200) {
|
||||
print(' ❌ API错误: ${json['message']}');
|
||||
return {};
|
||||
}
|
||||
|
||||
final data = json['data'] as Map<String, dynamic>;
|
||||
final recipes = (data['recipes'] as List?) ?? [];
|
||||
final ingredients = (data['ingredients'] as List?) ?? [];
|
||||
final categories = (data['categories'] as List?) ?? [];
|
||||
final tags = (data['tags'] as List?) ?? [];
|
||||
final mealTimes = (data['meal_times'] as List?) ?? [];
|
||||
|
||||
return {
|
||||
'items_count': recipes.length + ingredients.length + categories.length + tags.length + mealTimes.length,
|
||||
'recipes_count': recipes.length,
|
||||
'ingredients_count': ingredients.length,
|
||||
'categories_count': categories.length,
|
||||
'tags_count': tags.length,
|
||||
'meal_times_count': mealTimes.length,
|
||||
'recipe_ids': recipes.map((r) => r['id'] as int).toList(),
|
||||
'recipes': recipes,
|
||||
};
|
||||
} catch (e) {
|
||||
print(' ❌ 请求错误: $e');
|
||||
return {};
|
||||
} finally {
|
||||
client.close();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> testRecipeDetail(int id) async {
|
||||
final client = HttpClient();
|
||||
try {
|
||||
// 测试 api.php?act=full&id=xxx
|
||||
final uri = Uri.parse('$baseUrl/api.php?act=full&id=$id');
|
||||
final request = await client.getUrl(uri);
|
||||
final response = await request.close();
|
||||
final body = await response.transform(utf8.decoder).join();
|
||||
final json = jsonDecode(body) as Map<String, dynamic>;
|
||||
|
||||
if (json['code'] != 200) {
|
||||
print(' ❌ 详情API错误: ${json['message']}');
|
||||
return;
|
||||
}
|
||||
|
||||
final data = json['data'] as Map<String, dynamic>?;
|
||||
if (data == null) {
|
||||
print(' ❌ 详情数据为空');
|
||||
return;
|
||||
}
|
||||
|
||||
print(' ✅ 详情数据加载成功');
|
||||
print(' id: ${data['id']}');
|
||||
print(' title: ${data['title']}');
|
||||
print(' 字段数: ${data.keys.length}');
|
||||
print(' 主要字段: ${data.keys.take(10).toList()}');
|
||||
} catch (e) {
|
||||
print(' ❌ 详情请求错误: $e');
|
||||
} finally {
|
||||
client.close();
|
||||
}
|
||||
}
|
||||
@@ -1,173 +0,0 @@
|
||||
// 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>;
|
||||
}
|
||||
151
scripts/test_recipe_detail_api.dart
Normal file
151
scripts/test_recipe_detail_api.dart
Normal file
@@ -0,0 +1,151 @@
|
||||
// 2026-04-13 | test_recipe_detail_api.dart | 详情页API测试 | 验证详情页API返回数据
|
||||
// 运行: dart run scripts/test_recipe_detail_api.dart
|
||||
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
const String baseUrl = 'https://eat.wktyl.com/api';
|
||||
|
||||
Future<void> main() async {
|
||||
print('=== 详情页API测试 ===\n');
|
||||
|
||||
// 先获取一个有效的recipe ID
|
||||
print('📡 步骤1: 获取有效的recipe ID');
|
||||
final discoverUrl = Uri.parse(
|
||||
'$baseUrl/api_discover.php?total=10&recipe=10&ingredient=0&category=0&tag=0&nutrition=0&meal_time=0',
|
||||
);
|
||||
final discoverClient = HttpClient();
|
||||
try {
|
||||
final discoverRequest = await discoverClient.getUrl(discoverUrl);
|
||||
final discoverResponse = await discoverRequest.close();
|
||||
final discoverBody = await discoverResponse.transform(utf8.decoder).join();
|
||||
final discoverJson = jsonDecode(discoverBody) as Map<String, dynamic>;
|
||||
final discoverData = discoverJson['data'] as Map<String, dynamic>;
|
||||
final recipes = discoverData['recipes'] as List;
|
||||
|
||||
if (recipes.isEmpty) {
|
||||
print(' ❌ 没有找到recipe');
|
||||
return;
|
||||
}
|
||||
|
||||
final testId = recipes.first['id'];
|
||||
print(' ✅ 找到recipe ID: $testId');
|
||||
|
||||
// 测试详情API
|
||||
await testDetailApi(testId);
|
||||
} catch (e) {
|
||||
print(' ❌ 错误: $e');
|
||||
} finally {
|
||||
discoverClient.close();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> testDetailApi(int id) async {
|
||||
print('\n📡 步骤2: 测试详情API (id=$id)');
|
||||
|
||||
final client = HttpClient();
|
||||
try {
|
||||
// 测试 api.php?act=full&id=xxx
|
||||
final url = Uri.parse('$baseUrl/api.php?act=full&id=$id');
|
||||
print(' 请求URL: $url');
|
||||
|
||||
final request = await client.getUrl(url);
|
||||
final response = await request.close();
|
||||
|
||||
print(' 状态码: ${response.statusCode}');
|
||||
|
||||
final body = await response.transform(utf8.decoder).join();
|
||||
print(' 响应长度: ${body.length} 字符');
|
||||
|
||||
final json = jsonDecode(body) as Map<String, dynamic>;
|
||||
print(' code: ${json['code']}');
|
||||
print(' message: ${json['message']}');
|
||||
|
||||
if (json['code'] != 200) {
|
||||
print(' ❌ API返回错误');
|
||||
return;
|
||||
}
|
||||
|
||||
final data = json['data'] as Map<String, dynamic>?;
|
||||
if (data == null) {
|
||||
print(' ❌ data字段为null');
|
||||
return;
|
||||
}
|
||||
|
||||
print('\n ✅ 详情数据加载成功');
|
||||
print(' ─────────────────────────────');
|
||||
print(' id: ${data['id']}');
|
||||
print(' code: ${data['code']}');
|
||||
print(' pic_id: ${data['pic_id']}');
|
||||
print(' title: ${data['title']}');
|
||||
print(' intro: ${(data['intro'] as String?)?.substring(0, (data['intro'] as String?)?.length.clamp(0, 50) ?? 0)}...');
|
||||
print(' content: ${(data['content'] as String?)?.substring(0, (data['content'] as String?)?.length.clamp(0, 50) ?? 0)}...');
|
||||
print(' cover: ${data['cover']}');
|
||||
print(' status: ${data['status']}');
|
||||
print(' create_time: ${data['create_time']}');
|
||||
print(' update_time: ${data['update_time']}');
|
||||
print(' ─────────────────────────────');
|
||||
|
||||
// 检查关键字段
|
||||
print('\n 关键字段检查:');
|
||||
print(' - id存在: ${data.containsKey('id')}');
|
||||
print(' - title存在: ${data.containsKey('title')}');
|
||||
print(' - cover存在: ${data.containsKey('cover')}');
|
||||
print(' - intro存在: ${data.containsKey('intro')}');
|
||||
print(' - content存在: ${data.containsKey('content')}');
|
||||
|
||||
// 检查是否有ingredients
|
||||
print(' - ingredients存在: ${data.containsKey('ingredients')}');
|
||||
if (data['ingredients'] != null) {
|
||||
final ingredients = data['ingredients'];
|
||||
if (ingredients is List) {
|
||||
print(' - ingredients数量: ${ingredients.length}');
|
||||
} else if (ingredients is Map) {
|
||||
print(' - ingredients是Map: ${ingredients.keys}');
|
||||
}
|
||||
}
|
||||
|
||||
// 检查是否有steps
|
||||
print(' - steps存在: ${data.containsKey('steps')}');
|
||||
if (data['steps'] != null) {
|
||||
final steps = data['steps'];
|
||||
if (steps is List) {
|
||||
print(' - steps数量: ${steps.length}');
|
||||
}
|
||||
}
|
||||
|
||||
// 检查是否有nutrition
|
||||
print(' - nutrition存在: ${data.containsKey('nutrition')}');
|
||||
if (data['nutrition'] != null) {
|
||||
print(' - nutrition: ${data['nutrition']}');
|
||||
}
|
||||
|
||||
// 检查是否有tags
|
||||
print(' - tags存在: ${data.containsKey('tags')}');
|
||||
if (data['tags'] != null) {
|
||||
final tags = data['tags'];
|
||||
if (tags is List) {
|
||||
print(' - tags数量: ${tags.length}');
|
||||
}
|
||||
}
|
||||
|
||||
// 检查是否有category
|
||||
print(' - category存在: ${data.containsKey('category')}');
|
||||
if (data['category'] != null) {
|
||||
print(' - category: ${data['category']}');
|
||||
}
|
||||
|
||||
// 检查是否有statistics
|
||||
print(' - statistics存在: ${data.containsKey('statistics')}');
|
||||
if (data['statistics'] != null) {
|
||||
print(' - statistics: ${data['statistics']}');
|
||||
}
|
||||
|
||||
print('\n 所有字段: ${data.keys.toList()}');
|
||||
} catch (e, stackTrace) {
|
||||
print(' ❌ 请求错误: $e');
|
||||
print(' 堆栈: $stackTrace');
|
||||
} finally {
|
||||
client.close();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user