diff --git a/marking_app/lib/common/mixin/common.dart b/marking_app/lib/common/mixin/common.dart index def6f47..baf6f08 100644 --- a/marking_app/lib/common/mixin/common.dart +++ b/marking_app/lib/common/mixin/common.dart @@ -33,6 +33,12 @@ mixin CommonMixin { return RestClientReport(dio, baseUrl: RequestConfig().baseUrlOfReport); } + // 获取 CLIENT + Future getClientLogin() async { + Dio dio = await getDio(); + return RestClient(dio, baseUrl: RequestConfig().loginBaseUrl); + } + void setTimeOut(int seconds, call) => Future.delayed(Duration(seconds: seconds), call); // 执行 context diff --git a/marking_app/lib/pages/login/index.dart b/marking_app/lib/pages/login/index.dart index 16ec42d..2317dec 100644 --- a/marking_app/lib/pages/login/index.dart +++ b/marking_app/lib/pages/login/index.dart @@ -44,8 +44,10 @@ class _TheLoginState extends ConsumerState with CommonMixin { //添加证书 setHttpsPEM() async { - (dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate = (client) { - client.badCertificateCallback = (X509Certificate cert, String host, int port) { + (dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate = + (client) { + client.badCertificateCallback = + (X509Certificate cert, String host, int port) { return true; }; }; @@ -63,6 +65,7 @@ class _TheLoginState extends ConsumerState with CommonMixin { bool canLogin = true; bool hasNameVal = false; bool _isShowPwd = true; + bool showRegister = false; void _showPassword() { setState(() { @@ -77,7 +80,7 @@ class _TheLoginState extends ConsumerState with CommonMixin { // 延迟更新 Provider ref.read(userTokenProvider.notifier).clean(); // 进入登录页先清空信息 }); - + getShowRegister(); super.initState(); dio = Dio( BaseOptions( @@ -86,12 +89,14 @@ class _TheLoginState extends ConsumerState with CommonMixin { receiveTimeout: 8000, ), ); - dio.interceptors.add(LogInterceptor(responseBody: true, requestBody: true)); //添加日志 + dio.interceptors + .add(LogInterceptor(responseBody: true, requestBody: true)); //添加日志 setHttpsPEM(); client = RestClient(dio, baseUrl: RequestConfig().loginBaseUrl); - _userNameController = TextEditingController()..addListener(userNameListener); + _userNameController = TextEditingController() + ..addListener(userNameListener); _passwordController = TextEditingController(); _pwdFocus = FocusNode(); _theFocus = FocusNode(); @@ -106,11 +111,23 @@ class _TheLoginState extends ConsumerState with CommonMixin { }); } + void getShowRegister() async { + RestClient client = await getClientLogin(); + BaseStructureResult resultData = await client.showRegister(); + if(resultData.success){ + setState(() { + showRegister = resultData.data; + }); + + } + } + void userNameListener() { String userName = _userNameController.text; int useNameLength = userName.length; bool hasNameValNew = useNameLength > 0; - if (hasNameValNew != hasNameVal) toUpState(setState, () => hasNameVal = hasNameValNew, mounted); + if (hasNameValNew != hasNameVal) + toUpState(setState, () => hasNameVal = hasNameValNew, mounted); const isProd = bool.fromEnvironment('dart.vm.product'); if (!isProd && useNameLength == 11) { _passwordController.text = userName.substring(useNameLength - 6); @@ -165,12 +182,15 @@ class _TheLoginState extends ConsumerState with CommonMixin { child: SizedBox( height: 86.w, width: 86.w, - child: Image.asset('assets/images/logo.png', fit: BoxFit.cover), + child: Image.asset('assets/images/logo.png', + fit: BoxFit.cover), ), ), Container( - margin: EdgeInsets.symmetric(horizontal: 32.w, vertical: 24.h), - padding: EdgeInsets.only(top: 34.h, bottom: 16.h, left: 22.w, right: 22.w), + margin: EdgeInsets.symmetric( + horizontal: 32.w, vertical: 24.h), + padding: EdgeInsets.only( + top: 34.h, bottom: 16.h, left: 22.w, right: 22.w), decoration: BoxDecoration( color: Colors.white, border: Border.all(width: 1.w, color: Colors.white), @@ -199,13 +219,18 @@ class _TheLoginState extends ConsumerState with CommonMixin { ), decoration: InputDecoration( hintText: "请输入账号", - hintStyle: TextStyle(fontSize: 16.sp, color: const Color.fromRGBO(153, 153, 153, 1)), + hintStyle: TextStyle( + fontSize: 16.sp, + color: const Color.fromRGBO(153, 153, 153, 1)), labelText: "账号", - labelStyle: TextStyle(fontSize: 16.sp, color: const Color.fromRGBO(148, 163, 182, 1)), + labelStyle: TextStyle( + fontSize: 16.sp, + color: const Color.fromRGBO(148, 163, 182, 1)), suffixIcon: !hasNameVal ? null : Transform.translate( - offset: Offset(10, 10), // 根据原始组件的padding值来设置偏移量 + offset: + Offset(10, 10), // 根据原始组件的padding值来设置偏移量 child: IconButton( alignment: Alignment.center, padding: EdgeInsets.zero, @@ -227,7 +252,8 @@ class _TheLoginState extends ConsumerState with CommonMixin { controller: _passwordController, keyboardType: TextInputType.number, maxLines: 1, - obscureText: _isShowPwd, //隐藏密码显示 + obscureText: _isShowPwd, + //隐藏密码显示 textInputAction: TextInputAction.go, onSubmitted: (val) => toLogin(), style: TextStyle( @@ -240,13 +266,19 @@ class _TheLoginState extends ConsumerState with CommonMixin { onTap: _showPassword, child: Icon( Icons.remove_red_eye, - color: !_isShowPwd ? Theme.of(context).primaryColor : Colors.grey, + color: !_isShowPwd + ? Theme.of(context).primaryColor + : Colors.grey, ), ), - hintStyle: TextStyle(fontSize: 16.sp, color: const Color.fromRGBO(153, 153, 153, 1)), + hintStyle: TextStyle( + fontSize: 16.sp, + color: const Color.fromRGBO(153, 153, 153, 1)), labelText: "密码", isDense: true, - labelStyle: TextStyle(fontSize: 16.sp, color: const Color.fromRGBO(148, 163, 182, 1)), + labelStyle: TextStyle( + fontSize: 16.sp, + color: const Color.fromRGBO(148, 163, 182, 1)), ), ), SizedBox( @@ -262,8 +294,10 @@ class _TheLoginState extends ConsumerState with CommonMixin { checkColor: Colors.white, value: keepPwd, onChanged: (value) { - FocusScope.of(context).requestFocus(_pwdFocus); - FocusScope.of(context).requestFocus(_theFocus); + FocusScope.of(context) + .requestFocus(_pwdFocus); + FocusScope.of(context) + .requestFocus(_theFocus); setState(() { keepPwd = value ?? false; }); @@ -284,6 +318,20 @@ class _TheLoginState extends ConsumerState with CommonMixin { ), ), ), + Spacer(), + if (showRegister == true) + InkWell( + onTap: () { + RouterManager.router.navigateTo( + context, RouterManager.registerPath); + }, + child: Text( + '注册', + style: TextStyle( + fontSize: 14.sp, + color: const Color.fromRGBO( + 148, 163, 182, 1)), + )), ], ), InkWell( @@ -291,7 +339,9 @@ class _TheLoginState extends ConsumerState with CommonMixin { child: Container( margin: EdgeInsets.symmetric(vertical: 10.h), decoration: BoxDecoration( - color: canLogin ? const Color.fromRGBO(9, 105, 246, 1) : Colors.grey, + color: canLogin + ? const Color.fromRGBO(9, 105, 246, 1) + : Colors.grey, boxShadow: [ BoxShadow( color: const Color.fromRGBO(46, 91, 255, 0.5), @@ -309,7 +359,8 @@ class _TheLoginState extends ConsumerState with CommonMixin { height: 50.h, child: Text( '登 录', - style: TextStyle(fontSize: 16.sp, color: Colors.white), + style: TextStyle( + fontSize: 16.sp, color: Colors.white), ), ), ), @@ -323,8 +374,10 @@ class _TheLoginState extends ConsumerState with CommonMixin { checkColor: Colors.white, value: readAgreement, onChanged: (value) { - FocusScope.of(context).requestFocus(_pwdFocus); - FocusScope.of(context).requestFocus(_theFocus); + FocusScope.of(context) + .requestFocus(_pwdFocus); + FocusScope.of(context) + .requestFocus(_theFocus); setState(() { readAgreement = value ?? false; }); @@ -402,18 +455,26 @@ class _TheLoginState extends ConsumerState with CommonMixin { if (!readAgreement) return toMsg('请勾选我已阅读用户协议和隐私协议'); String userPwdMd5 = CommonUtils.generateMD5(userPwd); + print('userPwdMd5=$userPwdMd5'); EasyLoading.show(status: 'loading...'); try { - BaseStructureResult resultData = await client.toLogin(UserLoginParams(userName, userPwdMd5)); - UserLogin? userData = resultData.code == 200 && resultData.data != null ? UserLogin.fromJson(resultData.data) : null; - if (resultData.code != 200 || userData?.accessToken == null || userData?.accessToken == '') { + BaseStructureResult resultData = + await client.toLogin(UserLoginParams(userName, userPwdMd5)); + UserLogin? userData = resultData.code == 200 && resultData.data != null + ? UserLogin.fromJson(resultData.data) + : null; + if (resultData.code != 200 || + userData?.accessToken == null || + userData?.accessToken == '') { return toMsg(resultData.message ?? '登录失败,请重试'); } FastData fastData = FastData.getInstance(); fastData.setToken(userData!.accessToken); - BaseStructureResult userRes = await client.getUserInfo('Bearer ${userData.accessToken}'); + BaseStructureResult userRes = + await client.getUserInfo('Bearer ${userData.accessToken}'); + if (userRes.code != 200 || userRes.data == null) { throw Exception('登录失败,请重试'); } @@ -428,7 +489,8 @@ class _TheLoginState extends ConsumerState with CommonMixin { ref.read(userTokenProvider.notifier).initToken(); // 跳转登录页 - RouterManager.router.navigateTo(context, RouterManager.root, clearStack: true, transition: getTransition()); + RouterManager.router.navigateTo(context, RouterManager.root, + clearStack: true, transition: getTransition()); }); } catch (e) { toPrint(val: e.toString()); diff --git a/marking_app/lib/pages/mainPage.dart b/marking_app/lib/pages/mainPage.dart index 2dc02c1..e6052aa 100644 --- a/marking_app/lib/pages/mainPage.dart +++ b/marking_app/lib/pages/mainPage.dart @@ -79,6 +79,7 @@ class TheMainPageState extends ConsumerState with CommonMixin { if (!value) { return toLoginPage(context); } + if(ref.read(userProvider).id == '540117143121989') return; ref.read(userReportProvider.notifier).initUserReport(); // 初始化报告页面用户身份职位 }); // 定值token // 初始化偏好设置 @@ -98,7 +99,9 @@ class TheMainPageState extends ConsumerState with CommonMixin { void getAppUpgrade(UserInfo user) async { try { showUpgrade = true; - if (user.loginName == '18888888888') return; + // if (user.loginName == '18888888888') return; + // if (user.loginName == 'u0001') return; + if (user.loginName == '13350366646') return; // 获取设备信息 String deviceInfo; int deviceType; diff --git a/marking_app/lib/pages/mine/log_off.dart b/marking_app/lib/pages/mine/log_off.dart new file mode 100644 index 0000000..aaf8f14 --- /dev/null +++ b/marking_app/lib/pages/mine/log_off.dart @@ -0,0 +1,198 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_easyloading/flutter_easyloading.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:marking_app/common/mixin/common.dart'; +import 'package:marking_app/common/model/common/base_structure_result.dart'; +import 'package:marking_app/provider/user_provider.dart'; +import 'package:marking_app/routes/RouterManager.dart'; +import 'package:marking_app/utils/const_text.dart'; +import 'package:marking_app/utils/index.dart'; +import 'package:marking_app/utils/my_text.dart'; +import 'package:marking_app/utils/request/rest_client.dart'; + +class LogOff extends StatefulHookConsumerWidget { + const LogOff({Key? key}) : super(key: key); + + @override + ConsumerState createState() => _LogOffState(); +} + +class _LogOffState extends ConsumerState with CommonMixin{ + bool canClick = true; + bool readAgreement = false; // 阅读协议 + + logOff() async{ + + if (!canClick) return; + setState(() => canClick = false); + void toMsg(msg) { + ToastUtils.showError(msg); + setState(() => canClick = true); + } + if (!readAgreement) return toMsg('请勾选我已阅读用户协议和隐私协议'); + + final userState = ref.watch(userProvider); + EasyLoading.show(status: 'loading...'); + RestClient client = await getClientLogin(); + BaseStructureResult resultData = await client.getLogOff(userState.loginName); + if (resultData.code != 200) { + return ToastUtils.showError(resultData.message ?? '注销失败,请重试'); + } + EasyLoading.dismiss(); + ToastUtils.showSuccess('注销成功'); + // 跳转登录页 + RouterManager.router.navigateTo(context, RouterManager.loginPath); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: const Color.fromRGBO(248, 248, 248, 1), + appBar: AppBar( + backgroundColor: Colors.white, + title: Text( + '注销', + style: TextStyle(fontSize: 14.sp, color: Color(0xFF333333)), + ), + centerTitle: true, + leading: IconButton( + icon: Icon(Icons.arrow_back_ios, color: Colors.black), + onPressed: () => Navigator.of(context).pop(), + ), + ), + body: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox( + height: 30.r, + ), + Center( + child: Text( + '温馨提示,请仔细阅读', + style: TextStyle( + fontSize: 16.sp, + color: Color(0xFF464646), + fontWeight: FontWeight.w500), + ), + ), + SizedBox( + height: 20.r, + ), + cont('您仅可注销您本人申请的账号'), + cont('注销后,账号的全部权益将被清除'), + cont('注销后,账号下的所有数据、记录等将无法访问或找回'), + cont('注销后,将清除该账号在网站保留的个人信息'), + cont('注销账号(账号删除)属于用户自主行为'), + /* Padding( + padding: EdgeInsets.symmetric(vertical: 5.r, horizontal: 14.r), + child: Row( + children: [ + Text( + '注销账号即表示您已确认并同意', + style: TextStyle(fontSize: 14.sp, color: Color(0xFF616161)), + ), + InkWell( + onTap: (){ + RouterManager.router.navigateTo( + context, + '${RouterManager.agreementPath}?type=${AGREEMENT_KEY.USER_LOGOUT.name}', + transition: getTransition(), + ); + }, + child: Text( + '注销协议', + style: TextStyle(fontSize: 14.sp, color: Color(0xFF6888FD)), + ), + ) + ], + ), + ),*/ + SizedBox( + height: 50.r, + ), + InkWell( + onTap:logOff, + child: Center( + child: Container( + margin: EdgeInsets.symmetric(vertical: 10.h), + alignment: Alignment.center, + width: 200.r, + height: 50.r, + decoration: BoxDecoration( + color: canClick + ? const Color.fromRGBO(9, 105, 246, 1) + : Colors.grey, + /*boxShadow: [ + BoxShadow( + color: const Color.fromRGBO(46, 91, 255, 0.5), + offset: Offset(6.w, 10.h), //阴影y轴偏移量 + blurRadius: 14, //阴影模糊程度 + spreadRadius: 0.5, //阴影扩散程度 + ) + ],*/ + borderRadius: BorderRadius.all( + Radius.circular(20.w), + ), + ), + child: Text( + '确认注销', + style: TextStyle(fontSize: 16.sp, color: Colors.white), + ), + ), + ), + ), + Padding( + padding: EdgeInsets.symmetric(vertical: 5.r, horizontal: 14.r), + child: Row( + children: [ + Container( + width: 30.w, + padding: EdgeInsets.only(right: 10.w), + child: Checkbox( + activeColor: Colors.deepOrangeAccent, + checkColor: Colors.white, + value: readAgreement, + onChanged: (value) { + setState(() { + readAgreement = value ?? false; + }); + }, + ), + ), + Text( + '已确认并同意', + style: TextStyle(fontSize: 14.sp, color: Color(0xFF616161)), + ), + InkWell( + onTap: () { + RouterManager.router.navigateTo( + context, + '${RouterManager.agreementPath}?type=${AGREEMENT_KEY.USER_LOGOUT.name}', + transition: getTransition(), + ); + }, + child: quickText( + '《注销协议》', + size: 12.sp, + color: Colors.deepOrangeAccent, + ), + ), + ], + ), + ), + ], + ), + ); + } +} + +Widget cont(String name) { + return Padding( + padding: EdgeInsets.symmetric(vertical: 5.r, horizontal: 14.r), + child: Text( + name, + style: TextStyle(fontSize: 14.sp, color: Color(0xFF616161)), + ), + ); +} diff --git a/marking_app/lib/pages/mine/other_pages/index.dart b/marking_app/lib/pages/mine/other_pages/index.dart index 9c89526..59dfd4f 100644 --- a/marking_app/lib/pages/mine/other_pages/index.dart +++ b/marking_app/lib/pages/mine/other_pages/index.dart @@ -1,11 +1,14 @@ import 'package:fluro/fluro.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:marking_app/common/mixin/common.dart'; +import 'package:marking_app/common/model/common/base_structure_result.dart'; import 'package:marking_app/routes/RouterManager.dart'; import 'package:marking_app/utils/const_text.dart'; import 'package:marking_app/utils/fluro/index.dart'; import 'package:marking_app/utils/index.dart'; import 'package:marking_app/utils/my_text.dart'; +import 'package:marking_app/utils/request/rest_client.dart'; import 'package:package_info/package_info.dart'; // 其他页面 @@ -16,12 +19,14 @@ class OhterPage extends StatefulWidget { State createState() => _OhterPageState(); } -class _OhterPageState extends State { +class _OhterPageState extends State with CommonMixin{ String localVersion = ''; + bool showLogOff = false; @override void initState() { super.initState(); + getShowLogOff(); getPageInfo(); } @@ -31,6 +36,16 @@ class _OhterPageState extends State { toUpState(setState, () => localVersion = packageInfo.version, mounted); } + getShowLogOff() async{ + RestClient client = await getClientLogin(); + BaseStructureResult resultData = await client.showLogOff(); + if(resultData.success){ + setState(() { + showLogOff = resultData.data; + }); + } + } + @override Widget build(BuildContext context) { final personalInfoTitleStly = TextStyle( @@ -56,7 +71,7 @@ class _OhterPageState extends State { Container( margin: EdgeInsets.symmetric(vertical: 22.h, horizontal: 16.w), padding: EdgeInsets.symmetric(vertical: 22.h, horizontal: 16.w), - height: 200.h, + height: showLogOff?250.h:200.h, decoration: BoxDecoration( borderRadius: BorderRadius.all(Radius.circular(6.w)), color: Colors.white, @@ -126,11 +141,40 @@ class _OhterPageState extends State { height: 1.w, color: const Color.fromRGBO(240, 243, 255, 1), ), - SizedBox(height: 8.h), + // SizedBox(height: 8.h), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [Text('APP版本', style: personalInfoTitleStly), quickText(localVersion)], - ) + ), + Container( + height: 1.w, + color: const Color.fromRGBO(240, 243, 255, 1), + ), + // SizedBox(height: 8.h), + if(showLogOff) + InkWell( + onTap: () { + RouterManager.router.navigateTo( + context, + RouterManager.logOffPath + ); + }, + child: Container( + padding: EdgeInsets.only(bottom: 4.h,top: 8.r), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text('注销账号', style: personalInfoTitleStly), + Icon( + Icons.arrow_forward_ios, + color: const Color.fromRGBO(80, 87, 103, 1), + size: 16.sp, + ) + ], + ), + ), + ), + ], ), ), diff --git a/marking_app/lib/pages/register/index.dart b/marking_app/lib/pages/register/index.dart new file mode 100644 index 0000000..1f8dfbd --- /dev/null +++ b/marking_app/lib/pages/register/index.dart @@ -0,0 +1,293 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_easyloading/flutter_easyloading.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:marking_app/common/config/request_config.dart'; +import 'package:marking_app/common/mixin/common.dart'; +import 'package:marking_app/common/model/common/base_structure_result.dart'; +import 'package:marking_app/common/model/user/user_login_params.dart'; +import 'package:marking_app/routes/RouterManager.dart'; +import 'package:marking_app/utils/common_utils.dart'; +import 'package:marking_app/utils/const_text.dart'; +import 'package:marking_app/utils/index.dart'; +import 'package:marking_app/utils/my_text.dart'; +import 'package:marking_app/utils/request/rest_client.dart'; + +class Register extends StatefulWidget { + const Register({Key? key}) : super(key: key); + + @override + State createState() => _RegisterState(); +} + +class _RegisterState extends State with CommonMixin{ + + late final FocusNode _theFocus; + late final FocusNode _pwdFocus; // 密码 + //文本输入框控制器 + late final TextEditingController _userNameController; + late final TextEditingController _passwordController; + + bool readAgreement = false; // 阅读协议 + bool _isShowPwd = true; + bool canLogin = true; + + @override + void initState(){ + super.initState(); + _userNameController = TextEditingController(); + _passwordController = TextEditingController(); + _pwdFocus = FocusNode(); + _theFocus = FocusNode(); + } + + @override + void dispose() { + super.dispose(); + _userNameController.dispose(); + _passwordController.dispose(); + _pwdFocus.dispose(); + _theFocus.dispose(); + } + + void toRegister() async{ + if (!canLogin) return; + setState(() => canLogin = false); + void toMsg(msg) { + ToastUtils.showError(msg); + setState(() => canLogin = true); + } + + FocusScope.of(context).requestFocus(_theFocus); + + String userName = _userNameController.text.trim(); + String userPwd = _passwordController.text.trim(); + if (userName == '') return toMsg('请填写用户账号'); + if (userPwd == '') return toMsg('请填写密码'); + if (!readAgreement) return toMsg('请勾选我已阅读用户协议和隐私协议'); + + String userPwdMd5 = CommonUtils.generateMD5(userPwd); + print('注册userPwdMd5=$userPwdMd5'); + EasyLoading.show(status: 'loading...'); + RestClient client = await getClientLogin(); + BaseStructureResult resultData = await client.toRegister(UserLoginParams(userName, userPwdMd5)); + + if (resultData.code != 200) { + return toMsg(resultData.message ?? '注册失败,请重试'); + } + EasyLoading.dismiss(); + ToastUtils.showSuccess('注册成功,请登录'); + // 跳转登录页 + RouterManager.router.navigateTo(context, RouterManager.loginPath); + } + + void _showPassword() { + setState(() { + _isShowPwd = !_isShowPwd; + }); + } + + @override + Widget build(BuildContext context) { + return GestureDetector( + behavior: HitTestBehavior.translucent, + onTap: () { + FocusScope.of(context).requestFocus(_theFocus); + }, + child: AnnotatedRegion( + value: const SystemUiOverlayStyle( + statusBarColor: Colors.transparent, + systemNavigationBarIconBrightness: Brightness.light, + statusBarIconBrightness: Brightness.light, + statusBarBrightness: Brightness.dark, + ), + child: Scaffold( + backgroundColor: Colors.transparent, + resizeToAvoidBottomInset: false, + body: Stack( + children: [ + Container( + width: double.infinity, + height: double.infinity, + alignment: Alignment.center, + decoration: const BoxDecoration( + image: DecorationImage( + image: AssetImage('assets/images/login_bgi.png'), + fit: BoxFit.fill, // 完全填充 + ), + ), + child: SingleChildScrollView( + child: Column( + children: [ + Container( + width: 86.w, + height: 86.w, + alignment: Alignment.center, + child: SizedBox( + height: 86.w, + width: 86.w, + child: Image.asset('assets/images/logo.png', fit: BoxFit.cover), + ), + ), + Container( + margin: EdgeInsets.symmetric(horizontal: 32.w, vertical: 24.h), + padding: EdgeInsets.only(top: 34.h, bottom: 16.h, left: 22.w, right: 22.w), + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(width: 1.w, color: Colors.white), + borderRadius: BorderRadius.all(Radius.circular(10.w)), + boxShadow: const [ + BoxShadow( + color: Color.fromRGBO(46, 91, 255, 0.1), + offset: Offset.zero, //阴影y轴偏移量 + blurRadius: 100, //阴影模糊程度 + spreadRadius: 100, //阴影扩散程度 + ) + ], + ), + child: Column(children: [ + TextField( + controller: _userNameController, + maxLines: 1, + maxLength: 20, + textInputAction: TextInputAction.next, + onEditingComplete: () { + FocusScope.of(context).requestFocus(_pwdFocus); + }, + style: TextStyle( + color: const Color.fromRGBO(80, 87, 103, 1), + fontSize: 15.sp, + ), + decoration: InputDecoration( + hintText: "请输入账号", + hintStyle: TextStyle(fontSize: 16.sp, color: const Color.fromRGBO(153, 153, 153, 1)), + labelText: "账号", + labelStyle: TextStyle(fontSize: 16.sp, color: const Color.fromRGBO(148, 163, 182, 1)), + ), + ), + TextField( + focusNode: _pwdFocus, + controller: _passwordController, + keyboardType: TextInputType.number, + maxLines: 1, + obscureText: _isShowPwd, //隐藏密码显示 + textInputAction: TextInputAction.go, + onSubmitted: (val) => toRegister(), + style: TextStyle( + color: const Color.fromRGBO(80, 87, 103, 1), + fontSize: 15.sp, + ), + decoration: InputDecoration( + hintText: "请输入密码", + suffix: GestureDetector( + onTap: _showPassword, + child: Icon( + Icons.remove_red_eye, + color: !_isShowPwd ? Theme.of(context).primaryColor : Colors.grey, + ), + ), + hintStyle: TextStyle(fontSize: 16.sp, color: const Color.fromRGBO(153, 153, 153, 1)), + labelText: "密码", + isDense: true, + labelStyle: TextStyle(fontSize: 16.sp, color: const Color.fromRGBO(148, 163, 182, 1)), + ), + ), + SizedBox( + height: 12.h, + ), + InkWell( + onTap: toRegister, + child: Container( + margin: EdgeInsets.symmetric(vertical: 10.h), + decoration: BoxDecoration( + color: canLogin ? const Color.fromRGBO(9, 105, 246, 1) : Colors.grey, + boxShadow: [ + BoxShadow( + color: const Color.fromRGBO(46, 91, 255, 0.5), + offset: Offset(6.w, 10.h), //阴影y轴偏移量 + blurRadius: 14, //阴影模糊程度 + spreadRadius: 0.5, //阴影扩散程度 + ) + ], + borderRadius: BorderRadius.all( + Radius.circular(8.w), + ), + ), + alignment: Alignment.center, + width: double.infinity, + height: 50.h, + child: Text( + '注 册', + style: TextStyle(fontSize: 16.sp, color: Colors.white), + ), + ), + ), + Row( + children: [ + Container( + width: 30.w, + padding: EdgeInsets.only(right: 10.w), + child: Checkbox( + activeColor: Colors.deepOrangeAccent, + checkColor: Colors.white, + value: readAgreement, + onChanged: (value) { + FocusScope.of(context) + .requestFocus(_pwdFocus); + FocusScope.of(context) + .requestFocus(_theFocus); + setState(() { + readAgreement = value ?? false; + }); + }, + ), + ), + InkWell( + onTap: () { + RouterManager.router.navigateTo( + context, + '${RouterManager.agreementPath}?type=${AGREEMENT_KEY.USER_AGREEMENT.name}', + transition: getTransition(), + ); + }, + child: quickText('我已阅读', size: 11.sp), + ), + InkWell( + onTap: () { + RouterManager.router.navigateTo( + context, + '${RouterManager.agreementPath}?type=${AGREEMENT_KEY.USER_AGREEMENT.name}', + transition: getTransition(), + ); + }, + child: quickText( + '《用户协议》', + size: 12.sp, + color: Colors.deepOrangeAccent, + ), + ), + ], + ), + ]), + ) + + + ], + ), + )), + Positioned( + top: MediaQuery.of(context).padding.top+20.r, + left: 20.r, + child: InkWell( + onTap: () => Navigator.pop(context), + child: Icon(Icons.arrow_back_ios_new_rounded, + color: Colors.white, size: 24.sp), + ), + ), + ], + ), + ), + ), + ); + } +} diff --git a/marking_app/lib/pages/reports/index.dart b/marking_app/lib/pages/reports/index.dart index 9baebd1..089007e 100644 --- a/marking_app/lib/pages/reports/index.dart +++ b/marking_app/lib/pages/reports/index.dart @@ -181,6 +181,7 @@ class _TheReportState extends ConsumerState RestClientReport clientReport = await getClientReport(); UserInfoReport _userReport = ref.read(userReportProvider); if (!_userReport.normal) { + if(ref.read(userProvider).id == '540117143121989') return null; // 用户职位数据是否已经请求,在主页已经请求一次 为正常使用 备用 bool theFlag = await ref.read(userReportProvider.notifier).initUserReport(); diff --git a/marking_app/lib/routes/RouterManager.dart b/marking_app/lib/routes/RouterManager.dart index 21516c5..8bad1ec 100644 --- a/marking_app/lib/routes/RouterManager.dart +++ b/marking_app/lib/routes/RouterManager.dart @@ -31,8 +31,10 @@ import 'package:marking_app/pages/marking/progress.dart'; import 'package:marking_app/pages/marking/progress_abnormal.dart'; import 'package:marking_app/pages/marking/review.dart'; import 'package:marking_app/pages/mine/index.dart'; +import 'package:marking_app/pages/mine/log_off.dart'; import 'package:marking_app/pages/mine/other_pages/index.dart'; import 'package:marking_app/pages/other/agreement_page.dart'; +import 'package:marking_app/pages/register/index.dart'; import 'package:marking_app/pages/report_detail/index.dart'; import 'package:marking_app/pages/report_detail/report_history.dart'; import 'package:marking_app/pages/reports/report_class_teacher.dart'; @@ -77,7 +79,8 @@ class RouterManager { static const String jobPersonalDetailPath = '/homework_correction/job_personal_detail'; static const String reportCardDialogPath = '/report_detail/widgets/report_card_dialog'; static const String reportHistoryPath = '/report_detail/report_history'; - + static const String registerPath = '/register/index'; + static const String logOffPath = '/mine/log_off'; // TheMine static final FluroRouter router = FluroRouter(); @@ -363,6 +366,15 @@ class RouterManager { return ReportHistory(); }, ); + + // 注册页 + static final _registerPathHandler = + Handler(handlerFunc: (BuildContext? context, Map> params) => const Register()); + + // 注销页 + static final _logOffPathHandler = + Handler(handlerFunc: (BuildContext? context, Map> params) => const LogOff()); + // 开始阅卷页面 // static final _doMarkingPapers = Handler(handlerFunc: (BuildContext? context, Map> params) => MarkingPapers()); @@ -409,7 +421,8 @@ class RouterManager { router.define(jobPersonalDetailPath, handler: _jobPersonalDetailPathHandler, transitionType: TransitionType.material); router.define(reportCardDialogPath, handler: _reportCardDialogPathHandler, transitionType: TransitionType.material); router.define(reportHistoryPath, handler: _reportHistoryPathHandler, transitionType: TransitionType.material); - + router.define(registerPath, handler: _registerPathHandler,transitionType: TransitionType.material); + router.define(logOffPath, handler: _logOffPathHandler,transitionType: TransitionType.material); // getTransition() router.notFoundHandler = Handler(handlerFunc: (BuildContext? context, Map> params) { diff --git a/marking_app/lib/utils/const_text.dart b/marking_app/lib/utils/const_text.dart index 184915f..95758e2 100644 --- a/marking_app/lib/utils/const_text.dart +++ b/marking_app/lib/utils/const_text.dart @@ -1,7 +1,7 @@ /*协议*/ // ignore_for_file: constant_identifier_names // ignore: camel_case_types -enum AGREEMENT_KEY { PRIVACY_GREEMENT, USER_AGREEMENT } +enum AGREEMENT_KEY { PRIVACY_GREEMENT, USER_AGREEMENT, USER_LOGOUT } // ignore: non_constant_identifier_names final Map AGREEMENT_MAP = { @@ -148,12 +148,103 @@ final Map AGREEMENT_MAP = {

4.2 本协议条款无论因何种原因部分无效或不可执行,其余条款仍有效,对双方具有约束力。

''', - ) + ), + AGREEMENT_KEY.USER_LOGOUT: AgreementClass( + title: '注销协议', + richText: ''' + + + + + 《账号注销协议》 + + +

+ 尊敬的用户,在您正式开始下一步有关账号注销流程前,我们先为您做出如下特别说明:注销本账号后,除法律法规另有规定外,您在该账号下的个人信息将进行删除或匿名化处理,且此前已关联该账号的相关产品与服务将不再关联。该账号一旦注销完成,将无法恢复,请您谨慎操作。 +

+

+ 若您经过慎重考虑后仍决定注销本账号的,请您务必先行仔细阅读和充分理解本《账号注销协议》(“本协议”),并同意本协议全部内容。您按照我们的注销操作流程开始注销流程的,或者您勾选本注销协议并开始下一步操作的,均视为您已经同意和遵守本协议全部内容。 +

+

+ 如您在注销后需要再次使用我们的服务的,欢迎您重新注册登录。 +

+

一、您知悉并同意:在您的账号注销后,将(可能)产生包括但不限于如下结果,并需要您自行承担:

+

+ 1.您将无法登录、使用该账号,无法以此账号使用的服务; +

+

+ 2.如您曾使用该账号登录其他用户产品,一旦您注销账号,将无法使用全线用户产品的服务。 +

+

+ 3.除法律法规另有规定外,您该账号下的个人信息将会被删除或匿名化处理。您无法再找回您的个人信息,也无权要求我们找回,前述个人信息包括但不限于:头像昵称等个人资料信息、设备信息、收藏、订阅、播放历史、观看记录、浏览记录、订阅/关注信息、私信、会员信息及购买、充值信息、积分、优惠卡券等信息; +

+

+ 4.您同意,一旦您同意本协议或您注销本账号的,即视为您放弃该账号在使用期间已产生的及未来可能产生的权益,我们有权对该账号下的全部权益做清除处理,该等权益包括但不限于:会员权益及已产生但未消耗完毕的其他权益或未来预期的权益等,因此产生的后果由您自行承担; +

+

+ 5.本账号一旦注销,将无法恢复。即使您在注销后以相同或其他提供的登录方式作为账号再次向我们申请注册登录的,此时该账号将视为新的用户账号。因此,我们善意地提醒您在申请注销前对需要备份的内容提前做好备份。同时,也建议您在申请注销前清除系统缓存; +

+

+ 6.本账号一旦注销,您与我们签署的有关的《服务协议》(“服务协议”)终止(但已约定继续生效的除外)。但服务协议的终止并不影响账号注销前您使用的服务应当承担的相关责任,您仍需要对账号注销前使用的服务的行为承担相应责任,包括但不限于可能产生的违约责任、损害赔偿责任及履约义务等; +

+

+ 7.其他因账号注销(可能)产生的结果。 +

+

二、在您向我们申请/继续申请注销账号之前,为保障您的账号安全和相关权益, 您需先行检查与确保您申请注销的账号已经同时满足以下条件,这些条件包括但不限于:

+

+ 1.该账号为您本人合法拥有并登录使用,且符合用户协议及相关说明规则中有关账号的规定; +

+

+ 2.该账号已解绑其他共享设备; +

+

+ 3.该账号处于安全状态:账号为正常使用中且无违规、被封、被盗等情形; +

+

+ 4.该账号中的相关权益(见本协议第一条第4款)已结清或得到妥善处理。请您妥善处理您的产品权益,可待相关权益使用完毕后再进行注销,若您未予以处理且继续进行账号注销流程,视为您自愿放弃该等权益; +

+

+ 5.该账号无未完成状态订单; +

+

+ 6.该账号所涉及到的会员自动续费功能已解除; +

+

+ 7.该账号无任何纠纷:包括投诉举报、被投诉举报、国家机关调查、仲裁、诉讼等纠纷; +

+

+ 上述问题您可首先尝试自行处理,如您无法处理的或在处理过程中有任何疑惑的,可联系客服协助处理。 +

+

三、如何注销账号?

+

+ 1.您需按照我们的官方渠道提供的注销流程和操作指引,在相关功能设置页面进行注销操作; +

+ 2.您已经同意本注销协议的全部内容;同时,您已经检查与确认满足了本协议第二条的要求; +

+

+ 3.在您完成上述第2点后,为进一步保障您的相关合法权益,我们有权根据您的账号安全状态以及您的相关产品与服务的使用情况等综合判断您的账号是否符合注销条件。为保障您的账号安全和财产权益,我们有权进行注销申请的身份验证以判断您是该账号的有权使用人(如由您提供操作相关信息供我们核实等)。如我们在综合判断后发现该账号不符合注销条件的,或者身份验证失败的,您的注销可能会失败,您可以按照我们的指引进行后续操作或联系客服协助处理。即使我们判断您符合注销条件的,也是基于您的承诺(即您自身确保账号符合上述注销条件的承诺)进行的形式审查,仍由您自身对账号符合上述注销条件承担保证责任,我们对此不承担相应的法律责任; +

+

+ 4.我们在您成功完成上述第3点的 “身份验证 ”后,视为您已成功向我们提交了账号注销申请。 +

+

+ 具体的注销流程化和操作以官方公布为准。您理解并同意,在您申请注销账号期间,如我们需要对相关信息、投诉或其他与您的账号相关的事项进行核实的,或者我们有其他合理的理由的,我们有权冻结您的该账号且暂时不为您提供注销服务。 +

+

四、其他

+

+ 本协议为用户协议组成部分,本协议未尽事宜适用用户协议。本协议与用户协议不一致的,以本协议为准。同时,您知悉并同意: 即使您该账号被注销,也并不减轻或免除您应根据相关法律法规、相关协议、规则等(可能)需要承担的相关责任。 +

+ + + + ''', + ), }; /* TYPE */ class AgreementClass { String title; String richText; + AgreementClass({required this.title, required this.richText}); } diff --git a/marking_app/lib/utils/request/rest_client.dart b/marking_app/lib/utils/request/rest_client.dart index 8fc35b9..eb5d1f0 100644 --- a/marking_app/lib/utils/request/rest_client.dart +++ b/marking_app/lib/utils/request/rest_client.dart @@ -357,5 +357,20 @@ abstract class RestClient { @the_retrofit.Query("PageSize") int pageSize, ); + // 注册 + @the_retrofit.POST("/auth/login/reg") + Future> toRegister(@the_retrofit.Body() UserLoginParams params); + + // 是否显示注册 + @the_retrofit.GET("/auth/login/status/reg") + Future> showRegister(); + + // 是否显示注销 + @the_retrofit.GET("/auth/login/status/lg") + Future> showLogOff(); + + // 注销账号 + @the_retrofit.POST("/auth/login/lg") + Future getLogOff(@the_retrofit.Field("loginName") String loginName); }