详细页优化

This commit is contained in:
Developer
2026-04-11 22:55:27 +08:00
parent 2d7484fd29
commit 442f648128
213 changed files with 6170 additions and 29298 deletions

View File

@@ -0,0 +1,32 @@
// 时间戳调试脚本
void main() {
final timestamp = 146085838541;
print('🔍 时间戳调试');
print('原始值: $timestamp (${timestamp.toString().length}位)');
// 尝试不同的解析方式
print('\n方式1: 当作毫秒 (直接使用)');
final d1 = DateTime.fromMillisecondsSinceEpoch(timestamp);
print('结果: ${d1.year}-${d1.month}-${d1.day} ${d1.hour}:${d1.minute}');
print('\n方式2: 当作秒 (×1000转毫秒)');
final d2 = DateTime.fromMillisecondsSinceEpoch(timestamp * 1000);
print('结果: ${d2.year}-${d2.month}-${d2.day} ${d2.hour}:${d2.minute}');
print('\n方式3: 除以1000当作秒 (可能是微秒?)');
final d3 = DateTime.fromMillisecondsSinceEpoch((timestamp / 1000).round() * 1000);
print('结果: ${d3.year}-${d3.month}-${d3.day} ${d3.hour}:${d3.minute}');
// 2016年的正确时间戳
print('\n--- 参考值 ---');
final date2016 = DateTime(2016, 4, 18, 15, 35);
print('2016-04-18 15:35 的毫秒时间戳: ${date2016.millisecondsSinceEpoch}');
print('2016-04-18 15:35 的秒时间戳: ${date2016.millisecondsSinceEpoch ~/ 1000}');
// 检查是否差1000倍
final correctMs = 1460858385000; // 13位
print('\n如果是13位: $correctMs');
final d4 = DateTime.fromMillisecondsSinceEpoch(correctMs);
print('结果: ${d4.year}-${d4.month}-${d4.day} ${d4.hour}:${d4.minute}');
}

View File

@@ -0,0 +1,173 @@
// 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>;
}