提交 ab492862 authored 作者: yueweilu's avatar yueweilu

1、账户安全界面

2、修改手机号界面 3、修改密码界面
上级 9feb9302
...@@ -25,5 +25,5 @@ linter: ...@@ -25,5 +25,5 @@ linter:
# avoid_print: false # Uncomment to disable the `avoid_print` rule # avoid_print: false # Uncomment to disable the `avoid_print` rule
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
# Additional information about this file can be found at # Additional information user_about this file can be found at
# https://dart.dev/guides/language/analysis-options # https://dart.dev/guides/language/analysis-options
...@@ -4,13 +4,13 @@ abstract class MineAPI { ...@@ -4,13 +4,13 @@ abstract class MineAPI {
/// 1、个人信息以及8个数据 /// 1、个人信息以及8个数据
/// ///
static Future <Map<String,dynamic>> userInfo() async { static Future <UserInfoModel> userInfo() async {
final result = await HttpService.to.post( final result = await HttpService.to.post(
'/v1/members/Information/getMyStatistics', '/v1/members/Information/getMyStatistics',
params: {}, params: {},
); );
if (result.data is! Map ) return {}; if (result.data is! Map ) return UserInfoModel();
return result.data; return UserInfoModel.fromJson(result.data);
} }
/// 2、我的收藏 /// 2、我的收藏
......
...@@ -203,4 +203,108 @@ class VersionModel { ...@@ -203,4 +203,108 @@ class VersionModel {
return map; return map;
} }
}
class UserInfoModel {
UserInfoModel({
this.name,
this.headImg,
this.sex,
this.phone,
this.couponNums,
this.commentNums,
this.ordersNums,
this.noteNums,
this.wrongNums,
this.collectNums,
this.integralNums,
this.password,
this.gradeId,
this.gradeName,
this.beanNums,});
UserInfoModel.fromJson(dynamic json) {
name = json['name'];
headImg = json['head_img'];
sex = json['sex'];
phone = json['phone'];
couponNums = json['coupon_nums'];
commentNums = json['comment_nums'];
ordersNums = json['orders_nums'];
noteNums = json['note_nums'];
wrongNums = json['wrong_nums'];
collectNums = json['collect_nums'];
integralNums = json['integral_nums'];
password = json['password'];
gradeId = json['grade_id'];
gradeName = json['grade_name'];
beanNums = json['bean_nums'];
}
String? name;
String? headImg;
num? sex;
String? phone;
num? couponNums;
num? commentNums;
num? ordersNums;
num? noteNums;
num? wrongNums;
num? collectNums;
num? integralNums;
String? password;
num? gradeId;
String? gradeName;
String? beanNums;
UserInfoModel copyWith({ String? name,
String? headImg,
num? sex,
String? phone,
num? couponNums,
num? commentNums,
num? ordersNums,
num? noteNums,
num? wrongNums,
num? collectNums,
num? integralNums,
String? password,
num? gradeId,
String? gradeName,
String? beanNums,
}) => UserInfoModel( name: name ?? this.name,
headImg: headImg ?? this.headImg,
sex: sex ?? this.sex,
phone: phone ?? this.phone,
couponNums: couponNums ?? this.couponNums,
commentNums: commentNums ?? this.commentNums,
ordersNums: ordersNums ?? this.ordersNums,
noteNums: noteNums ?? this.noteNums,
wrongNums: wrongNums ?? this.wrongNums,
collectNums: collectNums ?? this.collectNums,
integralNums: integralNums ?? this.integralNums,
password: password ?? this.password,
gradeId: gradeId ?? this.gradeId,
gradeName: gradeName ?? this.gradeName,
beanNums: beanNums ?? this.beanNums,
);
Map<String, dynamic> toJson() {
final map = <String, dynamic>{};
map['name'] = name;
map['head_img'] = headImg;
map['sex'] = sex;
map['phone'] = phone;
map['coupon_nums'] = couponNums;
map['comment_nums'] = commentNums;
map['orders_nums'] = ordersNums;
map['note_nums'] = noteNums;
map['wrong_nums'] = wrongNums;
map['collect_nums'] = collectNums;
map['integral_nums'] = integralNums;
map['password'] = password;
map['grade_id'] = gradeId;
map['grade_name'] = gradeName;
map['bean_nums'] = beanNums;
return map;
}
} }
\ No newline at end of file
part of change_phone;
class ChangePhoneController extends GetxController {
// 账号
final TextEditingController phoneInput = TextEditingController();
// 验证码
final TextEditingController codeInput = TextEditingController();
// 定时器
late Timer _timer;
// 按钮是否可用
bool _enable = false;
bool get enable => _enable;
// 倒计时60秒
int _countDown = 60;
int get countDown => _countDown;
bool _isCounting = false;
bool get isCounting => _isCounting;
// 开启定时器
void start() {
_isCounting = true;
_timer = Timer.periodic(const Duration(seconds: 1), (timer) {
if (_countDown > 1) {
_countDown--;
} else {
stop();
}
update();
});
}
// 停止计时器
void stop() {
if (_timer != null){
_timer.cancel();
_isCounting = false;
}
_countDown = 60;
}
void setCanClick(){
if (phoneInput.text.length == 11 && codeInput.text.length == 6){
_enable = true;
}
else{
_enable = false;
}
update();
}
@override
void onInit() {
_timer = Timer.periodic(const Duration(seconds: 1), (timer) {
// 定时器回调
});
/// 测试账号
if (kDebugMode) {
phoneInput.text = '13521054068';
codeInput.text = '123456';
}
super.onInit();
}
@override
void onClose() {
phoneInput.dispose();
codeInput.dispose();
_timer.cancel();
_isCounting = false;
super.onClose();
}
void sendCode() async {
final result = await AccountAPI.sendCode(phone: phoneInput.text, type: 'login');
if (result){
Toast.show('发送成功');
start();
}
else{
Toast.show('发送失败');
}
}
}
\ No newline at end of file
library change_phone;
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:go_router/go_router.dart';
import '../../apis/index.dart';
import '../../routes/index.dart';
import '../../theme.dart';
import '../../utils/index.dart';
import '../../widgets/index.dart';
part 'view.dart';
part 'controller.dart';
\ No newline at end of file
part of change_phone;
class ChangePhonePage extends StatefulWidget {
const ChangePhonePage({Key? key}) : super(key: key);
@override
State<ChangePhonePage> createState() => _ChangePhonePageState();
}
class _ChangePhonePageState extends State<ChangePhonePage> {
@override
Widget build(BuildContext context) {
return GetBuilder<ChangePhoneController>(
init: ChangePhoneController(),
builder: (controller) =>Scaffold(
appBar: AppBar(
centerTitle: true,
title: const Text('修改手机号'),
),
body: Container(
margin: const EdgeInsets.only(left: 10, right: 10,top: 15),
child: Column(
children: [
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
color: const Color(0xFFF9F9F9),
boxShadow: [
BoxShadow(
color: const Color(0xFFC7C7C7).withOpacity(0.35),
offset: const Offset(3, 0),
blurRadius: 10.w,
spreadRadius: 0.w,
),
],
),
child: ClipRRect(
borderRadius: BorderRadius.circular(8),
child: CustomFormInput(
// label: 'Phone',
// required: true,
hintText: '请输入新的手机号',
keyboardType: TextInputType.number,
controller: controller.phoneInput,
onChanged: (text){
controller.setCanClick();
},
decoration: const InputDecoration(
focusedBorder: InputBorder.none,
border: InputBorder.none,
enabledBorder: InputBorder.none,
errorBorder: InputBorder.none
)
),
),
),
Gaps.vGaps10,
Stack(
alignment: Alignment.centerRight,
children: [
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
color: const Color(0xFFF9F9F9),
boxShadow: [
BoxShadow(
color: const Color(0xFFC7C7C7).withOpacity(0.35),
offset: const Offset(3, 0),
blurRadius: 10.w,
spreadRadius: 0.w,
),
],
),
child: ClipRRect(
borderRadius: BorderRadius.circular(8),
child: CustomFormInput(
// label: 'Phone',
// required: true,
hintText: '请输入验证码',
keyboardType: TextInputType.number,
controller: controller.codeInput,
decoration: const InputDecoration(
focusedBorder: InputBorder.none,
border: InputBorder.none,
enabledBorder: InputBorder.none,
errorBorder: InputBorder.none
),
onChanged: (text){
controller.setCanClick();
},
),
),
),
Positioned(
right: 10,
child: Row(
children: [
Container(height: 20,width: 1,color: const Color(0xFFEBEBEB),),
Gaps.hGaps10,
GestureDetector(
child: Container(
padding: const EdgeInsets.symmetric(vertical: 10),
// color: Colors.yellow,
child: Text(controller.isCounting?'${controller.countDown}':'获取验证码',style: const TextStyle(fontSize: 11,color: AppTheme.primary,height: 1.4),)),
onTap: (){
if (controller.isCounting == false){
controller.sendCode();
}
},
),
],
)
),
],
),
Gaps.vGaps40,
CustomGradientButton(
text: '下一步',
isEnabled: controller.enable,
onPressed: () {
context.pushNamed(Routes.resetPwd,queryParameters: {'phone': controller.phoneInput.text,'code': controller.codeInput.text});
},
)
],
),
),
),
);
}
}
part of change_pwd;
class ChangePwdController extends GetxController {
// 新密码
final TextEditingController pwdInput = TextEditingController();
// 确认密码
final TextEditingController pwd2Input = TextEditingController();
// 显示密码
final ValueNotifier<bool> showPassword = ValueNotifier(false);
// 显示密码
final ValueNotifier<bool> showPassword2 = ValueNotifier(false);
// 按钮是否可用
bool _enable = false;
bool get enable => _enable;
void onShowPassword() => showPassword.value = !showPassword.value;
void onShowPassword2() => showPassword2.value = !showPassword2.value;
void setCanClick(){
if (ValidatorTool.isValidPassword(pwdInput.text) && ValidatorTool.isValidPassword(pwd2Input.text) && (pwdInput.text == pwd2Input.text)){
Console.log('-------${pwdInput.text}-------------${pwd2Input.text}');
_enable = true;
}
else{
_enable = false;
}
update();
}
@override
void onClose() {
pwd2Input.dispose();
pwdInput.dispose();
super.onClose();
}
// void resetPassword(BuildContext context) async {
// final result = await AccountAPI.resetPassword(
// phone: phone,
// code: code,
// password: pwdInput.text,
// rePassword: pwd2Input.text
// );
// if (result){
// if (context.mounted){
// context.goNamed(Routes.login);
// }
// }
// else{
//
// }
// }
}
library change_pwd;
import 'package:flutter_book/utils/index.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import '../../apis/index.dart';
import '../../routes/index.dart';
import '../../widgets/index.dart';
part 'view.dart';
part 'controller.dart';
\ No newline at end of file
part of change_pwd;
class ChangePwdPage extends StatefulWidget {
final String type;
const ChangePwdPage({
Key? key ,
required this.type,
}) : super(key: key);
// const ResetPwdPage({Key? key}) : super(key: key);
@override
State<ChangePwdPage> createState() => _ChangePwdPageState();
}
class _ChangePwdPageState extends State<ChangePwdPage> {
@override
Widget build(BuildContext context) {
return GetBuilder<ChangePwdController>(
init: ChangePwdController(),
builder: (controller) =>Scaffold(
appBar: AppBar(
centerTitle: true,
title: Text(widget.type =='1'?'设置密码':'修改密码'),
),
body: Container(
margin: const EdgeInsets.only(left: 10,top: 15,right: 10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ValueListenableBuilder<bool>(
valueListenable: controller.showPassword,
builder:(context, value, child) => Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
color: const Color(0xFFF9F9F9),
boxShadow: [
BoxShadow(
color: const Color(0xFFC7C7C7).withOpacity(0.35),
offset: const Offset(3, 0),
blurRadius: 10.w,
spreadRadius: 0.w,
),
],
),
child: ClipRRect(
borderRadius: BorderRadius.circular(8),
child: CustomFormInput(
obscureText: !value,
hintText: '请输入新密码',
iconData:
value ? Image.asset(
'assets/images/eye_open.png',
) : Image.asset(
'assets/images/eye_close.png',
),
controller: controller.pwdInput,
onChanged: (text){
controller.setCanClick();
},
decoration: const InputDecoration(
focusedBorder: InputBorder.none,
border: InputBorder.none,
enabledBorder: InputBorder.none,
errorBorder: InputBorder.none
),
onIcon: controller.onShowPassword,
),
),
),
),
Gaps.vGaps10,
ValueListenableBuilder<bool>(
valueListenable: controller.showPassword2,
builder:(context, value, child) => Container(
decoration: BoxDecoration(
// borderRadius: BorderRadius.circular(8),
color: const Color(0xFFF9F9F9),
boxShadow: [
BoxShadow(
color: const Color(0xFFC7C7C7).withOpacity(0.35),
offset: const Offset(3, 0),
blurRadius: 10.w,
spreadRadius: 0.w,
),
],
),
child: ClipRRect(
borderRadius: BorderRadius.circular(8),
child: CustomFormInput(
obscureText: !value,
hintText: '请再次输入密码',
iconData:
value ? Image.asset(
'assets/images/eye_open.png',
) : Image.asset(
'assets/images/eye_close.png',
),
controller: controller.pwd2Input,
onChanged: (text){
controller.setCanClick();
},
decoration: const InputDecoration(
focusedBorder: InputBorder.none,
border: InputBorder.none,
enabledBorder: InputBorder.none,
errorBorder: InputBorder.none
),
onIcon: controller.onShowPassword2,
),
),
),
),
Container(
margin: const EdgeInsets.only(left: 5,top: 5),
child: const Text('密码必须是6-20个英文字母、数字或符号',style: TextStyle(fontSize: 10,color: Colours.c9),),
),
Gaps.vGaps40,
CustomGradientButton(
text: widget.type == '1'?'确认':'确认修改',
isEnabled: controller.enable,
onPressed: () {
// context.goNamed(Routes.login);
},
)
],
),
),
),
);
}
}
...@@ -7,7 +7,7 @@ class MineController extends GetxController { ...@@ -7,7 +7,7 @@ class MineController extends GetxController {
// 广告数据 // 广告数据
List<AdModel> ads = []; List<AdModel> ads = [];
// 个人信息数据 // 个人信息数据
Map<String,dynamic> userInfo = {'name':'','phone':''}; UserInfoModel userInfo = UserInfoModel();
// 笔记 讨论 错题 收藏 // 笔记 讨论 错题 收藏
List<ReadModel> reads = []; List<ReadModel> reads = [];
// 我的账户数据 // 我的账户数据
...@@ -42,16 +42,16 @@ class MineController extends GetxController { ...@@ -42,16 +42,16 @@ class MineController extends GetxController {
void getInfo() async { void getInfo() async {
userInfo = await MineAPI.userInfo(); userInfo = await MineAPI.userInfo();
reads = [ reads = [
ReadModel(name: '笔记',value: userInfo['note_nums'].toString(),link: Routes.note), ReadModel(name: '笔记',value: userInfo.noteNums.toString(),link: Routes.note),
ReadModel(name: '讨论',value: userInfo['comment_nums'].toString(),link: Routes.discuss), ReadModel(name: '讨论',value: userInfo.commentNums.toString(),link: Routes.discuss),
ReadModel(name: '错题',value: userInfo['wrong_nums'].toString(),link: Routes.wrong), ReadModel(name: '错题',value: userInfo.wrongNums.toString(),link: Routes.wrong),
ReadModel(name: '收藏',value: userInfo['collect_nums'].toString(),link: Routes.love) ReadModel(name: '收藏',value: userInfo.collectNums.toString(),link: Routes.love)
]; ];
accounts = [ accounts = [
ReadModel(name: '优惠券',value: userInfo['coupon_nums'].toString(),link: Routes.coupon,icon: 'assets/images/coupon.png'), ReadModel(name: '优惠券',value: userInfo.couponNums.toString(),link: Routes.coupon,icon: 'assets/images/coupon.png'),
ReadModel(name: '积分',value: userInfo['integral_nums'].toString(),link: Routes.point,icon: 'assets/images/point.png'), ReadModel(name: '积分',value: userInfo.integralNums.toString(),link: Routes.point,icon: 'assets/images/point.png'),
ReadModel(name: '紫金币',value: userInfo['bean_nums'].toString(),link: Routes.coin,icon: 'assets/images/coin.png'), ReadModel(name: '紫金币',value: userInfo.beanNums.toString(),link: Routes.coin,icon: 'assets/images/coin.png'),
ReadModel(name: '订单',value: userInfo['orders_nums'].toString(),icon: 'assets/images/order.png') ReadModel(name: '订单',value: userInfo.ordersNums.toString(),icon: 'assets/images/order.png')
]; ];
update(); update();
} }
......
...@@ -65,56 +65,64 @@ class _MinePageState extends State<MinePage> { ...@@ -65,56 +65,64 @@ class _MinePageState extends State<MinePage> {
body: Container( body: Container(
color: Colors.transparent, color: Colors.transparent,
child: SingleChildScrollView( child: SingleChildScrollView(
child: Container( child: Column(
// margin: const EdgeInsets.symmetric(horizontal: AppTheme.margin), children: [
child: Column( BuildUser(userInfo:controller.userInfo,onTap: (){
children: [ context.pushNamed(Routes.userInfo);
BuildUser(userInfo:controller.userInfo,onTap: (){ },),
context.pushNamed(Routes.userInfo); Gaps.vGaps10,
},), BuildRead(items: controller.reads,onTap: (ReadModel model) async{
Gaps.vGaps10, final result = await context.pushNamed(model.link??'');
BuildRead(items: controller.reads,onTap: (ReadModel model) async{ if (result == true){
final result = await context.pushNamed(model.link??''); controller.getInfo();
if (result == true){ }
controller.getInfo(); }),
} controller.ads.isNotEmpty?Gaps.vGaps10:const SizedBox(),
}), controller.ads.isNotEmpty?
controller.ads.isNotEmpty?Gaps.vGaps10:const SizedBox(), Container(
controller.ads.isNotEmpty? color: Colors.transparent,
Container( padding: const EdgeInsets.symmetric(horizontal: 10),
color: Colors.transparent, child: BuildBanner(items:controller.ads),
padding: const EdgeInsets.symmetric(horizontal: 10), ):const SizedBox(),
child: BuildBanner(items:controller.ads), Gaps.vGaps5,
):const SizedBox(), BuildAccount(items:controller.accounts,),
Gaps.vGaps5, Gaps.vGaps10,
BuildAccount(items:controller.accounts,), Container(
Gaps.vGaps10, margin: const EdgeInsets.symmetric(horizontal: AppTheme.margin),
Container( decoration: BoxDecoration(
margin: const EdgeInsets.symmetric(horizontal: AppTheme.margin), borderRadius: BorderRadius.circular(8),
decoration: BoxDecoration( color: Colors.white,
borderRadius: BorderRadius.circular(8), boxShadow: [
color: Colors.white, BoxShadow(
boxShadow: [ color: const Color(0xFFC7C7C7).withOpacity(0.5),
BoxShadow( offset: const Offset(3, 0),
color: const Color(0xFFC7C7C7).withOpacity(0.5), blurRadius: 10.w,
offset: const Offset(3, 0), spreadRadius: 0.w,
blurRadius: 10.w, ),
spreadRadius: 0.w, ],
), ),
], child: ClipRRect(
), borderRadius: BorderRadius.circular(8),
child: Column( child: Column(
children: [ children: [
_buildItem('账户安全', ''), GestureDetector(
onTap:(){
context.pushNamed(Routes.security,extra: controller.userInfo);
}, child: _buildItem('账户安全')
),
Container(color: Colours.cLine,margin: const EdgeInsets.symmetric(horizontal: 15),height: 1,), Container(color: Colours.cLine,margin: const EdgeInsets.symmetric(horizontal: 15),height: 1,),
_buildItem('意见反馈', ''), _buildItem('意见反馈'),
Container(color: Colours.cLine,margin: const EdgeInsets.symmetric(horizontal: 15),height: 1,), Container(color: Colours.cLine,margin: const EdgeInsets.symmetric(horizontal: 15),height: 1,),
_buildItem('关于我们', Routes.about), GestureDetector(
onTap: (){
context.pushNamed(Routes.about);
}, child: _buildItem('关于我们',)
),
], ],
), ),
), ),
], ),
), ],
), ),
), ),
), ),
...@@ -124,30 +132,22 @@ class _MinePageState extends State<MinePage> { ...@@ -124,30 +132,22 @@ class _MinePageState extends State<MinePage> {
); );
} }
Widget _buildItem(String title, String linkTo,{VoidCallback? onTap}) { Widget _buildItem(String title) {
return GestureDetector( return Container(
behavior: HitTestBehavior.opaque, padding: const EdgeInsets.only(left: 18,right: 15),
onTap: (){ color: Colors.white,
if (linkTo.isNotEmpty){ height: 42,
context.pushNamed(linkTo); child: Row(
if (onTap !=null) onTap; mainAxisAlignment: MainAxisAlignment.spaceBetween,
} crossAxisAlignment: CrossAxisAlignment.center,
}, children: [
child: Container( Text(title,style: const TextStyle(fontSize: 14,color: Colours.c3,),),
padding: const EdgeInsets.only(left: 18,right: 15), SizedBox(
height: 42, width: 5,
child: Row( height: 8,
mainAxisAlignment: MainAxisAlignment.spaceBetween, child: Image.asset('assets/images/right_arrow.png'),
crossAxisAlignment: CrossAxisAlignment.center, )
children: [ ],
Text(title,style: const TextStyle(fontSize: 14,color: Colours.c3,),),
SizedBox(
width: 5,
height: 8,
child: Image.asset('assets/images/right_arrow.png'),
)
],
),
), ),
); );
} }
......
...@@ -4,7 +4,7 @@ part of mine; ...@@ -4,7 +4,7 @@ part of mine;
class BuildUser extends StatelessWidget { class BuildUser extends StatelessWidget {
final void Function()? onTap; final void Function()? onTap;
final Map<String,dynamic> userInfo; final UserInfoModel userInfo;
const BuildUser ({ const BuildUser ({
super.key, super.key,
...@@ -18,7 +18,7 @@ class BuildUser extends StatelessWidget { ...@@ -18,7 +18,7 @@ class BuildUser extends StatelessWidget {
behavior: HitTestBehavior.opaque, behavior: HitTestBehavior.opaque,
onTap:onTap, onTap:onTap,
child: Container( child: Container(
margin: EdgeInsets.only(left: 10,right: 10), margin: const EdgeInsets.only(left: 10,right: 10),
color: Colors.transparent, color: Colors.transparent,
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
...@@ -33,7 +33,7 @@ class BuildUser extends StatelessWidget { ...@@ -33,7 +33,7 @@ class BuildUser extends StatelessWidget {
color: Colors.cyan, color: Colors.cyan,
), ),
// color: Colors.cyan, // color: Colors.cyan,
child: CustomImage.network(url: userInfo.containsKey('head_img')?userInfo['head_img']:'',radius: 22.5,), child: CustomImage.network(url: userInfo.headImg??'',radius: 22.5,),
), ),
Gaps.hGaps10, Gaps.hGaps10,
Column( Column(
...@@ -42,7 +42,7 @@ class BuildUser extends StatelessWidget { ...@@ -42,7 +42,7 @@ class BuildUser extends StatelessWidget {
Row( Row(
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
children: [ children: [
Text(userInfo.containsKey('name')?userInfo['name']:'',style: TextStyle( Text(userInfo.name??'',style: TextStyle(
color: Colours.c3, color: Colours.c3,
fontSize: 15.w, fontSize: 15.w,
fontWeight: Fonts.medium, fontWeight: Fonts.medium,
...@@ -52,7 +52,7 @@ class BuildUser extends StatelessWidget { ...@@ -52,7 +52,7 @@ class BuildUser extends StatelessWidget {
Stack( Stack(
children: [ children: [
Container( Container(
padding: EdgeInsets.only(right:8,left: 8), padding: const EdgeInsets.only(right:8,left: 8),
height: 20, height: 20,
decoration: BoxDecoration( decoration: BoxDecoration(
borderRadius: BorderRadius.circular(21), borderRadius: BorderRadius.circular(21),
...@@ -64,11 +64,11 @@ class BuildUser extends StatelessWidget { ...@@ -64,11 +64,11 @@ class BuildUser extends StatelessWidget {
), ),
child: Row( child: Row(
children: [ children: [
Container( const SizedBox(
width: 16, width: 16,
height: 17, height: 17,
), ),
const Text('初级学者',style: TextStyle(fontSize: 11,color: AppTheme.primary),) Text(userInfo.gradeName??'',style: const TextStyle(fontSize: 11,color: AppTheme.primary),)
], ],
), ),
), ),
...@@ -84,7 +84,7 @@ class BuildUser extends StatelessWidget { ...@@ -84,7 +84,7 @@ class BuildUser extends StatelessWidget {
], ],
), ),
Gaps.vGaps5, Gaps.vGaps5,
Text(userInfo.containsKey('phone')?userInfo['phone']:'',style: TextStyle( Text(userInfo.phone??'',style: TextStyle(
fontSize: 12.w, fontSize: 12.w,
color: Colours.c6 color: Colours.c6
),) ),)
......
library user_security;
import 'package:flutter/material.dart';
import 'package:flutter_book/models/index.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:go_router/go_router.dart';
import '../../routes/index.dart';
import '../../utils/index.dart';
part 'view.dart';
\ No newline at end of file
part of user_security;
class UserSecurityPage extends StatefulWidget {
final UserInfoModel model;
const UserSecurityPage({
Key? key,
required this.model
}) : super(key: key);
@override
State<UserSecurityPage> createState() => _UserSecurityPageState();
}
class _UserSecurityPageState extends State<UserSecurityPage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: const Text('账号安全'),
),
body: Column(
children: [
Container(
margin: const EdgeInsets.symmetric(vertical: 10,horizontal: 10),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
color: Colors.white,
boxShadow: [
BoxShadow(
color: const Color(0xFFC7C7C7).withOpacity(0.5),
offset: const Offset(3, 0),
blurRadius: 10.w,
spreadRadius: 0.w,
),
],
),
child: Column(
children: [
GestureDetector(
onTap:(){
context.pushNamed(Routes.changePhone);
},
child: _buildItem(title: '修改手机号码', value: widget.model.phone??'')
),
Container(
margin: const EdgeInsets.symmetric(horizontal: 10),
height: 0.5,
color:Colours.cF0,
),
GestureDetector(
onTap: (){
context.pushNamed(Routes.changePwd,queryParameters: {'type':widget.model.password.toString().isEmpty?'1':'2'});
},
child: _buildItem(title: '修改密码', value: widget.model.password.toString().isEmpty?'未设置':'')
),
],
),
),
Container(
margin: const EdgeInsets.symmetric(horizontal: 10),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
color: Colors.white,
boxShadow: [
BoxShadow(
color: const Color(0xFFC7C7C7).withOpacity(0.5),
offset: const Offset(3, 0),
blurRadius: 10.w,
spreadRadius: 0.w,
),
],
),
child: Column(
children: [
_buildItem(title: '账号注销', value: ''),
],
),
)
],
),
);
}
Widget _buildItem({required String title,required String value}){
return Container(
margin: const EdgeInsets.only(left: 15,right: 15),
color: Colors.white,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
GestureDetector(
onTap: () async{
},
child: Container(
color: Colors.white,
height:45,
alignment: Alignment.centerLeft,
child: Text(title,style: const TextStyle(fontSize: 13,height: 1.5, color: Colours.c3)),
),
),
Row(
children: [
Text(value,style: const TextStyle(fontSize: 13,height: 1.5,color: Colours.c9),),
Gaps.hGaps10,
Image.asset('assets/images/right_arrow.png')
],
)
],
),
);
}
}
...@@ -19,6 +19,7 @@ class _UserSetPageState extends State<UserSetPage> { ...@@ -19,6 +19,7 @@ class _UserSetPageState extends State<UserSetPage> {
children: [ children: [
Container( Container(
margin: const EdgeInsets.symmetric(vertical: 10,horizontal: 10), margin: const EdgeInsets.symmetric(vertical: 10,horizontal: 10),
padding: const EdgeInsets.only(right: 10),
decoration: BoxDecoration( decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
color: Colors.white, color: Colors.white,
...@@ -47,7 +48,7 @@ class _UserSetPageState extends State<UserSetPage> { ...@@ -47,7 +48,7 @@ class _UserSetPageState extends State<UserSetPage> {
), ),
), ),
Container( Container(
margin: const EdgeInsets.symmetric(horizontal: 10), margin: const EdgeInsets.only(left: 10),
height: 0.5, height: 0.5,
color:Colours.cF0, color:Colours.cF0,
), ),
...@@ -99,7 +100,6 @@ class _UserSetPageState extends State<UserSetPage> { ...@@ -99,7 +100,6 @@ class _UserSetPageState extends State<UserSetPage> {
} }
}, },
child: Container( child: Container(
color: Colors.white,
height: 42, height: 42,
width: double.infinity, width: double.infinity,
alignment: Alignment.center, alignment: Alignment.center,
......
...@@ -2,12 +2,13 @@ library routes; ...@@ -2,12 +2,13 @@ library routes;
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter_book/pages/about/index.dart';
import 'package:flutter_book/pages/ad/index.dart'; import 'package:flutter_book/pages/ad/index.dart';
import 'package:flutter_book/pages/book_detail/index.dart'; import 'package:flutter_book/pages/book_detail/index.dart';
import 'package:flutter_book/pages/book_pay/index.dart'; import 'package:flutter_book/pages/book_pay/index.dart';
import 'package:flutter_book/pages/book_score/index.dart'; import 'package:flutter_book/pages/book_score/index.dart';
import 'package:flutter_book/pages/book_shop/index.dart'; import 'package:flutter_book/pages/book_shop/index.dart';
import 'package:flutter_book/pages/change_phone/index.dart';
import 'package:flutter_book/pages/change_pwd/index.dart';
import 'package:flutter_book/pages/credit_points/index.dart'; import 'package:flutter_book/pages/credit_points/index.dart';
import 'package:flutter_book/pages/forget_pwd/index.dart'; import 'package:flutter_book/pages/forget_pwd/index.dart';
import 'package:flutter_book/pages/login/index.dart'; import 'package:flutter_book/pages/login/index.dart';
...@@ -26,6 +27,7 @@ import 'package:flutter_book/pages/user_msg/index.dart'; ...@@ -26,6 +27,7 @@ import 'package:flutter_book/pages/user_msg/index.dart';
import 'package:flutter_book/pages/user_nick/index.dart'; import 'package:flutter_book/pages/user_nick/index.dart';
import 'package:flutter_book/pages/user_notes/index.dart'; import 'package:flutter_book/pages/user_notes/index.dart';
import 'package:flutter_book/pages/user_point/index.dart'; import 'package:flutter_book/pages/user_point/index.dart';
import 'package:flutter_book/pages/user_security/index.dart';
import 'package:flutter_book/pages/user_set/index.dart'; import 'package:flutter_book/pages/user_set/index.dart';
import 'package:flutter_book/pages/user_wrong/index.dart'; import 'package:flutter_book/pages/user_wrong/index.dart';
import 'package:flutter_book/pages/version_des/index.dart'; import 'package:flutter_book/pages/version_des/index.dart';
...@@ -33,6 +35,7 @@ import 'package:flutter_book/pages/web/index.dart'; ...@@ -33,6 +35,7 @@ import 'package:flutter_book/pages/web/index.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import '../models/index.dart'; import '../models/index.dart';
import '../pages/user_about/index.dart';
import '../pages/user_terms/index.dart'; import '../pages/user_terms/index.dart';
import '../pages/version/index.dart'; import '../pages/version/index.dart';
import '../store/index.dart'; import '../store/index.dart';
......
...@@ -67,7 +67,7 @@ abstract class Routes { ...@@ -67,7 +67,7 @@ abstract class Routes {
// 消息 // 消息
static const msgs = 'msgs'; static const msgs = 'msgs';
// 关于 // 关于
static const about = 'about'; static const about = 'user_about';
// 最近学习 // 最近学习
static const studyHistory = 'study_history'; static const studyHistory = 'study_history';
// 我的收藏 // 我的收藏
...@@ -80,6 +80,12 @@ abstract class Routes { ...@@ -80,6 +80,12 @@ abstract class Routes {
static const discuss = 'discuss'; static const discuss = 'discuss';
// 优惠券 // 优惠券
static const coupon = 'coupon'; static const coupon = 'coupon';
// 账号安全
static const security = 'security';
// 修改手机号
static const changePhone = 'change_change';
// 修改密码
static const changePwd = 'change_pwd';
...@@ -368,6 +374,33 @@ abstract class Routes { ...@@ -368,6 +374,33 @@ abstract class Routes {
child: VersionDesPage(model: state.extra as VersionModel,) child: VersionDesPage(model: state.extra as VersionModel,)
) )
), ),
GoRoute(
path: '/$security',
name: security,
pageBuilder: (context, state) =>CupertinoPage(
name: state.uri.toString(),
key: state.pageKey,
child: UserSecurityPage(model: state.extra as UserInfoModel,)
)
),
GoRoute(
path: '/$changePhone',
name: changePhone,
pageBuilder: (context, state) =>CupertinoPage(
name: state.uri.toString(),
key: state.pageKey,
child: const ChangePhonePage()
)
),
GoRoute(
path: '/$changePwd',
name: changePwd,
pageBuilder: (context, state) =>CupertinoPage(
name: state.uri.toString(),
key: state.pageKey,
child: ChangePwdPage(type:state.uri.queryParameters['type'].toString())
)
)
] ]
); );
......
...@@ -141,7 +141,7 @@ abstract class AppTheme { ...@@ -141,7 +141,7 @@ abstract class AppTheme {
), ),
appBarTheme: AppBarTheme( appBarTheme: AppBarTheme(
systemOverlayStyle: SystemUiOverlayStyle.dark, systemOverlayStyle: SystemUiOverlayStyle.dark,
backgroundColor: Color(0xFFAB1941).withOpacity(0.02), backgroundColor: const Color(0xFFAB1941).withOpacity(0.02),
scrolledUnderElevation: 0, scrolledUnderElevation: 0,
elevation: 0, elevation: 0,
centerTitle: true, centerTitle: true,
......
...@@ -17,6 +17,7 @@ class CustomFormInput extends FormField<String> { ...@@ -17,6 +17,7 @@ class CustomFormInput extends FormField<String> {
final ValueChanged<String>? onChanged; final ValueChanged<String>? onChanged;
final TextInputType? keyboardType; final TextInputType? keyboardType;
final List<TextInputFormatter>? inputFormatters; final List<TextInputFormatter>? inputFormatters;
final InputDecoration? decoration;
CustomFormInput({ CustomFormInput({
Key? key, Key? key,
...@@ -35,6 +36,7 @@ class CustomFormInput extends FormField<String> { ...@@ -35,6 +36,7 @@ class CustomFormInput extends FormField<String> {
this.onChanged, this.onChanged,
this.keyboardType, this.keyboardType,
this.inputFormatters, this.inputFormatters,
this.decoration,
Validator<String?>? validator, Validator<String?>? validator,
}) : super( }) : super(
key: key, key: key,
...@@ -48,9 +50,10 @@ class CustomFormInput extends FormField<String> { ...@@ -48,9 +50,10 @@ class CustomFormInput extends FormField<String> {
}, },
builder: (field) { builder: (field) {
final state = field as _CustomFormInputState; final state = field as _CustomFormInputState;
final decoration = const InputDecoration().applyDefaults( final defaultDecoration = const InputDecoration().applyDefaults(
Theme.of(field.context).inputDecorationTheme, Theme.of(field.context).inputDecorationTheme,
); );
final effectiveDecoration = decoration ?? defaultDecoration;
return UnmanagedRestorationScope( return UnmanagedRestorationScope(
bucket: field.bucket, bucket: field.bucket,
child: CustomInput( child: CustomInput(
...@@ -66,7 +69,7 @@ class CustomFormInput extends FormField<String> { ...@@ -66,7 +69,7 @@ class CustomFormInput extends FormField<String> {
iconData: iconData, iconData: iconData,
maxLines: maxLines, maxLines: maxLines,
error: field.errorText, error: field.errorText,
decoration: decoration, decoration: effectiveDecoration,
inputFormatters: inputFormatters, inputFormatters: inputFormatters,
keyboardType: keyboardType, keyboardType: keyboardType,
onChanged: (value) { onChanged: (value) {
......
...@@ -10,9 +10,9 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev ...@@ -10,9 +10,9 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
# Both the version and the builder number may be overridden in flutter # Both the version and the builder number may be overridden in flutter
# build by specifying --build-name and --build-number, respectively. # build by specifying --build-name and --build-number, respectively.
# In Android, build-name is used as versionName while build-number used as versionCode. # In Android, build-name is used as versionName while build-number used as versionCode.
# Read more about Android versioning at https://developer.android.com/studio/publish/versioning # Read more user_about Android versioning at https://developer.android.com/studio/publish/versioning
# In iOS, build-name is used as CFBundleShortVersionString while build-number is used as CFBundleVersion. # In iOS, build-name is used as CFBundleShortVersionString while build-number is used as CFBundleVersion.
# Read more about iOS versioning at # Read more user_about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
# In Windows, build-name is used as the major, minor, and patch parts # In Windows, build-name is used as the major, minor, and patch parts
# of the product and file versions while build-number is used as the build suffix. # of the product and file versions while build-number is used as the build suffix.
...@@ -100,7 +100,7 @@ dev_dependencies: ...@@ -100,7 +100,7 @@ dev_dependencies:
# The "flutter_lints" package below contains a set of recommended lints to # The "flutter_lints" package below contains a set of recommended lints to
# encourage good coding practices. The lint set provided by the package is # encourage good coding practices. The lint set provided by the package is
# activated in the `analysis_options.yaml` file located at the root of your # activated in the `analysis_options.yaml` file located at the root of your
# package. See that file for information about deactivating specific lint # package. See that file for information user_about deactivating specific lint
# rules and activating additional ones. # rules and activating additional ones.
flutter_lints: ^2.0.0 flutter_lints: ^2.0.0
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论