提交 1cc1304a authored 作者: 祁增奎's avatar 祁增奎

组件重构逻辑,待验证,后续切换需要通知测试验证

上级 59255731
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"fluttertoast","path":"/Users/mrqi/.pub-cache/hosted/pub.flutter-io.cn/fluttertoast-8.2.8/","native_build":true,"dependencies":[]}],"android":[{"name":"fluttertoast","path":"/Users/mrqi/.pub-cache/hosted/pub.flutter-io.cn/fluttertoast-8.2.8/","native_build":true,"dependencies":[]}],"macos":[],"linux":[],"windows":[],"web":[{"name":"fluttertoast","path":"/Users/mrqi/.pub-cache/hosted/pub.flutter-io.cn/fluttertoast-8.2.8/","dependencies":[]}]},"dependencyGraph":[{"name":"fluttertoast","dependencies":[]}],"date_created":"2025-04-24 14:46:53.353732","version":"3.19.6"}
\ No newline at end of file
<!--
This README describes the package. If you publish this package to pub.dev,
this README's contents appear on the landing page for your package.
# CLX Verification Code
For information about how to write a good package README, see the guide for
[writing package pages](https://dart.dev/guides/libraries/writing-package-pages).
一个功能强大、高度可定制的 Flutter 验证码业务组件。支持短信验证码、语音验证码、倒计时管理、自动状态流转(如短信未收到自动提示语音验证码)以及完善的错误处理。
For general information about developing packages, see the Dart guide for
[creating packages](https://dart.dev/guides/libraries/create-library-packages)
and the Flutter guide for
[developing packages and plugins](https://flutter.dev/developing-packages).
-->
## 🚀 快速开始
TODO: Put a short description of the package here that helps potential users
know whether this package might be useful for them.
### 1. 实现服务接口
## Features
首先,你需要实现 `IVerificationService` 接口,对接你的后端 API。
TODO: List what your package can do. Maybe include images, gifs, or videos.
```dart
import 'package:clx_verification_code/clx_verification_code.dart';
class MyVerificationService implements IVerificationService {
@override
Future<bool> sendSmsCode() async {
// TODO: 调用发送短信 API
// return await api.sendSms();
return true;
}
## Getting started
@override
Future<bool> sendVoiceCode() async {
// TODO: 调用发送语音 API
return true;
}
TODO: List prerequisites and provide or point to information on how to
start using the package.
@override
Future<String?> verifyCode(String code) async {
// TODO: 调用校验 API
// return null; // 校验通过
return "验证码错误"; // 返回错误信息
}
## Usage
@override
Future<void> contactCustomerService() async {
// TODO: 处理联系客服逻辑
}
}
```
TODO: Include short and useful examples for package users. Add longer examples
to `/example` folder.
### 2. 使用组件
在你的页面中使用 `CLXLineCodeManageView``CLXPageCodeManageView`
```dart
const like = 'sample';
import 'package:flutter/material.dart';
import 'package:clx_verification_code/clx_verification_code.dart';
class LoginPage extends StatefulWidget {
@override
_LoginPageState createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
late VerificationCodeViewModel _viewModel;
@override
void initState() {
super.initState();
// 初始化 ViewModel
_viewModel = VerificationCodeViewModel(
service: MyVerificationService(),
maxLength: 6,
onShowToast: (msg) {
// 处理 Toast 提示
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(msg)));
},
);
}
@override
void dispose() {
_viewModel.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("验证码示例")),
body: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
children: [
// 使用行内样式组件
CLXLineCodeManageView(
viewModel: _viewModel,
config: LineCodeManageConfig(
hintText: "请输入验证码",
// 更多样式配置...
),
),
SizedBox(height: 20),
ElevatedButton(
onPressed: () {
// 可以在这里获取输入内容
print("输入内容: ${_viewModel.codeInputCtrl.text}");
},
child: Text("提交"),
)
],
),
),
);
}
}
```
## Additional information
## 📚 API 文档
### VerificationCodeViewModel
| 参数 | 类型 | 说明 | 默认值 |
| --- | --- | --- | --- |
| `service` | `IVerificationService` | **必传**。业务逻辑实现接口。 | - |
| `maxLength` | `int` | 验证码长度。 | `6` |
| `isFirstResponsed` | `bool` | 是否自动获取焦点。 | `false` |
| `isAccessOutbound` | `bool` | 是否开启语音验证码/外呼功能。 | `true` |
| `onShowToast` | `Function(String)` | Toast 提示回调。 | `null` |
### IVerificationService
| 方法 | 返回值 | 说明 |
| --- | --- | --- |
| `sendSmsCode()` | `Future<bool>` | 发送短信验证码。返回 `true` 表示成功。 |
| `sendVoiceCode()` | `Future<bool>` | 发送语音验证码。返回 `true` 表示成功。 |
| `verifyCode(String code)` | `Future<String?>` | 校验验证码。返回 `null` 表示通过,否则返回错误文案。 |
| `contactCustomerService()` | `Future<void>` | 联系客服的回调。 |
### 组件视图
#### CLXLineCodeManageView
适用于表单行内的验证码输入(通常是左侧输入框,右侧发送按钮)。
| 参数 | 类型 | 说明 |
| --- | --- | --- |
| `viewModel` | `VerificationCodeViewModel` | ViewModel 实例。 |
| `config` | `LineCodeManageConfig` | 样式配置对象。 |
| `disabled` | `bool` | 是否禁用输入。 |
#### CLXPageCodeManageView
适用于独立的验证码输入页面(通常是分格输入框)。
| 参数 | 类型 | 说明 |
| --- | --- | --- |
| `viewModel` | `VerificationCodeViewModel` | ViewModel 实例。 |
| `config` | `PageCodeManageConfig` | 样式配置对象。 |
### 配置对象
#### LineCodeManageConfig / PageCodeManageConfig
### 1.0.1
- 增加拦截,防止直接粘贴提示文案导致触发多次输入变化
支持配置 `margin`, `padding`, `decoration`, `hintText`, `hintStyle`, `style`, `countdownStyle`, `errorStyle` 等几乎所有视觉元素。详情请参考源码注释。
library clx_verification_code;
/// 公共控制器
export 'code_manage/clx_code_manage_logic.dart';
export 'code_manage/verification_code_view_model.dart';
/// -------公共View---------
export 'views/clx_line_code_manage_view.dart';
export 'views/clx_page_code_manage_view.dart';
/// -------公共Package---------
export 'package:get/get.dart';
export 'package:fluttertoast/fluttertoast.dart';
/// -------公共Widget---------
export 'widgets/input_widget/code_input_paint.dart';
export 'widgets/input_widget/code_input_view.dart';
......@@ -22,3 +18,8 @@ export 'widgets/tips_widget/no_receive_voice_view.dart';
export 'utils/line_code_manage_config.dart';
export 'utils/page_code_manage_config.dart';
export 'utils/code_send_enum.dart';
/// -------Core---------
export 'core/verification_service_interface.dart';
export 'core/countdown_controller.dart';
export 'core/verification_state_machine.dart';
import 'dart:async';
import 'package:flutter/widgets.dart';
import 'package:get/get.dart';
import 'package:fluttertoast/fluttertoast.dart';
import '../utils/code_send_enum.dart';
class CLXCodeManageLogic extends GetxController {
CLXCodeManageLogic(
{this.maxLength = 6,
this.isFirstResponsed = false,
this.isAccessOutbound = true});
/// 验证码长度
final int maxLength;
/// 是否是成为第一响应者
final bool isFirstResponsed;
/// 是否接入外呼功能
final bool isAccessOutbound;
/// 验证码输入框焦点
final FocusNode codeInoutFocus = FocusNode();
/// 验证码输入框控制器
final TextEditingController codeInoutCtrl = TextEditingController();
/// 倒计时
RxInt countdown = 60.obs;
/// 定时器
Timer? timer;
/// 获取短信验证码
Future<bool?> Function()? getSmsVerificationCode;
/// 获取语音验证码
Future<bool?> Function()? obtainVoiceVerificationCode;
/// 校验验证码输入是否有误
Future<String?> Function(String code)? verifyCode;
/// 联系客服点击事件
Future Function()? contactCustomerService;
/// 验证码校验错误信息
RxString verifyCodeError = ''.obs;
/// 获取验证码按钮文案
RxString codeSendBtn = '获取验证码'.obs;
/// 验证码发送状态
Rx<CodeSendType> codeSendType = CodeSendType.none.obs;
/// 是否展示提示信息模块
RxBool isShowTip = false.obs;
/// 刷新页面需要
RxString refreshPage = ''.obs;
/// 是否允许发送验证码
bool canSend = true;
@override
void onInit() {
super.onInit();
codeInoutCtrl.addListener(_verifyCodeInput);
if (isFirstResponsed) {
codeInoutFocus.requestFocus();
}
}
/// 校验验证码
_verifyCodeInput() async {
/// 处理多次发送校验间隔问题
if (refreshPage.value == codeInoutCtrl.text) {
return;
}
handleTipInfo();
update();
refreshPage.value = codeInoutCtrl.text;
if (codeInoutCtrl.text.length != maxLength) {
return;
}
final result = await verifyCode?.call(codeInoutCtrl.text) ?? '';
verifyCodeError.value = result;
handleTipInfo();
}
/// 外部调用开启定时器
startTimerAndChangeType() {
if (!canSend) {
return;
}
canSend = false;
_startCountdown();
handleCodeSendType();
}
/// 发送短信验证码
sendSmsCode() async {
if (!canSend) {
return;
}
canSend = false;
if (countdown.value != 60) {
return;
}
final result = await getSmsVerificationCode?.call();
if (result == true) {
handleCodeSendType();
_startCountdown();
} else {
canSend = true;
}
}
/// 发送语音验证码
sendVoiceCode() async {
if (!canSend) {
return;
}
canSend = false;
if (countdown.value != 60) {
return;
}
final result = await obtainVoiceVerificationCode?.call();
if (result == true) {
handleCodeSendType(isSmsSend: false);
_startCountdown(isSmsSend: false);
Fluttertoast.showToast(
msg: '即将向您电话播报',
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.CENTER,
timeInSecForIosWeb: 2,
);
} else {
canSend = true;
}
}
/// 联系客服
contactService() async {
await contactCustomerService?.call();
}
/// 开启倒计时
_startCountdown({bool isSmsSend = true}) {
if (countdown.value != 60) {
return;
}
timer = Timer.periodic(const Duration(seconds: 1), (timer) {
if (countdown.value == 0) {
timer.cancel();
codeSendBtn.value = '';
countdown.value = 60;
canSend = true;
handleCodeSendType(isSmsSend: isSmsSend);
handleTipInfo();
} else {
countdown.value--;
codeSendBtn.value = '已发送${countdown.value}s';
}
});
}
/// 处理验证码发送状态
handleCodeSendType({bool isSmsSend = true}) {
switch (codeSendType.value) {
case CodeSendType.none:
codeSendType.value = CodeSendType.firstSendSmsCode;
break;
case CodeSendType.firstSendSmsCode:
codeSendType.value = CodeSendType.notReceiveSmsCode;
break;
case CodeSendType.notReceiveSmsCode:
if (isSmsSend) {
codeSendType.value = CodeSendType.resendSmsCode;
} else {
codeSendType.value = CodeSendType.firstSendVoiceCode;
}
break;
case CodeSendType.resendSmsCode:
if (isAccessOutbound) {
codeSendType.value = CodeSendType.notReceiveResendSmsCode;
}
break;
case CodeSendType.notReceiveResendSmsCode:
codeSendType.value = CodeSendType.firstSendVoiceCode;
break;
case CodeSendType.firstSendVoiceCode:
codeSendType.value = CodeSendType.notReceiveVoiceCode;
break;
case CodeSendType.notReceiveVoiceCode:
codeSendType.value = CodeSendType.resendVoiceCode;
break;
case CodeSendType.resendVoiceCode:
codeSendType.value = CodeSendType.notReceiveResendVoiceCode;
break;
case CodeSendType.notReceiveResendVoiceCode:
codeSendType.value = CodeSendType.resendVoiceCode;
break;
default:
codeSendType.value = CodeSendType.notReceiveResendVoiceCode;
break;
}
}
/// 处理提示信息
handleTipInfo() {
/// 如果输入框内容不为空,则不展示提示信息
isShowTip.value = verifyCodeError.value.isNotEmpty ||
codeInoutCtrl.text.isEmpty && countdown.value == 60;
}
}
import 'package:flutter/widgets.dart';
import '../core/verification_service_interface.dart';
import '../core/countdown_controller.dart';
import '../core/verification_state_machine.dart';
import '../utils/code_send_enum.dart';
/// 验证码 ViewModel
class VerificationCodeViewModel extends ChangeNotifier {
VerificationCodeViewModel({
required this.service,
this.maxLength = 6,
this.isFirstResponsed = false,
this.isAccessOutbound = true,
this.onShowToast,
}) : _countdownController = CountdownController(),
_stateMachine = VerificationStateMachine(isAccessOutbound: isAccessOutbound) {
codeInputCtrl.addListener(_verifyCodeInput);
_countdownController.addListener(_onCountdownChanged);
if (isFirstResponsed) {
codeInputFocus.requestFocus();
}
}
/// 外部注入的服务接口
final IVerificationService service;
/// 倒计时控制器
final CountdownController _countdownController;
/// 状态机
final VerificationStateMachine _stateMachine;
/// 验证码长度
final int maxLength;
/// 是否是成为第一响应者
final bool isFirstResponsed;
/// 是否接入外呼功能
final bool isAccessOutbound;
/// Toast 回调
final Function(String msg)? onShowToast;
/// 验证码输入框焦点
final FocusNode codeInputFocus = FocusNode();
/// 验证码输入框控制器
final TextEditingController codeInputCtrl = TextEditingController();
/// 验证码校验错误信息
String _verifyCodeError = '';
String get verifyCodeError => _verifyCodeError;
/// 获取验证码按钮文案
String _codeSendBtn = '获取验证码';
String get codeSendBtn => _codeSendBtn;
/// 验证码发送状态
CodeSendType _codeSendType = CodeSendType.none;
CodeSendType get codeSendType => _codeSendType;
/// 是否展示提示信息模块
bool _isShowTip = false;
bool get isShowTip => _isShowTip;
/// 记录上一次输入,防止重复校验
String _lastInput = '';
/// 是否允许发送验证码
bool _canSend = true;
@override
void dispose() {
codeInputCtrl.removeListener(_verifyCodeInput);
_countdownController.removeListener(_onCountdownChanged);
codeInputCtrl.dispose();
codeInputFocus.dispose();
_countdownController.dispose();
super.dispose();
}
/// 倒计时变化回调
void _onCountdownChanged() {
if (_countdownController.isRunning) {
_codeSendBtn = '已发送${_countdownController.currentCount}s';
} else {
// 倒计时结束
_codeSendBtn = '';
_canSend = true;
// 在 startTimer 时记录类型,或者直接根据当前状态判断
if (_codeSendType.isSend) {
_codeSendType = _stateMachine.nextState(_codeSendType, isSmsSend: _codeSendType.isSms);
_handleTipInfo();
}
}
notifyListeners();
}
/// 校验验证码
void _verifyCodeInput() async {
if (_lastInput == codeInputCtrl.text) return;
_lastInput = codeInputCtrl.text;
_handleTipInfo();
notifyListeners();
if (codeInputCtrl.text.length != maxLength) return;
final result = await service.verifyCode(codeInputCtrl.text);
_verifyCodeError = result ?? '';
_handleTipInfo();
notifyListeners();
}
/// 外部调用开启定时器
void startTimerAndChangeType() {
if (!_canSend) return;
_canSend = false;
_codeSendType = _stateMachine.nextState(_codeSendType);
_countdownController.start();
notifyListeners();
}
/// 发送短信验证码
Future<void> sendSmsCode() async {
if (!_canSend) return;
_canSend = false;
if (_countdownController.isRunning) return;
final success = await service.sendSmsCode();
if (success) {
_codeSendType = _stateMachine.nextState(_codeSendType, isSmsSend: true);
_countdownController.start();
} else {
_canSend = true;
}
notifyListeners();
}
/// 发送语音验证码
Future<void> sendVoiceCode() async {
if (!_canSend) return;
_canSend = false;
if (_countdownController.isRunning) return;
final success = await service.sendVoiceCode();
if (success) {
_codeSendType = _stateMachine.nextState(_codeSendType, isSmsSend: false);
_countdownController.start();
onShowToast?.call('即将向您电话播报');
} else {
_canSend = true;
}
notifyListeners();
}
/// 联系客服
Future<void> contactService() async {
await service.contactCustomerService();
}
/// 处理提示信息
void _handleTipInfo() {
_isShowTip = _verifyCodeError.isNotEmpty ||
(codeInputCtrl.text.isEmpty && !_countdownController.isRunning && _codeSendType != CodeSendType.none);
}
}
import 'dart:async';
import 'package:flutter/foundation.dart';
/// 倒计时控制器
class CountdownController extends ChangeNotifier {
CountdownController({this.duration = 60});
final int duration;
Timer? _timer;
int _currentCount = 0;
bool _isRunning = false;
int get currentCount => _currentCount;
bool get isRunning => _isRunning;
/// 开始倒计时
void start() {
if (_isRunning) return;
_currentCount = duration;
_isRunning = true;
notifyListeners();
_timer?.cancel();
_timer = Timer.periodic(const Duration(seconds: 1), (timer) {
if (_currentCount <= 0) {
stop();
} else {
_currentCount--;
notifyListeners();
}
});
}
/// 停止倒计时
void stop() {
_timer?.cancel();
_timer = null;
_isRunning = false;
_currentCount = duration; // 重置为初始值
notifyListeners();
}
@override
void dispose() {
_timer?.cancel();
super.dispose();
}
}
/// 验证码服务接口
abstract class IVerificationService {
/// 获取短信验证码
/// 返回 true 表示发送成功,false 表示失败
Future<bool> sendSmsCode();
/// 获取语音验证码
/// 返回 true 表示发送成功,false 表示失败
Future<bool> sendVoiceCode();
/// 校验验证码
/// 返回 null 表示校验通过,否则返回错误信息
Future<String?> verifyCode(String code);
/// 联系客服
Future<void> contactCustomerService();
}
import '../utils/code_send_enum.dart';
/// 验证码状态机
class VerificationStateMachine {
final bool isAccessOutbound;
VerificationStateMachine({required this.isAccessOutbound});
/// 根据当前状态和触发动作计算下一个状态
CodeSendType nextState(CodeSendType currentState, {bool isSmsSend = true}) {
switch (currentState) {
case CodeSendType.none:
return CodeSendType.firstSendSmsCode;
case CodeSendType.firstSendSmsCode:
return CodeSendType.notReceiveSmsCode;
case CodeSendType.notReceiveSmsCode:
return isSmsSend
? CodeSendType.resendSmsCode
: CodeSendType.firstSendVoiceCode;
case CodeSendType.resendSmsCode:
return isAccessOutbound
? CodeSendType.notReceiveResendSmsCode
: CodeSendType.resendSmsCode; // 如果没有外呼,可能保持原状或进入其他逻辑,这里保持原逻辑
case CodeSendType.notReceiveResendSmsCode:
return CodeSendType.firstSendVoiceCode;
case CodeSendType.firstSendVoiceCode:
return CodeSendType.notReceiveVoiceCode;
case CodeSendType.notReceiveVoiceCode:
return CodeSendType.resendVoiceCode;
case CodeSendType.resendVoiceCode:
return CodeSendType.notReceiveResendVoiceCode;
case CodeSendType.notReceiveResendVoiceCode:
return CodeSendType.resendVoiceCode;
default:
return CodeSendType.notReceiveResendVoiceCode;
}
}
}
import 'package:flutter/material.dart';
import '../clx_verification_code.dart';
import '../widgets/tips_widget/status_tips_widget.dart';
class CLXLineCodeManageView extends StatelessWidget {
const CLXLineCodeManageView({
super.key,
required this.loigc,
required this.viewModel,
required this.config,
this.disabled = false,
});
/// 页面状态变化处理控制器
final CLXCodeManageLogic loigc;
final VerificationCodeViewModel viewModel;
/// 是否禁用
final bool disabled;
......@@ -20,6 +21,9 @@ class CLXLineCodeManageView extends StatelessWidget {
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: viewModel,
builder: (context, child) {
return Container(
margin: config.margin,
padding: config.padding,
......@@ -32,9 +36,9 @@ class CLXLineCodeManageView extends StatelessWidget {
children: [
Expanded(
child: TextField(
controller: loigc.codeInoutCtrl,
controller: viewModel.codeInputCtrl,
keyboardType: TextInputType.number,
maxLength: loigc.maxLength,
maxLength: viewModel.maxLength,
style: config.style,
enabled: !disabled,
enableInteractiveSelection: false,
......@@ -48,85 +52,51 @@ class CLXLineCodeManageView extends StatelessWidget {
),
),
const SizedBox(width: 10),
Obx(
() => Visibility(
visible: loigc.codeSendBtn.value.isNotEmpty,
Visibility(
visible: viewModel.codeSendBtn.isNotEmpty,
child: GestureDetector(
onTap: loigc.sendSmsCode,
onTap: viewModel.sendSmsCode,
child: Text(
loigc.codeSendBtn.value,
style: loigc.codeSendType.value.isUnSend
viewModel.codeSendBtn,
style: viewModel.codeSendType.isUnSend
? config.countdownStyle
: config.codeSendStyle,
),
),
),
),
],
),
Obx(
() => Visibility(
visible: loigc.verifyCodeError.value.isNotEmpty,
Visibility(
visible: viewModel.verifyCodeError.isNotEmpty,
child: Column(
children: [
const SizedBox(height: 5),
Text(
loigc.verifyCodeError.value,
viewModel.verifyCodeError,
style: config.errorStyle,
),
],
),
),
),
Obx(
() => Visibility(
visible: loigc.isShowTip.value,
child: Column(
children: [
/// 展示重新发送验证码按钮以及获取语音验证码按钮
if (loigc.codeSendType.value ==
CodeSendType.notReceiveSmsCode)
NoReceiveSmsView(
isAccessOutCall: loigc.isAccessOutbound,
Visibility(
visible: viewModel.isShowTip,
child: StatusTipsWidget(
codeSendType: viewModel.codeSendType,
isAccessOutbound: viewModel.isAccessOutbound,
onSendSms: viewModel.sendSmsCode,
onSendVoice: viewModel.sendVoiceCode,
onContactService: viewModel.contactService,
tipsStyle: config.tipsStyle,
reSendStyle: config.reSendStyle,
voiceSendStyle: config.voiceSendStyle,
isSmallWindow: config.isSmallWindow,
sendSmsCode: loigc.sendSmsCode,
sendVoiceCode: loigc.sendVoiceCode,
),
/// 展示没有收到二次发送的验证码的提示
if (loigc.codeSendType.value ==
CodeSendType.notReceiveResendSmsCode)
NoReceiveResendSmsView(
isAccessOutCall: loigc.isAccessOutbound,
tipsStyle: config.tipsStyle,
reSendStyle: config.reSendStyle,
sendVoiceCode: loigc.sendVoiceCode,
),
/// 展示没有收到首次发送的语音验证码的提示
if (loigc.codeSendType.value ==
CodeSendType.notReceiveVoiceCode ||
loigc.codeSendType.value ==
CodeSendType.notReceiveResendVoiceCode)
NoReceiveVoiceView(
isSmallWindow: config.isSmallWindow,
tipsStyle: config.tipsStyle,
reSendStyle: config.reSendStyle,
contactStyle: config.contactStyle,
sendVoiceCode: loigc.sendVoiceCode,
contactService: loigc.contactService,
isShowContact: loigc.codeSendType.value ==
CodeSendType.notReceiveResendVoiceCode,
),
],
),
isSmallWindow: config.isSmallWindow,
),
),
],
),
);
},
);
}
}
import 'package:flutter/widgets.dart';
import '../clx_verification_code.dart';
import '../widgets/tips_widget/status_tips_widget.dart';
class CLXPageCodeManageView extends StatelessWidget {
const CLXPageCodeManageView({
super.key,
required this.loigc,
required this.viewModel,
required this.config,
});
/// 页面状态变化处理控制器
final CLXCodeManageLogic loigc;
final VerificationCodeViewModel viewModel;
/// 是否隐藏输入内容
final PageCodeManageConfig config;
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: viewModel,
builder: (context, child) {
return Container(
margin: config.margin,
padding: config.padding,
......@@ -24,83 +28,46 @@ class CLXPageCodeManageView extends StatelessWidget {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
GetBuilder(
init: loigc,
builder: (controller) {
return CodeInputView(
controller: loigc.codeInoutCtrl,
focusNode: loigc.codeInoutFocus,
CodeInputView(
controller: viewModel.codeInputCtrl,
focusNode: viewModel.codeInputFocus,
obscureText: config.obscureText,
maxLength: loigc.maxLength,
maxLength: viewModel.maxLength,
inputRectBg: config.inputRectBg,
runSpance: config.runSpance,
radius: config.radius,
);
},
),
Obx(
() => Visibility(
visible: loigc.verifyCodeError.value.isNotEmpty,
Visibility(
visible: viewModel.verifyCodeError.isNotEmpty,
child: Column(
children: [
const SizedBox(height: 5),
Text(
loigc.verifyCodeError.value,
viewModel.verifyCodeError,
style: config.errorStyle,
),
],
),
),
),
Obx(
() => Visibility(
visible: loigc.isShowTip.value,
child: Column(
children: [
/// 展示重新发送验证码按钮以及获取语音验证码按钮
if (loigc.codeSendType.value ==
CodeSendType.notReceiveSmsCode)
NoReceiveSmsView(
isAccessOutCall: loigc.isAccessOutbound,
Visibility(
visible: viewModel.isShowTip,
child: StatusTipsWidget(
codeSendType: viewModel.codeSendType,
isAccessOutbound: viewModel.isAccessOutbound,
onSendSms: viewModel.sendSmsCode,
onSendVoice: viewModel.sendVoiceCode,
onContactService: viewModel.contactService,
tipsStyle: config.tipsStyle,
reSendStyle: config.reSendStyle,
voiceSendStyle: config.voiceSendStyle,
isSmallWindow: false,
sendSmsCode: loigc.sendSmsCode,
sendVoiceCode: loigc.sendVoiceCode,
),
/// 展示没有收到二次发送的验证码的提示
if (loigc.codeSendType.value ==
CodeSendType.notReceiveResendSmsCode)
NoReceiveResendSmsView(
isAccessOutCall: loigc.isAccessOutbound,
tipsStyle: config.tipsStyle,
reSendStyle: config.reSendStyle,
sendVoiceCode: loigc.sendVoiceCode,
),
/// 展示没有收到首次发送的语音验证码的提示
if (loigc.codeSendType.value ==
CodeSendType.notReceiveVoiceCode ||
loigc.codeSendType.value ==
CodeSendType.notReceiveResendVoiceCode)
NoReceiveVoiceView(
tipsStyle: config.tipsStyle,
reSendStyle: config.reSendStyle,
contactStyle: config.contactStyle,
isSmallWindow: false,
sendVoiceCode: loigc.sendVoiceCode,
contactService: loigc.contactService,
isShowContact: loigc.codeSendType.value ==
CodeSendType.notReceiveResendVoiceCode,
),
],
),
),
),
],
),
);
},
);
}
}
import 'package:flutter/widgets.dart';
import '../../utils/code_send_enum.dart';
import 'no_receive_sms_view.dart';
import 'no_receive_resend_sms_view.dart';
import 'no_receive_voice_view.dart';
/// 状态提示组件
class StatusTipsWidget extends StatelessWidget {
const StatusTipsWidget({
super.key,
required this.codeSendType,
required this.isAccessOutbound,
required this.onSendSms,
required this.onSendVoice,
required this.onContactService,
this.tipsStyle,
this.reSendStyle,
this.voiceSendStyle,
this.contactStyle,
this.isSmallWindow = false,
});
final CodeSendType codeSendType;
final bool isAccessOutbound;
final VoidCallback onSendSms;
final VoidCallback onSendVoice;
final VoidCallback onContactService;
final TextStyle? tipsStyle;
final TextStyle? reSendStyle;
final TextStyle? voiceSendStyle;
final TextStyle? contactStyle;
final bool isSmallWindow;
@override
Widget build(BuildContext context) {
return Column(
children: [
/// 展示重新发送验证码按钮以及获取语音验证码按钮
if (codeSendType == CodeSendType.notReceiveSmsCode)
NoReceiveSmsView(
isAccessOutCall: isAccessOutbound,
tipsStyle: tipsStyle,
reSendStyle: reSendStyle,
voiceSendStyle: voiceSendStyle,
isSmallWindow: isSmallWindow,
sendSmsCode: onSendSms,
sendVoiceCode: onSendVoice,
),
/// 展示没有收到二次发送的验证码的提示
if (codeSendType == CodeSendType.notReceiveResendSmsCode)
NoReceiveResendSmsView(
isAccessOutCall: isAccessOutbound,
tipsStyle: tipsStyle,
reSendStyle: reSendStyle,
sendVoiceCode: onSendVoice,
),
/// 展示没有收到首次发送的语音验证码的提示
if (codeSendType == CodeSendType.notReceiveVoiceCode ||
codeSendType == CodeSendType.notReceiveResendVoiceCode)
NoReceiveVoiceView(
isSmallWindow: isSmallWindow,
tipsStyle: tipsStyle,
reSendStyle: reSendStyle,
contactStyle: contactStyle,
sendVoiceCode: onSendVoice,
contactService: onContactService,
isShowContact: codeSendType == CodeSendType.notReceiveResendVoiceCode,
),
],
);
}
}
......@@ -11,11 +11,6 @@ dependencies:
flutter:
sdk: flutter
# 状态管理
get: ^4.3.7
# 吐司管理
fluttertoast: ^8.2.4
dev_dependencies:
flutter_test:
sdk: flutter
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论