Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
浙江兰德纵横网络技术股份有限公司
o2oa-flutter
比较版本
1a6f15a9952206830b475acb239a24576d5ad80b...8e95f7d0612b224178ed84e908f015ce99c59c86
O
o2oa-flutter
项目概览
浙江兰德纵横网络技术股份有限公司
/
o2oa-flutter
通知
0
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
O
o2oa-flutter
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
源分支
8e95f7d0612b224178ed84e908f015ce99c59c86
选择Git版本
...
目标分支
1a6f15a9952206830b475acb239a24576d5ad80b
选择Git版本
比较
Commits (2)
https://gitcode.net/O2OA/o2oa-flutter/-/commit/043d7ea73dd76320c0968a6fe2c5905375b5c1bc
注册功能
2024-05-11T15:01:39+08:00
fancy
fancylou@outlook.com
https://gitcode.net/O2OA/o2oa-flutter/-/commit/8e95f7d0612b224178ed84e908f015ce99c59c86
注册多语言文件
2024-05-11T15:10:29+08:00
fancy
fancylou@outlook.com
隐藏空白更改
内联
并排
Showing
18 changed file
with
785 addition
and
41 deletion
+785
-41
lib/common/api/x_organization_assemble_personal.dart
lib/common/api/x_organization_assemble_personal.dart
+116
-31
lib/common/i18n/lang/en_US.dart
lib/common/i18n/lang/en_US.dart
+11
-0
lib/common/i18n/lang/es_ES.dart
lib/common/i18n/lang/es_ES.dart
+11
-0
lib/common/i18n/lang/zh_HK.dart
lib/common/i18n/lang/zh_HK.dart
+11
-0
lib/common/i18n/lang/zh_Hans.dart
lib/common/i18n/lang/zh_Hans.dart
+11
-0
lib/common/models/index.dart
lib/common/models/index.dart
+1
-0
lib/common/models/value_data_string.dart
lib/common/models/value_data_string.dart
+12
-0
lib/common/routers/pages.dart
lib/common/routers/pages.dart
+5
-0
lib/common/routers/routes.dart
lib/common/routers/routes.dart
+1
-0
lib/common/values/o2.dart
lib/common/values/o2.dart
+5
-0
lib/pages/login/controller.dart
lib/pages/login/controller.dart
+20
-5
lib/pages/login/register/bindings.dart
lib/pages/login/register/bindings.dart
+10
-0
lib/pages/login/register/controller.dart
lib/pages/login/register/controller.dart
+218
-0
lib/pages/login/register/index.dart
lib/pages/login/register/index.dart
+6
-0
lib/pages/login/register/state.dart
lib/pages/login/register/state.dart
+35
-0
lib/pages/login/register/view.dart
lib/pages/login/register/view.dart
+297
-0
lib/pages/login/state.dart
lib/pages/login/state.dart
+4
-0
lib/pages/login/view.dart
lib/pages/login/view.dart
+11
-5
未找到文件。
lib/common/api/x_organization_assemble_personal.dart
浏览文件 @
8e95f7d0
import
'dart:io'
;
import
'package:get/get.dart'
;
...
...
@@ -14,28 +10,107 @@ import '../utils/index.dart';
///组织人员服务
///
class
OrganizationPersonalService
extends
GetxService
{
static
OrganizationPersonalService
get
to
=>
Get
.
find
();
//
String
baseUrl
()
{
return
O2ApiManager
.
instance
.
getModuleBaseUrl
(
O2DistributeModuleEnum
.
x_organization_assemble_personal
)
??
''
;
O2DistributeModuleEnum
.
x_organization_assemble_personal
)
??
''
;
}
/// 注册配置
///
/// @return value = disable 没有启用注册 ; value = captcha 验证码注册 ; value = code 短信验证注册
Future
<
ValueStringData
?>
registerMode
()
async
{
try
{
ApiResponse
response
=
await
O2HttpClient
.
instance
.
get
(
'
${baseUrl()}
jaxrs/regist/mode'
);
return
ValueStringData
.
fromJson
(
response
.
data
);
}
catch
(
err
,
stackTrace
)
{
OLogger
.
e
(
'注册配置获取失败'
,
err
,
stackTrace
);
}
return
null
;
}
///
///获取图片验证码
///
Future
<
CaptchaImgData
?>
getRegisterCaptchaImgData
(
int
width
,
int
height
)
async
{
try
{
ApiResponse
response
=
await
O2HttpClient
.
instance
.
get
(
'
${baseUrl()}
jaxrs/regist/captcha/width/
$width
/height/
$height
'
,
needToken:
false
);
CaptchaImgData
mode
=
CaptchaImgData
.
fromJson
(
response
.
data
);
return
mode
;
}
catch
(
err
,
stackTrace
)
{
OLogger
.
e
(
'获取图片验证码失败'
,
err
,
stackTrace
);
}
return
null
;
}
/// 发送注册短信
Future
<
ValueBoolData
?>
getRegisterCode
(
String
mobile
)
async
{
try
{
ApiResponse
response
=
await
O2HttpClient
.
instance
.
get
(
'
${baseUrl()}
jaxrs/regist/code/mobile/
$mobile
'
);
return
ValueBoolData
.
fromJson
(
response
.
data
);
}
catch
(
err
,
stackTrace
)
{
OLogger
.
e
(
'注册获取失败'
,
err
,
stackTrace
);
}
return
null
;
}
/// 用户名是否已经注册
Future
<
ValueBoolData
?>
checkRegisterUserName
(
String
username
)
async
{
try
{
ApiResponse
response
=
await
O2HttpClient
.
instance
.
get
(
'
${baseUrl()}
jaxrs/regist/check/name/
$username
'
);
return
ValueBoolData
.
fromJson
(
response
.
data
);
}
catch
(
err
,
stackTrace
)
{
OLogger
.
e
(
'用户名是否已经注册失败'
,
err
,
stackTrace
);
}
return
null
;
}
/// 手机号码是否已经注册
Future
<
ValueBoolData
?>
checkRegisterMobile
(
String
mobile
)
async
{
try
{
ApiResponse
response
=
await
O2HttpClient
.
instance
.
get
(
'
${baseUrl()}
jaxrs/regist/check/mobile/
$mobile
'
);
return
ValueBoolData
.
fromJson
(
response
.
data
);
}
catch
(
err
,
stackTrace
)
{
OLogger
.
e
(
'手机号码是否已经注册失败'
,
err
,
stackTrace
);
}
return
null
;
}
///
/// 注册人员
///
Future
<
ValueBoolData
?>
register
(
Map
<
String
,
String
>
form
)
async
{
try
{
ApiResponse
response
=
await
O2HttpClient
.
instance
.
post
(
'
${baseUrl()}
jaxrs/regist'
,
form
);
return
ValueBoolData
.
fromJson
(
response
.
data
);
}
catch
(
err
,
stackTrace
)
{
OLogger
.
e
(
'注册人员失败'
,
err
,
stackTrace
);
}
return
null
;
}
///
/// 会议管理的配置文件
///
///
Future
<
MeetingConfigModel
?>
meetingConfig
()
async
{
try
{
ApiResponse
response
=
await
O2HttpClient
.
instance
.
get
(
'
${baseUrl()}
jaxrs/definition/meetingConfig'
);
if
(
response
.
data
!=
null
&&
response
.
data
is
String
)
{
SharedPreferenceService
.
to
.
putString
(
SharedPreferenceService
.
meetingConfigKey
,
response
.
data
);
return
MeetingConfigModel
.
fromJson
(
O2Utils
.
parseStringToJson
(
response
.
data
));
SharedPreferenceService
.
to
.
putString
(
SharedPreferenceService
.
meetingConfigKey
,
response
.
data
);
return
MeetingConfigModel
.
fromJson
(
O2Utils
.
parseStringToJson
(
response
.
data
));
}
}
catch
(
err
,
stackTrace
)
{
OLogger
.
e
(
' 会议管理的配置文件获取失败'
,
err
,
stackTrace
);
...
...
@@ -45,11 +120,11 @@ class OrganizationPersonalService extends GetxService {
///
/// 获取当前用户信息
///
///
Future
<
O2Person
?>
person
()
async
{
try
{
ApiResponse
response
=
await
O2HttpClient
.
instance
.
get
(
'
${baseUrl()}
jaxrs/person'
);
ApiResponse
response
=
await
O2HttpClient
.
instance
.
get
(
'
${baseUrl()}
jaxrs/person'
);
O2Person
idData
=
O2Person
.
fromJson
(
response
.
data
);
return
idData
;
}
catch
(
err
,
stackTrace
)
{
...
...
@@ -78,7 +153,8 @@ class OrganizationPersonalService extends GetxService {
///
Future
<
ValueBoolData
?>
updateAvatar
(
File
file
)
async
{
try
{
ApiResponse
response
=
await
O2HttpClient
.
instance
.
putUploadFile
(
'
${baseUrl()}
jaxrs/person/icon'
,
file
);
ApiResponse
response
=
await
O2HttpClient
.
instance
.
putUploadFile
(
'
${baseUrl()}
jaxrs/person/icon'
,
file
);
ValueBoolData
valueBoolData
=
ValueBoolData
.
fromJson
(
response
.
data
);
return
valueBoolData
;
}
catch
(
err
,
stackTrace
)
{
...
...
@@ -90,7 +166,8 @@ class OrganizationPersonalService extends GetxService {
///
/// 登录
///
Future
<
ValueBoolData
?>
updateLoginPassword
(
UpdateLoginPasswordForm
form
)
async
{
Future
<
ValueBoolData
?>
updateLoginPassword
(
UpdateLoginPasswordForm
form
)
async
{
try
{
ApiResponse
response
=
await
O2HttpClient
.
instance
.
put
(
'
${baseUrl()}
jaxrs/person/password'
,
form
.
toJson
());
...
...
@@ -104,11 +181,11 @@ class OrganizationPersonalService extends GetxService {
///
/// 获取个性化数据
///
///
Future
<
String
?>
getMyCustomData
(
String
name
)
async
{
try
{
ApiResponse
response
=
await
O2HttpClient
.
instance
.
get
(
'
${baseUrl()}
jaxrs/custom/
$name
'
);
try
{
ApiResponse
response
=
await
O2HttpClient
.
instance
.
get
(
'
${baseUrl()}
jaxrs/custom/
$name
'
);
if
(
response
.
data
!=
null
&&
response
.
data
is
String
)
{
return
response
.
data
;
}
...
...
@@ -120,9 +197,10 @@ class OrganizationPersonalService extends GetxService {
///
/// 保存个性化数据
///
Future
<
IdData
?>
saveMyCustomData
(
String
name
,
Map
<
String
,
dynamic
>
data
)
async
{
try
{
///
Future
<
IdData
?>
saveMyCustomData
(
String
name
,
Map
<
String
,
dynamic
>
data
)
async
{
try
{
ApiResponse
response
=
await
O2HttpClient
.
instance
.
put
(
'
${baseUrl()}
jaxrs/custom/
$name
'
,
data
);
IdData
idData
=
IdData
.
fromJson
(
response
.
data
);
...
...
@@ -135,8 +213,9 @@ class OrganizationPersonalService extends GetxService {
/// 我的委托
Future
<
List
<
EmpowerData
>?>
myEmpowerList
()
async
{
try
{
ApiResponse
response
=
await
O2HttpClient
.
instance
.
get
(
'
${baseUrl()}
jaxrs/empower/list/currentperson'
);
try
{
ApiResponse
response
=
await
O2HttpClient
.
instance
.
get
(
'
${baseUrl()}
jaxrs/empower/list/currentperson'
);
final
list
=
response
.
data
==
null
?
[]
:
response
.
data
as
List
;
return
list
.
map
((
group
)
=>
EmpowerData
.
fromJson
(
group
)).
toList
();
}
catch
(
err
,
stackTrace
)
{
...
...
@@ -144,10 +223,12 @@ class OrganizationPersonalService extends GetxService {
}
return
null
;
}
/// 收到的委托
Future
<
List
<
EmpowerData
>?>
empowerToMeList
()
async
{
try
{
ApiResponse
response
=
await
O2HttpClient
.
instance
.
get
(
'
${baseUrl()}
jaxrs/empower/list/to'
);
try
{
ApiResponse
response
=
await
O2HttpClient
.
instance
.
get
(
'
${baseUrl()}
jaxrs/empower/list/to'
);
final
list
=
response
.
data
==
null
?
[]
:
response
.
data
as
List
;
return
list
.
map
((
group
)
=>
EmpowerData
.
fromJson
(
group
)).
toList
();
}
catch
(
err
,
stackTrace
)
{
...
...
@@ -155,24 +236,28 @@ class OrganizationPersonalService extends GetxService {
}
return
null
;
}
/// 删除委托
Future
<
ValueBoolData
?>
empowerDelete
(
String
id
)
async
{
try
{
ApiResponse
response
=
await
O2HttpClient
.
instance
.
delete
(
'
${baseUrl()}
jaxrs/empower/
$id
'
);
try
{
ApiResponse
response
=
await
O2HttpClient
.
instance
.
delete
(
'
${baseUrl()}
jaxrs/empower/
$id
'
);
return
ValueBoolData
.
fromJson
(
response
.
data
);
}
catch
(
err
,
stackTrace
)
{
OLogger
.
e
(
'删除委托失败'
,
err
,
stackTrace
);
}
return
null
;
}
/// 创建委托
Future
<
IdData
?>
empowerCreate
(
EmpowerData
body
)
async
{
try
{
ApiResponse
response
=
await
O2HttpClient
.
instance
.
post
(
'
${baseUrl()}
jaxrs/empower'
,
body
.
toJson
());
try
{
ApiResponse
response
=
await
O2HttpClient
.
instance
.
post
(
'
${baseUrl()}
jaxrs/empower'
,
body
.
toJson
());
return
IdData
.
fromJson
(
response
.
data
);
}
catch
(
err
,
stackTrace
)
{
OLogger
.
e
(
'创建委托失败'
,
err
,
stackTrace
);
}
return
null
;
}
}
\ No newline at end of file
}
lib/common/i18n/lang/en_US.dart
浏览文件 @
8e95f7d0
...
...
@@ -682,4 +682,15 @@ const Map<String, String> en_US = {
'account_safe_gesture_unlock_error_setup_not_match'
:
'The passwords entered twice are inconsistent'
,
'account_safe_gesture_unlock_error_check_pwd'
:
'Password error, please re-enter'
,
'account_safe_gesture_unlock_toast_success'
:
'Password set successfully!'
,
'login_to_register'
:
'Go register'
,
'register'
:
'register'
,
'register_to_login'
:
'Go log in'
,
'register_success_to_login'
:
'Registration successful, please log in!'
,
'login_form_register_user_name'
:
'user name'
,
'login_form_user_password_repeat'
:
'Confirm password'
,
'login_form_user_password_repeat_not_empty'
:
'Confirm password cannot be empty'
,
'login_form_user_password_repeat_not_equals'
:
'The passwords entered twice are inconsistent'
,
'login_form_register_phone'
:
'mobile phone'
,
'login_form_register_phone_not_empty'
:
'Mobile phone number cannot be empty'
,
'login_form_register_email'
:
'mailbox'
,
};
lib/common/i18n/lang/es_ES.dart
浏览文件 @
8e95f7d0
...
...
@@ -682,4 +682,15 @@ const Map<String, String> es_ES = {
'account_safe_gesture_unlock_error_setup_not_match'
:
'La contraseña introducida dos veces es inconsistente'
,
'account_safe_gesture_unlock_error_check_pwd'
:
'Contraseña incorrecta, vuelva a ingresar'
,
'account_safe_gesture_unlock_toast_success'
:
'¡La configuración de la contraseña fue exitosa!'
,
'login_to_register'
:
'Ir a registrarse'
,
'register'
:
'Registro'
,
'register_to_login'
:
'Ir a iniciar sesión'
,
'register_success_to_login'
:
'¡El registro fue exitoso, ¡ por favor, inicie sesión!'
,
'login_form_register_user_name'
:
'Nombre de usuario'
,
'login_form_user_password_repeat'
:
'Confirmar contraseña'
,
'login_form_user_password_repeat_not_empty'
:
'La contraseña de confirmación no puede estar vacía'
,
'login_form_user_password_repeat_not_equals'
:
'La contraseña introducida dos veces es inconsistente'
,
'login_form_register_phone'
:
'Teléfono móvil'
,
'login_form_register_phone_not_empty'
:
'El número de teléfono móvil no puede estar vacío'
,
'login_form_register_email'
:
'Buzón'
,
};
lib/common/i18n/lang/zh_HK.dart
浏览文件 @
8e95f7d0
...
...
@@ -682,4 +682,15 @@ const Map<String, String> zh_HK = {
'account_safe_gesture_unlock_error_setup_not_match'
:
'兩次輸入的密碼不一致'
,
'account_safe_gesture_unlock_error_check_pwd'
:
'密碼錯誤,請重新輸入'
,
'account_safe_gesture_unlock_toast_success'
:
'密碼設定成功!'
,
'login_to_register'
:
'去注册'
,
'register'
:
'注册'
,
'register_to_login'
:
'去登入'
,
'register_success_to_login'
:
'注册成功,請登入!'
,
'login_form_register_user_name'
:
'用戶名'
,
'login_form_user_password_repeat'
:
'確認密碼'
,
'login_form_user_password_repeat_not_empty'
:
'確認密碼不能為空'
,
'login_form_user_password_repeat_not_equals'
:
'兩次輸入的密碼不一致'
,
'login_form_register_phone'
:
'手機'
,
'login_form_register_phone_not_empty'
:
'手機號碼不能為空'
,
'login_form_register_email'
:
'郵箱'
,
};
lib/common/i18n/lang/zh_Hans.dart
浏览文件 @
8e95f7d0
...
...
@@ -104,10 +104,21 @@ const Map<String, String> zh_Hans = {
// login
'login'
:
'登录'
,
'login_to_register'
:
'去注册'
,
'register'
:
'注册'
,
'register_to_login'
:
'去登录'
,
'register_success_to_login'
:
'注册成功,请登录!'
,
'login_form_user_name'
:
'用户名或手机号码'
,
'login_form_register_user_name'
:
'用户名'
,
'login_form_user_name_not_empty'
:
'用户名不能为空'
,
'login_form_user_password'
:
'密码'
,
'login_form_user_password_not_empty'
:
'密码不能为空'
,
'login_form_user_password_repeat'
:
'确认密码'
,
'login_form_user_password_repeat_not_empty'
:
'确认密码不能为空'
,
'login_form_user_password_repeat_not_equals'
:
'两次输入的密码不一致'
,
'login_form_register_phone'
:
'手机'
,
'login_form_register_phone_not_empty'
:
'手机号码不能为空'
,
'login_form_register_email'
:
'邮箱'
,
'login_form_user_code'
:
'验证码'
,
'login_form_user_code_not_empty'
:
'验证码不能为空'
,
'login_form_code_btn_send'
:
'发送验证码'
,
...
...
lib/common/models/index.dart
浏览文件 @
8e95f7d0
...
...
@@ -5,6 +5,7 @@ export './o2_app_update_info.dart';
export
'./echo_data.dart'
;
export
'./jpush_device.dart'
;
export
'./value_data_bool.dart'
;
export
'./value_data_string.dart'
;
export
'./id_data.dart'
;
export
'./o2_api_response.dart'
;
export
'./server/index.dart'
;
...
...
lib/common/models/value_data_string.dart
0 → 100644
浏览文件 @
8e95f7d0
class
ValueStringData
{
String
?
value
;
ValueStringData
({
this
.
value
});
ValueStringData
.
fromJson
(
Map
<
String
,
dynamic
>
jsonMap
)
{
value
=
jsonMap
[
'value'
];
}
Map
<
String
,
dynamic
>
toJson
()
=>
{
"value"
:
value
,
};
}
\ No newline at end of file
lib/common/routers/pages.dart
浏览文件 @
8e95f7d0
...
...
@@ -72,6 +72,7 @@ import '../../pages/home/settings/my_profile/index.dart';
import
'../../pages/home/settings/settings_common/index.dart'
;
import
'../../pages/home/settings/skin/index.dart'
;
import
'../../pages/login/index.dart'
;
import
'../../pages/login/register/index.dart'
;
import
'../../pages/login/server_info/index.dart'
;
import
'../../pages/splash/index.dart'
;
import
'routes.dart'
;
...
...
@@ -90,6 +91,10 @@ class O2OAPages {
name:
O2OARoutes
.
bind
,
page:
()
=>
const
BindPage
(),
binding:
BindBinding
()),
GetPage
(
name:
O2OARoutes
.
register
,
page:
()
=>
const
RegisterPage
(),
binding:
RegisterBinding
()),
GetPage
(
name:
O2OARoutes
.
login
,
page:
()
=>
const
LoginPage
(),
...
...
lib/common/routers/routes.dart
浏览文件 @
8e95f7d0
...
...
@@ -47,6 +47,7 @@ class O2OARoutes {
static
const
String
login
=
'/login'
;
// 登录页面
static
const
String
loginServerInfo
=
'/login/server/info'
;
// 服务器信息配置
static
const
String
register
=
'/register'
;
// 注册页面
static
const
String
demoLogin
=
'/login/demo'
;
// 演示版本登录
static
const
String
processWebview
=
'/process/webview'
;
// webview页面
...
...
lib/common/values/o2.dart
浏览文件 @
8e95f7d0
...
...
@@ -18,6 +18,11 @@ class O2 {
// 隐私政策 地址
static
const
String
privacyPolicyUrl
=
'https://www.o2oa.net/secret.html'
;
/// 注册模式
static
const
String
registerModeDisable
=
'disable'
;
static
const
String
registerModeCaptcha
=
'captcha'
;
static
const
String
registerModeCode
=
'code'
;
// 极光推送appKey
static
const
String
jPushAppKey
=
"9aca7cc20fe0cc987cd913ca"
;
static
const
String
jPushAppChannel
=
"o2oa_flutter_channel"
;
...
...
lib/pages/login/controller.dart
浏览文件 @
8e95f7d0
...
...
@@ -36,8 +36,6 @@ class LoginController extends GetxController {
// 登录加密
RSAPublicKeyData
?
_publicKeyData
;
///
/// 登录加密服务
///
...
...
@@ -64,6 +62,17 @@ class LoginController extends GetxController {
}
}
/// 是否能注册
Future
<
void
>
loadRegisterMode
()
async
{
ValueStringData
?
data
=
await
OrganizationPersonalService
.
to
.
registerMode
();
OLogger
.
d
(
"注册模式:
${data?.value}
"
);
if
(
data
!=
null
&&
data
.
value
?.
isNotEmpty
==
true
&&
data
.
value
!=
O2
.
registerModeDisable
)
{
state
.
registerEnable
=
true
;
}
}
///
/// 获取图片验证码
///
...
...
@@ -117,7 +126,7 @@ class LoginController extends GetxController {
/// 登录
///
void
login
()
async
{
if
(
state
.
isVisibleAgree
&&
!
state
.
isAgree
)
{
if
(
state
.
isVisibleAgree
&&
!
state
.
isAgree
)
{
Loading
.
showError
(
'privacy_policy_bind_disagree_alert'
.
tr
);
return
;
}
...
...
@@ -196,8 +205,10 @@ class LoginController extends GetxController {
if
(
context
==
null
)
{
return
;
}
O2UI
.
showConfirm
(
context
,
'login_form_rebind_confirm_message'
.
tr
,
okPressed:
()
=>
_rebindExecute
())
;
O2UI
.
showConfirm
(
context
,
'login_form_rebind_confirm_message'
.
tr
,
okPressed:
()
=>
_rebindExecute
());
}
_rebindExecute
()
async
{
await
O2ApiManager
.
instance
.
cleanO2UnitAndSp
();
Get
.
offNamed
(
O2OARoutes
.
splash
);
...
...
@@ -229,6 +240,10 @@ class LoginController extends GetxController {
InnerWebviewPage
.
open
(
O2
.
privacyPolicyUrl
);
}
void
gotoRegister
()
{
Get
.
offAllNamed
(
O2OARoutes
.
register
);
}
/// 在 onInit() 之后调用 1 帧。这是进入的理想场所
@override
void
onReady
()
{
...
...
@@ -236,6 +251,7 @@ class LoginController extends GetxController {
// O2UI.hideStatusBar();
loadRSAPublicKey
();
loadLoginMode
();
loadRegisterMode
();
state
.
year
=
'
${DateTime.now().year}
'
;
super
.
onReady
();
}
...
...
@@ -245,5 +261,4 @@ class LoginController extends GetxController {
// O2UI.showStatusBar();
super
.
onClose
();
}
}
lib/pages/login/register/bindings.dart
0 → 100644
浏览文件 @
8e95f7d0
import
'package:get/get.dart'
;
import
'controller.dart'
;
class
RegisterBinding
implements
Bindings
{
@override
void
dependencies
()
{
Get
.
lazyPut
<
RegisterController
>(()
=>
RegisterController
());
}
}
lib/pages/login/register/controller.dart
0 → 100644
浏览文件 @
8e95f7d0
import
'dart:convert'
;
import
'dart:typed_data'
;
import
'package:flutter/material.dart'
;
import
'package:get/get.dart'
;
import
'../../../common/api/index.dart'
;
import
'../../../common/models/index.dart'
;
import
'../../../common/routers/index.dart'
;
import
'../../../common/utils/index.dart'
;
import
'../../../common/values/index.dart'
;
import
'../../../environment_config.dart'
;
import
'../../common/inner_webview/view.dart'
;
import
'index.dart'
;
class
RegisterController
extends
GetxController
{
RegisterController
();
final
state
=
RegisterState
();
// 注册用户名的控制器
final
TextEditingController
userNameController
=
TextEditingController
();
// 密码的控制器
final
TextEditingController
passwordController
=
TextEditingController
();
// 第二次密码的控制器
final
TextEditingController
repeatPasswordController
=
TextEditingController
();
// 邮箱的控制器
final
TextEditingController
emailController
=
TextEditingController
();
// 手机号码的控制器
final
TextEditingController
phoneController
=
TextEditingController
();
// 图片验证码的控制器
final
TextEditingController
captchaController
=
TextEditingController
();
// 验证码的控制器
final
TextEditingController
codeController
=
TextEditingController
();
final
FocusNode
passwordNode
=
FocusNode
();
final
FocusNode
repeatPasswordNode
=
FocusNode
();
final
FocusNode
emailNode
=
FocusNode
();
final
FocusNode
phoneNode
=
FocusNode
();
final
FocusNode
codeNode
=
FocusNode
();
final
FocusNode
captchaNode
=
FocusNode
();
// 图片验证码对象
CaptchaImgData
?
_captchaImgData
;
/// 在 onInit() 之后调用 1 帧。这是进入的理想场所
@override
void
onReady
()
{
state
.
isVisibleAgree
=
EnvironmentConfig
.
needCheckPrivacyAgree
();
loadRegisterMode
();
super
.
onReady
();
}
/// 在 [onDelete] 方法之前调用。
@override
void
onClose
()
{
super
.
onClose
();
}
Future
<
void
>
loadRegisterMode
()
async
{
ValueStringData
?
data
=
await
OrganizationPersonalService
.
to
.
registerMode
();
if
(
data
!=
null
&&
data
.
value
?.
isNotEmpty
==
true
)
{
if
(
data
.
value
==
O2
.
registerModeDisable
)
{
OLogger
.
e
(
'错误,注册已经关闭!
${data.value}
'
);
Get
.
back
();
return
;
}
state
.
isCaptcha
=
(
data
.
value
==
O2
.
registerModeCaptcha
);
if
(
state
.
isCaptcha
)
{
getCaptchaImageData
();
}
OLogger
.
d
(
"注册模式:
${data.value}
"
);
}
}
///
/// 获取图片验证码
///
Future
<
void
>
getCaptchaImageData
()
async
{
_captchaImgData
=
await
OrganizationPersonalService
.
to
.
getRegisterCaptchaImgData
(
100
,
50
);
if
(
_captchaImgData
!=
null
)
{
captchaController
.
clear
();
state
.
captchaBase64String
=
_captchaImgData
?.
image
??
''
;
}
else
{
OLogger
.
e
(
'获取图片验证码失败!'
);
}
}
///
/// 解析图片验证码
///
Uint8List
parseCaptchaImg
()
{
return
base64Decode
(
state
.
captchaBase64String
);
}
/// 检查手机号码
bool
onCheckMobile
()
{
var
phone
=
phoneController
.
value
.
text
;
if
(
phone
.
isEmpty
)
{
Loading
.
toast
(
'login_form_register_phone_not_empty'
.
tr
);
return
false
;
}
return
true
;
}
/// 发送短信验证码
Future
<
void
>
sendSmsCode
()
async
{
var
mobile
=
phoneController
.
value
.
text
;
if
(
mobile
.
isEmpty
)
{
Loading
.
toast
(
'login_form_register_phone_not_empty'
.
tr
);
return
;
}
var
res
=
await
OrganizationPersonalService
.
to
.
getRegisterCode
(
mobile
);
if
(
res
!=
null
&&
res
.
value
==
true
)
{
if
(
Get
.
context
!=
null
)
{
FocusScope
.
of
(
Get
.
context
!).
requestFocus
(
codeNode
);
Loading
.
toast
(
'bind_send_code_success'
.
tr
);
}
}
}
Future
<
bool
>
checkUserName
(
String
username
)
async
{
final
res
=
await
OrganizationPersonalService
.
to
.
checkRegisterUserName
(
username
);
return
(
res
!=
null
&&
res
.
value
!=
null
&&
res
.
value
==
true
);
}
Future
<
void
>
register
()
async
{
final
username
=
userNameController
.
value
.
text
;
if
(
username
.
isEmpty
)
{
Loading
.
toast
(
'login_form_user_name_not_empty'
.
tr
);
return
;
}
final
checkName
=
await
checkUserName
(
username
);
if
(!
checkName
)
{
return
;
}
final
password
=
passwordController
.
value
.
text
;
if
(
password
.
isEmpty
)
{
Loading
.
toast
(
'login_form_user_password_not_empty'
.
tr
);
return
;
}
final
repeatPassword
=
repeatPasswordController
.
value
.
text
;
if
(
repeatPassword
.
isEmpty
)
{
Loading
.
toast
(
'login_form_user_password_repeat_not_empty'
.
tr
);
return
;
}
if
(
password
!=
repeatPassword
)
{
Loading
.
toast
(
'login_form_user_password_repeat_not_equals'
.
tr
);
return
;
}
final
mobile
=
phoneController
.
value
.
text
;
if
(
mobile
.
isEmpty
)
{
Loading
.
toast
(
'login_form_register_phone_not_empty'
.
tr
);
return
;
}
Map
<
String
,
String
>
post
=
{};
post
[
'name'
]
=
username
;
post
[
'password'
]
=
password
;
post
[
'mobile'
]
=
mobile
;
if
(
state
.
isCaptcha
)
{
final
captchaInput
=
captchaController
.
value
.
text
;
if
(
captchaInput
.
isEmpty
)
{
Loading
.
toast
(
'login_form_user_code_not_empty'
.
tr
);
return
;
}
// 图片验证码注册
post
[
'captchaAnswer'
]
=
captchaInput
;
post
[
'captcha'
]
=
_captchaImgData
?.
id
??
''
;
}
else
{
final
codeInput
=
codeController
.
value
.
text
;
if
(
codeInput
.
isEmpty
)
{
Loading
.
toast
(
'login_form_user_code_not_empty'
.
tr
);
return
;
}
// 短信验证码
post
[
'codeAnswer'
]
=
codeInput
;
}
post
[
'mail'
]
=
emailController
.
value
.
text
;
post
[
'genderType'
]
=
'd'
;
final
result
=
await
OrganizationPersonalService
.
to
.
register
(
post
);
if
(
result
!=
null
&&
result
.
value
==
true
)
{
Loading
.
toast
(
'register_success_to_login'
.
tr
);
gotoLogin
();
}
else
{
if
(
state
.
isCaptcha
)
{
getCaptchaImageData
();
}
}
}
void
gotoLogin
()
{
Get
.
offAllNamed
(
O2OARoutes
.
login
);
}
/// 同意协议
void
changeAgree
(
bool
?
v
)
{
state
.
isAgree
=
v
==
true
;
}
/// 打开用户协议
void
openUserAgreement
()
{
InnerWebviewPage
.
open
(
O2
.
userAgreementUrl
);
}
/// 打开隐私政策
void
openPrivacyPolicy
()
{
InnerWebviewPage
.
open
(
O2
.
privacyPolicyUrl
);
}
}
lib/pages/login/register/index.dart
0 → 100644
浏览文件 @
8e95f7d0
library
register
;
export
'./state.dart'
;
export
'./controller.dart'
;
export
'./bindings.dart'
;
export
'./view.dart'
;
lib/pages/login/register/state.dart
0 → 100644
浏览文件 @
8e95f7d0
import
'package:get/get.dart'
;
class
RegisterState
{
// title
final
_title
=
"注册"
.
obs
;
set
title
(
value
)
=>
_title
.
value
=
value
;
get
title
=>
_title
.
value
;
// 当前年份
final
_year
=
"2024"
.
obs
;
set
year
(
value
)
=>
_year
.
value
=
value
;
get
year
=>
_year
.
value
;
/// 图片验证码是否启用
final
_isCaptcha
=
false
.
obs
;
set
isCaptcha
(
value
)
=>
_isCaptcha
.
value
=
value
;
get
isCaptcha
=>
_isCaptcha
.
value
;
final
_captchaBase64String
=
''
.
obs
;
set
captchaBase64String
(
value
)
=>
_captchaBase64String
.
value
=
value
;
get
captchaBase64String
=>
_captchaBase64String
.
value
;
// 是否显示 同意协议
final
_isVisibleAgree
=
false
.
obs
;
set
isVisibleAgree
(
bool
value
)
=>
_isVisibleAgree
.
value
=
value
;
bool
get
isVisibleAgree
=>
_isVisibleAgree
.
value
;
// 是否同意协议
final
_isAgree
=
false
.
obs
;
set
isAgree
(
bool
value
)
=>
_isAgree
.
value
=
value
;
bool
get
isAgree
=>
_isAgree
.
value
;
}
lib/pages/login/register/view.dart
0 → 100644
浏览文件 @
8e95f7d0
import
'package:flutter/gestures.dart'
;
import
'package:flutter/material.dart'
;
import
'package:get/get.dart'
;
import
'../../../common/widgets/index.dart'
;
import
'index.dart'
;
class
RegisterPage
extends
GetView
<
RegisterController
>
{
const
RegisterPage
({
Key
?
key
})
:
super
(
key:
key
);
@override
Widget
build
(
BuildContext
context
)
{
return
GetBuilder
<
RegisterController
>(
builder:
(
_
)
{
return
Scaffold
(
body:
PageScrollContentWidget
(
contentWidget:
Column
(
children:
<
Widget
>[
_buildInputForm
(
context
),
const
Spacer
(),
_buildBottom
(),
],
),
));
},
);
}
// 底部copyright
Widget
_buildBottom
()
{
return
Obx
(()
=>
Container
(
margin:
const
EdgeInsets
.
only
(
bottom:
10
),
child:
Align
(
alignment:
Alignment
.
center
,
child:
Text
(
'copy_right'
.
trArgs
([
'appName'
.
tr
,
controller
.
state
.
year
])),
),
));
}
// 表单
Widget
_buildInputForm
(
BuildContext
context
)
{
return
Obx
(()
=>
Container
(
width:
295
,
margin:
const
EdgeInsets
.
only
(
top:
49
),
child:
Column
(
children:
[
// 账号输入框
TextField
(
maxLines:
1
,
autofocus:
true
,
style:
Theme
.
of
(
context
).
textTheme
.
bodyMedium
,
keyboardType:
TextInputType
.
text
,
textInputAction:
TextInputAction
.
next
,
controller:
controller
.
userNameController
,
onEditingComplete:
()
{
FocusScope
.
of
(
context
).
requestFocus
(
controller
.
passwordNode
);
},
decoration:
InputDecoration
(
labelText:
'login_form_register_user_name'
.
tr
,
prefixIcon:
Icon
(
Icons
.
person
,
color:
Theme
.
of
(
context
).
colorScheme
.
secondary
),
),
),
const
SizedBox
(
height:
16
,
),
TextField
(
maxLines:
1
,
obscureText:
true
,
style:
Theme
.
of
(
context
).
textTheme
.
bodyMedium
,
focusNode:
controller
.
passwordNode
,
controller:
controller
.
passwordController
,
textInputAction:
TextInputAction
.
next
,
onEditingComplete:
()
{
FocusScope
.
of
(
context
)
.
requestFocus
(
controller
.
repeatPasswordNode
);
},
decoration:
InputDecoration
(
labelText:
'login_form_user_password'
.
tr
,
prefixIcon:
Icon
(
Icons
.
lock
,
color:
Theme
.
of
(
context
).
colorScheme
.
secondary
),
),
),
const
SizedBox
(
height:
16
,
),
TextField
(
maxLines:
1
,
obscureText:
true
,
style:
Theme
.
of
(
context
).
textTheme
.
bodyMedium
,
focusNode:
controller
.
repeatPasswordNode
,
controller:
controller
.
repeatPasswordController
,
textInputAction:
TextInputAction
.
next
,
onEditingComplete:
()
{
FocusScope
.
of
(
context
).
requestFocus
(
controller
.
phoneNode
);
},
decoration:
InputDecoration
(
labelText:
'login_form_user_password_repeat'
.
tr
,
prefixIcon:
Icon
(
Icons
.
lock
,
color:
Theme
.
of
(
context
).
colorScheme
.
secondary
),
),
),
const
SizedBox
(
height:
16
,
),
TextField
(
maxLines:
1
,
style:
Theme
.
of
(
context
).
textTheme
.
bodyMedium
,
keyboardType:
TextInputType
.
number
,
textInputAction:
TextInputAction
.
next
,
focusNode:
controller
.
phoneNode
,
controller:
controller
.
phoneController
,
onEditingComplete:
()
{
FocusScope
.
of
(
context
).
requestFocus
(
controller
.
emailNode
);
},
decoration:
InputDecoration
(
labelText:
'login_form_register_phone'
.
tr
,
prefixIcon:
Icon
(
Icons
.
phone_android
,
color:
Theme
.
of
(
context
).
colorScheme
.
secondary
),
),
),
const
SizedBox
(
height:
16
,
),
TextField
(
maxLines:
1
,
style:
Theme
.
of
(
context
).
textTheme
.
bodyMedium
,
textInputAction:
TextInputAction
.
next
,
focusNode:
controller
.
emailNode
,
controller:
controller
.
emailController
,
onEditingComplete:
()
{
if
(
controller
.
state
.
isCaptcha
)
{
FocusScope
.
of
(
context
).
requestFocus
(
controller
.
captchaNode
);
}
else
{
FocusScope
.
of
(
context
).
requestFocus
(
controller
.
codeNode
);
}
},
decoration:
InputDecoration
(
labelText:
'login_form_register_email'
.
tr
,
prefixIcon:
Icon
(
Icons
.
email
,
color:
Theme
.
of
(
context
).
colorScheme
.
secondary
),
),
),
const
SizedBox
(
height:
16
,
),
// 密码或短信验证码 输入框
controller
.
state
.
isCaptcha
?
_captchaInput
(
context
)
:
_codeModeTextFormField
(
context
),
const
SizedBox
(
height:
16
,
),
SizedBox
(
width:
double
.
infinity
,
height:
42
,
child:
O2ElevatedButton
(
()
{
controller
.
register
();
},
Text
(
'register'
.
tr
),
),
),
const
SizedBox
(
height:
16
,
),
Visibility
(
visible:
controller
.
state
.
isVisibleAgree
,
child:
Row
(
children:
[
Obx
(()
=>
Checkbox
(
value:
controller
.
state
.
isAgree
,
onChanged:
(
value
)
=>
controller
.
changeAgree
(
value
),
)),
Expanded
(
flex:
1
,
child:
RichText
(
maxLines:
2
,
softWrap:
true
,
overflow:
TextOverflow
.
ellipsis
,
text:
TextSpan
(
text:
'privacy_policy_bind_content_part1'
.
tr
,
style:
Theme
.
of
(
context
).
textTheme
.
bodySmall
,
children:
[
TextSpan
(
text:
'user_agreement_book_mark'
.
tr
,
style:
TextStyle
(
color:
Theme
.
of
(
context
)
.
colorScheme
.
primary
,
fontSize:
12
),
recognizer:
TapGestureRecognizer
()
..
onTap
=
()
=>
controller
.
openUserAgreement
()),
TextSpan
(
text:
'privacy_policy_dialog_content_part2'
.
tr
,
style:
Theme
.
of
(
context
).
textTheme
.
bodySmall
,
),
TextSpan
(
text:
'privacy_policy_book_mark'
.
tr
,
style:
TextStyle
(
color:
Theme
.
of
(
context
)
.
colorScheme
.
primary
,
fontSize:
12
),
recognizer:
TapGestureRecognizer
()
..
onTap
=
()
=>
controller
.
openPrivacyPolicy
()),
]),
))
],
)),
const
SizedBox
(
height:
16
,
),
TextButton
(
onPressed:
()
=>
controller
.
gotoLogin
(),
child:
Text
(
'register_to_login'
.
tr
,
style:
Theme
.
of
(
context
).
textTheme
.
bodySmall
)),
]),
));
}
Widget
_captchaInput
(
BuildContext
context
)
{
return
Row
(
children:
[
Expanded
(
flex:
1
,
child:
TextField
(
maxLines:
1
,
style:
Theme
.
of
(
context
).
textTheme
.
bodyMedium
,
keyboardType:
TextInputType
.
number
,
focusNode:
controller
.
captchaNode
,
controller:
controller
.
captchaController
,
textInputAction:
TextInputAction
.
done
,
decoration:
InputDecoration
(
labelText:
'login_form_user_code'
.
tr
,
prefixIcon:
Icon
(
Icons
.
lock
,
color:
Theme
.
of
(
context
).
colorScheme
.
secondary
),
),
)),
controller
.
state
.
captchaBase64String
.
isEmpty
?
TextButton
(
onPressed:
()
{
controller
.
getCaptchaImageData
();
},
child:
const
Text
(
'点击刷新'
))
:
InkWell
(
onTap:
()
{
controller
.
getCaptchaImageData
();
},
child:
Image
.
memory
(
controller
.
parseCaptchaImg
(),
width:
100
,
height:
50
,
fit:
BoxFit
.
cover
,
),
)
],
);
}
///
/// 短信验证码登录
///
Widget
_codeModeTextFormField
(
BuildContext
context
)
{
return
Row
(
children:
[
Expanded
(
flex:
2
,
child:
TextField
(
maxLines:
1
,
obscureText:
true
,
style:
Theme
.
of
(
context
).
textTheme
.
bodyMedium
,
keyboardType:
TextInputType
.
text
,
controller:
controller
.
codeController
,
focusNode:
controller
.
codeNode
,
textInputAction:
TextInputAction
.
done
,
decoration:
InputDecoration
(
labelText:
'login_form_user_code'
.
tr
,
prefixIcon:
Icon
(
Icons
.
lock
,
color:
Theme
.
of
(
context
).
colorScheme
.
secondary
),
),
),
),
Expanded
(
flex:
1
,
child:
CountDownButton
(()
{
return
controller
.
onCheckMobile
();
},
()
{
controller
.
sendSmsCode
();
}))
],
);
}
}
lib/pages/login/state.dart
浏览文件 @
8e95f7d0
...
...
@@ -11,6 +11,10 @@ class LoginState {
set
year
(
value
)
=>
_year
.
value
=
value
;
get
year
=>
_year
.
value
;
/// 是否能注册
final
_registerEnable
=
false
.
obs
;
set
registerEnable
(
value
)
=>
_registerEnable
.
value
=
value
;
get
registerEnable
=>
_registerEnable
.
value
;
/// 密码登录模式
final
_isPasswordLogin
=
true
.
obs
;
...
...
lib/pages/login/view.dart
浏览文件 @
8e95f7d0
...
...
@@ -149,12 +149,18 @@ class LoginPage extends GetView<LoginController> {
style:
Theme
.
of
(
context
).
textTheme
.
bodySmall
))),
),
Expanded
(
child:
Visibility
(
visible:
!
EnvironmentConfig
.
isDirectConnectMode
(),
child:
TextButton
(
child:
EnvironmentConfig
.
isDirectConnectMode
()
?
Visibility
(
visible:
controller
.
state
.
registerEnable
,
child:
TextButton
(
onPressed:
()
=>
controller
.
gotoRegister
(),
child:
Text
(
'login_to_register'
.
tr
,
style:
Theme
.
of
(
context
).
textTheme
.
bodySmall
)))
:
TextButton
(
onPressed:
()
=>
controller
.
rebind
(),
child:
Text
(
'login_form_rebind'
.
tr
,
style:
Theme
.
of
(
context
).
textTheme
.
bodySmall
)))
)
style:
Theme
.
of
(
context
).
textTheme
.
bodySmall
)))
],
),
const
SizedBox
(
...
...
@@ -283,7 +289,7 @@ class LoginPage extends GetView<LoginController> {
style:
Theme
.
of
(
context
).
textTheme
.
bodyMedium
,
focusNode:
controller
.
passwordNode
,
controller:
controller
.
passwordController
,
textInputAction:
TextInputAction
.
next
,
textInputAction:
TextInputAction
.
done
,
decoration:
InputDecoration
(
labelText:
'login_form_user_password'
.
tr
,
prefixIcon:
Icon
(
Icons
.
lock
,
...
...