马良AI写作初始化仓库
This commit is contained in:
120
AINoval/lib/screens/editor/components/add_act_button.dart
Normal file
120
AINoval/lib/screens/editor/components/add_act_button.dart
Normal file
@@ -0,0 +1,120 @@
|
||||
/**
|
||||
* 添加新卷按钮组件
|
||||
*
|
||||
* 用于显示一个可点击的"添加新卷"按钮,用户点击后会触发创建新卷的逻辑。
|
||||
* 包含加载状态反馈和防抖功能,避免短时间内重复点击触发多次创建操作。
|
||||
*/
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:ainoval/utils/logger.dart';
|
||||
import 'package:ainoval/widgets/common/top_toast.dart';
|
||||
import 'package:ainoval/screens/editor/controllers/editor_screen_controller.dart';
|
||||
import 'package:ainoval/utils/web_theme.dart';
|
||||
|
||||
/// 添加新卷按钮组件
|
||||
///
|
||||
/// 在编辑器中用于添加新卷时使用的按钮组件,包含点击反馈和加载态。
|
||||
/// 使用Provider模式调用EditorScreenController中的创建方法。
|
||||
class AddActButton extends StatefulWidget {
|
||||
/// 创建一个添加新卷按钮
|
||||
const AddActButton({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<AddActButton> createState() => _AddActButtonState();
|
||||
}
|
||||
|
||||
class _AddActButtonState extends State<AddActButton> {
|
||||
/// 标记是否正在添加中,用于显示加载状态
|
||||
bool _isAdding = false;
|
||||
|
||||
/// 记录上次点击时间,用于防抖
|
||||
DateTime? _lastAddTime;
|
||||
|
||||
/// 防抖时间间隔(2秒)
|
||||
static const Duration _debounceInterval = Duration(seconds: 2);
|
||||
|
||||
/// 添加新卷的处理方法
|
||||
///
|
||||
/// 包含防抖和错误处理逻辑,避免短时间内多次触发
|
||||
void _addNewAct() {
|
||||
// 防止频繁点击导致重复添加
|
||||
final now = DateTime.now();
|
||||
if (_isAdding || (_lastAddTime != null &&
|
||||
now.difference(_lastAddTime!) < _debounceInterval)) {
|
||||
// 如果正在添加中或最后添加时间在2秒内,忽略此次点击
|
||||
AppLogger.i('AddActButton', '忽略重复点击: 正在添加=${_isAdding}, 距上次点击=${_lastAddTime != null ? now.difference(_lastAddTime!).inMilliseconds : "首次点击"}ms');
|
||||
|
||||
// 显示提示(仅在UI上)
|
||||
TopToast.warning(context, '操作正在处理中,请稍候...');
|
||||
return;
|
||||
}
|
||||
|
||||
// 记录当前时间并标记为添加中
|
||||
_lastAddTime = now;
|
||||
setState(() {
|
||||
_isAdding = true;
|
||||
});
|
||||
|
||||
AppLogger.i('AddActButton', '触发EditorScreenController的createNewAct方法');
|
||||
// 使用EditorScreenController创建新卷及章节
|
||||
Provider.of<EditorScreenController>(context, listen: false).createNewAct().then((_) {
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_isAdding = false;
|
||||
});
|
||||
}
|
||||
}).catchError((error) {
|
||||
AppLogger.e('AddActButton', '调用createNewAct失败', error);
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_isAdding = false;
|
||||
});
|
||||
TopToast.error(context, '创建失败: ${error.toString()}');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 16.0),
|
||||
child: OutlinedButton.icon(
|
||||
onPressed: _isAdding ? null : _addNewAct, // 如果正在添加中,禁用按钮
|
||||
icon: _isAdding
|
||||
// 添加中状态显示加载指示器
|
||||
? SizedBox(
|
||||
width: 18,
|
||||
height: 18,
|
||||
child: CircularProgressIndicator(
|
||||
strokeWidth: 2,
|
||||
valueColor: AlwaysStoppedAnimation<Color>(WebTheme.getPrimaryColor(context)),
|
||||
),
|
||||
)
|
||||
// 常规状态显示加号图标
|
||||
: const Icon(Icons.add, size: 18),
|
||||
label: Text(_isAdding ? '添加中...' : '添加新卷'),
|
||||
style: OutlinedButton.styleFrom(
|
||||
foregroundColor: WebTheme.getPrimaryColor(context),
|
||||
backgroundColor: WebTheme.getSurfaceColor(context),
|
||||
side: BorderSide(color: WebTheme.getPrimaryColor(context), width: 1.5),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
elevation: 1,
|
||||
).copyWith(
|
||||
overlayColor: MaterialStateProperty.resolveWith<Color?>(
|
||||
(Set<MaterialState> states) {
|
||||
if (states.contains(MaterialState.hovered)) {
|
||||
return WebTheme.getPrimaryColor(context).withOpacity(0.1);
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user