@@ -217,6 +217,12 @@ | |||
"packageUri": "lib/", | |||
"languageVersion": "2.6" | |||
}, | |||
{ | |||
"name": "flutter_cupertino_date_picker", | |||
"rootUri": "file:///Users/fnuser/.pub-cache/hosted/pub.flutter-io.cn/flutter_cupertino_date_picker-1.0.26+2", | |||
"packageUri": "lib/", | |||
"languageVersion": "1.19" | |||
}, | |||
{ | |||
"name": "flutter_native_image", | |||
"rootUri": "file:///Users/fnuser/.pub-cache/hosted/pub.flutter-io.cn/flutter_native_image-0.0.5+2", | |||
@@ -229,6 +235,12 @@ | |||
"packageUri": "lib/", | |||
"languageVersion": "2.0" | |||
}, | |||
{ | |||
"name": "flutter_plugin_android_lifecycle", | |||
"rootUri": "file:///Users/fnuser/.pub-cache/hosted/pub.flutter-io.cn/flutter_plugin_android_lifecycle-1.0.9", | |||
"packageUri": "lib/", | |||
"languageVersion": "2.1" | |||
}, | |||
{ | |||
"name": "flutter_screenutil", | |||
"rootUri": "file:///Users/fnuser/.pub-cache/hosted/pub.flutter-io.cn/flutter_screenutil-1.1.0", | |||
@@ -301,6 +313,24 @@ | |||
"packageUri": "lib/", | |||
"languageVersion": "2.0" | |||
}, | |||
{ | |||
"name": "image_cropper", | |||
"rootUri": "file:///Users/fnuser/.pub-cache/git/Image_Cropper-e32f2264f86a27a2f5d7a7a5e26c6154eaf5798e/", | |||
"packageUri": "lib/", | |||
"languageVersion": "1.20" | |||
}, | |||
{ | |||
"name": "image_picker", | |||
"rootUri": "file:///Users/fnuser/.pub-cache/hosted/pub.flutter-io.cn/image_picker-0.6.7+7", | |||
"packageUri": "lib/", | |||
"languageVersion": "2.1" | |||
}, | |||
{ | |||
"name": "image_picker_platform_interface", | |||
"rootUri": "file:///Users/fnuser/.pub-cache/hosted/pub.flutter-io.cn/image_picker_platform_interface-1.1.0", | |||
"packageUri": "lib/", | |||
"languageVersion": "2.5" | |||
}, | |||
{ | |||
"name": "intl", | |||
"rootUri": "file:///Users/fnuser/.pub-cache/hosted/pub.flutter-io.cn/intl-0.16.1", | |||
@@ -680,7 +710,7 @@ | |||
"languageVersion": "2.1" | |||
} | |||
], | |||
"generated": "2020-09-15T07:31:12.840893Z", | |||
"generated": "2020-09-16T07:59:23.044545Z", | |||
"generator": "pub", | |||
"generatorVersion": "2.7.2" | |||
} |
@@ -4,11 +4,18 @@ PODS: | |||
- Flutter (1.0.0) | |||
- flutter_native_image (0.0.1): | |||
- Flutter | |||
- flutter_plugin_android_lifecycle (0.0.1): | |||
- Flutter | |||
- fluttertoast (0.0.2): | |||
- Flutter | |||
- FMDB (2.7.5): | |||
- FMDB/standard (= 2.7.5) | |||
- FMDB/standard (2.7.5) | |||
- image_cropper (0.0.2): | |||
- Flutter | |||
- TOCropViewController (~> 2.5.2) | |||
- image_picker (0.0.1): | |||
- Flutter | |||
- package_info (0.0.1): | |||
- Flutter | |||
- path_provider (0.0.1): | |||
@@ -28,6 +35,7 @@ PODS: | |||
- sqflite (0.0.1): | |||
- Flutter | |||
- FMDB (~> 2.7.2) | |||
- TOCropViewController (2.5.3) | |||
- zhiying_base_widget (0.0.1): | |||
- Flutter | |||
- zhiying_comm (0.0.1): | |||
@@ -37,7 +45,10 @@ DEPENDENCIES: | |||
- device_info (from `.symlinks/plugins/device_info/ios`) | |||
- Flutter (from `Flutter`) | |||
- flutter_native_image (from `.symlinks/plugins/flutter_native_image/ios`) | |||
- flutter_plugin_android_lifecycle (from `.symlinks/plugins/flutter_plugin_android_lifecycle/ios`) | |||
- fluttertoast (from `.symlinks/plugins/fluttertoast/ios`) | |||
- image_cropper (from `.symlinks/plugins/image_cropper/ios`) | |||
- image_picker (from `.symlinks/plugins/image_picker/ios`) | |||
- package_info (from `.symlinks/plugins/package_info/ios`) | |||
- path_provider (from `.symlinks/plugins/path_provider/ios`) | |||
- path_provider_linux (from `.symlinks/plugins/path_provider_linux/ios`) | |||
@@ -53,6 +64,7 @@ DEPENDENCIES: | |||
SPEC REPOS: | |||
trunk: | |||
- FMDB | |||
- TOCropViewController | |||
EXTERNAL SOURCES: | |||
device_info: | |||
@@ -61,8 +73,14 @@ EXTERNAL SOURCES: | |||
:path: Flutter | |||
flutter_native_image: | |||
:path: ".symlinks/plugins/flutter_native_image/ios" | |||
flutter_plugin_android_lifecycle: | |||
:path: ".symlinks/plugins/flutter_plugin_android_lifecycle/ios" | |||
fluttertoast: | |||
:path: ".symlinks/plugins/fluttertoast/ios" | |||
image_cropper: | |||
:path: ".symlinks/plugins/image_cropper/ios" | |||
image_picker: | |||
:path: ".symlinks/plugins/image_picker/ios" | |||
package_info: | |||
:path: ".symlinks/plugins/package_info/ios" | |||
path_provider: | |||
@@ -90,8 +108,11 @@ SPEC CHECKSUMS: | |||
device_info: d7d233b645a32c40dfdc212de5cf646ca482f175 | |||
Flutter: 0e3d915762c693b495b44d77113d4970485de6ec | |||
flutter_native_image: 9c0b7451838484458e5b0fae007b86a4c2d4bdfe | |||
flutter_plugin_android_lifecycle: dc0b544e129eebb77a6bfb1239d4d1c673a60a35 | |||
fluttertoast: b644586ef3b16f67fae9a1f8754cef6b2d6b634b | |||
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a | |||
image_cropper: 3c16d7651730ffe85897f5a1c4e2547e6b54989a | |||
image_picker: 9c3312491f862b28d21ecd8fdf0ee14e601b3f09 | |||
package_info: 873975fc26034f0b863a300ad47e7f1ac6c7ec62 | |||
path_provider: abfe2b5c733d04e238b0d8691db0cfd63a27a93c | |||
path_provider_linux: 4d630dc393e1f20364f3e3b4a2ff41d9674a84e4 | |||
@@ -101,6 +122,7 @@ SPEC CHECKSUMS: | |||
shared_preferences_macos: f3f29b71ccbb56bf40c9dd6396c9acf15e214087 | |||
shared_preferences_web: 141cce0c3ed1a1c5bf2a0e44f52d31eeb66e5ea9 | |||
sqflite: 4001a31ff81d210346b500c55b17f4d6c7589dd0 | |||
TOCropViewController: 20a14b6a7a098308bf369e7c8d700dc983a974e6 | |||
zhiying_base_widget: 00868c0d2723a3a425c18b27204fbc67e3f7e59d | |||
zhiying_comm: 0daef4a480f4f4dbea3e11b615f3264aafea924b | |||
@@ -162,6 +162,7 @@ | |||
9705A1C41CF9048500538489 /* Embed Frameworks */, | |||
3B06AD1E1E4923F5004D2608 /* Thin Binary */, | |||
3DD5E1C6552F1CEFD4C31B18 /* [CP] Embed Pods Frameworks */, | |||
E6B4F9F34A4509DF5D9BF2D8 /* [CP] Copy Pods Resources */, | |||
); | |||
buildRules = ( | |||
); | |||
@@ -286,6 +287,21 @@ | |||
shellPath = /bin/sh; | |||
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; | |||
}; | |||
E6B4F9F34A4509DF5D9BF2D8 /* [CP] Copy Pods Resources */ = { | |||
isa = PBXShellScriptBuildPhase; | |||
buildActionMask = 2147483647; | |||
files = ( | |||
); | |||
inputPaths = ( | |||
); | |||
name = "[CP] Copy Pods Resources"; | |||
outputPaths = ( | |||
); | |||
runOnlyForDeploymentPostprocessing = 0; | |||
shellPath = /bin/sh; | |||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n"; | |||
showEnvVarsInLog = 0; | |||
}; | |||
/* End PBXShellScriptBuildPhase section */ | |||
/* Begin PBXSourcesBuildPhase section */ | |||
@@ -386,6 +402,7 @@ | |||
"$(PROJECT_DIR)/Flutter", | |||
); | |||
INFOPLIST_FILE = Runner/Info.plist; | |||
IPHONEOS_DEPLOYMENT_TARGET = 8.0; | |||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; | |||
LIBRARY_SEARCH_PATHS = ( | |||
"$(inherited)", | |||
@@ -519,6 +536,7 @@ | |||
"$(PROJECT_DIR)/Flutter", | |||
); | |||
INFOPLIST_FILE = Runner/Info.plist; | |||
IPHONEOS_DEPLOYMENT_TARGET = 8.0; | |||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; | |||
LIBRARY_SEARCH_PATHS = ( | |||
"$(inherited)", | |||
@@ -545,6 +563,7 @@ | |||
"$(PROJECT_DIR)/Flutter", | |||
); | |||
INFOPLIST_FILE = Runner/Info.plist; | |||
IPHONEOS_DEPLOYMENT_TARGET = 8.0; | |||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; | |||
LIBRARY_SEARCH_PATHS = ( | |||
"$(inherited)", | |||
@@ -41,5 +41,19 @@ | |||
</array> | |||
<key>UIViewControllerBasedStatusBarAppearance</key> | |||
<false/> | |||
<key>NSCameraUsageDescription</key> | |||
<string>获取相机权限更换头像或者扫码</string> | |||
<key>NSContactsUsageDescription</key> | |||
<string>获取访问通信录权限添加联系人信息</string> | |||
<key>NSLocationAlwaysUsageDescription</key> | |||
<string>获取定位权限用于搜索附近的网点和查找附近的油站信息</string> | |||
<key>NSLocationWhenInUseUsageDescription</key> | |||
<string>获取定位权限用于搜索附近的网点和查找附近的油站信息</string> | |||
<key>NSMicrophoneUsageDescription</key> | |||
<string>获取访问麦克风权限录制语音或视频</string> | |||
<key>NSPhotoLibraryAddUsageDescription</key> | |||
<string>获取访问相册权限更换头像</string> | |||
<key>NSPhotoLibraryUsageDescription</key> | |||
<string>获取访问相册权限更换头像</string> | |||
</dict> | |||
</plist> |
@@ -0,0 +1,83 @@ | |||
import 'dart:async'; | |||
import 'dart:io'; | |||
import 'package:fluttertoast/fluttertoast.dart'; | |||
import 'package:path/path.dart'; | |||
import 'package:zhiying_base_widget/pages/mine_detail_page/models/mine_detail_model.dart'; | |||
import 'package:zhiying_comm/util/base_bloc.dart'; | |||
import 'package:zhiying_comm/zhiying_comm.dart'; | |||
class MineDetailBloc extends BlocBase { | |||
MineDetailModel _user; | |||
StreamController<MineDetailModel> _userController = | |||
StreamController<MineDetailModel>(); | |||
Stream<MineDetailModel> get outData => _userController.stream; | |||
@override | |||
void dispose() { | |||
_userController.close(); | |||
_userController = null; | |||
} | |||
void loadData() { | |||
NetUtil.request('/api/v1/user/info', method: NetMethod.GET, | |||
onCache: (data) { | |||
if (_user == null) _loadData(data); | |||
}, onSuccess: (data) { | |||
_loadData(data); | |||
}); | |||
} | |||
void _loadData(dynamic data) { | |||
_user = MineDetailModel.fromJson(Map<String, dynamic>.from(data)); | |||
_userController.add(_user); | |||
} | |||
/* 更新用户信息 | |||
nickname 昵称 | |||
gender 性别(1女2男3未知) | |||
birthday 生日(时间戳) | |||
* */ | |||
void updateUser({String nickname, String gender, String birthday}) { | |||
Map<String, dynamic> params = Map(); | |||
if (nickname != null && nickname != '') { | |||
params['nickname'] = nickname; | |||
} | |||
if (gender != null && gender != '') { | |||
params['gender'] = gender; | |||
} | |||
if (birthday != null && birthday != '') { | |||
params['birthday'] = birthday; | |||
} | |||
NetUtil.request('/api/v1/user/info', | |||
method: NetMethod.POST, | |||
params: params, | |||
onCache: (data) {}, onSuccess: (data) { | |||
Fluttertoast.showToast(msg: '修改成功'); | |||
loadData(); | |||
}); | |||
} | |||
void uploadAvatar(File file) async { | |||
List<int> originBytes = await file.readAsBytes(); | |||
print('原图大小:' + originBytes.length.toString() + 'byte'); | |||
print('原图大小:' + basename(file.path)); | |||
Map<String, dynamic> params = Map(); | |||
params['dir'] = 'avatar'; | |||
params['file_size'] = originBytes.length; | |||
params['file_name'] = basename(file.path); | |||
NetUtil.request('/api/v1/file/upload', | |||
method: NetMethod.PUT, | |||
params: params, | |||
onCache: (data) {}, onSuccess: (data) { | |||
String method = data['method']; | |||
String host = data['host']; | |||
String key = data['key']; | |||
String token = data['token']; | |||
}); | |||
} | |||
} |
@@ -0,0 +1,347 @@ | |||
import 'dart:io'; | |||
import 'package:cached_network_image/cached_network_image.dart'; | |||
import 'package:flutter/cupertino.dart'; | |||
import 'package:flutter/material.dart'; | |||
import 'package:fluttertoast/fluttertoast.dart'; | |||
import 'package:image_cropper/image_cropper.dart'; | |||
import 'package:image_picker/image_picker.dart'; | |||
import 'package:intl/intl.dart'; | |||
import 'package:zhiying_base_widget/pages/mine_detail_page/mine_detail_bloc.dart'; | |||
import 'package:zhiying_base_widget/pages/mine_detail_page/models/mine_detail_model.dart'; | |||
import 'package:zhiying_base_widget/widgets/others/action_date_alert/action_date_alert.dart'; | |||
import 'package:zhiying_base_widget/widgets/others/action_list_alert/action_list_alert.dart'; | |||
import 'package:zhiying_base_widget/widgets/others/action_selected_alert/action_selected_alert.dart'; | |||
import 'package:zhiying_comm/util/base_bloc.dart'; | |||
import 'package:zhiying_comm/zhiying_comm.dart'; | |||
class MineDetailPage extends StatefulWidget { | |||
@override | |||
_MineDetailPageState createState() => _MineDetailPageState(); | |||
} | |||
class _MineDetailPageState extends State<MineDetailPage> { | |||
@override | |||
Widget build(BuildContext context) { | |||
return Scaffold( | |||
backgroundColor: Color(0xfff9f9f9), | |||
appBar: _createNav(), | |||
body: SafeArea( | |||
child: BlocProvider<MineDetailBloc>( | |||
bloc: MineDetailBloc(), | |||
child: _MineDetailContainer(), | |||
), | |||
), | |||
); | |||
} | |||
// 导航栏 | |||
Widget _createNav() { | |||
return CupertinoNavigationBar( | |||
border: Border( | |||
bottom: BorderSide( | |||
width: 0.0, // One physical pixel. | |||
style: BorderStyle.none, | |||
), | |||
), | |||
backgroundColor: Colors.white, | |||
leading: Navigator.canPop(context) | |||
? GestureDetector( | |||
child: Container( | |||
padding: EdgeInsets.zero, | |||
child: Icon( | |||
Icons.arrow_back_ios, | |||
size: 20, | |||
), | |||
), | |||
onTap: () { | |||
if (Navigator.canPop(context)) { | |||
Navigator.pop(context); | |||
} | |||
}, | |||
) | |||
: Container(), | |||
middle: Text( | |||
'个人信息', | |||
style: TextStyle( | |||
fontSize: 15, | |||
color: Color(0xff333333), | |||
), | |||
), | |||
); | |||
} | |||
} | |||
class _MineDetailContainer extends StatefulWidget { | |||
@override | |||
_MineDetailContainerState createState() => _MineDetailContainerState(); | |||
} | |||
class _MineDetailContainerState extends State<_MineDetailContainer> { | |||
MineDetailBloc _bloc; | |||
TextEditingController _nickController = TextEditingController(); | |||
@override | |||
void initState() { | |||
_bloc = BlocProvider.of<MineDetailBloc>(context); | |||
_bloc.loadData(); | |||
super.initState(); | |||
} | |||
@override | |||
Widget build(BuildContext context) { | |||
return StreamBuilder<MineDetailModel>( | |||
stream: _bloc.outData, | |||
builder: (BuildContext context, AsyncSnapshot snapshot) { | |||
MineDetailModel user = snapshot.data; | |||
int birthday = int.tryParse(user?.birthday) ?? 0; | |||
int registTime = int.tryParse(user?.registerTime) ?? 0; | |||
_nickController.text = user?.nickname ?? ''; | |||
return SingleChildScrollView( | |||
child: Column( | |||
children: <Widget>[ | |||
_creteHeader(user, onTap: () { | |||
_selectImage(); | |||
}), | |||
_createInput('昵称', _nickController, onTap: () {}), | |||
_createLine(), | |||
_createItem('性别', user?.gender, onTap: () { | |||
_selectSex(); | |||
}), | |||
_createLine(), | |||
_createItem( | |||
'出生日期', | |||
birthday > 0 | |||
? DateFormat('yyyy-MM-dd').format( | |||
DateTime.fromMillisecondsSinceEpoch( | |||
birthday * 1000)) | |||
: user?.birthday ?? '', onTap: () { | |||
_selectBrithday(); | |||
}), | |||
_createLine(), | |||
_createItem( | |||
'注册时间', | |||
registTime > 0 | |||
? DateFormat('yyyy-MM-dd').format( | |||
DateTime.fromMillisecondsSinceEpoch( | |||
registTime * 1000)) | |||
: user?.registerTime ?? ''), | |||
], | |||
), | |||
); | |||
}); | |||
} | |||
// 头像 | |||
Widget _creteHeader(MineDetailModel user, {VoidCallback onTap}) { | |||
return GestureDetector( | |||
child: Container( | |||
height: 140, | |||
width: double.infinity, | |||
margin: EdgeInsets.only(top: 5), | |||
color: Colors.white, | |||
child: Column( | |||
children: <Widget>[ | |||
Container( | |||
width: 80, | |||
height: 80, | |||
margin: EdgeInsets.only(top: 15), | |||
decoration: BoxDecoration( | |||
borderRadius: BorderRadius.circular(40), | |||
color: Colors.black12), | |||
child: ClipRRect( | |||
borderRadius: BorderRadius.circular(40), | |||
child: CachedNetworkImage( | |||
imageUrl: user?.avatar ?? '', | |||
fit: BoxFit.cover, | |||
), | |||
), | |||
), | |||
Padding( | |||
padding: const EdgeInsets.all(6.0), | |||
child: Text( | |||
user == null ? '' : '点击更换头像', | |||
style: TextStyle(fontSize: 11, color: Color(0xff999999)), | |||
), | |||
) | |||
], | |||
), | |||
), | |||
onTap: onTap, | |||
); | |||
} | |||
Widget _createItem(String title, String desc, {VoidCallback onTap}) { | |||
return GestureDetector( | |||
child: Container( | |||
padding: EdgeInsets.only(left: 12.5, right: 12.5), | |||
height: 48, | |||
color: Colors.white, | |||
child: Row( | |||
children: <Widget>[ | |||
Expanded( | |||
child: Text( | |||
title ?? '', | |||
style: TextStyle( | |||
fontSize: 13, | |||
color: Color(0xff333333), | |||
fontWeight: FontWeight.bold), | |||
), | |||
), | |||
Text( | |||
desc ?? '', | |||
style: TextStyle( | |||
fontSize: 13, | |||
color: Color(0xff999999), | |||
), | |||
), | |||
onTap == null | |||
? Container() | |||
: Icon( | |||
Icons.arrow_forward_ios, | |||
size: 12, | |||
color: Color(0xff999999), | |||
) | |||
], | |||
), | |||
), | |||
onTap: onTap, | |||
); | |||
} | |||
Widget _createInput(String title, TextEditingController controller, | |||
{VoidCallback onTap}) { | |||
return GestureDetector( | |||
child: Container( | |||
padding: EdgeInsets.only(left: 12.5, right: 12.5), | |||
height: 48, | |||
color: Colors.white, | |||
child: Row( | |||
children: <Widget>[ | |||
Expanded( | |||
child: Text( | |||
title ?? '', | |||
style: TextStyle( | |||
fontSize: 13, | |||
color: Color(0xff333333), | |||
fontWeight: FontWeight.bold), | |||
), | |||
), | |||
Expanded( | |||
child: CupertinoTextField( | |||
decoration: BoxDecoration(color: Colors.transparent), | |||
textInputAction: TextInputAction.done, | |||
controller: controller, | |||
textAlign: TextAlign.right, | |||
placeholder: '输入昵称', | |||
style: TextStyle( | |||
fontSize: 13, | |||
color: Color(0xff999999), | |||
), | |||
onSubmitted: (value) { | |||
if (value == null || value == '') { | |||
Fluttertoast.showToast(msg: '昵称不为空'); | |||
return; | |||
} | |||
_bloc.updateUser(nickname: value); | |||
}, | |||
), | |||
), | |||
onTap == null | |||
? Container() | |||
: Icon( | |||
Icons.arrow_forward_ios, | |||
size: 12, | |||
color: Color(0xff999999), | |||
) | |||
], | |||
), | |||
), | |||
onTap: onTap, | |||
); | |||
} | |||
Widget _createLine() { | |||
return Container( | |||
width: double.infinity, | |||
height: 0.5, | |||
margin: EdgeInsets.only(left: 12.5, right: 12.5), | |||
color: Color(0xfff4f4f4), | |||
); | |||
} | |||
void _selectImage() async { | |||
final picker = ImagePicker(); | |||
PickedFile file; | |||
int index = await showModalBottomSheet( | |||
context: context, | |||
builder: (context) { | |||
return ActionSelectedAlert( | |||
// title: '拍照/选择图片', | |||
actions: ['拍照', '从相册选择图片'], | |||
); | |||
}, | |||
isScrollControlled: false, | |||
backgroundColor: Colors.transparent); | |||
if (index != null) { | |||
if (index == 0) { | |||
file = await picker.getImage(source: ImageSource.camera); | |||
} else { | |||
file = await picker.getImage(source: ImageSource.gallery); | |||
} | |||
if (file == null) return; | |||
File cropperFile = await ImageCropper.cropImage( | |||
sourcePath: file.path, | |||
aspectRatioPresets: [ | |||
CropAspectRatioPreset.square, | |||
], | |||
androidUiSettings: AndroidUiSettings( | |||
toolbarTitle: '图片剪裁', | |||
toolbarColor: HexColor.fromHex('#E52425'), | |||
toolbarWidgetColor: Colors.white, | |||
initAspectRatio: CropAspectRatioPreset.original, | |||
lockAspectRatio: true), | |||
iosUiSettings: IOSUiSettings( | |||
minimumAspectRatio: 1.0, aspectRatioLockEnabled: true)); | |||
File resultFile = await EncodeUtil.compressImage(cropperFile, 800); | |||
_bloc.uploadAvatar(resultFile); | |||
} | |||
} | |||
// 选择性别 | |||
void _selectSex() async { | |||
int index = await showModalBottomSheet( | |||
context: context, | |||
builder: (context) { | |||
return ActionListAlert( | |||
title: '选择性别', | |||
actions: ['女', '男'], | |||
); | |||
}, | |||
isScrollControlled: false, | |||
backgroundColor: Colors.transparent); | |||
if (index != null) { | |||
print(index); | |||
_bloc.updateUser(gender: index == 0 ? '1' : '2'); | |||
} | |||
} | |||
void _selectBrithday() async { | |||
DateTime dateTime = await showModalBottomSheet( | |||
context: context, | |||
builder: (context) { | |||
return ActionDateAlert( | |||
title: '选择出生日期', | |||
); | |||
}, | |||
isScrollControlled: false, | |||
backgroundColor: Colors.transparent); | |||
if (dateTime != null) { | |||
String timeStamp = | |||
(dateTime.millisecondsSinceEpoch / 1000).ceil().toString(); | |||
_bloc.updateUser(birthday: timeStamp); | |||
} | |||
} | |||
} |
@@ -0,0 +1,34 @@ | |||
import 'package:json_annotation/json_annotation.dart'; | |||
part 'mine_detail_model.g.dart'; | |||
@JsonSerializable() | |||
class MineDetailModel extends Object { | |||
@JsonKey(name: 'avatar') | |||
String avatar; | |||
@JsonKey(name: 'nickname') | |||
String nickname; | |||
@JsonKey(name: 'gender') | |||
String gender; | |||
@JsonKey(name: 'birthday') | |||
String birthday; | |||
@JsonKey(name: 'register_time') | |||
String registerTime; | |||
MineDetailModel( | |||
this.avatar, | |||
this.nickname, | |||
this.gender, | |||
this.birthday, | |||
this.registerTime, | |||
); | |||
factory MineDetailModel.fromJson(Map<String, dynamic> srcJson) => | |||
_$MineDetailModelFromJson(srcJson); | |||
Map<String, dynamic> toJson() => _$MineDetailModelToJson(this); | |||
} |
@@ -0,0 +1,26 @@ | |||
// GENERATED CODE - DO NOT MODIFY BY HAND | |||
part of 'mine_detail_model.dart'; | |||
// ************************************************************************** | |||
// JsonSerializableGenerator | |||
// ************************************************************************** | |||
MineDetailModel _$MineDetailModelFromJson(Map<String, dynamic> json) { | |||
return MineDetailModel( | |||
json['avatar'] as String, | |||
json['nickname'] as String, | |||
json['gender'] as String, | |||
json['birthday'] as String, | |||
json['register_time'] as String, | |||
); | |||
} | |||
Map<String, dynamic> _$MineDetailModelToJson(MineDetailModel instance) => | |||
<String, dynamic>{ | |||
'avatar': instance.avatar, | |||
'nickname': instance.nickname, | |||
'gender': instance.gender, | |||
'birthday': instance.birthday, | |||
'register_time': instance.registerTime, | |||
}; |
@@ -1,5 +1,6 @@ | |||
import 'package:zhiying_base_widget/pages/home_page/home_page.dart'; | |||
import 'package:zhiying_base_widget/pages/main_page/main_page.dart'; | |||
import 'package:zhiying_base_widget/pages/mine_detail_page/mine_detail_page.dart'; | |||
import 'package:zhiying_base_widget/pages/wallet_page/wallet_page.dart'; | |||
import 'package:zhiying_base_widget/widgets/home/home_banner/home_banner_creater.dart'; | |||
import 'package:zhiying_base_widget/widgets/home/home_banner/home_banner_widget.dart'; | |||
@@ -35,6 +36,9 @@ class BaseWidgetRegister { | |||
// PageFactory.regist('login_quick', (model) => LoginQuickPage(model)); | |||
// PageFactory.regist('login_account', (model) => LoginAccountPage(model)); | |||
// PageFactory.regist('login_invite', (model) => LoginInvitePage()); | |||
PageFactory.regist( | |||
'pub.flutter.profile_settings', (model) => MineDetailPage()); | |||
} | |||
// 注册控件 | |||
@@ -12,11 +12,10 @@ class MineDataWidget extends StatelessWidget { | |||
Map<String, dynamic> _json; | |||
MineDataModel _style; | |||
MineDataWidget( | |||
this.profile, | |||
this.data, { | |||
Key key, | |||
}) : super(key: key) { | |||
MineDataWidget(this.profile, | |||
this.data, { | |||
Key key, | |||
}) : super(key: key) { | |||
String d = data['data']; | |||
_json = convert.jsonDecode(d); | |||
_style = MineDataModel.fromJson(Map<String, dynamic>.from(_json)); | |||
@@ -87,7 +86,11 @@ class MineDataWidget extends StatelessWidget { | |||
fontWeight: FontWeight.w800, | |||
color: HexColor.fromHex( | |||
_style.accumulatedEarningsNameColor), | |||
fontFamily: 'Din', | |||
fontFamily: 'Din-Bold' | |||
'' | |||
'' | |||
'' | |||
'', | |||
package: 'zhiying_base_widget', | |||
), | |||
), | |||
@@ -218,7 +221,7 @@ class MineDataWidget extends StatelessWidget { | |||
style: TextStyle( | |||
fontSize: 18, | |||
color: HexColor.fromHex(_style.gridViewValueColor), | |||
fontFamily: 'Din', | |||
fontFamily: 'Din-Bold', | |||
package: 'zhiying_base_widget'), | |||
), | |||
), | |||
@@ -250,7 +253,7 @@ class MineDataWidget extends StatelessWidget { | |||
style: TextStyle( | |||
fontSize: 12, | |||
color: HexColor.fromHex(_style.gridViewValueColor), | |||
fontFamily: 'Din', | |||
fontFamily: 'Din-Bold', | |||
package: 'zhiying_base_widget'), | |||
), | |||
), | |||
@@ -28,6 +28,16 @@ class _MineHeaderState extends State<MineHeader> { | |||
@override | |||
Widget build(BuildContext context) { | |||
// return Consumer<UserInfoNotifier>(builder: (context, user, child) { | |||
// print('user ${user.toString()}'); | |||
// if (user == null) { | |||
// return MineStaticContainer(widget.data); | |||
// } | |||
// return BlocProvider<MineHeaderBloc>( | |||
// bloc: MineHeaderBloc(), | |||
// child: MineHeaderContainer(widget.data), | |||
// ); | |||
// }); | |||
if (_isSketelon) { | |||
Provider.of<UserInfoNotifier>(context).getUserInfoModel().then((user) { | |||
setState(() { | |||
@@ -0,0 +1,107 @@ | |||
import 'package:flutter/cupertino.dart'; | |||
import 'package:flutter/material.dart'; | |||
import 'package:flutter_cupertino_date_picker/flutter_cupertino_date_picker.dart'; | |||
import 'package:zhiying_comm/zhiying_comm.dart'; | |||
class ActionDateAlert extends StatefulWidget { | |||
final String title; | |||
final TextStyle normalStyle; | |||
final TextStyle selectedStyle; | |||
const ActionDateAlert({ | |||
Key key, | |||
this.title, | |||
this.normalStyle, | |||
this.selectedStyle, | |||
}) : super(key: key); | |||
@override | |||
State<StatefulWidget> createState() => _ActionDateAlert(); | |||
} | |||
class _ActionDateAlert extends State<ActionDateAlert> { | |||
DateTime _dateTime = DateTime.now(); | |||
@override | |||
Widget build(BuildContext context) { | |||
return Scaffold( | |||
backgroundColor: Colors.transparent, | |||
body: GestureDetector( | |||
child: Column( | |||
children: <Widget>[ | |||
Expanded( | |||
child: Container(), | |||
), | |||
Container( | |||
width: double.infinity, | |||
height: 250, | |||
margin: EdgeInsets.all(0), | |||
decoration: BoxDecoration( | |||
color: Colors.white, | |||
borderRadius: BorderRadius.only( | |||
topLeft: Radius.circular(10), | |||
topRight: Radius.circular(10))), | |||
child: Column( | |||
children: <Widget>[ | |||
widget.title == null || widget.title == '' | |||
? Container() | |||
: Container( | |||
height: 44, | |||
child: Row( | |||
children: <Widget>[ | |||
FlatButton( | |||
child: Text('取消'), | |||
onPressed: () { | |||
Navigator.pop(context); | |||
}, | |||
), | |||
Expanded( | |||
child: Center( | |||
child: Text( | |||
widget.title, | |||
style: TextStyle( | |||
fontSize: 13, | |||
color: Colors.black.withAlpha(180)), | |||
), | |||
), | |||
), | |||
FlatButton( | |||
child: Text( | |||
'完成', | |||
style: TextStyle( | |||
color: HexColor.fromHex('#E52425')), | |||
), | |||
onPressed: () { | |||
Navigator.pop(context, _dateTime); | |||
}, | |||
), | |||
], | |||
)), | |||
Expanded( | |||
child: _createContent(context), | |||
) | |||
], | |||
), | |||
), | |||
], | |||
), | |||
onTap: () { | |||
Navigator.pop(context); | |||
}, | |||
), | |||
); | |||
} | |||
Widget _createContent(BuildContext context) { | |||
return DatePickerWidget( | |||
initialDateTime: _dateTime, | |||
onChange: (dataTime, list) { | |||
_dateTime = dataTime; | |||
}, | |||
pickerTheme: DateTimePickerTheme( | |||
pickerHeight: 180, | |||
title: Container(), | |||
), | |||
); | |||
} | |||
} |
@@ -0,0 +1,128 @@ | |||
import 'package:flutter/cupertino.dart'; | |||
import 'package:flutter/material.dart'; | |||
import 'package:zhiying_comm/zhiying_comm.dart'; | |||
class ActionListAlert extends StatefulWidget { | |||
final String title; | |||
final List<String> actions; | |||
final TextStyle normalStyle; | |||
final TextStyle selectedStyle; | |||
const ActionListAlert( | |||
{Key key, this.title, this.actions, this.normalStyle, this.selectedStyle}) | |||
: super(key: key); | |||
@override | |||
State<StatefulWidget> createState() => _ActionListAlert(); | |||
} | |||
class _ActionListAlert extends State<ActionListAlert> { | |||
int _currentIndex = 0; | |||
@override | |||
Widget build(BuildContext context) { | |||
return Scaffold( | |||
backgroundColor: Colors.transparent, | |||
body: GestureDetector( | |||
child: Column( | |||
children: <Widget>[ | |||
Expanded( | |||
child: Container(), | |||
), | |||
Container( | |||
width: double.infinity, | |||
height: 250, | |||
margin: EdgeInsets.all(0), | |||
decoration: BoxDecoration( | |||
color: Colors.white, | |||
borderRadius: BorderRadius.only( | |||
topLeft: Radius.circular(10), | |||
topRight: Radius.circular(10))), | |||
child: Column( | |||
children: <Widget>[ | |||
widget.title == null || widget.title == '' | |||
? Container() | |||
: Container( | |||
height: 44, | |||
child: Row( | |||
children: <Widget>[ | |||
FlatButton( | |||
child: Text('取消'), | |||
onPressed: () { | |||
Navigator.pop(context); | |||
}, | |||
), | |||
Expanded( | |||
child: Center( | |||
child: Text( | |||
widget.title, | |||
style: TextStyle( | |||
fontSize: 13, | |||
color: Colors.black.withAlpha(180)), | |||
), | |||
), | |||
), | |||
FlatButton( | |||
child: Text( | |||
'完成', | |||
style: TextStyle( | |||
color: HexColor.fromHex('#E52425')), | |||
), | |||
onPressed: () { | |||
Navigator.pop(context, _currentIndex); | |||
}, | |||
), | |||
], | |||
)), | |||
Expanded( | |||
child: _createContent(context), | |||
) | |||
], | |||
), | |||
), | |||
], | |||
), | |||
onTap: () { | |||
Navigator.pop(context); | |||
}, | |||
), | |||
); | |||
} | |||
Widget _createContent(BuildContext context) { | |||
List<Widget> widgets = List<Widget>(); | |||
TextStyle normalStyle = widget.normalStyle ?? | |||
TextStyle(fontSize: 12, color: HexColor.fromHex('#7f7f7f')); | |||
TextStyle selectedStyle = widget.selectedStyle ?? | |||
TextStyle(fontSize: 14, color: HexColor.fromHex('#E52425')); | |||
for (int index = 0; index < widget.actions.length; index++) { | |||
int i = index; | |||
widgets.add(Column( | |||
children: <Widget>[ | |||
Container( | |||
// color: HexColor.random(), | |||
height: 40, | |||
child: Center( | |||
child: Text( | |||
widget.actions[index], | |||
style: i == _currentIndex ? selectedStyle : normalStyle, | |||
), | |||
), | |||
) | |||
], | |||
)); | |||
} | |||
return CupertinoPicker( | |||
backgroundColor: Colors.white, | |||
children: widgets, | |||
itemExtent: 40, | |||
onSelectedItemChanged: (int index) { | |||
setState(() { | |||
_currentIndex = index; | |||
}); | |||
}, | |||
); | |||
} | |||
} |
@@ -0,0 +1,125 @@ | |||
import 'package:flutter/material.dart'; | |||
import 'package:zhiying_comm/zhiying_comm.dart'; | |||
class ActionSelectedAlert extends StatelessWidget { | |||
final String title; | |||
final List<String> actions; | |||
const ActionSelectedAlert({Key key, this.title, this.actions}) | |||
: super(key: key); | |||
@override | |||
Widget build(BuildContext context) { | |||
return Scaffold( | |||
backgroundColor: Colors.transparent, | |||
body: GestureDetector( | |||
child: Container( | |||
width: double.infinity, | |||
// height: double.infinity, | |||
color: Colors.transparent, | |||
child: Container( | |||
width: double.infinity, | |||
// height: double.infinity, | |||
// color: Colors.red, | |||
child: Column( | |||
children: <Widget>[ | |||
Expanded( | |||
child: Container(), | |||
), | |||
Container( | |||
width: double.infinity, | |||
margin: EdgeInsets.all(0), | |||
decoration: BoxDecoration( | |||
color: Colors.white, | |||
borderRadius: BorderRadius.only( | |||
topLeft: Radius.circular(10), | |||
topRight: Radius.circular(10))), | |||
child: Column( | |||
children: <Widget>[ | |||
title == null || title == '' | |||
? Container() | |||
: Container( | |||
height: 44, | |||
child: Center( | |||
child: Text( | |||
title, | |||
style: TextStyle( | |||
fontSize: 13, | |||
color: Colors.black.withAlpha(180)), | |||
), | |||
), | |||
), | |||
title == null || title == '' || actions.length == 0 | |||
? Container() | |||
: Container( | |||
width: double.infinity, | |||
height: 0.5, | |||
color: HexColor.fromHex('#F2F2F2'), | |||
), | |||
_createContent(context), | |||
Container( | |||
width: double.infinity, | |||
height: 4, | |||
color: HexColor.fromHex('#F2F2F2'), | |||
), | |||
SafeArea( | |||
child: Container( | |||
width: double.infinity, | |||
margin: EdgeInsets.all(0), | |||
color: Colors.white, | |||
height: 56, | |||
child: Center( | |||
child: Text( | |||
'取消', | |||
style: TextStyle( | |||
fontSize: 17, color: Colors.black), | |||
), | |||
), | |||
), | |||
), | |||
], | |||
), | |||
), | |||
], | |||
), | |||
)), | |||
onTap: () { | |||
Navigator.pop(context); | |||
}, | |||
), | |||
); | |||
} | |||
Widget _createContent(BuildContext context) { | |||
List<Widget> widgets = List<Widget>(); | |||
for (int index = 0; index < actions.length; index++) { | |||
int i = index; | |||
widgets.add(Column( | |||
children: <Widget>[ | |||
GestureDetector( | |||
child: Container( | |||
color: Colors.transparent, | |||
height: 54, | |||
child: Center( | |||
child: Text( | |||
actions[index], | |||
style: TextStyle(fontSize: 17, color: Colors.black), | |||
), | |||
), | |||
), | |||
onTap: () { | |||
print(i); | |||
Navigator.pop(context, i); | |||
}, | |||
), | |||
Container( | |||
width: double.infinity, | |||
height: 0.5, | |||
color: HexColor.fromHex('#F2F2F2'), | |||
) | |||
], | |||
)); | |||
} | |||
return Column(children: widgets); | |||
} | |||
} |
@@ -11,11 +11,16 @@ dependencies: | |||
flutter: | |||
sdk: flutter | |||
flutter_swiper : ^1.1.6 | |||
flutter_swiper: ^1.1.6 | |||
bloc: ^4.0.0 | |||
event_bus: ^1.1.1 | |||
pull_to_refresh: ^1.6.1 | |||
flutter_cupertino_date_picker: ^1.0.26+2 | |||
image_picker: ^0.6.7+3 | |||
image_cropper: | |||
git: | |||
url: 'http://192.168.0.138:3000/FnuoOS_Flutter_Components/Image_Cropper.git' | |||
ref: '1.2.3+1' | |||
dev_dependencies: | |||
flutter_test: | |||
@@ -58,10 +63,14 @@ flutter: | |||
# list giving the asset and other descriptors for the font. For | |||
# example: | |||
fonts: | |||
- family: Din | |||
- family: Din-Bold | |||
fonts: | |||
- asset: assets/fonts/DIN-Bold.otf | |||
- family: Din-Medium | |||
fonts: | |||
- asset: assets/fonts/DIN-Medium.otf | |||
- family: Din | |||
fonts: | |||
- asset: assets/fonts/DIN-Regular.otf | |||
# | |||