迷你卡片
This commit is contained in:
@@ -1,206 +0,0 @@
|
||||
/*
|
||||
* 文件: test_discover_api.dart
|
||||
* 名称: 发现页API测试脚本
|
||||
* 作用: 验证 api_discover.php 接口返回的新字段
|
||||
* 创建时间: 2026-04-13
|
||||
* 更新时间: 2026-04-13
|
||||
*
|
||||
* 运行方式: dart run scripts/test_discover_api.dart
|
||||
*/
|
||||
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
const String baseUrl = 'https://eat.wktyl.com/api';
|
||||
const String discoverEndpoint = '/api_discover.php';
|
||||
|
||||
void main(List<String> args) async {
|
||||
print('========================================');
|
||||
print(' 发现页 API 接口测试');
|
||||
print(' 测试时间: ${DateTime.now().toString().split('.')[0]}');
|
||||
print('========================================\n');
|
||||
|
||||
try {
|
||||
await testBasicRequest();
|
||||
await testCustomParams();
|
||||
await testRefreshParam();
|
||||
await testNewFields();
|
||||
await testMultipleRequests();
|
||||
|
||||
print('\n✅ 所有测试完成!');
|
||||
} catch (e, stackTrace) {
|
||||
print('\n❌ 测试失败: $e');
|
||||
print('Stack trace: $stackTrace');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> testBasicRequest() async {
|
||||
print('📋 测试1: 基础请求(默认参数)');
|
||||
print('----------------------------------------');
|
||||
|
||||
final url = Uri.parse('$baseUrl$discoverEndpoint?total=20');
|
||||
final response = await _makeRequest(url);
|
||||
|
||||
if (response['code'] == 200) {
|
||||
final data = response['data'] as Map<String, dynamic>;
|
||||
print(' ✅ 请求成功');
|
||||
print(' - 菜谱数量: ${(data['recipes'] as List).length}');
|
||||
print(' - 食材数量: ${(data['ingredients'] as List).length}');
|
||||
print(' - 分类数量: ${(data['categories'] as List).length}');
|
||||
print(' - 标签数量: ${(data['tags'] as List).length}');
|
||||
print(' - 营养成分数量: ${(data['nutrition_types'] as List).length}');
|
||||
print(' - 用餐时段数量: ${(data['meal_times'] as List).length}');
|
||||
print(' - 查询时间: ${response['_query_time']}');
|
||||
print(' - 缓存状态: ${response['meta']?['cache_status'] ?? 'unknown'}');
|
||||
} else {
|
||||
print(' ❌ 请求失败: ${response['message']}');
|
||||
}
|
||||
print('');
|
||||
}
|
||||
|
||||
Future<void> testCustomParams() async {
|
||||
print('📋 测试2: 自定义参数请求');
|
||||
print('----------------------------------------');
|
||||
|
||||
final url = Uri.parse(
|
||||
'$baseUrl$discoverEndpoint?recipe=5&ingredient=3&category=4&tag=5&nutrition=2&meal_time=2',
|
||||
);
|
||||
final response = await _makeRequest(url);
|
||||
|
||||
if (response['code'] == 200) {
|
||||
final data = response['data'] as Map<String, dynamic>;
|
||||
print(' ✅ 请求成功');
|
||||
print(' - 菜谱数量: ${(data['recipes'] as List).length} (预期: 5)');
|
||||
print(' - 食材数量: ${(data['ingredients'] as List).length} (预期: 3)');
|
||||
print(' - 分类数量: ${(data['categories'] as List).length} (预期: 4)');
|
||||
print(' - 标签数量: ${(data['tags'] as List).length} (预期: 5)');
|
||||
print(' - 营养成分数量: ${(data['nutrition_types'] as List).length} (预期: 2)');
|
||||
print(' - 用餐时段数量: ${(data['meal_times'] as List).length} (预期: 2)');
|
||||
} else {
|
||||
print(' ❌ 请求失败: ${response['message']}');
|
||||
}
|
||||
print('');
|
||||
}
|
||||
|
||||
Future<void> testRefreshParam() async {
|
||||
print('📋 测试3: 强制刷新参数');
|
||||
print('----------------------------------------');
|
||||
|
||||
final url = Uri.parse('$baseUrl$discoverEndpoint?total=10&_refresh=1');
|
||||
final response = await _makeRequest(url);
|
||||
|
||||
if (response['code'] == 200) {
|
||||
print(' ✅ 请求成功');
|
||||
print(' - 缓存状态: ${response['meta']?['cache_status'] ?? 'unknown'}');
|
||||
print(' - 请求次数: ${response['meta']?['request_count'] ?? 0}');
|
||||
final cacheHeader = response['_cache_header'] ?? '';
|
||||
print(' - X-Cache Header: $cacheHeader');
|
||||
} else {
|
||||
print(' ❌ 请求失败: ${response['message']}');
|
||||
}
|
||||
print('');
|
||||
}
|
||||
|
||||
Future<void> testNewFields() async {
|
||||
print('📋 测试4: 验证新字段');
|
||||
print('----------------------------------------');
|
||||
|
||||
final url = Uri.parse('$baseUrl$discoverEndpoint?category=10');
|
||||
final response = await _makeRequest(url);
|
||||
|
||||
if (response['code'] == 200) {
|
||||
final data = response['data'] as Map<String, dynamic>;
|
||||
final categories = data['categories'] as List;
|
||||
|
||||
print(' ✅ 分类数据验证:');
|
||||
for (var i = 0; i < categories.length && i < 3; i++) {
|
||||
final cat = categories[i] as Map<String, dynamic>;
|
||||
print(' ---');
|
||||
print(' 分类 ${i + 1}:');
|
||||
print(' - id: ${cat['id']}');
|
||||
print(' - name: ${cat['name']}');
|
||||
print(' - type: ${cat['type']}');
|
||||
print(' - count: ${cat['count']}');
|
||||
print(' - recipe_count: ${cat['recipe_count']} (新字段)');
|
||||
print(' - ingredient_count: ${cat['ingredient_count']} (新字段)');
|
||||
print(' - parent_id: ${cat['parent_id']}');
|
||||
print(' - parent_name: ${cat['parent_name']} (新字段)');
|
||||
}
|
||||
|
||||
final tags = data['tags'] as List;
|
||||
print(' ✅ 标签数据验证:');
|
||||
for (var i = 0; i < tags.length && i < 3; i++) {
|
||||
final tag = tags[i] as Map<String, dynamic>;
|
||||
print(' ---');
|
||||
print(' 标签 ${i + 1}:');
|
||||
print(' - id: ${tag['id']}');
|
||||
print(' - name: ${tag['name']}');
|
||||
print(' - type: ${tag['type']}');
|
||||
print(' - count: ${tag['count']} (已修复)');
|
||||
}
|
||||
} else {
|
||||
print(' ❌ 请求失败: ${response['message']}');
|
||||
}
|
||||
print('');
|
||||
}
|
||||
|
||||
Future<void> testMultipleRequests() async {
|
||||
print('📋 测试5: 多次请求去重验证');
|
||||
print('----------------------------------------');
|
||||
|
||||
final recipeIds = <int>{};
|
||||
final categoryIds = <int>{};
|
||||
|
||||
for (var i = 0; i < 3; i++) {
|
||||
final url = Uri.parse('$baseUrl$discoverEndpoint?total=15');
|
||||
final response = await _makeRequest(url);
|
||||
|
||||
if (response['code'] == 200) {
|
||||
final data = response['data'] as Map<String, dynamic>;
|
||||
|
||||
final recipes = data['recipes'] as List;
|
||||
final categories = data['categories'] as List;
|
||||
|
||||
final newRecipeIds =
|
||||
recipes.map((r) => (r as Map<String, dynamic>)['id'] as int).toSet();
|
||||
final newCategoryIds =
|
||||
categories.map((c) => (c as Map<String, dynamic>)['id'] as int).toSet();
|
||||
|
||||
final duplicateRecipes = recipeIds.intersection(newRecipeIds);
|
||||
final duplicateCategories = categoryIds.intersection(newCategoryIds);
|
||||
|
||||
print(' 请求 ${i + 1}:');
|
||||
print(' - 新菜谱: ${newRecipeIds.length}');
|
||||
print(' - 重复菜谱: ${duplicateRecipes.length}');
|
||||
print(' - 新分类: ${newCategoryIds.length}');
|
||||
print(' - 重复分类: ${duplicateCategories.length}');
|
||||
|
||||
recipeIds.addAll(newRecipeIds);
|
||||
categoryIds.addAll(newCategoryIds);
|
||||
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
} else {
|
||||
print(' ❌ 请求 ${i + 1} 失败: ${response['message']}');
|
||||
}
|
||||
}
|
||||
|
||||
print(' ✅ 去重验证完成');
|
||||
print(' - 总计菜谱ID: ${recipeIds.length}');
|
||||
print(' - 总计分类ID: ${categoryIds.length}');
|
||||
print('');
|
||||
}
|
||||
|
||||
Future<Map<String, dynamic>> _makeRequest(Uri url) async {
|
||||
final client = HttpClient();
|
||||
try {
|
||||
final request = await client.getUrl(url);
|
||||
final response = await request.close();
|
||||
final body = await response.transform(utf8.decoder).join();
|
||||
|
||||
final result = json.decode(body) as Map<String, dynamic>;
|
||||
result['_cache_header'] = response.headers.value('X-Cache') ?? '';
|
||||
return result;
|
||||
} finally {
|
||||
client.close();
|
||||
}
|
||||
}
|
||||
146
scripts/test_discover_image.dart
Normal file
146
scripts/test_discover_image.dart
Normal file
@@ -0,0 +1,146 @@
|
||||
// 2026-04-14 | test_discover_image.dart | Discover图片数据验证 | 验证api_discover.php返回的cover/picId字段
|
||||
// 运行: dart run scripts/test_discover_image.dart
|
||||
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
const String baseUrl = 'https://eat.wktyl.com/api';
|
||||
|
||||
Future<void> main() async {
|
||||
print('=== Discover 图片数据验证 ===\n');
|
||||
|
||||
await testDiscoverApi();
|
||||
await testDetailApi();
|
||||
await testImageUrl();
|
||||
}
|
||||
|
||||
Future<void> testDiscoverApi() async {
|
||||
print('📡 测试 api_discover.php 接口');
|
||||
final client = HttpClient();
|
||||
try {
|
||||
final url = Uri.parse('$baseUrl/api_discover.php?total=10');
|
||||
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();
|
||||
|
||||
if (body.isEmpty) {
|
||||
print(' ❌ 响应体为空');
|
||||
return;
|
||||
}
|
||||
|
||||
final json = jsonDecode(body) as Map<String, dynamic>;
|
||||
print(' code: ${json['code']}');
|
||||
|
||||
final data = json['data'] as Map<String, dynamic>?;
|
||||
if (data == null) {
|
||||
print(' ❌ data字段为null');
|
||||
return;
|
||||
}
|
||||
|
||||
final recipes = data['recipes'] as List?;
|
||||
if (recipes == null || recipes.isEmpty) {
|
||||
print(' ❌ recipes为空');
|
||||
return;
|
||||
}
|
||||
|
||||
print(' 菜谱数量: ${recipes.length}');
|
||||
print('');
|
||||
|
||||
for (int i = 0; i < recipes.length && i < 5; i++) {
|
||||
final recipe = recipes[i] as Map<String, dynamic>;
|
||||
print(' ─── 菜谱 #${i + 1} ───');
|
||||
print(' id: ${recipe['id']}');
|
||||
print(' title: ${recipe['title']}');
|
||||
print(' cover: ${recipe['cover']}');
|
||||
print(' pic_id: ${recipe['pic_id']}');
|
||||
print(' picId: ${recipe['picId']}');
|
||||
print(' pic: ${recipe['pic']}');
|
||||
|
||||
final allKeys = recipe.keys.toList();
|
||||
print(' 所有字段: $allKeys');
|
||||
|
||||
final cover = recipe['cover'] ?? '';
|
||||
if (cover.isNotEmpty) {
|
||||
final regex = RegExp(r'/pic/(\d+)[ab]?\.(jpg|png|webp)$');
|
||||
final match = regex.firstMatch(cover.toString());
|
||||
if (match != null) {
|
||||
print(' ✅ 从cover提取picId: ${match.group(1)}');
|
||||
} else {
|
||||
print(' ⚠️ cover不匹配picId正则: $cover');
|
||||
}
|
||||
} else {
|
||||
print(' ❌ cover为空');
|
||||
}
|
||||
print('');
|
||||
}
|
||||
} catch (e) {
|
||||
print(' ❌ 请求失败: $e');
|
||||
} finally {
|
||||
client.close();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> testDetailApi() async {
|
||||
print('\n📡 测试 api.php?act=detail 接口(对比picId字段)');
|
||||
final client = HttpClient();
|
||||
try {
|
||||
final url = Uri.parse('$baseUrl/api.php?act=detail&id=32390');
|
||||
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();
|
||||
|
||||
if (body.isEmpty) return;
|
||||
|
||||
final json = jsonDecode(body) as Map<String, dynamic>;
|
||||
final data = json['data'] as Map<String, dynamic>?;
|
||||
if (data == null) return;
|
||||
|
||||
print(' id: ${data['id']}');
|
||||
print(' title: ${data['title']}');
|
||||
print(' cover: ${data['cover']}');
|
||||
print(' pic_id: ${data['pic_id']}');
|
||||
print(' picId: ${data['picId']}');
|
||||
print(' pic: ${data['pic']}');
|
||||
|
||||
final allKeys = data.keys.toList();
|
||||
print(' 所有字段: $allKeys');
|
||||
} catch (e) {
|
||||
print(' ❌ 请求失败: $e');
|
||||
} finally {
|
||||
client.close();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> testImageUrl() async {
|
||||
print('\n📡 测试图片URL可访问性');
|
||||
final client = HttpClient();
|
||||
try {
|
||||
final testUrls = [
|
||||
'https://eat.wktyl.com/api/assets/pic/32390a.jpg',
|
||||
'https://eat.wktyl.com/api/assets/pic/32390b.jpg',
|
||||
'https://eat.wktyl.com/api/assets/pic/32390.jpg',
|
||||
];
|
||||
|
||||
for (final url in testUrls) {
|
||||
try {
|
||||
final request = await client.getUrl(Uri.parse(url));
|
||||
final response = await request.close();
|
||||
print(
|
||||
' $url → ${response.statusCode} (${response.contentLength} bytes)',
|
||||
);
|
||||
} catch (e) {
|
||||
print(' $url → ❌ $e');
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
client.close();
|
||||
}
|
||||
}
|
||||
55
scripts/test_ingredient_cache.dart
Normal file
55
scripts/test_ingredient_cache.dart
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 文件: test_ingredient_cache.dart
|
||||
* 名称: 食材缓存测试脚本
|
||||
* 作用: 验证食材缓存服务的读写功能
|
||||
* 创建: 2026-04-14
|
||||
*/
|
||||
|
||||
import 'dart:io';
|
||||
|
||||
void main() async {
|
||||
print('========================================');
|
||||
print('食材缓存测试脚本');
|
||||
print('========================================\n');
|
||||
|
||||
// 测试 API 接口
|
||||
await testIngredientApi();
|
||||
|
||||
print('\n========================================');
|
||||
print('测试完成');
|
||||
print('========================================');
|
||||
}
|
||||
|
||||
Future<void> testIngredientApi() async {
|
||||
final testIds = [849, 1248, 1, 1206, 1209];
|
||||
|
||||
for (final id in testIds) {
|
||||
print('\n--- 测试食材 ID: $id ---');
|
||||
|
||||
try {
|
||||
final client = HttpClient();
|
||||
final request = await client.getUrl(
|
||||
Uri.parse('https://eat.wktyl.com/api/api.php?act=ingredient_detail&id=$id'),
|
||||
);
|
||||
|
||||
final response = await request.close();
|
||||
final body = await response.transform(const SystemEncoding().decoder).join();
|
||||
|
||||
print('状态码: ${response.statusCode}');
|
||||
print('响应长度: ${body.length} 字符');
|
||||
|
||||
if (body.isNotEmpty && body.startsWith('{')) {
|
||||
print('✅ API 响应正常');
|
||||
} else {
|
||||
print('❌ API 响应异常');
|
||||
}
|
||||
|
||||
client.close();
|
||||
} catch (e) {
|
||||
print('❌ 请求失败: $e');
|
||||
}
|
||||
|
||||
// 延迟避免请求过快
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
/*
|
||||
* 测试 qr 包 API
|
||||
*/
|
||||
|
||||
import 'package:qr/qr.dart';
|
||||
|
||||
void main() {
|
||||
final qrCode = QrCode.fromData(
|
||||
data: 'https://example.com',
|
||||
errorCorrectLevel: QrErrorCorrectLevel.M,
|
||||
);
|
||||
|
||||
print('Module count: ${qrCode.moduleCount}');
|
||||
print('QR Code type: ${qrCode.runtimeType}');
|
||||
|
||||
// 检查可用的方法和属性
|
||||
final mirror = reflect(qrCode);
|
||||
final instance = mirror.type;
|
||||
print('Available methods:');
|
||||
for (final method in instance.declarations.keys) {
|
||||
print(' - $method');
|
||||
}
|
||||
}
|
||||
@@ -1,152 +0,0 @@
|
||||
/*
|
||||
* 文件: test_recipe_code.dart
|
||||
* 作用: 测试菜谱code字段,验证二维码海报功能所需数据
|
||||
* 创建: 2026-04-13
|
||||
*/
|
||||
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
const String baseUrl = 'http://eat.wktyl.com/api';
|
||||
|
||||
Future<void> main() async {
|
||||
final client = HttpClient();
|
||||
|
||||
print('=== 菜谱 Code 字段测试 ===\n');
|
||||
|
||||
// 测试1: detail接口是否返回code字段
|
||||
print('📋 测试1: detail接口 code字段');
|
||||
try {
|
||||
final url = Uri.parse('$baseUrl/api.php?act=detail&id=32892');
|
||||
final request = await client.getUrl(url);
|
||||
final response = await request.close();
|
||||
final body = await response.transform(utf8.decoder).join();
|
||||
final data = json.decode(body);
|
||||
|
||||
if (data['code'] == 200) {
|
||||
final recipe = data['data'];
|
||||
print(' ✅ 菜谱标题: ${recipe['title']}');
|
||||
print(' ✅ Code字段: ${recipe['code']}');
|
||||
print(' ✅ Pic_id: ${recipe['pic_id']}');
|
||||
print(' ✅ Statistics: ${recipe['statistics']}');
|
||||
} else {
|
||||
print(' ❌ 接口返回错误: ${data['message']}');
|
||||
}
|
||||
} catch (e) {
|
||||
print(' ❌ 请求失败: $e');
|
||||
}
|
||||
|
||||
print('');
|
||||
|
||||
// 测试2: full接口是否返回code字段
|
||||
print('📋 测试2: full接口 code字段');
|
||||
try {
|
||||
final url = Uri.parse('$baseUrl/api.php?act=full&id=32892');
|
||||
final request = await client.getUrl(url);
|
||||
final response = await request.close();
|
||||
final body = await response.transform(utf8.decoder).join();
|
||||
final data = json.decode(body);
|
||||
|
||||
if (data['code'] == 200) {
|
||||
final recipe = data['data'];
|
||||
print(' ✅ 菜谱标题: ${recipe['title']}');
|
||||
print(' ✅ Code字段: ${recipe['code']}');
|
||||
print(' ✅ Category: ${recipe['category']}');
|
||||
print(' ✅ Allergens: ${recipe['allergens']}');
|
||||
}
|
||||
} catch (e) {
|
||||
print(' ❌ 请求失败: $e');
|
||||
}
|
||||
|
||||
print('');
|
||||
|
||||
// 测试3: what_to_eat detail接口通过code查询
|
||||
print('📋 测试3: what_to_eat detail接口 code查询');
|
||||
try {
|
||||
final url =
|
||||
Uri.parse('$baseUrl/api_what_to_eat.php?act=detail&code=CP032892');
|
||||
final request = await client.getUrl(url);
|
||||
final response = await request.close();
|
||||
final body = await response.transform(utf8.decoder).join();
|
||||
final data = json.decode(body);
|
||||
|
||||
if (data['code'] == 200) {
|
||||
final recipe = data['data'];
|
||||
print(' ✅ 通过code查询成功: ${recipe['title']}');
|
||||
} else {
|
||||
print(' ❌ code查询失败: ${data['message']}');
|
||||
}
|
||||
} catch (e) {
|
||||
print(' ❌ 请求失败: $e');
|
||||
}
|
||||
|
||||
print('');
|
||||
|
||||
// 测试4: mini接口是否返回code字段
|
||||
print('📋 测试4: mini接口 code字段');
|
||||
try {
|
||||
final url = Uri.parse('$baseUrl/api.php?act=mini&id=32892');
|
||||
final request = await client.getUrl(url);
|
||||
final response = await request.close();
|
||||
final body = await response.transform(utf8.decoder).join();
|
||||
final data = json.decode(body);
|
||||
|
||||
if (data['code'] == 200) {
|
||||
final recipe = data['data'];
|
||||
print(' ✅ 菜谱标题: ${recipe['title']}');
|
||||
print(' ✅ Code字段: ${recipe['code']}');
|
||||
print(' ✅ 返回字段: ${recipe.keys.toList()}');
|
||||
}
|
||||
} catch (e) {
|
||||
print(' ❌ 请求失败: $e');
|
||||
}
|
||||
|
||||
print('');
|
||||
|
||||
// 测试5: feed recommend接口
|
||||
print('📋 测试5: feed recommend接口');
|
||||
try {
|
||||
final url = Uri.parse('$baseUrl/api_feed.php?act=recommend&page=1&limit=3');
|
||||
final request = await client.getUrl(url);
|
||||
final response = await request.close();
|
||||
final body = await response.transform(utf8.decoder).join();
|
||||
final data = json.decode(body);
|
||||
|
||||
if (data['code'] == 200) {
|
||||
final items = data['data'] as List;
|
||||
print(' ✅ 推荐数量: ${items.length}');
|
||||
for (final item in items) {
|
||||
print(
|
||||
' - ${item['title']} (code: ${item['code']}, views: ${item['statistics']?['view_count']})');
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
print(' ❌ 请求失败: $e');
|
||||
}
|
||||
|
||||
print('');
|
||||
|
||||
// 测试6: filter_apply接口(每日菜单规划用)
|
||||
print('📋 测试6: filter_apply接口 三餐推荐');
|
||||
for (final meal in ['早餐', '中餐', '晚餐']) {
|
||||
try {
|
||||
final url = Uri.parse(
|
||||
'$baseUrl/api_what_to_eat.php?act=filter_apply&count=2&meal_time=$meal');
|
||||
final request = await client.getUrl(url);
|
||||
final response = await request.close();
|
||||
final body = await response.transform(utf8.decoder).join();
|
||||
final data = json.decode(body);
|
||||
|
||||
if (data['code'] == 200) {
|
||||
final items = data['data'] as List;
|
||||
final titles = items.map((e) => e['title']).join(', ');
|
||||
print(' ✅ $meal: $titles');
|
||||
}
|
||||
} catch (e) {
|
||||
print(' ❌ $meal 请求失败: $e');
|
||||
}
|
||||
}
|
||||
|
||||
print('\n=== 测试完成 ===');
|
||||
client.close();
|
||||
}
|
||||
@@ -1,153 +0,0 @@
|
||||
/*
|
||||
* 文件: test_recipe_code_v2.dart
|
||||
* 作用: 测试feed recommend和filter_apply接口的真实数据结构
|
||||
* 创建: 2026-04-13
|
||||
*/
|
||||
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
const String baseUrl = 'http://eat.wktyl.com/api';
|
||||
|
||||
Future<void> main() async {
|
||||
final client = HttpClient();
|
||||
|
||||
// 测试1: feed recommend接口真实结构
|
||||
print('📋 测试1: feed recommend接口');
|
||||
try {
|
||||
final url = Uri.parse('$baseUrl/api_feed.php?act=recommend&page=1&limit=3');
|
||||
final request = await client.getUrl(url);
|
||||
final response = await request.close();
|
||||
final body = await response.transform(utf8.decoder).join();
|
||||
final data = json.decode(body) as Map<String, dynamic>;
|
||||
|
||||
if (data['code'] == 200) {
|
||||
final d = data['data'];
|
||||
if (d is List) {
|
||||
print(' data是List, 长度: ${d.length}');
|
||||
for (final item in d) {
|
||||
print(' - ${(item as Map)['title']}');
|
||||
}
|
||||
} else if (d is Map) {
|
||||
print(' data是Map, keys: ${d.keys.toList()}');
|
||||
final items = d['items'] ?? d['list'] ?? d['recipes'];
|
||||
if (items is List) {
|
||||
print(' 列表字段长度: ${items.length}');
|
||||
for (final item in items) {
|
||||
print(' - ${(item as Map)['title']}');
|
||||
}
|
||||
} else {
|
||||
print(' data内容: ${d.toString().substring(0, 200)}...');
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
print(' ❌ 请求失败: $e');
|
||||
}
|
||||
|
||||
print('');
|
||||
|
||||
// 测试2: filter_apply接口真实结构
|
||||
print('📋 测试2: filter_apply接口');
|
||||
try {
|
||||
final url = Uri.parse(
|
||||
'$baseUrl/api_what_to_eat.php?act=filter_apply&count=2&meal_time=早餐');
|
||||
final request = await client.getUrl(url);
|
||||
final response = await request.close();
|
||||
final body = await response.transform(utf8.decoder).join();
|
||||
final data = json.decode(body) as Map<String, dynamic>;
|
||||
|
||||
if (data['code'] == 200) {
|
||||
final d = data['data'];
|
||||
if (d is List) {
|
||||
print(' data是List, 长度: ${d.length}');
|
||||
for (final item in d) {
|
||||
print(' - ${(item as Map)['title']}');
|
||||
}
|
||||
} else if (d is Map) {
|
||||
print(' data是Map, keys: ${d.keys.toList()}');
|
||||
final items = d['items'] ?? d['list'] ?? d['recipes'];
|
||||
if (items is List) {
|
||||
print(' 列表字段长度: ${items.length}');
|
||||
for (final item in items) {
|
||||
print(' - ${(item as Map)['title']}');
|
||||
}
|
||||
} else {
|
||||
print(' data内容: ${d.toString().substring(0, 300)}...');
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
print(' ❌ 请求失败: $e');
|
||||
}
|
||||
|
||||
print('');
|
||||
|
||||
// 测试3: filter_apply无meal_time参数
|
||||
print('📋 测试3: filter_apply无meal_time');
|
||||
try {
|
||||
final url =
|
||||
Uri.parse('$baseUrl/api_what_to_eat.php?act=filter_apply&count=3');
|
||||
final request = await client.getUrl(url);
|
||||
final response = await request.close();
|
||||
final body = await response.transform(utf8.decoder).join();
|
||||
final data = json.decode(body) as Map<String, dynamic>;
|
||||
|
||||
if (data['code'] == 200) {
|
||||
final d = data['data'];
|
||||
if (d is List) {
|
||||
print(' data是List, 长度: ${d.length}');
|
||||
for (final item in d) {
|
||||
print(' - ${(item as Map)['title']}');
|
||||
}
|
||||
} else if (d is Map) {
|
||||
print(' data是Map, keys: ${d.keys.toList()}');
|
||||
final items = d['items'] ?? d['list'] ?? d['recipes'];
|
||||
if (items is List) {
|
||||
print(' 列表字段长度: ${items.length}');
|
||||
for (final item in items) {
|
||||
print(' - ${(item as Map)['title']}');
|
||||
}
|
||||
} else {
|
||||
print(' data内容: ${d.toString().substring(0, 300)}...');
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
print(' ❌ 请求失败: $e');
|
||||
}
|
||||
|
||||
print('');
|
||||
|
||||
// 测试4: filter_recipes接口 meal_time参数
|
||||
print('📋 测试4: filter_recipes接口 meal_time参数');
|
||||
try {
|
||||
final url = Uri.parse(
|
||||
'$baseUrl/api_filter.php?act=filter_recipes&meal_time=早餐&limit=3');
|
||||
final request = await client.getUrl(url);
|
||||
final response = await request.close();
|
||||
final body = await response.transform(utf8.decoder).join();
|
||||
final data = json.decode(body) as Map<String, dynamic>;
|
||||
|
||||
if (data['code'] == 200) {
|
||||
final d = data['data'];
|
||||
if (d is Map) {
|
||||
print(' data是Map, keys: ${d.keys.toList()}');
|
||||
final items = d['items'] ?? d['list'];
|
||||
if (items is List) {
|
||||
print(' 列表长度: ${items.length}');
|
||||
for (final item in items) {
|
||||
print(' - ${(item as Map)['title']}');
|
||||
}
|
||||
}
|
||||
} else if (d is List) {
|
||||
print(' data是List, 长度: ${d.length}');
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
print(' ❌ 请求失败: $e');
|
||||
}
|
||||
|
||||
print('\n=== 测试完成 ===');
|
||||
client.close();
|
||||
}
|
||||
@@ -1,151 +0,0 @@
|
||||
// 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