import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../core/network/api_exception.dart'; import '../../core/theme/app_theme.dart'; import '../../models/video_item.dart'; import '../../providers/profile_provider.dart'; import '../../providers/upload_provider.dart'; import '../../services/video_service.dart'; import '../feed/widgets/feed_overlays.dart'; /// 编辑作品(《03-接口文档》5.12 / 5.13,仅作者): /// 可改标题/简介/分类/标签;删除为服务端软删除,二次确认后立即下架。 class EditVideoScreen extends ConsumerStatefulWidget { const EditVideoScreen({super.key, required this.video}); final VideoItem video; @override ConsumerState createState() => _EditVideoScreenState(); } class _EditVideoScreenState extends ConsumerState { late final TextEditingController _titleCtrl; late final TextEditingController _descCtrl; late final TextEditingController _tagsCtrl; late int _categoryId; bool _submitting = false; @override void initState() { super.initState(); final v = widget.video; _titleCtrl = TextEditingController(text: v.title); _descCtrl = TextEditingController(text: v.description); _tagsCtrl = TextEditingController(text: v.tags.join(' ')); _categoryId = v.categoryId; } @override void dispose() { _titleCtrl.dispose(); _descCtrl.dispose(); _tagsCtrl.dispose(); super.dispose(); } /// 空格/逗号/顿号分隔,去重,最多 5 个 List _parseTags() => _tagsCtrl.text .split(RegExp(r'[\s,,、]+')) .map((e) => e.trim()) .where((e) => e.isNotEmpty) .toSet() .take(5) .toList(); void _toast(String message) { if (mounted) showTopToast(context, message); } Future _save() async { final title = _titleCtrl.text.trim(); if (title.isEmpty) { _toast('请填写标题'); return; } setState(() => _submitting = true); try { await VideoService.updateVideo( widget.video.videoId, title: title, description: _descCtrl.text.trim(), categoryId: _categoryId, tags: _parseTags(), ); // 刷新我的作品列表,返回后展示最新信息 ref.invalidate(myVideosProvider); _toast('已保存'); if (mounted) Navigator.of(context).maybePop(); } on ApiException catch (e) { _toast(e.message); } catch (_) { _toast('网络异常,请稍后重试'); } finally { if (mounted) setState(() => _submitting = false); } } Future _confirmDelete() async { final confirmed = await showDialog( context: context, builder: (ctx) => AlertDialog( backgroundColor: AppColors.surface, title: const Text('删除作品'), content: const Text('删除后作品立即下架且不可恢复,确定删除?'), actions: [ TextButton( onPressed: () => Navigator.pop(ctx, false), child: const Text('取消', style: TextStyle(color: AppColors.textSecondary)), ), TextButton( onPressed: () => Navigator.pop(ctx, true), child: const Text('删除', style: TextStyle(color: AppColors.primary)), ), ], ), ); if (confirmed != true) return; setState(() => _submitting = true); try { await VideoService.deleteVideo(widget.video.videoId); ref.invalidate(myVideosProvider); _toast('已删除'); if (mounted) Navigator.of(context).maybePop(); } on ApiException catch (e) { _toast(e.message); } catch (_) { _toast('网络异常,请稍后重试'); } finally { if (mounted) setState(() => _submitting = false); } } @override Widget build(BuildContext context) { final categories = ref.watch(uploadCategoriesProvider); return Scaffold( appBar: AppBar(title: const Text('编辑作品')), body: ListView( padding: const EdgeInsets.all(16), children: [ TextField( controller: _titleCtrl, enabled: !_submitting, maxLength: 100, decoration: const InputDecoration(labelText: '标题'), ), const SizedBox(height: 8), TextField( controller: _descCtrl, enabled: !_submitting, maxLength: 500, maxLines: 3, decoration: const InputDecoration(labelText: '简介'), ), const SizedBox(height: 8), const Text('分类', style: TextStyle(color: AppColors.textSecondary)), const SizedBox(height: 8), categories.when( loading: () => const LinearProgressIndicator(), error: (_, __) => const Text('分类加载失败', style: TextStyle(color: AppColors.textWeak, fontSize: 12)), data: (list) => Wrap( spacing: 8, runSpacing: 8, children: [ for (final c in list) ChoiceChip( label: Text(c.name), selected: _categoryId == c.categoryId, onSelected: _submitting ? null : (_) => setState(() => _categoryId = c.categoryId), ), ], ), ), const SizedBox(height: 16), TextField( controller: _tagsCtrl, enabled: !_submitting, decoration: const InputDecoration( labelText: '标签', hintText: '空格分隔,最多 5 个', ), ), const SizedBox(height: 24), ElevatedButton( onPressed: _submitting ? null : _save, style: ElevatedButton.styleFrom(minimumSize: const Size(0, 48)), child: const Text('保存'), ), const SizedBox(height: 8), OutlinedButton( onPressed: _submitting ? null : _confirmDelete, style: OutlinedButton.styleFrom( minimumSize: const Size(0, 48), side: const BorderSide(color: AppColors.primary), ), child: const Text('删除作品', style: TextStyle(color: AppColors.primary)), ), ], ), ); } }