Files
xianyan/lib/features/template/services/wallpaper_service.dart
Developer d2bd53f3bc refactor: 完成v6.5.28版本迭代,修复多项体验问题
主要变更:
1. 重构多处Provider初始化逻辑,使用Future.microtask避免build阶段修改state
2. 重命名"灵感"模块为"工作流","天气诗词"改为"情景诗词"
3. 新增插件系统页面与路由,添加speech_to_text_windows插件支持
4. 优化玻璃容器性能,添加性能节流与模糊值适配
5. 新增离线横幅、阅读体验控制器、手势控制器等组件
6. 完善头像审核状态展示与缓存管理
7. 修复键盘弹出与页面路由问题
8. 更新依赖与项目配置,优化widget默认数据
2026-05-26 01:47:47 +08:00

196 lines
5.9 KiB
Dart

/// ============================================================
/// 闲言APP — 壁纸图库服务
/// 创建时间: 2026-05-01
/// 更新时间: 2026-05-26
/// 作用: 壁纸图库API对接 — 12个源 + 分页 + 搜索 + 缓存
/// 上次更新: 增加超时时间(connect 8s/receive 12s)避免慢源请求失败
/// ============================================================
import 'package:dio/dio.dart';
import '../../../core/utils/logger.dart';
import '../models/template_models.dart';
class WallpaperService {
WallpaperService._();
static final Dio _dio = Dio(
BaseOptions(
baseUrl: 'http://bz.wktyl.com',
connectTimeout: const Duration(seconds: 8),
receiveTimeout: const Duration(seconds: 12),
headers: {'User-Agent': 'Xianyan/1.0'},
),
);
// ============================================================
// 获取壁纸列表
// ============================================================
static Future<WallpaperResult> fetchWallpapers({
WallpaperSource source = WallpaperSource.unsplash,
int page = 1,
int limit = 20,
WallpaperCategory category = WallpaperCategory.all,
String sort = 'hot',
String? search,
}) async {
try {
final url = source.buildUrl(
limit: limit,
page: page,
category: category.id,
sort: sort,
search: search,
);
final response = await _dio.get<Map<String, dynamic>>(url);
final data = response.data;
if (data == null || data['success'] != true) {
Log.w('壁纸API返回失败: source=${source.label}');
return const WallpaperResult(items: [], currentPage: 1, totalPages: 0);
}
final pagination = data['pagination'] as Map<String, dynamic>? ?? {};
final rawData = data['data'];
final List<WallpaperItem> list;
if (rawData is List<dynamic>) {
list = rawData
.whereType<Map<String, dynamic>>()
.map((e) => WallpaperItem.fromApi(e))
.toList();
} else if (rawData is Map<String, dynamic>) {
list = [WallpaperItem.fromApi(rawData)];
} else {
list = [];
}
return WallpaperResult(
items: list,
currentPage: pagination['current_page'] as int? ?? page,
totalPages: pagination['total_pages'] as int? ?? 1,
totalItems: pagination['total_items'] as int? ?? list.length,
hasNext: pagination['has_next'] as bool? ?? false,
);
} on DioException catch (e) {
Log.e('壁纸请求失败 [${source.label}]', e);
return const WallpaperResult(items: [], currentPage: 1, totalPages: 0);
} catch (e) {
Log.e('壁纸解析失败 [${source.label}]', e);
return const WallpaperResult(items: [], currentPage: 1, totalPages: 0);
}
}
// ============================================================
// 快速获取 (极速源)
// ============================================================
static Future<List<WallpaperItem>> fetchQuick({
int limit = 10,
WallpaperCategory category = WallpaperCategory.all,
}) async {
final result = await fetchWallpapers(limit: limit, category: category);
return result.items;
}
// ============================================================
// 快速源聚合 (avgMs < 500)
// ============================================================
static Future<List<WallpaperItem>> fetchQuickSources({
int limitPerSource = 6,
WallpaperCategory category = WallpaperCategory.all,
}) async {
final quickSources = WallpaperSource.values.where((s) => s.isFast).toList();
return fetchMultiSource(
sources: quickSources,
limitPerSource: limitPerSource,
category: category,
);
}
// ============================================================
// 多源聚合
// ============================================================
static Future<List<WallpaperItem>> fetchMultiSource({
List<WallpaperSource>? sources,
int limitPerSource = 6,
WallpaperCategory category = WallpaperCategory.all,
}) async {
final effectiveSources =
sources ?? WallpaperSource.values.where((s) => s.isFast).toList();
final allItems = <WallpaperItem>[];
final futures = effectiveSources.map(
(source) =>
fetchWallpapers(
source: source,
limit: limitPerSource,
category: category,
)
.timeout(
const Duration(seconds: 5),
onTimeout: () => const WallpaperResult(
items: [],
currentPage: 1,
totalPages: 0,
),
)
.catchError(
(_) => const WallpaperResult(
items: [],
currentPage: 1,
totalPages: 0,
),
),
);
final results = await Future.wait(futures);
for (final result in results) {
allItems.addAll(result.items);
}
allItems.shuffle();
return allItems;
}
// ============================================================
// 搜索壁纸
// ============================================================
static Future<List<WallpaperItem>> searchWallpapers(
String keyword, {
WallpaperSource source = WallpaperSource.unsplash,
int limit = 20,
}) async {
final result = await fetchWallpapers(
source: source,
limit: limit,
search: keyword,
);
return result.items;
}
}
// ============================================================
// 壁纸分页结果
// ============================================================
class WallpaperResult {
const WallpaperResult({
required this.items,
required this.currentPage,
required this.totalPages,
this.totalItems = 0,
this.hasNext = false,
});
final List<WallpaperItem> items;
final int currentPage;
final int totalPages;
final int totalItems;
final bool hasNext;
}