feat: 增加接口封装、获取验证码接口
This commit is contained in:
parent
4e8e860810
commit
1adeb429cc
@ -1,3 +1,3 @@
|
||||
class ApiPath {
|
||||
static const String login = "/auth/login";
|
||||
static const String sendValidationCode = "/v1/common/sendValidationCode";
|
||||
}
|
||||
|
||||
@ -1,51 +1,70 @@
|
||||
class ApiResponse<T> {
|
||||
final bool success;
|
||||
final String? description;
|
||||
final T? data;
|
||||
final String? message;
|
||||
final int? statusCode;
|
||||
final String? errorMsg;
|
||||
final int? errorCode;
|
||||
|
||||
// 构造函数
|
||||
const ApiResponse({
|
||||
required this.success,
|
||||
this.description,
|
||||
this.data,
|
||||
this.message,
|
||||
this.statusCode,
|
||||
this.errorMsg,
|
||||
this.errorCode,
|
||||
});
|
||||
|
||||
// 成功响应
|
||||
factory ApiResponse.success(T data,
|
||||
{String message = 'Success', int? statusCode}) {
|
||||
// ✅ 新增:从 JSON 创建 ApiResponse
|
||||
factory ApiResponse.fromJson(
|
||||
Map<String, dynamic> json,
|
||||
T Function(dynamic)? dataFromJson, // 可为空,有些接口 data 是 null
|
||||
) {
|
||||
final dataJson = json['data'];
|
||||
final T? parsedData = dataJson != null && dataFromJson != null
|
||||
? dataFromJson(dataJson)
|
||||
: null;
|
||||
|
||||
return ApiResponse<T>(
|
||||
errorCode: json['errorCode'],
|
||||
errorMsg: json['errorMsg'],
|
||||
description: json['description'],
|
||||
data: parsedData,
|
||||
);
|
||||
}
|
||||
|
||||
// 成功工厂构造
|
||||
factory ApiResponse.success(T data, {
|
||||
String? errorMsg,
|
||||
int? errorCode,
|
||||
String? description,
|
||||
}) {
|
||||
return ApiResponse<T>(
|
||||
success: true,
|
||||
data: data,
|
||||
message: message,
|
||||
statusCode: statusCode,
|
||||
errorMsg: errorMsg ?? 'success',
|
||||
errorCode: errorCode,
|
||||
description: description ?? 'success',
|
||||
);
|
||||
}
|
||||
|
||||
// 失败响应
|
||||
factory ApiResponse.error(String message, {int? statusCode, T? data}) {
|
||||
// 失败工厂构造
|
||||
factory ApiResponse.error(
|
||||
String errorMsg, {
|
||||
int? errorCode,
|
||||
T? data,
|
||||
String? description,
|
||||
}) {
|
||||
return ApiResponse<T>(
|
||||
success: false,
|
||||
message: message,
|
||||
statusCode: statusCode,
|
||||
data: data, // 可选:返回部分数据(如错误时的缓存数据)
|
||||
description: description,
|
||||
errorMsg: errorMsg,
|
||||
errorCode: errorCode,
|
||||
data: data,
|
||||
);
|
||||
}
|
||||
|
||||
// 加载中(可选)
|
||||
factory ApiResponse.loading() {
|
||||
return ApiResponse<T>(
|
||||
success: false,
|
||||
message: 'Loading...',
|
||||
);
|
||||
bool get isSuccess {
|
||||
return errorCode == 0;
|
||||
}
|
||||
|
||||
@override
|
||||
List<Object?> get props => [success, data, message, statusCode];
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'ApiResponse(success: $success, message: $message, data: $data, statusCode: $statusCode)';
|
||||
return 'ApiResponse(description: $description, errorMsg: $errorMsg, data: $data, errorCode: $errorCode)';
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,7 +1,9 @@
|
||||
// api/service/user_api_service.dart
|
||||
import 'package:dio/dio.dart' as dioAlias;
|
||||
|
||||
import 'package:starwork_flutter/api/api_response.dart';
|
||||
import 'package:starwork_flutter/common/constant/http_constant.dart';
|
||||
import 'package:starwork_flutter/flavors.dart';
|
||||
import 'package:flutter/foundation.dart'; // 用于 debugPrint
|
||||
|
||||
class BaseApiService {
|
||||
final dioAlias.Dio dio = dioAlias.Dio();
|
||||
@ -10,37 +12,62 @@ class BaseApiService {
|
||||
dio.options.baseUrl = F.apiHost;
|
||||
dio.options.connectTimeout = const Duration(seconds: 30);
|
||||
dio.options.receiveTimeout = const Duration(seconds: 30);
|
||||
// 可添加拦截器、token 等
|
||||
|
||||
// 🔥 添加日志拦截器
|
||||
if (kDebugMode) {
|
||||
dio.interceptors.add(dioAlias.LogInterceptor(
|
||||
request: true,
|
||||
requestHeader: true,
|
||||
requestBody: true,
|
||||
responseHeader: true,
|
||||
responseBody: true,
|
||||
error: true,
|
||||
logPrint: (obj) {
|
||||
debugPrint('[DIO] $obj');
|
||||
},
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// 统一请求方法(私有,但子类可用)
|
||||
/// 统一请求方法
|
||||
Future<ApiResponse<T>> makeRequest<T>({
|
||||
required String path,
|
||||
String method = 'GET',
|
||||
String method = HttpConstant.post,
|
||||
dynamic data,
|
||||
Map<String, dynamic>? queryParameters,
|
||||
required T Function(dynamic) fromJson,
|
||||
}) async {
|
||||
try {
|
||||
// 🔍 打印请求信息(更详细控制)
|
||||
if (kDebugMode) {
|
||||
final uri = Uri.parse('${dio.options.baseUrl}$path');
|
||||
final queryString =
|
||||
queryParameters != null ? '?${uri.queryParameters.toString()}' : '';
|
||||
debugPrint('🟦 API Request: $method ${uri.toString()}$queryString');
|
||||
if (data != null) {
|
||||
debugPrint('🟦 Request Body: $data');
|
||||
}
|
||||
}
|
||||
|
||||
dioAlias.Response response;
|
||||
|
||||
switch (method.toUpperCase()) {
|
||||
case 'GET':
|
||||
case HttpConstant.get:
|
||||
response = await dio.get(path, queryParameters: queryParameters);
|
||||
break;
|
||||
case 'POST':
|
||||
case HttpConstant.post:
|
||||
response = await dio.post(path,
|
||||
data: data, queryParameters: queryParameters);
|
||||
break;
|
||||
case 'PUT':
|
||||
case HttpConstant.put:
|
||||
response =
|
||||
await dio.put(path, data: data, queryParameters: queryParameters);
|
||||
break;
|
||||
case 'DELETE':
|
||||
case HttpConstant.delete:
|
||||
response = await dio.delete(path,
|
||||
data: data, queryParameters: queryParameters);
|
||||
break;
|
||||
case 'PATCH':
|
||||
case HttpConstant.patch:
|
||||
response = await dio.patch(path,
|
||||
data: data, queryParameters: queryParameters);
|
||||
break;
|
||||
@ -48,20 +75,46 @@ class BaseApiService {
|
||||
return ApiResponse.error('Unsupported method: $method');
|
||||
}
|
||||
|
||||
// ✅ 打印响应
|
||||
if (kDebugMode) {
|
||||
debugPrint(
|
||||
'🟩 API Response [${response.statusCode}] ${response.requestOptions.path}');
|
||||
debugPrint('🟩 Response Data: ${response.data}');
|
||||
}
|
||||
|
||||
if (response.statusCode! >= 200 && response.statusCode! < 300) {
|
||||
final parsedData = fromJson(response.data);
|
||||
return ApiResponse.success(
|
||||
parsedData,
|
||||
statusCode: response.statusCode,
|
||||
message: 'Success',
|
||||
);
|
||||
final jsonMap = response.data as Map<String, dynamic>;
|
||||
|
||||
// ✅ 直接用 ApiResponse.fromJson 解析整个响应
|
||||
final apiResponse = ApiResponse<T>.fromJson(jsonMap, fromJson);
|
||||
|
||||
// ✅ 判断业务是否成功(根据 errorCode)
|
||||
if (apiResponse.errorCode == 0) {
|
||||
return apiResponse; // 直接返回,data 已解析
|
||||
} else {
|
||||
// 业务失败,但 data 可能有部分信息
|
||||
return ApiResponse.error(
|
||||
apiResponse.errorMsg ?? 'Request failed',
|
||||
errorCode: apiResponse.errorCode,
|
||||
data: apiResponse.data,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
return ApiResponse.error(
|
||||
response.statusMessage ?? 'Request failed',
|
||||
statusCode: response.statusCode,
|
||||
errorCode: response.statusCode,
|
||||
);
|
||||
}
|
||||
} on dioAlias.DioException catch (e) {
|
||||
// ❌ 打印错误
|
||||
if (kDebugMode) {
|
||||
debugPrint('🟥 API Error: ${e.type} - ${e.message}');
|
||||
if (e.response != null) {
|
||||
debugPrint('🟥 Error Response: ${e.response?.data}');
|
||||
debugPrint('🟥 Status Code: ${e.response?.statusCode}');
|
||||
}
|
||||
}
|
||||
|
||||
String message = 'Unknown error';
|
||||
int? statusCode = e.response?.statusCode;
|
||||
|
||||
@ -77,8 +130,11 @@ class BaseApiService {
|
||||
message = e.message ?? 'Something went wrong';
|
||||
}
|
||||
|
||||
return ApiResponse.error(message, statusCode: statusCode);
|
||||
return ApiResponse.error(message, errorCode: statusCode);
|
||||
} catch (e) {
|
||||
if (kDebugMode) {
|
||||
debugPrint('🟥 Unexpected Error: $e');
|
||||
}
|
||||
return ApiResponse.error('Unexpected error: $e');
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,26 @@
|
||||
// 验证码接口请求参数
|
||||
// 登陆后可使用 sendValidationCodeAuth 接口,免图片滑动验证,只需要 channel,codeType 两个参数即可
|
||||
import 'package:starwork_flutter/common/constant/validation_code_type.dart';
|
||||
|
||||
class SendValidationCodeRequest {
|
||||
final String countryCode;
|
||||
final String account;
|
||||
final String channel; //1 短信,2 邮箱
|
||||
final ValidationCodeType codeType;
|
||||
|
||||
SendValidationCodeRequest({
|
||||
required this.countryCode,
|
||||
required this.account,
|
||||
required this.channel,
|
||||
required this.codeType,
|
||||
});
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'countryCode': countryCode,
|
||||
'account': account,
|
||||
'channel': channel,
|
||||
'codeType': codeType.value,
|
||||
};
|
||||
}
|
||||
}
|
||||
18
lib/api/model/string_response.dart
Normal file
18
lib/api/model/string_response.dart
Normal file
@ -0,0 +1,18 @@
|
||||
// models/string_response.dart
|
||||
class StringResponse {
|
||||
final String value;
|
||||
|
||||
StringResponse(this.value);
|
||||
|
||||
factory StringResponse.fromJson(dynamic data) {
|
||||
if (data is String) {
|
||||
return StringResponse(data);
|
||||
} else if (data is Map && data['message'] != null) {
|
||||
return StringResponse(data['message'].toString());
|
||||
} else if (data is Map && data['data'] != null) {
|
||||
return StringResponse(data['data'].toString());
|
||||
} else {
|
||||
return StringResponse(data.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
19
lib/api/model/user/request/validation_code_login.dart
Normal file
19
lib/api/model/user/request/validation_code_login.dart
Normal file
@ -0,0 +1,19 @@
|
||||
class ValidationCodeLoginRequest {
|
||||
final int platId; //平台 1web 2app 3小程序 4pc
|
||||
final String phone; // 登录账号(手机号)
|
||||
final String verificationCode; //验证码
|
||||
|
||||
ValidationCodeLoginRequest({
|
||||
required this.platId,
|
||||
required this.phone,
|
||||
required this.verificationCode,
|
||||
});
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'platId': platId,
|
||||
'phone': phone,
|
||||
'verificationCode': verificationCode,
|
||||
};
|
||||
}
|
||||
}
|
||||
25
lib/api/service/common_api_service.dart
Normal file
25
lib/api/service/common_api_service.dart
Normal file
@ -0,0 +1,25 @@
|
||||
import 'package:starwork_flutter/api/api_path.dart';
|
||||
import 'package:starwork_flutter/api/api_response.dart';
|
||||
import 'package:starwork_flutter/api/base_api_service.dart';
|
||||
import 'package:starwork_flutter/api/model/common/request/send_validation_code_request.dart';
|
||||
import 'package:starwork_flutter/api/model/string_response.dart';
|
||||
import 'package:starwork_flutter/api/model/user/user_model.dart';
|
||||
import 'package:starwork_flutter/common/constant/http_constant.dart';
|
||||
|
||||
class CommonApiService {
|
||||
final BaseApiService _api;
|
||||
|
||||
CommonApiService(this._api); // 通过构造函数注入
|
||||
// 发送验证码
|
||||
Future<ApiResponse<void>> sendValidationCode({
|
||||
required SendValidationCodeRequest request,
|
||||
}) {
|
||||
return _api.makeRequest(
|
||||
// 通过实例调用
|
||||
path: ApiPath.sendValidationCode,
|
||||
method: HttpConstant.post,
|
||||
data: request.toJson(),
|
||||
fromJson: (data) {},
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -4,7 +4,9 @@ import 'package:starwork_flutter/api/base_api_service.dart';
|
||||
import 'package:starwork_flutter/api/model/user/user_model.dart';
|
||||
|
||||
class UserApiService {
|
||||
final BaseApiService _api = BaseApiService();
|
||||
final BaseApiService _api;
|
||||
|
||||
UserApiService(this._api); // 通过构造函数注入
|
||||
|
||||
Future<ApiResponse<UserModel>> login(Map<String, dynamic> userData) {
|
||||
return _api.makeRequest(
|
||||
|
||||
13
lib/app.dart
13
lib/app.dart
@ -19,12 +19,11 @@ class App extends StatelessWidget {
|
||||
builder: (_, child) {
|
||||
return GetMaterialApp(
|
||||
theme: ThemeData(
|
||||
textSelectionTheme: TextSelectionThemeData(
|
||||
cursorColor: Colors.blue.shade200,
|
||||
selectionColor: Colors.blue.shade100,
|
||||
selectionHandleColor: Colors.blue.shade300,
|
||||
)
|
||||
),
|
||||
textSelectionTheme: TextSelectionThemeData(
|
||||
cursorColor: Colors.blue.shade200,
|
||||
selectionColor: Colors.blue.shade100,
|
||||
selectionHandleColor: Colors.blue.shade300,
|
||||
)),
|
||||
// 必须配置以下三个本地化代理
|
||||
localizationsDelegates: const [
|
||||
GlobalMaterialLocalizations.delegate, // 提供Material组件本地化字符串
|
||||
@ -42,7 +41,7 @@ class App extends StatelessWidget {
|
||||
fallbackLocale: const Locale('zh', 'CN'),
|
||||
// 必须设置 fallback 没有该语言时使用
|
||||
getPages: AppPages.pages,
|
||||
initialRoute: AppRoutes.main,
|
||||
initialRoute: AppRoutes.login,
|
||||
debugShowCheckedModeBanner: false,
|
||||
);
|
||||
},
|
||||
|
||||
@ -5,20 +5,31 @@ import 'package:flutter/services.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:starwork_flutter/api/base_api_service.dart';
|
||||
import 'package:starwork_flutter/api/service/common_api_service.dart';
|
||||
import 'package:starwork_flutter/api/service/user_api_service.dart';
|
||||
import 'package:starwork_flutter/common/utils/shared_preferences_utils.dart';
|
||||
import 'package:starwork_flutter/i18n/app_i18n.dart';
|
||||
|
||||
class AppInitialization {
|
||||
static Future<void> initializeApp() async {
|
||||
// 确保绑定已初始化,能够安全使用插件
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
// 设置系统状态栏
|
||||
setSystemStatusBar();
|
||||
// 初始化 SharedPreferences
|
||||
await SharedPreferencesUtils.init();
|
||||
// 初始化api服务(单例)
|
||||
Get.put(BaseApiService(),permanent: true);
|
||||
try {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
setSystemStatusBar();
|
||||
await SharedPreferencesUtils.init();
|
||||
|
||||
// 日志:方便调试
|
||||
print('✅ SharedPreferences initialized');
|
||||
|
||||
Get.lazyPut(() => BaseApiService());
|
||||
Get.lazyPut(() => CommonApiService(Get.find<BaseApiService>()));
|
||||
|
||||
print('✅ API services registered');
|
||||
} catch (e, stack) {
|
||||
print('❌ Initialization failed: $e');
|
||||
print(stack);
|
||||
// 可以上报错误(Sentry 等)
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
static void setSystemStatusBar() {
|
||||
|
||||
8
lib/common/constant/http_constant.dart
Normal file
8
lib/common/constant/http_constant.dart
Normal file
@ -0,0 +1,8 @@
|
||||
class HttpConstant {
|
||||
static const String post="POST";
|
||||
static const String get="GET";
|
||||
static const String put="PUT";
|
||||
static const String delete="DELETE";
|
||||
static const String patch="PATCH";
|
||||
|
||||
}
|
||||
34
lib/common/constant/login_type.dart
Normal file
34
lib/common/constant/login_type.dart
Normal file
@ -0,0 +1,34 @@
|
||||
class LoginType {
|
||||
static const phoneCodeLogin = LoginType('1', '手机验证码');
|
||||
static const emailCodeLogin = LoginType('2', '邮箱验证码');
|
||||
static const emailPasswordLogin = LoginType('3', '邮箱验证码');
|
||||
static const phonePassword = LoginType('4', '手机号密码');
|
||||
|
||||
final String value;
|
||||
final String label;
|
||||
|
||||
const LoginType(this.value, this.label);
|
||||
|
||||
// 支持通过字符串值查找枚举实例
|
||||
static LoginType? fromValue(String? value) {
|
||||
return {
|
||||
'1': phoneCodeLogin,
|
||||
'2': phonePassword,
|
||||
}[value];
|
||||
}
|
||||
|
||||
// 支持 toString() 直接输出 value
|
||||
@override
|
||||
String toString() => value;
|
||||
|
||||
// 可选:支持 == 比较
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is LoginType &&
|
||||
runtimeType == other.runtimeType &&
|
||||
value == other.value;
|
||||
|
||||
@override
|
||||
int get hashCode => value.hashCode;
|
||||
}
|
||||
33
lib/common/constant/validation_code_channel.dart
Normal file
33
lib/common/constant/validation_code_channel.dart
Normal file
@ -0,0 +1,33 @@
|
||||
// Description: 验证码渠道枚举类
|
||||
class ValidationCodeChannel {
|
||||
static const sms = ValidationCodeChannel('1', '短信');
|
||||
static const email = ValidationCodeChannel('2', '邮箱');
|
||||
|
||||
final String value;
|
||||
final String label;
|
||||
|
||||
const ValidationCodeChannel(this.value, this.label);
|
||||
|
||||
// 支持通过字符串值查找枚举实例
|
||||
static ValidationCodeChannel? fromValue(String? value) {
|
||||
return {
|
||||
'1': sms,
|
||||
'2': email,
|
||||
}[value];
|
||||
}
|
||||
|
||||
// 支持 toString() 直接输出 value
|
||||
@override
|
||||
String toString() => value;
|
||||
|
||||
// 可选:支持 == 比较
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is ValidationCodeChannel &&
|
||||
runtimeType == other.runtimeType &&
|
||||
value == other.value;
|
||||
|
||||
@override
|
||||
int get hashCode => value.hashCode;
|
||||
}
|
||||
46
lib/common/constant/validation_code_type.dart
Normal file
46
lib/common/constant/validation_code_type.dart
Normal file
@ -0,0 +1,46 @@
|
||||
class ValidationCodeType {
|
||||
static const login = ValidationCodeType('1', '登录');
|
||||
static const reset = ValidationCodeType('2', '重置密码');
|
||||
static const bindPhone = ValidationCodeType('3', '绑定手机号');
|
||||
static const unbindPhone = ValidationCodeType('4', '解绑手机号');
|
||||
static const deleteAccount = ValidationCodeType('5', '删除账号');
|
||||
static const bindEmail = ValidationCodeType('6', '绑定邮箱');
|
||||
static const unbindEmail = ValidationCodeType('7', '解绑邮箱');
|
||||
static const deleteLock = ValidationCodeType('8', '删除门锁');
|
||||
static const updatePassword = ValidationCodeType('9', '修改密码');
|
||||
|
||||
final String value;
|
||||
final String label;
|
||||
|
||||
const ValidationCodeType(this.value, this.label);
|
||||
|
||||
// 支持通过字符串值查找枚举实例
|
||||
static ValidationCodeType? fromValue(String? value) {
|
||||
return {
|
||||
'1': login,
|
||||
'2': reset,
|
||||
'3': bindPhone,
|
||||
'4': unbindPhone,
|
||||
'5': deleteAccount,
|
||||
'6': bindEmail,
|
||||
'7': unbindEmail,
|
||||
'8': deleteLock,
|
||||
'9': updatePassword,
|
||||
}[value];
|
||||
}
|
||||
|
||||
// 支持 toString() 直接输出 value
|
||||
@override
|
||||
String toString() => value;
|
||||
|
||||
// 可选:支持 == 比较
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is ValidationCodeType &&
|
||||
runtimeType == other.runtimeType &&
|
||||
value == other.value;
|
||||
|
||||
@override
|
||||
int get hashCode => value.hashCode;
|
||||
}
|
||||
@ -1,5 +0,0 @@
|
||||
enum LoginType {
|
||||
phoneCode,
|
||||
phonePassword;
|
||||
|
||||
}
|
||||
@ -32,7 +32,7 @@ class F {
|
||||
static String get apiHost {
|
||||
switch (appFlavor) {
|
||||
case Flavor.skyDev:
|
||||
return 'https://loacl.work.star-lock.cn/api';
|
||||
return 'http://192.168.1.136/api';
|
||||
case Flavor.skyPre:
|
||||
return 'https://loacl.work.star-lock.cn/api';
|
||||
case Flavor.skyRelease:
|
||||
|
||||
@ -4,12 +4,19 @@ import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:fluttertoast/fluttertoast.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:starwork_flutter/api/model/common/request/send_validation_code_request.dart';
|
||||
import 'package:starwork_flutter/api/service/common_api_service.dart';
|
||||
import 'package:starwork_flutter/base/base_controller.dart';
|
||||
import 'package:starwork_flutter/common/enums/login_type.dart';
|
||||
import 'package:starwork_flutter/common/constant/login_type.dart';
|
||||
import 'package:starwork_flutter/common/constant/validation_code_channel.dart';
|
||||
import 'package:starwork_flutter/common/constant/validation_code_type.dart';
|
||||
|
||||
import 'package:starwork_flutter/routes/app_pages.dart';
|
||||
import 'package:starwork_flutter/routes/app_routes.dart';
|
||||
|
||||
class LoginController extends BaseController {
|
||||
final commonApi = Get.find<CommonApiService>();
|
||||
|
||||
int phoneNumberSize = 11;
|
||||
TextEditingController phoneController = TextEditingController();
|
||||
TextEditingController passwordController = TextEditingController();
|
||||
@ -17,7 +24,7 @@ class LoginController extends BaseController {
|
||||
final isFormValid = false.obs;
|
||||
final isPasswordVisible = true.obs;
|
||||
final isPrivacyAgreementValid = 0.obs;
|
||||
final loginType = LoginType.phoneCode.obs;
|
||||
final loginType = LoginType.phoneCodeLogin.obs;
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
@ -41,28 +48,34 @@ class LoginController extends BaseController {
|
||||
}
|
||||
|
||||
// 获取手机验证码
|
||||
void requestPhoneCode() {
|
||||
void requestPhoneCode() async {
|
||||
if (isPrivacyAgreementValid.value != 1) {
|
||||
_showCustomDialog(
|
||||
title: '欢迎使用星勤'.tr,
|
||||
content: '1',
|
||||
onConfirm: () {
|
||||
onConfirm: () async {
|
||||
isPrivacyAgreementValid.value = 1;
|
||||
Get.toNamed(
|
||||
AppRoutes.inputVerificationCode,
|
||||
parameters: {
|
||||
'phone': phoneController.text.trim(),
|
||||
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
} else {
|
||||
}
|
||||
_handleRequestPhoneCode();
|
||||
}
|
||||
|
||||
void _handleRequestPhoneCode() async {
|
||||
var sendValidationCodeResult = await commonApi.sendValidationCode(
|
||||
request: SendValidationCodeRequest(
|
||||
countryCode: '+86',
|
||||
account: phoneController.text.trim(),
|
||||
channel: ValidationCodeChannel.sms.value,
|
||||
codeType: ValidationCodeType.login,
|
||||
),
|
||||
);
|
||||
|
||||
if (sendValidationCodeResult.isSuccess) {
|
||||
Get.toNamed(
|
||||
AppRoutes.inputVerificationCode,
|
||||
parameters: {
|
||||
'phone': phoneController.text.trim(),
|
||||
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@ -3,7 +3,8 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:starwork_flutter/common/enums/login_type.dart';
|
||||
import 'package:starwork_flutter/common/constant/login_type.dart';
|
||||
|
||||
import 'package:starwork_flutter/routes/app_routes.dart';
|
||||
|
||||
import 'login_controller.dart';
|
||||
@ -173,7 +174,7 @@ class LoginView extends GetView<LoginController> {
|
||||
),
|
||||
),
|
||||
child: Text(
|
||||
controller.loginType.value == LoginType.phoneCode
|
||||
controller.loginType.value == LoginType.phoneCodeLogin
|
||||
? '获取验证码'.tr
|
||||
: '登录'.tr,
|
||||
style: TextStyle(
|
||||
@ -188,7 +189,7 @@ class LoginView extends GetView<LoginController> {
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Visibility(
|
||||
visible: LoginType.phoneCode == controller.loginType.value,
|
||||
visible: LoginType.phoneCodeLogin == controller.loginType.value,
|
||||
child: TextButton(
|
||||
onPressed: () {
|
||||
controller.loginType.value = LoginType.phonePassword;
|
||||
@ -208,7 +209,7 @@ class LoginView extends GetView<LoginController> {
|
||||
visible: LoginType.phonePassword == controller.loginType.value,
|
||||
child: TextButton(
|
||||
onPressed: () {
|
||||
controller.loginType.value = LoginType.phoneCode;
|
||||
controller.loginType.value = LoginType.phoneCodeLogin;
|
||||
},
|
||||
child: Text(
|
||||
'验证码登录'.tr,
|
||||
@ -236,7 +237,8 @@ class LoginView extends GetView<LoginController> {
|
||||
visible: LoginType.phonePassword == controller.loginType.value,
|
||||
child: TextButton(
|
||||
style: ButtonStyle(
|
||||
overlayColor: MaterialStateProperty.all(Colors.transparent), // 墨水覆盖
|
||||
overlayColor:
|
||||
MaterialStateProperty.all(Colors.transparent), // 墨水覆盖
|
||||
side: MaterialStateProperty.all(null), // 取消边框
|
||||
),
|
||||
onPressed: () {
|
||||
@ -266,7 +268,7 @@ class LoginView extends GetView<LoginController> {
|
||||
}
|
||||
|
||||
_handleLoginButtonText() {
|
||||
if (controller.loginType.value == LoginType.phoneCode) {
|
||||
if (controller.loginType.value == LoginType.phoneCodeLogin) {
|
||||
return;
|
||||
} else if (controller.loginType.value == LoginType.phonePassword) {
|
||||
return '验证码登录'.tr + ' | '.tr + '忘记密码'.tr;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user