完善
This commit is contained in:
32
scripts/verify_categories_detail.dart
Normal file
32
scripts/verify_categories_detail.dart
Normal file
@@ -0,0 +1,32 @@
|
||||
// 2026-04-11 | verify_categories_detail.dart | 分类数据详细验证 | 检查子分类parent_id字段
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
const String baseUrl = 'http://eat.wktyl.com/api';
|
||||
|
||||
void main() async {
|
||||
final uri = Uri.parse('$baseUrl/api.php').replace(queryParameters: {'act': 'categories'});
|
||||
final client = HttpClient();
|
||||
client.connectionTimeout = const Duration(seconds: 12);
|
||||
final request = await client.getUrl(uri);
|
||||
final response = await request.close();
|
||||
final body = await response.transform(utf8.decoder).join();
|
||||
client.close();
|
||||
|
||||
final json = jsonDecode(body) as Map<String, dynamic>;
|
||||
final data = json['data'] as List;
|
||||
|
||||
for (final topCat in data) {
|
||||
final m = topCat as Map<String, dynamic>;
|
||||
print('=== Top: id=${m['id']}, name=${m['name']} ===');
|
||||
final children = m['children'] as List?;
|
||||
if (children != null && children.isNotEmpty) {
|
||||
print(' children count: ${children.length}');
|
||||
for (final child in children.take(5)) {
|
||||
final cm = child as Map<String, dynamic>;
|
||||
print(' child keys: ${cm.keys.join(', ')}');
|
||||
print(' child: id=${cm['id'] ?? cm['cate_id']}, name=${cm['name'] ?? cm['cate_name']}, parent_id=${cm['parent_id']}');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
27
scripts/verify_eating_times.dart
Normal file
27
scripts/verify_eating_times.dart
Normal file
@@ -0,0 +1,27 @@
|
||||
// 2026-04-11 | verify_eating_times.dart | 用餐时段数据验证 | 获取eating_times.json数据结构
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
void main() async {
|
||||
final uri = Uri.parse('http://eat.wktyl.com/api/assets/eating_times.json');
|
||||
final client = HttpClient();
|
||||
client.connectionTimeout = const Duration(seconds: 12);
|
||||
final request = await client.getUrl(uri);
|
||||
final response = await request.close();
|
||||
final body = await response.transform(utf8.decoder).join();
|
||||
client.close();
|
||||
|
||||
final json = jsonDecode(body);
|
||||
if (json is List) {
|
||||
print('Total items: ${json.length}');
|
||||
for (final item in json.take(5)) {
|
||||
final m = item as Map<String, dynamic>;
|
||||
print('keys: ${m.keys.join(', ')}');
|
||||
print('item: ${jsonEncode(m)}');
|
||||
print('');
|
||||
}
|
||||
} else if (json is Map) {
|
||||
print('Top-level keys: ${json.keys.join(', ')}');
|
||||
print(jsonEncode(json).substring(0, 500));
|
||||
}
|
||||
}
|
||||
54
scripts/verify_filter_apply.dart
Normal file
54
scripts/verify_filter_apply.dart
Normal file
@@ -0,0 +1,54 @@
|
||||
// 2026-04-11 | verify_filter_apply.dart | filter_apply接口验证 | 测试不同分类ID的筛选
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
const String baseUrl = 'http://eat.wktyl.com/api';
|
||||
|
||||
void main() async {
|
||||
await testFilterApply(category: '12', label: '中国菜(id=12)');
|
||||
await testFilterApply(category: '13', label: '粤菜(id=13)');
|
||||
await testFilterApply(category: '11', label: '菜谱(id=11)');
|
||||
await testFilterApply(tag: '74', label: '粉蒸(tag=74)');
|
||||
await testFilterApply(category: '12', tag: '74', label: '中国菜+粉蒸');
|
||||
}
|
||||
|
||||
Future<void> testFilterApply({String? category, String? tag, required String label}) async {
|
||||
print('▶ $label');
|
||||
final params = <String, String>{'act': 'filter_apply', 'count': '3'};
|
||||
if (category != null) params['category'] = category;
|
||||
if (tag != null) params['tag'] = tag;
|
||||
|
||||
final uri = Uri.parse('$baseUrl/api_what_to_eat.php').replace(queryParameters: params);
|
||||
try {
|
||||
final client = HttpClient();
|
||||
client.connectionTimeout = const Duration(seconds: 12);
|
||||
final request = await client.getUrl(uri);
|
||||
final response = await request.close();
|
||||
final body = await response.transform(utf8.decoder).join();
|
||||
client.close();
|
||||
|
||||
final json = jsonDecode(body) as Map<String, dynamic>;
|
||||
final code = json['code'];
|
||||
final data = json['data'];
|
||||
|
||||
if (code == 200 && data != null) {
|
||||
if (data is Map) {
|
||||
final recipes = data['recipes'] as List?;
|
||||
print(' ✅ code=$code, recipes=${recipes?.length ?? 0}');
|
||||
if (recipes != null && recipes.isNotEmpty) {
|
||||
for (final r in recipes.take(2)) {
|
||||
final m = r as Map<String, dynamic>;
|
||||
print(' - id=${m['id']}, title=${m['title']}');
|
||||
}
|
||||
}
|
||||
} else if (data is List) {
|
||||
print(' ✅ code=$code, data is List, count=${data.length}');
|
||||
}
|
||||
} else {
|
||||
print(' ❌ code=$code, message=${json['message']}');
|
||||
}
|
||||
} catch (e) {
|
||||
print(' ❌ error: $e');
|
||||
}
|
||||
print('');
|
||||
}
|
||||
40
scripts/verify_recipe_images.dart
Normal file
40
scripts/verify_recipe_images.dart
Normal file
@@ -0,0 +1,40 @@
|
||||
// 2026-04-11 | verify_recipe_images.dart | 菜谱图片URL验证 | 测试fallback链
|
||||
import 'dart:io';
|
||||
|
||||
void main() async {
|
||||
final client = HttpClient();
|
||||
client.connectionTimeout = const Duration(seconds: 8);
|
||||
|
||||
final testIds = [1, 150, 1585];
|
||||
final base = 'http://eat.wktyl.com/api/assets';
|
||||
|
||||
for (final id in testIds) {
|
||||
print('\n--- Testing id=$id ---');
|
||||
final urls = [
|
||||
'$base/pic/${id}a.jpg',
|
||||
'$base/pic/${id}b.jpg',
|
||||
'$base/pic/$id.jpg',
|
||||
];
|
||||
|
||||
for (final url in urls) {
|
||||
try {
|
||||
final req = await client.headUrl(Uri.parse(url));
|
||||
final resp = await req.close();
|
||||
print(' ${resp.statusCode == 200 ? "✅" : "❌"} $url → ${resp.statusCode}');
|
||||
} catch (e) {
|
||||
print(' ❌ $url → error: $e');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test back.png
|
||||
try {
|
||||
final req = await client.headUrl(Uri.parse('$base/back.png'));
|
||||
final resp = await req.close();
|
||||
print('\n${resp.statusCode == 200 ? "✅" : "❌"} $base/back.png → ${resp.statusCode}');
|
||||
} catch (e) {
|
||||
print('\n❌ back.png → error: $e');
|
||||
}
|
||||
|
||||
client.close();
|
||||
}
|
||||
185
scripts/verify_what_to_eat_api.dart
Normal file
185
scripts/verify_what_to_eat_api.dart
Normal file
@@ -0,0 +1,185 @@
|
||||
// 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');
|
||||
}
|
||||
Reference in New Issue
Block a user