186 lines
6.8 KiB
Dart
186 lines
6.8 KiB
Dart
// 2026-04-11 | verify_what_to_eat_api.dart | 今天吃什么接口验证脚本 | 验证filter_apply/categories/tags接口连通性和数据格式
|
|
import 'dart:async';
|
|
import 'dart:convert';
|
|
import 'dart:io';
|
|
|
|
const String baseUrl = 'http://eat.wktyl.com/api';
|
|
const int timeoutSeconds = 12;
|
|
|
|
const String reset = '\x1B[0m';
|
|
const String green = '\x1B[32m';
|
|
const String red = '\x1B[31m';
|
|
const String yellow = '\x1B[33m';
|
|
const String blue = '\x1B[34m';
|
|
const String cyan = '\x1B[36m';
|
|
|
|
void main() async {
|
|
printHeader();
|
|
await testFilterApply();
|
|
await testCategories();
|
|
await testTags();
|
|
await testFilterSteps();
|
|
await testFilterApplyWithCategory();
|
|
printSummary();
|
|
}
|
|
|
|
void printHeader() {
|
|
print('$cyan═══════════════════════════════════════════════════$reset');
|
|
print('$cyan 🎲 今天吃什么 API 接口验证$reset');
|
|
print('$cyan═══════════════════════════════════════════════════$reset');
|
|
print('');
|
|
}
|
|
|
|
Future<Map<String, dynamic>?> apiGet(String endpoint, Map<String, String> params) async {
|
|
final uri = Uri.parse('$baseUrl$endpoint').replace(queryParameters: params);
|
|
final stopwatch = Stopwatch()..start();
|
|
try {
|
|
final client = HttpClient();
|
|
client.connectionTimeout = Duration(seconds: timeoutSeconds);
|
|
final request = await client.getUrl(uri);
|
|
final response = await request.close();
|
|
final body = await response.transform(utf8.decoder).join();
|
|
stopwatch.stop();
|
|
client.close();
|
|
|
|
if (response.statusCode != 200) {
|
|
print('$red ❌ HTTP ${response.statusCode} (${stopwatch.elapsedMilliseconds}ms)$reset');
|
|
return null;
|
|
}
|
|
|
|
final json = jsonDecode(body) as Map<String, dynamic>;
|
|
print('$green ✅ ${stopwatch.elapsedMilliseconds}ms | code=${json['code']}$reset');
|
|
return json;
|
|
} on TimeoutException {
|
|
stopwatch.stop();
|
|
print('$red ❌ 超时 (${stopwatch.elapsedMilliseconds}ms)$reset');
|
|
return null;
|
|
} catch (e) {
|
|
stopwatch.stop();
|
|
print('$red ❌ 错误: $e (${stopwatch.elapsedMilliseconds}ms)$reset');
|
|
return null;
|
|
}
|
|
}
|
|
|
|
Future<void> testFilterApply() async {
|
|
print('$yellow▶ 测试 1: filter_apply (无筛选随机推荐)$reset');
|
|
final result = await apiGet('/api_what_to_eat.php', {'act': 'filter_apply', 'count': '5'});
|
|
if (result != null) {
|
|
final data = result['data'];
|
|
if (data is Map) {
|
|
final recipes = data['recipes'] as List?;
|
|
print(' recipes count: ${recipes?.length ?? 0}');
|
|
if (recipes != null && recipes.isNotEmpty) {
|
|
final first = recipes.first as Map<String, dynamic>;
|
|
print(' first recipe: id=${first['id']}, title=${first['title']}');
|
|
print(' fields: ${first.keys.take(15).join(', ')}...');
|
|
}
|
|
print(' total_matched: ${data['total_matched']}');
|
|
print(' filters_applied: ${data['filters_applied']}');
|
|
} else if (data is List) {
|
|
print(' data is List, count: ${data.length}');
|
|
if (data.isNotEmpty) {
|
|
final first = data.first as Map<String, dynamic>;
|
|
print(' first: id=${first['id']}, title=${first['title']}');
|
|
}
|
|
}
|
|
}
|
|
print('');
|
|
}
|
|
|
|
Future<void> testCategories() async {
|
|
print('$yellow▶ 测试 2: categories (分类列表)$reset');
|
|
final result = await apiGet('/api.php', {'act': 'categories'});
|
|
if (result != null) {
|
|
final data = result['data'];
|
|
if (data is List) {
|
|
print(' categories count: ${data.length}');
|
|
for (final cat in data.take(5)) {
|
|
final m = cat as Map<String, dynamic>;
|
|
print(' - id=${m['id'] ?? m['cate_id']}, name=${m['name'] ?? m['cate_name']}, parent_id=${m['parent_id']}');
|
|
final children = m['children'] as List?;
|
|
if (children != null && children.isNotEmpty) {
|
|
print(' children: ${children.length}');
|
|
for (final child in children.take(3)) {
|
|
final cm = child as Map<String, dynamic>;
|
|
print(' - id=${cm['id'] ?? cm['cate_id']}, name=${cm['name'] ?? cm['cate_name']}');
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
print(' data type: ${data.runtimeType}');
|
|
}
|
|
}
|
|
print('');
|
|
}
|
|
|
|
Future<void> testTags() async {
|
|
print('$yellow▶ 测试 3: tags (标签列表)$reset');
|
|
final result = await apiGet('/api.php', {'act': 'tags'});
|
|
if (result != null) {
|
|
final data = result['data'];
|
|
if (data is List) {
|
|
print(' tags count: ${data.length}');
|
|
for (final tag in data.take(5)) {
|
|
final m = tag as Map<String, dynamic>;
|
|
print(' - id=${m['id'] ?? m['tag_id']}, name=${m['name'] ?? m['tag_name']}');
|
|
}
|
|
} else {
|
|
print(' data type: ${data.runtimeType}');
|
|
}
|
|
}
|
|
print('');
|
|
}
|
|
|
|
Future<void> testFilterSteps() async {
|
|
print('$yellow▶ 测试 4: filter_steps (筛选步骤)$reset');
|
|
final result = await apiGet('/api_what_to_eat.php', {'act': 'filter_steps'});
|
|
if (result != null) {
|
|
final data = result['data'];
|
|
if (data is Map) {
|
|
print(' keys: ${data.keys.join(', ')}');
|
|
final steps = data['steps'] as List?;
|
|
if (steps != null) {
|
|
print(' steps count: ${steps.length}');
|
|
for (final step in steps.take(3)) {
|
|
final m = step as Map<String, dynamic>;
|
|
print(' - step: ${m['step']}, title: ${m['title']}, type: ${m['type']}');
|
|
final options = m['options'] as List? ?? m['available_options'] as List? ?? [];
|
|
print(' options: ${options.length}');
|
|
}
|
|
}
|
|
final available = data['available_options'] as List?;
|
|
if (available != null) {
|
|
print(' available_options count: ${available.length}');
|
|
}
|
|
}
|
|
}
|
|
print('');
|
|
}
|
|
|
|
Future<void> testFilterApplyWithCategory() async {
|
|
print('$yellow▶ 测试 5: filter_apply (带分类筛选)$reset');
|
|
final result = await apiGet('/api_what_to_eat.php', {'act': 'filter_apply', 'category': '1', 'count': '3'});
|
|
if (result != null) {
|
|
final data = result['data'];
|
|
if (data is Map) {
|
|
final recipes = data['recipes'] as List?;
|
|
print(' recipes count: ${recipes?.length ?? 0}');
|
|
if (recipes != null && recipes.isNotEmpty) {
|
|
for (final r in recipes.take(3)) {
|
|
final m = r as Map<String, dynamic>;
|
|
print(' - id=${m['id']}, title=${m['title']}');
|
|
}
|
|
}
|
|
} else if (data is List) {
|
|
print(' data is List, count: ${data.length}');
|
|
}
|
|
}
|
|
print('');
|
|
}
|
|
|
|
void printSummary() {
|
|
print('$cyan═══════════════════════════════════════════════════$reset');
|
|
print('$cyan 验证完成$reset');
|
|
print('$cyan═══════════════════════════════════════════════════$reset');
|
|
}
|