UserChange.dart 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381
  1. import 'package:flutter/material.dart';
  2. import 'package:file_picker/file_picker.dart';
  3. import 'package:flutter/cupertino.dart';
  4. import 'package:flutter_screenutil/flutter_screenutil.dart';
  5. import 'package:dio/dio.dart';
  6. import 'package:intl/intl.dart';
  7. import 'package:package_info/package_info.dart';
  8. import '../styles/colors.dart';
  9. import 'dart:io';
  10. import 'dart:async';
  11. import 'dart:ui';
  12. import '../styles/totast.dart';
  13. import 'ChangeUserInfo.dart';
  14. import 'package:redux/redux.dart';
  15. import 'package:flutter_redux/flutter_redux.dart';
  16. import '../redux/AppState.dart';
  17. import '../model/UserInfo.dart';
  18. import '../net/HttpManager.dart';
  19. import '../net/Result.dart';
  20. import '../redux/UserRedux.dart';
  21. import 'package:image_cropper/image_cropper.dart';
  22. class UserChange extends StatefulWidget {
  23. @override
  24. UserChangeState createState() => UserChangeState();
  25. }
  26. class UserChangeState extends State<UserChange> {
  27. String version = '';
  28. bool receiveMsg = false;
  29. @override
  30. void initState() {
  31. super.initState();
  32. PackageInfo.fromPlatform().then((packageInfo) {
  33. setState(() {
  34. version = packageInfo.version;
  35. });
  36. });
  37. }
  38. @override
  39. Widget build(BuildContext context) {
  40. ScreenUtil.instance = ScreenUtil(width: 375, height: 667)..init(context);
  41. return StoreConnector<AppState, UserInfo>(
  42. converter: (Store store) => store.state.userInfo,
  43. builder: (context, userInfo) {
  44. return WillPopScope(
  45. key: Key('UserChangesPage'),
  46. child: Scaffold(
  47. backgroundColor: PAGE_BACKGROUND_COLOR,
  48. appBar: AppBar(
  49. backgroundColor: PRIMARY_COLOR,
  50. title: Text('系统设置'),
  51. centerTitle: true,
  52. elevation: 0,
  53. ),
  54. body: Stack(
  55. children: <Widget>[
  56. RefreshIndicator(
  57. color: PRIMARY_COLOR,
  58. backgroundColor: Colors.white,
  59. displacement: 10,
  60. onRefresh: () async {
  61. await Future.delayed(const Duration(seconds: 1));
  62. getUserInfo();
  63. },
  64. child: SizedBox.expand(
  65. child: SingleChildScrollView(
  66. physics: AlwaysScrollableScrollPhysics(),
  67. child: Column(
  68. children: <Widget>[
  69. _sectionDivier(),
  70. _section([
  71. _cell(
  72. '头像',
  73. ClipOval(
  74. child: Image.network(userInfo.icon, width: 36, height: 36),
  75. ),
  76. onTap: () {
  77. _chooseImage();
  78. },
  79. ),
  80. _cell(
  81. '昵称',
  82. userInfo.nickname,
  83. placeholder: '请填写昵称',
  84. onTap: () {
  85. Navigator.push(
  86. context, CupertinoPageRoute(builder: (context) => ChangeUserInfo(title: '昵称', val: userInfo.nickname)));
  87. },
  88. ),
  89. _cell(
  90. '性别',
  91. userInfo.sex,
  92. placeholder: '请添加性别信息',
  93. onTap: () {
  94. _chooseSex(context);
  95. },
  96. ),
  97. _cell(
  98. '生日',
  99. DateFormat('yyyy-MM-dd').format(
  100. DateTime.fromMillisecondsSinceEpoch(userInfo.birthday),
  101. ),
  102. placeholder: '选择生日',
  103. onTap: () {
  104. _chooseBirthday(context);
  105. },
  106. ),
  107. _cell('手机', userInfo.phone, showBorder: false, onTap: () {
  108. Navigator.push(context, CupertinoPageRoute(builder: (context) => ChangeUserInfo(title: '手机号', val: userInfo.phone)));
  109. })
  110. ]),
  111. ],
  112. ),
  113. ),
  114. ),
  115. ),
  116. // Positioned(
  117. // bottom: 10,
  118. // right: 15,
  119. // left: 15,
  120. // height: 48,
  121. // child: FlatButton(
  122. // textColor: Colors.white,
  123. // color: PRIMARY_COLOR,
  124. // highlightColor: Color(0xFF763434),
  125. // child: Text(
  126. // '退出登录',
  127. // style: TextStyle(fontSize: 16, fontWeight: FontWeight.w700),
  128. // ),
  129. // onPressed: () async {
  130. // Toast.show(context, '退出成功', 1500, 'success');
  131. // Navigator.push(context, MaterialPageRoute(builder: (context) => LoginFirst()));
  132. // final prefs = await SharedPreferences.getInstance();
  133. // prefs.remove('token');
  134. // JPush jpush = JPush();
  135. // jpush.deleteAlias();
  136. // // Future.delayed(const Duration(seconds: 1), () {
  137. // // StoreProvider.of<AppState>(context).dispatch(UpdateUserAction(null));
  138. // // });
  139. // }),
  140. // )
  141. ],
  142. ),
  143. ),
  144. onWillPop: () {
  145. Toast.hide();
  146. Navigator.pop(context);
  147. return Future.value(false);
  148. });
  149. });
  150. }
  151. Future<void> updateUserInfo(userInfo, value, key) async {
  152. if (Toast.preToast == null) {
  153. Toast.show(context, '加载中', -1, 'loading');
  154. }
  155. final Result res = await HttpManager.post('userInfo/update', data: {'id': userInfo.id, key: value});
  156. Toast.hide();
  157. if (res.success) {
  158. Toast.show(context, '修改成功', 1500, 'success');
  159. getUserInfo();
  160. } else {
  161. Toast.show(context, res.error, 1500, 'info');
  162. }
  163. }
  164. Future<void> getUserInfo() async {
  165. Result res = await HttpManager.get('userInfo/getUserInfo');
  166. if (res.success) {
  167. StoreProvider.of<AppState>(context).dispatch(UpdateUserAction(UserInfo.fromJson(res.data)));
  168. } else {}
  169. }
  170. Future<void> _chooseSex(BuildContext context) async {
  171. String sex = await showCupertinoModalPopup(
  172. context: context,
  173. builder: (BuildContext context) {
  174. return CupertinoActionSheet(
  175. title: Text('选择性别'),
  176. actions: <Widget>[
  177. CupertinoActionSheetAction(
  178. child: Text('男'),
  179. onPressed: () {
  180. Navigator.pop(context, '男');
  181. },
  182. ),
  183. CupertinoActionSheetAction(
  184. child: Text('女'),
  185. onPressed: () {
  186. Navigator.pop(context, '女');
  187. },
  188. )
  189. ],
  190. cancelButton: CupertinoDialogAction(
  191. child: const Text('取消'),
  192. onPressed: () {
  193. Navigator.pop(context);
  194. },
  195. ),
  196. );
  197. });
  198. if (sex != null) {
  199. updateUserInfo(StoreProvider.of<AppState>(context).state.userInfo, sex, 'sex');
  200. }
  201. }
  202. Future<void> _chooseBirthday(BuildContext context) async {
  203. UserInfo userInfo = StoreProvider.of<AppState>(context).state.userInfo;
  204. DateTime date = userInfo.birthday > 0 ? DateTime.fromMillisecondsSinceEpoch(userInfo.birthday) : DateTime.now();
  205. DateTime res = await showCupertinoModalPopup<DateTime>(
  206. context: context,
  207. builder: (BuildContext context) {
  208. return Container(
  209. height: 216,
  210. color: CupertinoColors.white,
  211. child: Column(
  212. children: <Widget>[
  213. SizedBox(
  214. height: 44,
  215. child: Stack(
  216. children: <Widget>[
  217. Positioned(
  218. left: 0,
  219. top: 0,
  220. bottom: 0,
  221. child: CupertinoButton(
  222. child: Text(
  223. '取消',
  224. style: TextStyle(color: PRIMARY_COLOR),
  225. ),
  226. onPressed: () {
  227. Navigator.of(context).pop();
  228. },
  229. ),
  230. ),
  231. Positioned(
  232. right: 0,
  233. top: 0,
  234. bottom: 0,
  235. child: CupertinoButton(
  236. child: Text(
  237. '确定',
  238. style: TextStyle(color: PRIMARY_COLOR),
  239. ),
  240. onPressed: () {
  241. Navigator.of(context).pop(date);
  242. },
  243. ),
  244. )
  245. ],
  246. ),
  247. ),
  248. Expanded(
  249. flex: 1,
  250. child: DefaultTextStyle(
  251. style: const TextStyle(
  252. color: CupertinoColors.black,
  253. fontSize: 22.0,
  254. ),
  255. child: GestureDetector(
  256. // Blocks taps from propagating to the modal sheet and popping.
  257. onTap: () {},
  258. child: SafeArea(
  259. top: false,
  260. child: CupertinoDatePicker(
  261. mode: CupertinoDatePickerMode.date,
  262. initialDateTime: date,
  263. onDateTimeChanged: (DateTime newDateTime) {
  264. date = newDateTime;
  265. },
  266. ),
  267. ),
  268. ),
  269. ),
  270. )
  271. ],
  272. ),
  273. );
  274. },
  275. );
  276. if (res != null) {
  277. updateUserInfo(userInfo, res.millisecondsSinceEpoch, 'birthday');
  278. }
  279. }
  280. Future<void> _chooseImage() async {
  281. String path = await FilePicker.getFilePath(type: FileType.IMAGE);
  282. if (path == null) {
  283. return;
  284. }
  285. File croppedFile = await ImageCropper.cropImage(
  286. sourcePath: path,
  287. ratioX: 1.0,
  288. ratioY: 1.0,
  289. maxWidth: 512,
  290. maxHeight: 512,
  291. toolbarColor: PRIMARY_COLOR,
  292. );
  293. if (croppedFile == null) {
  294. return;
  295. }
  296. Toast.show(context, '加载中', -1, 'loading');
  297. Result res = await HttpManager.post('assets/uploadFile', data: {
  298. 'file': UploadFileInfo(croppedFile, croppedFile.path),
  299. });
  300. Toast.hide();
  301. if (res.success) {
  302. updateUserInfo(StoreProvider.of<AppState>(context).state.userInfo, res.data[0], 'icon');
  303. }
  304. }
  305. Widget _sectionDivier() {
  306. return SizedBox(height: 10);
  307. }
  308. Widget _section(List<Widget> children) {
  309. return Container(
  310. color: CELL_COLOR,
  311. child: Column(
  312. children: children,
  313. ),
  314. );
  315. }
  316. Widget _cell(String title, dynamic child, {String placeholder, void Function() onTap, bool showBorder = true}) {
  317. Widget secondChild;
  318. if (child == null || (child is String && child.isEmpty)) {
  319. secondChild = Text(
  320. placeholder ?? '',
  321. style: TextStyle(color: PLACEHOLDER_COLOR, fontSize: 13),
  322. );
  323. } else if (child is String) {
  324. secondChild = Text(
  325. child ?? '',
  326. style: TextStyle(color: Colors.white, fontSize: 15),
  327. );
  328. } else {
  329. secondChild = child;
  330. }
  331. return Container(
  332. height: 60,
  333. padding: EdgeInsets.fromLTRB(15, 0, 15, 0),
  334. child: GestureDetector(
  335. onTap: onTap,
  336. child: Container(
  337. decoration: BoxDecoration(
  338. border: Border(
  339. bottom: BorderSide(
  340. color: Color(0x2E000000),
  341. width: showBorder ? 1 : 0,
  342. ),
  343. ),
  344. ),
  345. child: Row(
  346. mainAxisAlignment: MainAxisAlignment.center,
  347. children: <Widget>[
  348. Expanded(
  349. child: Text(
  350. title ?? '',
  351. style: TextStyle(color: Colors.white, fontSize: 14),
  352. ),
  353. ),
  354. secondChild,
  355. Padding(
  356. padding: EdgeInsets.only(left: 2),
  357. child: Image.asset(
  358. 'images/icon_inter.png',
  359. width: 24,
  360. height: 24,
  361. ),
  362. )
  363. ],
  364. ),
  365. ),
  366. ),
  367. );
  368. }
  369. }