// ============================================================ // 闲言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
articles; final List
myArticles; final Article? currentArticle; final List 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
? articles, List
? myArticles, Article? currentArticle, bool clearCurrentArticle = false, List? 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 { @override ArticleState build() => const ArticleState(); ArticleNotifier(); /// 加载文章列表 Future 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 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 submitArticle({ int? id, required String title, required String content, String? summary, String? category, List? 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 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 deleteArticle({required int id}) async { try { return await ArticleService.deleteArticle(id: id); } catch (e) { Log.e('删除文章失败', e); return false; } } } final articleProvider = NotifierProvider(ArticleNotifier.new);