feat(flutter): 接入互动评论点赞举报

This commit is contained in:
Zhou Weidong committed 2026-10-17 15:26:42 +08:00
1 parent 45f5f25640
commit d361034226
39 files changed
+3298 -462

No files matched your search

@@ -0,0 +1,62 @@
// Author: fruit.com.cn
import '../models/comment.dart';
import '../remote/comment_api.dart';
/// 评论数据来源抽象,页面与控制器不直接依赖 HTTP。
abstract interface class CommentRepository {
/// 拉取评论或回复的分页。
Future<CommentPage> page({
required String dramaId,
String? rootId,
String? cursor,
int size = commentPageSize,
});
/// 发表评论或回复。
Future<DramaComment> publish({
required String dramaId,
String? episodeId,
required String content,
String? parentId,
});
/// 删除指定评论。
Future<void> delete(String commentId);
}
/// HTTP 评论仓库。
class HttpCommentRepository implements CommentRepository {
const HttpCommentRepository(this._api);
final CommentApi _api;
@override
Future<CommentPage> page({
required String dramaId,
String? rootId,
String? cursor,
int size = commentPageSize,
}) => _api.page(
dramaId: dramaId,
rootId: rootId,
cursor: cursor,
size: size,
);
@override
Future<DramaComment> publish({
required String dramaId,
String? episodeId,
required String content,
String? parentId,
}) => _api.publish(
dramaId: dramaId,
episodeId: episodeId,
content: content,
parentId: parentId,
);
@override
Future<void> delete(String commentId) => _api.delete(commentId);
}
@@ -1,70 +0,0 @@
// Author: fruit.com.cn
import 'dart:convert';
import 'package:shared_preferences/shared_preferences.dart';
import '../models/engagement_snapshot.dart';
abstract interface class EngagementRepository {
Future<EngagementSnapshot> load();
Future<void> save(EngagementSnapshot snapshot);
}
class SharedPreferencesEngagementRepository implements EngagementRepository {
SharedPreferencesEngagementRepository({SharedPreferencesAsync? preferences})
: _preferences = preferences ?? SharedPreferencesAsync();
static const _key = 'engagement.v1.demo-local-v1';
final SharedPreferencesAsync _preferences;
@override
Future<EngagementSnapshot> load() async {
final raw = await _preferences.getString(_key);
if (raw == null) return const EngagementSnapshot();
try {
final json = jsonDecode(raw);
if (json is! Map<String, dynamic>) return const EngagementSnapshot();
Set<String> ids(Object? value) =>
value is List ? value.whereType<String>().toSet() : <String>{};
final comments = <String, List<String>>{};
final rawComments = json['comments'];
if (rawComments is Map<String, dynamic>) {
for (final entry in rawComments.entries) {
if (entry.value is List) {
comments[entry.key] = (entry.value as List)
.whereType<String>()
.toList();
}
}
}
return EngagementSnapshot(
savedDramaIds: ids(json['saved']),
likedDramaIds: ids(json['liked']),
commentsByDrama: comments,
);
} catch (_) {
return const EngagementSnapshot();
}
}
@override
Future<void> save(EngagementSnapshot snapshot) => _preferences.setString(
_key,
jsonEncode({
'saved': snapshot.savedDramaIds.toList(),
'liked': snapshot.likedDramaIds.toList(),
'comments': snapshot.commentsByDrama,
}),
);
}
class InMemoryEngagementRepository implements EngagementRepository {
EngagementSnapshot snapshot = const EngagementSnapshot();
@override
Future<EngagementSnapshot> load() async => snapshot;
@override
Future<void> save(EngagementSnapshot value) async => snapshot = value;
}
@@ -0,0 +1,32 @@
// Author: fruit.com.cn
import '../models/interaction.dart';
import '../remote/interaction_api.dart';
/// 点赞与举报数据来源抽象。
abstract interface class InteractionRepository {
/// 切换目标点赞状态。
Future<LikeToggleResult> toggleLike({
required InteractionTargetType targetType,
required String targetId,
});
/// 提交举报并返回工单 ID。
Future<String> report(ReportRequest request);
}
/// HTTP 互动仓库。
class HttpInteractionRepository implements InteractionRepository {
const HttpInteractionRepository(this._api);
final InteractionApi _api;
@override
Future<LikeToggleResult> toggleLike({
required InteractionTargetType targetType,
required String targetId,
}) => _api.toggleLike(targetType: targetType, targetId: targetId);
@override
Future<String> report(ReportRequest request) => _api.report(request);
}