全局验证码状态共享:验证码的倒计时状态需要手动重置
// 验证码倒计时的状态管理
// 验证码状态
enum CaptchaState {
init, // 初始状态
counting, // 倒计时中
restart, // 可重新发送
}
@riverpod
class Captcha extends _$Captcha {
Timer? _timer;
@override
({CaptchaState state, int countdown}) build() {
ref.onDispose(() {
_timer?.cancel();
_timer = null;
});
return (state: CaptchaState.init, countdown: 0);
}
// 初始化倒计时
void initCaptcha() {
// 取消之前的定时器,防止它继续修改状态
_timer?.cancel();
_timer = null;
// 重置状态
if (state.state != CaptchaState.init) {
state = (state: CaptchaState.init, countdown: 0);
}
}
// 启动倒计时
void startCountdown() {
if (state.state == CaptchaState.counting) {
return;
}
// 取消之前的定时器
_timer?.cancel();
// 初始化状态
state = (state: CaptchaState.counting, countdown: 60);
// 创建周期性定时器
_timer = Timer.periodic(const Duration(seconds: 1), (timer) {
final newCount = state.countdown - 1;
if (newCount <= 0) {
timer.cancel();
// 更新状态为可重新发送
state = (state: CaptchaState.restart, countdown: 0);
return;
}
// 更新倒计时状态
state = (state: CaptchaState.counting, countdown: newCount);
});
}
}
调用时:
Widget captCha() {
return Consumer(
builder: (context, ref, child) {
final captchaState = ref.watch(captchaProvider);
final notifier = ref.read(captchaProvider.notifier);
return TextButton(
onPressed: captchaState.state == CaptchaState.counting
? null // 倒计时中禁用按钮
: () {
ScaffoldMessenger.of(ref.context).showSnackBar(
const SnackBar(
content: Text('验证码已发送'),
duration: Duration(seconds: 1),
),
);
notifier.startCountdown();
},
style: TextButton.styleFrom(
padding: const EdgeInsets.symmetric(horizontal: 12),
),
child: Text(
// 根据状态显示不同的文本
captchaState.state == CaptchaState.counting
? '${captchaState.countdown}s后重发' // 倒计时中
: captchaState.state == CaptchaState.restart
? '重新获取验证码' // 倒计时结束后
: '获取验证码', // 初始状态
style: TextStyle(
color: captchaState.state == CaptchaState.counting
? Colors
.grey // 倒计时中为灰色
: Theme.of(ref.context).primaryColor, // 其他状态为主色
fontWeight: FontWeight.bold,
),
),
);
},
);
}