Commit c95453ce5bcaf94dde4967788c29dec4fa8e2264

Authored by Key
1 parent 6f617434

feat: User界面完善

android/app/src/main/kotlin/com/kouyuxingqiu/wow_english/MainActivity.kt
1 1 package com.kouyuxingqiu.wow_english
2 2  
  3 +import android.graphics.Color
  4 +import android.os.Build
  5 +import android.os.Bundle
  6 +import android.util.Log
  7 +import android.view.View
  8 +import androidx.core.view.WindowCompat
  9 +import androidx.core.view.WindowInsetsCompat
  10 +import androidx.core.view.WindowInsetsControllerCompat
3 11 import io.flutter.embedding.android.FlutterActivity
4 12  
5 13 class MainActivity : FlutterActivity() {
6   - // 测试有效
7   - /*override fun onCreate(savedInstanceState: Bundle?) {
  14 + override fun onCreate(savedInstanceState: Bundle?) {
8 15 super.onCreate(savedInstanceState)
9   - Toast.makeText(this, "onCreate", Toast.LENGTH_SHORT).show()
10   - }*/
  16 + Log.i("WowEnglish", "MainActivity onCreate")
  17 + }
  18 +
  19 + override fun onResume() {
  20 + super.onResume()
  21 + //setFullScreen()
  22 + }
  23 +
  24 + private fun setFullScreen() {
  25 + WindowInsetsControllerCompat(window, window.decorView).let {
  26 + it.hide(WindowInsetsCompat.Type.statusBars())
  27 + it.hide(WindowInsetsCompat.Type.navigationBars())
  28 + it.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
  29 + }
  30 + // 导航栏横线的颜色
  31 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
  32 + window.navigationBarDividerColor = Color.TRANSPARENT
  33 + }
  34 +
  35 + /*window.statusBarColor = Color.TRANSPARENT
  36 + val controller = WindowInsetsControllerCompat(window, window.decorView)
  37 + // 黑色状态栏字体
  38 + controller.isAppearanceLightStatusBars = false
  39 + // 状态栏隐藏
  40 + controller.hide(WindowInsetsCompat.Type.statusBars())
  41 + // 导航栏隐藏
  42 + controller.hide(WindowInsetsCompat.Type.navigationBars())
  43 + //window.navigationBarColor = Color.TRANSPARENT
  44 + // 打开沉浸式
  45 + WindowCompat.setDecorFitsSystemWindows(window, false)*/
  46 + }
11 47 }
... ...
lib/common/core/assets_const.dart
1 1 class AssetsConst {
2   - static const String _assetImagePrefix = "assets/images/";
3   - static const String wowLogo = "wow_logo.png";
4   - static const String icVip = "ic_vip.png";
  2 + static const String _assetImagePrefix = 'assets/images/';
  3 + static const String wowLogo = '${_assetImagePrefix}wow_logo.png';
  4 + static const String icVip = '${_assetImagePrefix}ic_vip.png';
  5 +//static String get icVip2 =>'ic_vip.png'.assetImg;
5 6 }
... ...
lib/common/pages/wow_web_page.dart
1   -import 'dart:io';
2   -
3 1 import 'package:flutter/material.dart';
4   -import 'package:flutter/services.dart';
5 2 import 'package:flutter_easyloading/flutter_easyloading.dart';
6   -import 'package:limiting_direction_csx/limiting_direction_csx.dart';
7 3 import 'package:webview_flutter/webview_flutter.dart';
8 4 import 'package:wow_english/common/widgets/we_app_bar.dart';
9 5  
... ... @@ -26,12 +22,11 @@ class _WowWebViewPageState extends State<WowWebViewPage> {
26 22 @override
27 23 void initState() {
28 24 super.initState();
29   -
30   - if (Platform.isIOS) {
  25 + /*if (Platform.isIOS) {
31 26 LimitingDirectionCsx.setScreenDirection(DeviceDirectionMask.PortraitUpsideDown);
32 27 } else {
33 28 SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
34   - }
  29 + }*/
35 30  
36 31 final WebViewController controller =WebViewController()
37 32 ..setJavaScriptMode(JavaScriptMode.unrestricted)
... ... @@ -69,14 +64,4 @@ class _WowWebViewPageState extends State<WowWebViewPage> {
69 64 body: WebViewWidget(controller: _controller,),
70 65 );
71 66 }
72   -
73   - @override
74   - void deactivate() {
75   - super.deactivate();
76   - if (Platform.isIOS) {
77   - LimitingDirectionCsx.setScreenDirection(DeviceDirectionMask.Landscape);
78   - } else {
79   - SystemChrome.setPreferredOrientations([DeviceOrientation.landscapeLeft,DeviceOrientation.landscapeRight]);
80   - }
81   - }
82   -}
83 67 \ No newline at end of file
  68 +}
... ...
lib/common/request/apis.dart
... ... @@ -10,6 +10,12 @@ class Apis {
10 10 /// 登出
11 11 static const String logout = 'logout';
12 12  
  13 + /// 获取用户信息
  14 + static const String getUserInfo = 'student/info';
  15 +
  16 + /// 更新用户信息
  17 + static const String setUserInfo = 'student/update/info';
  18 +
13 19 /// 发送验证码
14 20 static const String sendSmsCode = 'system/send/code';
15 21  
... ...
lib/common/request/dao/user_dao.dart
... ... @@ -5,6 +5,7 @@ import '../apis.dart';
5 5 import '../request_client.dart';
6 6  
7 7 class UserDao {
  8 + /// 登录
8 9 static Future<UserEntity?> login(phoneNumber, type, checkKey, checkNumber) async {
9 10 var params = {'phoneNum': phoneNumber, 'type': type, checkKey: checkNumber};
10 11 var data = await requestClient.post<UserEntity>(
... ... @@ -17,10 +18,27 @@ class UserDao {
17 18 return data;
18 19 }
19 20  
20   - static Future sendCode(phoneNumber,{smsType ='login'}) async {
21   - final params = {'phoneNum':phoneNumber,'smsType':smsType};
22   - await requestClient.post(
23   - Apis.sendSmsCode,data: params
24   - );
  21 + /// 登出
  22 + static Future logout() async {
  23 + var result = await requestClient.post(Apis.logout);
  24 + print('logout result=$result');
  25 + UserUtil.logout();
  26 + return result;
  27 + }
  28 +
  29 + /// 发送验证码
  30 + static Future sendCode(phoneNumber, {smsType = 'login'}) async {
  31 + final params = {'phoneNum': phoneNumber, 'smsType': smsType};
  32 + await requestClient.post(Apis.sendSmsCode, data: params);
  33 + }
  34 +
  35 + /// 获取用户信息
  36 + static Future<UserEntity?> getUserInfo() async {
  37 + return await requestClient.post(Apis.getUserInfo);
  38 + }
  39 +
  40 + /// 更新用户信息,返回即成功,无body
  41 + static Future updateUserInfo(UserEntity userEntity) async {
  42 + return await requestClient.put(Apis.setUserInfo, data: userEntity.toUpdateJson());
25 43 }
26 44 }
... ...
lib/common/widgets/ow_image_widget.dart
... ... @@ -16,7 +16,7 @@ class OwImageWidget extends StatelessWidget {
16 16 width: width,
17 17 );
18 18 }
19   - return name.contains('http')?
  19 + return name.startsWith('http')?
20 20 CachedNetworkImage(
21 21 imageUrl: name,
22 22 height: height,
... ... @@ -29,4 +29,4 @@ class OwImageWidget extends StatelessWidget {
29 29 fit: fit,
30 30 );
31 31 }
32   -}
33 32 \ No newline at end of file
  33 +}
... ...
lib/generated/json/user_entity.g.dart
... ... @@ -11,6 +11,10 @@ UserEntity $UserEntityFromJson(Map&lt;String, dynamic&gt; json) {
11 11 if (name != null) {
12 12 userEntity.name = name;
13 13 }
  14 + final String? token = jsonConvert.convert<String>(json['token']);
  15 + if (token != null) {
  16 + userEntity.token = token;
  17 + }
14 18 final int? age = jsonConvert.convert<int>(json['age']);
15 19 if (age != null) {
16 20 userEntity.age = age;
... ... @@ -27,13 +31,17 @@ UserEntity $UserEntityFromJson(Map&lt;String, dynamic&gt; json) {
27 31 if (phoneNum != null) {
28 32 userEntity.phoneNum = phoneNum;
29 33 }
30   - final String? token = jsonConvert.convert<String>(json['token']);
31   - if (token != null) {
32   - userEntity.token = token;
  34 + final int? fillUserInfo = jsonConvert.convert<int>(json['fillUserInfo']);
  35 + if (fillUserInfo != null) {
  36 + userEntity.fillUserInfo = fillUserInfo;
  37 + }
  38 + final int? nowCourseModuleId = jsonConvert.convert<int>(json['nowCourseModuleId']);
  39 + if (nowCourseModuleId != null) {
  40 + userEntity.nowCourseModuleId = nowCourseModuleId;
33 41 }
34   - final int? expireTime = jsonConvert.convert<int>(json['expireTime']);
35   - if (expireTime != null) {
36   - userEntity.expireTime = expireTime;
  42 + final String? effectiveDate = jsonConvert.convert<String>(json['effectiveDate']);
  43 + if (effectiveDate != null) {
  44 + userEntity.effectiveDate = effectiveDate;
37 45 }
38 46 return userEntity;
39 47 }
... ... @@ -42,11 +50,13 @@ Map&lt;String, dynamic&gt; $UserEntityToJson(UserEntity entity) {
42 50 final Map<String, dynamic> data = <String, dynamic>{};
43 51 data['id'] = entity.id;
44 52 data['name'] = entity.name;
  53 + data['token'] = entity.token;
45 54 data['age'] = entity.age;
46 55 data['gender'] = entity.gender;
47 56 data['avatarUrl'] = entity.avatarUrl;
48 57 data['phoneNum'] = entity.phoneNum;
49   - data['token'] = entity.token;
50   - data['expireTime'] = entity.expireTime;
  58 + data['fillUserInfo'] = entity.fillUserInfo;
  59 + data['nowCourseModuleId'] = entity.nowCourseModuleId;
  60 + data['effectiveDate'] = entity.effectiveDate;
51 61 return data;
52   -}
53 62 \ No newline at end of file
  63 +}
... ...
lib/models/response_model.dart.txt deleted
1   -import 'package:json_annotation/json_annotation.dart';
2   -
3   -part 'response_model.g.dart';
4   -
5   -@JsonSerializable()
6   -class ResponseModel {
7   - int? code;
8   - dynamic data;
9   - String? msg;
10   -
11   - ResponseModel(this.code,this.data,this.msg);
12   -
13   - factory ResponseModel.fromJson(Map<String, dynamic> json) => _$ResponseModelFromJson(json);
14   -
15   - Map<String, dynamic> toJson() => _$ResponseModelToJson(this);
16   -}
lib/models/response_model.g.dart.txt deleted
1   -// GENERATED CODE - DO NOT MODIFY BY HAND
2   -
3   -part of 'response_model.dart.txt';
4   -
5   -// **************************************************************************
6   -// JsonSerializableGenerator
7   -// **************************************************************************
8   -
9   -ResponseModel _$ResponseModelFromJson(Map<String, dynamic> json) =>
10   - ResponseModel(
11   - json['code'] as int?,
12   - json['data'],
13   - json['msg'] as String?,
14   - );
15   -
16   -Map<String, dynamic> _$ResponseModelToJson(ResponseModel instance) =>
17   - <String, dynamic>{
18   - 'code': instance.code,
19   - 'data': instance.data,
20   - 'msg': instance.msg,
21   - };
lib/models/user_entity.dart
... ... @@ -7,14 +7,27 @@ import &#39;package:wow_english/generated/json/user_entity.g.dart&#39;;
7 7 class UserEntity {
8 8 late int id;
9 9 late String name;
  10 +
  11 + /// 一定有也必须要有
  12 + late String token;
  13 +
  14 + //late int expireTime;
  15 +
10 16 int? age;
11 17  
12 18 /// 性别:0, 1
13 19 int? gender;
14 20 String? avatarUrl;
15   - late String phoneNum;
16   - late String token;
17   - late int expireTime;
  21 + String? phoneNum;
  22 +
  23 + /// 用户信息是否填写 0.未填写 1.已经填写
  24 + int? fillUserInfo;
  25 +
  26 + /// 当前模块Id
  27 + int? nowCourseModuleId;
  28 +
  29 + /// 有效时间,VIP,为null没有
  30 + String? effectiveDate;
18 31  
19 32 UserEntity();
20 33  
... ... @@ -26,4 +39,21 @@ class UserEntity {
26 39 String toString() {
27 40 return jsonEncode(this);
28 41 }
  42 +
  43 + Map<String, dynamic> toUpdateJson() {
  44 + final Map<String, dynamic> data = <String, dynamic>{};
  45 + data['name'] = name;
  46 + data['age'] = age;
  47 + data['gender'] = gender;
  48 + data['avatarUrl'] = avatarUrl;
  49 + return data;
  50 + }
  51 +
  52 + String getGenderString() {
  53 + return gender == null
  54 + ? ''
  55 + : gender == 0
  56 + ? '男'
  57 + : '女';
  58 + }
29 59 }
... ...
lib/network/api.dart.txt deleted
1   -class Api {
2   - /// app初始化配置信息
3   - // GET /system/app/config
4   - // 接口地址:https://app.apifox.com/link/project/2684751/apis/api-89897678
5   - static const String appConfig = '/system/app/config';
6   -
7   - /// 登陆
8   - static const String login = 'login';
9   -
10   - /// 登出
11   - static const String logout = 'logout';
12   -
13   - /// 发送验证码
14   - static const String sendSmsCode = '/system/send/code';
15   -
16   - /// 课程模块
17   - // GET /home/courseModule
18   - // 接口地址:https://app.apifox.com/link/project/2684751/apis/api-89897663
19   - static const String courseModule = '/home/courseModule';
20   -
21   - /// 课程列表
22   - // GET /home/courseLesson
23   - // 接口地址:https://app.apifox.com/link/project/2684751/apis/api-89897662
24   - static const String courseLesson = '/home/courseLesson';
25   -}
lib/network/basic_configuration.dart.txt deleted
1   -enum DevelopEvent {
2   - ///开发环境
3   - dev,
4   -
5   - ///正式环境
6   - formal
7   -}
8   -
9   -class BasicConfigurationManager {
10   - factory BasicConfigurationManager() => _getInstance();
11   -
12   - static BasicConfigurationManager? _instance;
13   -
14   - //服务器地址
15   - String? baseUrl;
16   -
17   - //SessionId
18   - String? sessionId;
19   -
20   - BasicConfigurationManager._internal() {
21   - DevelopEvent developType = DevelopEvent.dev;
22   - if (developType == DevelopEvent.dev) {
23   - baseUrl = 'http://wow-app.dev.kouyuxingqiu.com/';
24   - } else {
25   - baseUrl = 'http://wow-app.dev.kouyuxingqiu.com/';
26   - }
27   - sessionId = '';
28   - }
29   -
30   - static BasicConfigurationManager _getInstance() {
31   - _instance ??= BasicConfigurationManager._internal();
32   - return _instance!;
33   - }
34   -}
lib/network/network_manager.dart.txt deleted
1   -import 'package:dio/dio.dart';
2   -import 'package:flutter/foundation.dart';
3   -import 'package:wow_english/models/response_model.dart';
4   -import 'package:wow_english/network/basic_configuration.dart.txt';
5   -
6   -enum HttpMethod {
7   - get,
8   - put,
9   - post,
10   - head,
11   - patch,
12   - delete,
13   -}
14   -
15   -class DioUtil {
16   - static final Dio _dio = getDefDio();
17   -
18   - static Dio getDefDio() {
19   - Dio dio = Dio();
20   - dio.options = getDefOptions();
21   - return dio;
22   - }
23   -
24   - static BaseOptions getDefOptions() {
25   - final BaseOptions options = BaseOptions();
26   - options.baseUrl = BasicConfigurationManager().baseUrl ?? '';
27   - options.connectTimeout = const Duration(milliseconds: 1000);
28   - options.receiveTimeout = const Duration(milliseconds: 1000);
29   - return options;
30   - }
31   -
32   - Future<void> requestData<T>(
33   - HttpMethod method,
34   - String path, {
35   - data,
36   - Function? successCallBack,
37   - Function? errorCallBack,
38   - Map<String, dynamic>? queryParameters,
39   - ProgressCallback? onSendProgress,
40   - ProgressCallback? onReceiveProgress,
41   - }) async {
42   - try {
43   - Map<String, dynamic> headers = <String, dynamic>{};
44   -
45   - if (method == HttpMethod.post) {
46   - headers['content-type'] = 'application/json';
47   - }
48   - Response<dynamic> response;
49   - response = await _dio.request(path,
50   - data: data ?? {},
51   - queryParameters: queryParameters,
52   - options: Options(method: method.name, headers: headers),
53   - onSendProgress: onSendProgress,
54   - onReceiveProgress: onReceiveProgress);
55   - int statusCode = response.statusCode ?? 0;
56   - if (statusCode >= 200 && statusCode < 300) {
57   - if (kDebugMode) {
58   - print(response.data);
59   - }
60   - final ResponseModel model = ResponseModel.fromJson(response.data);
61   - if (model.code == 200) {
62   - successCallBack?.call(response.data);
63   - } else {
64   - errorCallBack?.call(model.msg);
65   - }
66   - } else {
67   - errorCallBack?.call('请求失败');
68   - }
69   - } on DioException catch (error) {
70   - if (kDebugMode) {
71   - print(error);
72   - }
73   - errorCallBack?.call("网络错误: ${error.message}");
74   - }
75   - }
76   -}
lib/pages/login/loginpage/login_page.dart
... ... @@ -104,7 +104,7 @@ class _LoginPageView extends StatelessWidget {
104 104 recognizer: TapGestureRecognizer()
105 105 ..onTap = () {
106 106 Navigator.of(context).pushNamed(AppRouteName.webView, arguments: {
107   - 'urlStr': 'https://www.zhihu.com',
  107 + 'urlStr': 'http://page.kouyuxingqiu.com/%E7%94%A8%E6%88%B7%E6%B3%A8%E5%86%8C%E5%8F%8A%E4%BD%BF%E7%94%A8APP%E9%9A%90%E7%A7%81%E5%8D%8F%E8%AE%AE.html',
108 108 'webViewTitle': '用户隐私协议'
109 109 });
110 110 }),
... ... @@ -116,7 +116,7 @@ class _LoginPageView extends StatelessWidget {
116 116 recognizer: TapGestureRecognizer()
117 117 ..onTap = () {
118 118 Navigator.of(context).pushNamed(AppRouteName.webView, arguments: {
119   - 'urlStr': 'https://www.zhihu.com',
  119 + 'urlStr': 'https://ishowedu-public-images.ishowedu.com/%E5%8F%A3%E8%AF%AD%E6%98%9F%E7%90%83%E5%84%BF%E7%AB%A5%E9%9A%90%E7%A7%81%E4%BF%9D%E6%8A%A4%E6%94%BF%E7%AD%96_iShowLD%E4%BF%AE%E8%AE%A2_20210913%281%29.html',
120 120 'webViewTitle': '儿童隐私协议'
121 121 });
122 122 })
... ...
lib/pages/user/bloc/user_bloc.dart
1 1 import 'package:bloc/bloc.dart';
2 2 import 'package:meta/meta.dart';
  3 +import 'package:wow_english/common/request/dao/user_dao.dart';
3 4  
4 5 part 'user_event.dart';
5 6 part 'user_state.dart';
6 7  
7 8 class UserBloc extends Bloc<UserEvent, UserState> {
8 9 UserBloc() : super(UserInitial()) {
  10 + on<UserLogout>(_test);
9 11 on<UserEvent>((event, emit) {
10 12 // TODO: implement event handler
11 13 });
12 14 }
  15 +
  16 + void _test(UserLogout event, Emitter<UserState> emitter) async {
  17 + print('UserBloc._test, event: $event, emitter: $emitter');
  18 + await UserDao.logout();
  19 + }
13 20 }
... ...
lib/pages/user/bloc/user_event.dart
... ... @@ -2,3 +2,7 @@ part of &#39;user_bloc.dart&#39;;
2 2  
3 3 @immutable
4 4 abstract class UserEvent {}
  5 +
  6 +class UserStarted extends UserEvent {}
  7 +
  8 +class UserLogout extends UserEvent {}
... ...
lib/pages/user/user_page.dart
... ... @@ -3,10 +3,11 @@ import &#39;package:flutter_bloc/flutter_bloc.dart&#39;;
3 3 import 'package:flutter_screenutil/flutter_screenutil.dart';
4 4 import 'package:wow_english/common/blocs/cachebloc/cache_bloc.dart';
5 5 import 'package:wow_english/common/core/assets_const.dart';
6   -import 'package:wow_english/common/extension/string_extension.dart';
  6 +import 'package:wow_english/common/widgets/ow_image_widget.dart';
7 7 import 'package:wow_english/common/widgets/we_app_bar.dart';
8 8 import 'package:wow_english/models/user_entity.dart';
9 9 import 'package:wow_english/pages/user/bloc/user_bloc.dart';
  10 +import 'package:wow_english/route/route.dart';
10 11  
11 12 class UserPage extends StatelessWidget {
12 13 const UserPage({super.key});
... ... @@ -15,7 +16,7 @@ class UserPage extends StatelessWidget {
15 16 Widget build(BuildContext context) {
16 17 return BlocProvider(
17 18 create: (context) => UserBloc(),
18   - child: _UserView(),
  19 + child: const _UserView(),
19 20 );
20 21 }
21 22 }
... ... @@ -25,65 +26,152 @@ class _UserView extends StatelessWidget {
25 26  
26 27 @override
27 28 Widget build(BuildContext context) {
28   - UserEntity? user = context.read<CacheBloc>().userEntity;
  29 + final cacheBloc = BlocProvider.of<CacheBloc>(context);
  30 + final userBloc = BlocProvider.of<UserBloc>(context);
  31 + UserEntity user = cacheBloc.userEntity!;
  32 +
  33 + // 常规按钮的字体样式
  34 + final textStyle21sp = TextStyle(
  35 + //fontWeight: FontWeight.w600,
  36 + color: const Color(0xFF333333),
  37 + fontSize: 21.sp,
  38 + );
  39 +
  40 + // 常规按钮的样式
  41 + var normalButtonStyle = ButtonStyle(
  42 + side: MaterialStateProperty.all(BorderSide(color: const Color(0xFF140C10), width: 1.5)),
  43 + shape: MaterialStateProperty.all(RoundedRectangleBorder(borderRadius: BorderRadius.circular(15.r))),
  44 + minimumSize: MaterialStateProperty.all(Size(double.infinity, 58.h)),
  45 + backgroundColor: MaterialStateProperty.all(Colors.white),
  46 + );
29 47 return Scaffold(
30 48 backgroundColor: Colors.white,
31   - appBar: WEAppBar(
32   - // 测试用的
33   - titleText: user?.name ?? '个人中心',
34   - ),
  49 + appBar: const WEAppBar(),
35 50 body: SingleChildScrollView(
  51 + //padding: EdgeInsets.symmetric(horizontal: 17.w),
  52 + padding: EdgeInsets.only(left: 17.w, right: 17.w, top: 10.h, bottom: 22.h),
36 53 child: Column(
37 54 mainAxisAlignment: MainAxisAlignment.center,
38 55 children: <Widget>[
39   - Container(
40   - child: Image.asset(AssetsConst.wowLogo.assetImg), constraints: BoxConstraints(maxHeight: 196.h)),
41   - _userInfo(context),
  56 + Container(child: Image.asset(AssetsConst.wowLogo), constraints: BoxConstraints(maxHeight: 196.h)),
  57 + 30.verticalSpace,
  58 + Row(
  59 + mainAxisAlignment: MainAxisAlignment.spaceBetween,
  60 + children: [
  61 + CircleAvatar(
  62 + radius: 40.r,
  63 + backgroundColor: Color(0xFF140C10),
  64 + /*child: CircleAvatar(
  65 + radius: 38.5.r,
  66 + backgroundImage: ImageUtil.getImageProviderOnDefault(user.avatarUrl),
  67 + ),*/
  68 + child: ClipOval(
  69 + child: OwImageWidget(name: user.avatarUrl ?? AssetsConst.wowLogo),
  70 + )),
  71 + 32.horizontalSpace,
  72 + Expanded(
  73 + child: Column(
  74 + children: [
  75 + Row(
  76 + children: [
  77 + LimitedBox(
  78 + maxWidth: 220.w,
  79 + child: Text(
  80 + user.name,
  81 + //'1231231231312312312312312312312312312312312312312',
  82 + style: textStyle21sp,
  83 + overflow: TextOverflow.ellipsis,
  84 + ),
  85 + ),
  86 + 14.horizontalSpace,
  87 + Text(
  88 + user.getGenderString(),
  89 + style: textStyle21sp,
  90 + ),
  91 + 14.horizontalSpace,
  92 + Offstage(
  93 + offstage: user.effectiveDate == null,
  94 + child: Image.asset(
  95 + AssetsConst.icVip,
  96 + height: 18.h,
  97 + ),
  98 + )
  99 + ],
  100 + ),
  101 + Offstage(
  102 + offstage: user.effectiveDate == null,
  103 + child: Row(
  104 + children: [
  105 + Text(
  106 + "${user.effectiveDate} 到期",
  107 + style: TextStyle(
  108 + color: const Color(0xFFE11212),
  109 + fontSize: 17.sp,
  110 + ),
  111 + )
  112 + ],
  113 + ),
  114 + )
  115 + ],
  116 + )),
  117 + TextButton(
  118 + child: Text(
  119 + "修改个人信息>",
  120 + style: textStyle21sp,
  121 + ),
  122 + onPressed: () {},
  123 + )
  124 + ],
  125 + ),
  126 + 30.verticalSpace,
  127 + OutlinedButton(
  128 + onPressed: () => {},
  129 + style: normalButtonStyle,
  130 + child: Text(
  131 + "修改密码",
  132 + style: textStyle21sp,
  133 + ),
  134 + ),
  135 + 12.verticalSpace,
  136 + OutlinedButton(
  137 + onPressed: () => {},
  138 + style: normalButtonStyle,
  139 + child: Text(
  140 + "兑换课程",
  141 + style: textStyle21sp,
  142 + )),
  143 + 12.verticalSpace,
  144 + OutlinedButton(
  145 + onPressed: () => {
  146 + Navigator.of(context).pushNamed(AppRouteName.webView, arguments: {
  147 + 'urlStr': 'http://page.kouyuxingqiu.com/%E7%94%A8%E6%88%B7%E6%B3%A8%E5%86%8C%E5%8F%8A%E4%BD%BF%E7%94%A8APP%E9%9A%90%E7%A7%81%E5%8D%8F%E8%AE%AE.html',
  148 + 'webViewTitle': '隐私协议'
  149 + })
  150 + },
  151 + style: normalButtonStyle,
  152 + child: Text(
  153 + "隐私协议",
  154 + style: textStyle21sp,
  155 + )),
  156 + 30.verticalSpace,
  157 + OutlinedButton(
  158 + onPressed: () => {userBloc.add(UserLogout())},
  159 + style: ButtonStyle(
  160 + side: MaterialStateProperty.all(BorderSide(color: const Color(0xFF140C10), width: 1.5)),
  161 + shape: MaterialStateProperty.all(RoundedRectangleBorder(borderRadius: BorderRadius.circular(15.r))),
  162 + minimumSize: MaterialStateProperty.all(Size(295.w, 40.h)),
  163 + backgroundColor: MaterialStateProperty.all(Color(0xFFFBB621)),
  164 + ),
  165 + child: Text(
  166 + "退出登陆",
  167 + style: TextStyle(
  168 + //fontWeight: FontWeight.w600,
  169 + color: Colors.white,
  170 + fontSize: 17.sp,
  171 + ),
  172 + )),
42 173 ],
43 174 ),
44 175 ));
45 176 }
46   -
47   - Widget _userInfo(BuildContext context) {
48   - return Row(
49   - children: [
50   - Image.asset(
51   - AssetsConst.wowLogo.assetImg,
52   - width: 80,
53   - height: 80,
54   - ),
55   - Column(
56   - children: [
57   - Row(
58   - children: [
59   - Text(
60   - context.read<CacheBloc>().userEntity?.name ?? '----',
61   - style: TextStyle(
62   - color: const Color(0xFF333333),
63   - fontSize: 21.sp,
64   - ),
65   - ),
66   - //Text(context.read<CacheBloc>().userEntity?.gender ?? '--'),
67   - Image.asset(
68   - AssetsConst.wowLogo.assetImg,
69   - height: 18.h,
70   - ),
71   - ],
72   - ),
73   - Row(
74   - children: [
75   - Text(
76   - "什么时候到期",
77   - style: TextStyle(
78   - color: const Color(0xFFE11212),
79   - fontSize: 17.sp,
80   - ),
81   - )
82   - ],
83   - )
84   - ],
85   - ),
86   - ],
87   - );
88   - }
89 177 }
... ...
lib/utils/image_util.dart 0 → 100644
  1 +import 'package:flutter/material.dart';
  2 +import 'package:wow_english/common/core/assets_const.dart';
  3 +
  4 +class ImageUtil {
  5 + static ImageProvider getImageProviderOnDefault(String? uri, {scale = 1.0}) {
  6 + if (uri == null || uri.isEmpty) {
  7 + return ExactAssetImage(AssetsConst.wowLogo, scale: scale);
  8 + }
  9 + if (uri.startsWith('http')) {
  10 + return NetworkImage(uri);
  11 + } else {
  12 + return ExactAssetImage(uri, scale: scale);
  13 + }
  14 + //return uri.startsWith('http') ? NetworkImage(uri) : ExactAssetImage(uri, scale: 0.5) as ImageProvider?;
  15 + }
  16 +}
... ...