Files
xianyan/lib/features/article/providers/article_provider.dart
Developer 7564e8893d chore: 完成多平台适配与代码优化
此提交包含多项变更:
1. 新增鸿蒙平台支持,完善设备检测与数据库适配
2. 替换旧版分享插件API为SharePlus
3. 批量迁移StateNotifier到Notifier以适配新版Riverpod
4. 修复zip编码判断、图表API参数等bug
5. 更新应用图标、启动页资源与多尺寸适配图标
6. 调整Android最小SDK版本与应用名称
7. 优化日志打印与正则表达式使用
8. 修正编辑器画布样式初始化与配置逻辑
9. 更新依赖与CI插件配置
2026-05-17 07:17:07 +08:00

206 lines
5.8 KiB
Dart

// ============================================================
// 闲言APP — 文章创作状态管理
// 创建时间: 2026-04-29
// 更新时间: 2026-04-29
// 作用: 文章列表/详情/创作/我的文章状态管理
// 上次更新: 初始创建
// ============================================================
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../../../core/utils/logger.dart';
import '../models/article_models.dart';
import '../services/article_service.dart';
class ArticleState {
const ArticleState({
this.isLoading = false,
this.isSubmitting = false,
this.error,
this.articles = const [],
this.myArticles = const [],
this.currentArticle,
this.comments = const [],
this.page = 1,
this.hasMore = true,
this.myPage = 1,
this.myHasMore = true,
this.selectedCategory,
this.searchKeyword = '',
});
final bool isLoading;
final bool isSubmitting;
final String? error;
final List<Article> articles;
final List<Article> myArticles;
final Article? currentArticle;
final List<ArticleComment> comments;
final int page;
final bool hasMore;
final int myPage;
final bool myHasMore;
final String? selectedCategory;
final String searchKeyword;
ArticleState copyWith({
bool? isLoading,
bool? isSubmitting,
String? error,
bool clearError = false,
List<Article>? articles,
List<Article>? myArticles,
Article? currentArticle,
bool clearCurrentArticle = false,
List<ArticleComment>? comments,
int? page,
bool? hasMore,
int? myPage,
bool? myHasMore,
String? selectedCategory,
bool clearSelectedCategory = false,
String? searchKeyword,
bool clearSearch = false,
}) {
return ArticleState(
isLoading: isLoading ?? this.isLoading,
isSubmitting: isSubmitting ?? this.isSubmitting,
error: clearError ? null : (error ?? this.error),
articles: articles ?? this.articles,
myArticles: myArticles ?? this.myArticles,
currentArticle: clearCurrentArticle
? null
: (currentArticle ?? this.currentArticle),
comments: comments ?? this.comments,
page: page ?? this.page,
hasMore: hasMore ?? this.hasMore,
myPage: myPage ?? this.myPage,
myHasMore: myHasMore ?? this.myHasMore,
selectedCategory: clearSelectedCategory
? null
: (selectedCategory ?? this.selectedCategory),
searchKeyword: clearSearch ? '' : (searchKeyword ?? this.searchKeyword),
);
}
}
class ArticleNotifier extends Notifier<ArticleState> {
@override
ArticleState build() => const ArticleState();
ArticleNotifier();
/// 加载文章列表
Future<void> loadArticles({
bool refresh = false,
String? category,
String? keyword,
}) async {
if (state.isLoading && !refresh) return;
final page = refresh ? 1 : state.page;
state = state.copyWith(
isLoading: true,
clearError: true,
page: page,
selectedCategory: category ?? state.selectedCategory,
searchKeyword: keyword ?? state.searchKeyword,
);
try {
final articles = await ArticleService.getArticleList(
page: page,
category: category ?? state.selectedCategory,
keyword: keyword ?? state.searchKeyword,
);
state = state.copyWith(
articles: refresh ? articles : [...state.articles, ...articles],
isLoading: false,
page: page + 1,
hasMore: articles.length >= 20,
);
} catch (e) {
Log.e('加载文章列表失败', e);
state = state.copyWith(isLoading: false, error: '加载失败');
}
}
/// 加载文章详情
Future<void> loadArticleDetail({required int id}) async {
state = state.copyWith(isLoading: true, clearError: true);
try {
final article = await ArticleService.getArticleDetail(id: id);
final comments =
await ArticleService.getArticleComments(articleId: id);
state = state.copyWith(
currentArticle: article,
comments: comments,
isLoading: false,
);
} catch (e) {
Log.e('加载文章详情失败', e);
state = state.copyWith(isLoading: false, error: '加载失败');
}
}
/// 提交文章
Future<bool> submitArticle({
int? id,
required String title,
required String content,
String? summary,
String? category,
List<String>? tags,
}) async {
state = state.copyWith(isSubmitting: true);
try {
await ArticleService.submitArticle(
id: id,
title: title,
content: content,
summary: summary,
category: category,
tags: tags,
);
state = state.copyWith(isSubmitting: false);
return true;
} catch (e) {
Log.e('提交文章失败', e);
state = state.copyWith(isSubmitting: false);
return false;
}
}
/// 加载我的文章
Future<void> loadMyArticles({bool refresh = false}) async {
if (state.isLoading && !refresh) return;
final page = refresh ? 1 : state.myPage;
state = state.copyWith(isLoading: true, clearError: true, myPage: page);
try {
final articles = await ArticleService.getMyArticles(page: page);
state = state.copyWith(
myArticles:
refresh ? articles : [...state.myArticles, ...articles],
isLoading: false,
myPage: page + 1,
myHasMore: articles.length >= 20,
);
} catch (e) {
Log.e('加载我的文章失败', e);
state = state.copyWith(isLoading: false, error: '加载失败');
}
}
/// 删除文章
Future<bool> deleteArticle({required int id}) async {
try {
return await ArticleService.deleteArticle(id: id);
} catch (e) {
Log.e('删除文章失败', e);
return false;
}
}
}
final articleProvider =
NotifierProvider<ArticleNotifier, ArticleState>(ArticleNotifier.new);