Hibok
25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

517 lines
16 KiB

  1. import 'dart:io';
  2. import 'dart:typed_data';
  3. import 'package:chat/data/UserData.dart';
  4. import 'package:chat/data/constants.dart';
  5. import 'package:chat/generated/i18n.dart';
  6. import 'package:chat/home/rich_title.dart';
  7. import 'package:chat/models/UserInfo.dart';
  8. import 'package:chat/models/money_change.dart';
  9. import 'package:chat/models/ref_name_provider.dart';
  10. import 'package:chat/utils/ChargeMoney.dart';
  11. import 'package:chat/utils/CustomUI.dart';
  12. import 'package:chat/utils/HttpUtil.dart';
  13. import 'package:chat/utils/MessageMgr.dart';
  14. import 'package:chat/utils/PicSwiper.dart';
  15. import 'package:chat/utils/TokenMgr.dart';
  16. import 'package:chat/utils/file_cache_mgr.dart';
  17. import 'package:chat/utils/screen.dart';
  18. import 'package:dio/dio.dart';
  19. import 'package:flutter/cupertino.dart';
  20. import 'package:flutter/material.dart';
  21. import 'package:multi_image_picker/multi_image_picker.dart';
  22. import 'package:oktoast/oktoast.dart';
  23. import 'package:provider/provider.dart';
  24. import 'VipPage.dart';
  25. const double LeftSize = 80;
  26. const MaxImgSize = 20;
  27. class PhotoPage extends StatefulWidget {
  28. @required
  29. final UserInfo userInfo;
  30. PhotoPage({Key key, this.userInfo}) : super(key: key);
  31. @override
  32. _PhotoPageState createState() => new _PhotoPageState();
  33. }
  34. class _PhotoPageState extends State<PhotoPage> {
  35. bool isMyself = false;
  36. bool isMan = false;
  37. Map imgList = {};
  38. bool isLoadingFinish = false;
  39. double imgWidth = (Screen.width - LeftSize - 60) / 3;
  40. var resultList = [];
  41. bool isBuyPicture = false;
  42. @override
  43. void initState() {
  44. super.initState();
  45. isMyself = widget.userInfo.userId == UserData().basicInfo.userId;
  46. isMan = widget.userInfo.sex == 1;
  47. isBuyPicture = (isMyself ||
  48. widget.userInfo.photoAut == 0 ||
  49. widget.userInfo.payStatus == 1);
  50. getImg();
  51. MessageMgr().on('refresh_photo', msgRefreshPhoto);
  52. }
  53. msgRefreshPhoto(data) {
  54. getImg();
  55. }
  56. void getImg() async {
  57. Map data = {
  58. "visitUserId": UserData().basicInfo.userId,
  59. "userId": widget.userInfo.userId,
  60. };
  61. data['sign'] = TokenMgr().getSign(data);
  62. Response res = await HttpUtil().post('user/personal/album', data: data);
  63. if (res == null) {
  64. return;
  65. }
  66. isLoadingFinish = true;
  67. Map resData = res.data;
  68. if (resData['code'] == 0) {
  69. imgList = {};
  70. resultList = resData['data'] ?? [];
  71. for (int i = 0; i < resultList.length; i++) {
  72. var temp = DateTime.parse(resultList[i]['CreatTime']);
  73. if (imgList[temp.year] == null) {
  74. imgList[temp.year] = {
  75. 1: [],
  76. 2: [],
  77. 3: [],
  78. 4: [],
  79. 5: [],
  80. 6: [],
  81. 7: [],
  82. 8: [],
  83. 9: [],
  84. 10: [],
  85. 11: [],
  86. 12: [],
  87. };
  88. }
  89. imgList[temp.year][temp.month].add(resultList[i]);
  90. }
  91. if (isMyself) {
  92. UserData().picNum = 0;
  93. for (int i = 0; i < resultList.length; i++) {
  94. if (resultList[i]['Status'] == 1) {
  95. UserData().picNum++;
  96. }
  97. if (resultList[i]['Status'] == 0 || resultList[i]['Status'] == 2) {
  98. UserData().haveReview = true;
  99. }
  100. }
  101. }
  102. if (mounted) {
  103. setState(() {});
  104. }
  105. }
  106. }
  107. @override
  108. Widget build(BuildContext context) {
  109. var content = Scaffold(
  110. appBar: AppBar(
  111. title: !isMyself
  112. ? Text(
  113. (isMyself
  114. ? I18n.of(context).my_album
  115. : (isMan
  116. ? I18n.of(context).his_photo
  117. : I18n.of(context).her_photo)),
  118. textScaleFactor: 1.0,
  119. style: TextStyle(
  120. color: AppColors.NewAppbarTextColor, fontSize: 20),
  121. )
  122. : Column(children: <Widget>[
  123. Text(
  124. (isMyself
  125. ? I18n.of(context).my_album
  126. : (isMan
  127. ? I18n.of(context).his_photo
  128. : I18n.of(context).her_photo)),
  129. textScaleFactor: 1.0,
  130. style: TextStyle(
  131. color: AppColors.NewAppbarTextColor, fontSize: 20),
  132. ),
  133. Text(
  134. '${resultList.length}/$MaxImgSize',
  135. style: TextStyle(fontSize: 11),
  136. )
  137. ]),
  138. leading: CustomUI.buildCustomLeading(context),
  139. titleSpacing: -10,
  140. centerTitle: true,
  141. elevation: 1),
  142. backgroundColor: Colors.white,
  143. body: SafeArea(
  144. child: SingleChildScrollView(
  145. child: Column(children: _buildBody()),
  146. )),
  147. );
  148. return CustomUI.buildPageLoading(context, content, !isLoadingFinish);
  149. }
  150. buyPhoto() {
  151. //女性用户付费,男性用户会员的话免费解锁,非会员付费解锁
  152. becomeVip() {
  153. Navigator.of(context).push(
  154. new MaterialPageRoute(
  155. builder: (context) {
  156. return VipPage();
  157. },
  158. ),
  159. );
  160. }
  161. payCallback() {
  162. if (Provider.of<MoneyChangeProvider>(context).money <
  163. widget.userInfo.price) {
  164. Navigator.of(context).pop();
  165. CustomUI.buildOneConfirm(context, I18n.of(context).balance_insufficien,
  166. I18n.of(context).recharge, () {
  167. Navigator.of(context).pop();
  168. ChargeMoney.showChargeSheet(context, () {
  169. setState(() {});
  170. });
  171. });
  172. return;
  173. }
  174. Navigator.of(context).pop();
  175. HttpUtil().buyPictures(
  176. widget.userInfo.price, widget.userInfo.userId, context, () {
  177. setState(() {
  178. isBuyPicture = true;
  179. widget.userInfo.payStatus = 1;
  180. });
  181. });
  182. }
  183. freeTime() {
  184. HttpUtil().userFreeTime(context, widget.userInfo.userId, 1, () {
  185. UserData().basicInfo.usedNum++;
  186. Navigator.of(context).pop();
  187. setState(() {
  188. isBuyPicture = true;
  189. widget.userInfo.payStatus = 1;
  190. });
  191. });
  192. }
  193. String title = I18n.of(context).unlock_user.replaceFirst(
  194. '/s1',
  195. Provider.of<RefNameProvider>(context)
  196. .getRefName(widget.userInfo.userId, widget.userInfo.nickName),
  197. );
  198. if (!UserData().isMan()) {
  199. CustomUI.buildOneConfirm(
  200. context,
  201. title,
  202. I18n.of(context)
  203. .pay_unlock
  204. .replaceFirst('/s1', widget.userInfo.price.toString()),
  205. payCallback);
  206. } else if (UserData().isVip) {
  207. if (UserData().basicInfo.freeNum < UserData().basicInfo.usedNum) {
  208. CustomUI.buildOneConfirm(
  209. context,
  210. title,
  211. I18n.of(context)
  212. .pay_unlock
  213. .replaceFirst('/s1', widget.userInfo.price.toString()),
  214. payCallback);
  215. } else {
  216. CustomUI.buildOneConfirm(
  217. context, title, I18n.of(context).unlock_choose, freeTime);
  218. }
  219. } else {
  220. CustomUI.buildTowConfirm(
  221. context,
  222. title,
  223. I18n.of(context).become_member,
  224. becomeVip,
  225. I18n.of(context)
  226. .pay_unlock
  227. .replaceFirst('/s1', widget.userInfo.price.toString()),
  228. payCallback);
  229. }
  230. }
  231. Widget _buildLockWidget() {
  232. TitleItem title;
  233. if (!isMan) {
  234. title = UserData().isVip
  235. ? TitleItem(
  236. title: I18n.of(context).unlock_user,
  237. name: Provider.of<RefNameProvider>(context)
  238. .getRefName(widget.userInfo.userId, widget.userInfo.nickName),
  239. )
  240. : TitleItem(
  241. title: I18n.of(context).free_unlock,
  242. name: widget.userInfo.price.toString() +
  243. I18n.of(context).mask_coin);
  244. } else {
  245. title = TitleItem(
  246. title: I18n.of(context).pay_unlock,
  247. name: widget.userInfo.price.toString());
  248. }
  249. return Container(
  250. height: Screen.height * 0.7,
  251. alignment: Alignment.center,
  252. child: Column(
  253. mainAxisAlignment: MainAxisAlignment.center,
  254. children: <Widget>[
  255. Image.asset(
  256. 'assets/images/lock_photo.png',
  257. width: 160,
  258. //color: Colors.grey[700],
  259. ),
  260. Container(
  261. margin: EdgeInsets.only(top: 20),
  262. alignment: Alignment.center,
  263. child: Text(
  264. isMan ? I18n.of(context).set_lock : I18n.of(context).set_lock2,
  265. textScaleFactor: 1.0,
  266. style: TextStyle(
  267. color: Colors.grey[700],
  268. fontSize: 15,
  269. fontWeight: FontWeight.bold),
  270. ),
  271. ),
  272. Container(
  273. margin: EdgeInsets.only(top: 8),
  274. alignment: Alignment.center,
  275. child: RichText(
  276. text: TextSpan(
  277. children: RichTitle.getRichText(title,
  278. titleStyle:
  279. TextStyle(color: Colors.grey[700], fontSize: 13),
  280. nameStyle: TextStyle(color: Colors.red, fontSize: 13))),
  281. ),
  282. ),
  283. InkWell(
  284. onTap: buyPhoto,
  285. child: Container(
  286. margin: EdgeInsets.only(top: 30),
  287. padding: EdgeInsets.only(top: 6, bottom: 6),
  288. width: 100,
  289. alignment: Alignment.center,
  290. decoration: Constants.ConfirmBUttonBoxDecoration,
  291. child: Text(
  292. I18n.of(context).unlock,
  293. textScaleFactor: 1.0,
  294. style: TextStyle(color: Colors.white, fontSize: 18),
  295. ),
  296. )),
  297. ],
  298. ));
  299. }
  300. List<Widget> _buildBody() {
  301. List<Widget> list = [_buildUpload()];
  302. if (imgList.length == 0 && isLoadingFinish && !isMyself) {
  303. list.add(CustomUI.buildNoData(context));
  304. return list;
  305. }
  306. if (!isBuyPicture) {
  307. list.add(_buildLockWidget());
  308. return list;
  309. }
  310. imgList.keys.forEach((k) {
  311. list.add(_buildYear(k));
  312. });
  313. return list;
  314. }
  315. //上传相册
  316. void _uploadPhoto() async {
  317. int leftLength = MaxImgSize - imgList.length;
  318. if (leftLength <= 0) {
  319. showToast(I18n.of(context)
  320. .max_upload_size
  321. .replaceFirst('/s1', MaxImgSize.toString()));
  322. return;
  323. }
  324. List<Asset> resultList = List<Asset>();
  325. resultList = await MultiImagePicker.pickImages(
  326. maxImages: leftLength > 9 ? 9 : leftLength,
  327. enableCamera: false,
  328. selectedAssets: [],
  329. cupertinoOptions: CupertinoOptions(takePhotoIcon: "chat"),
  330. materialOptions: MaterialOptions(
  331. actionBarColor: "#50A7F9",
  332. actionBarTitle: "Hibok",
  333. allViewTitle: "",
  334. useDetailsView: true,
  335. selectCircleStrokeColor: "#000000",
  336. ),
  337. );
  338. if (resultList != null && resultList.length > 0) {
  339. List<File> fileList = [];
  340. for (var i = 0; i < resultList.length; i++) {
  341. Asset photoEntity = resultList[i];
  342. print('名字:${photoEntity.name}');
  343. ByteData byteData = await photoEntity.getByteData();
  344. File file = await FileCacheMgr().writeFile(
  345. 'temp-photo-${DateTime.now().millisecondsSinceEpoch}.png',
  346. byteData.buffer.asInt8List(0));
  347. fileList.add(file);
  348. }
  349. print('文件列表${fileList.length}');
  350. Map data = {"type": 2, "userId": UserData().basicInfo.userId};
  351. data['sign'] = TokenMgr().getSign(data);
  352. data['sex'] = UserData().basicInfo.sex;
  353. data['isBurn'] = 0;
  354. Response res = await HttpUtil().uploadFiles(
  355. fileList, data, 'upload/post/postfiles', 'image',
  356. isShowLoading: true);
  357. var resData = res.data;
  358. if (resData['code'] == 0) {
  359. if (resData['data']['msg'] != '' && resData['data']['msg'] != null) {
  360. showToast(resData['data']['msg']);
  361. }
  362. if (resData['msg'].split('|').length != fileList.length) {
  363. showToast(I18n.of(context).hava_error_photo);
  364. }
  365. //MessageMgr().emit('refresh_photo');
  366. getImg();
  367. } else {
  368. showToast(resData['msg']);
  369. }
  370. }
  371. }
  372. Widget _buildUpload() {
  373. return isMyself
  374. ? Container(
  375. margin: EdgeInsets.only(top: 20),
  376. child: Row(
  377. crossAxisAlignment: CrossAxisAlignment.start,
  378. children: <Widget>[
  379. Container(
  380. alignment: Alignment.centerRight,
  381. margin: EdgeInsets.only(right: 15),
  382. width: LeftSize,
  383. child: Text(
  384. I18n.of(context).upload1,
  385. style:
  386. TextStyle(fontSize: 15, fontWeight: FontWeight.w600),
  387. )),
  388. InkWell(
  389. onTap: _uploadPhoto,
  390. child: Container(
  391. width: imgWidth,
  392. height: imgWidth,
  393. margin: EdgeInsets.all(5),
  394. decoration: BoxDecoration(
  395. color: Color(0xFFEDEDED),
  396. borderRadius: BorderRadius.circular(10)),
  397. child: Icon(
  398. IconData(0xe686, fontFamily: Constants.IconFontFamily),
  399. size: 35,
  400. color: Colors.white,
  401. ),
  402. ))
  403. ],
  404. ),
  405. )
  406. : Container();
  407. }
  408. Widget _buildYear(int year) {
  409. var list = [_buildYearTips(year)];
  410. imgList[year].keys.forEach((k) {
  411. if (imgList[year][k].length > 0) {
  412. list.add(_buildMonth(year, k));
  413. }
  414. });
  415. return Container(
  416. width: Screen.width,
  417. child: Column(
  418. crossAxisAlignment: CrossAxisAlignment.start,
  419. children: list,
  420. ));
  421. }
  422. Widget _buildYearTips(int year) {
  423. return Container(
  424. alignment: Alignment.centerRight,
  425. margin: EdgeInsets.only(right: 15, top: 20, bottom: 18),
  426. width: LeftSize,
  427. child: Text(
  428. '$year${I18n.of(context).year}',
  429. style: TextStyle(fontSize: 15, fontWeight: FontWeight.w600),
  430. ));
  431. }
  432. Widget _buildMonth(int year, int month) {
  433. if (imgList[year] == null || imgList[year][month] == null) {
  434. return Container();
  435. }
  436. List<PicSwiperItem> pisc = [];
  437. imgList[year][month].forEach((f) {
  438. pisc.add(PicSwiperItem(
  439. f['ImgUrl'],
  440. id: f['Id'],
  441. type: f['Type'],
  442. isWatch: f['IsCheck'] == 1,
  443. userId: widget.userInfo.userId,
  444. isBuy: f['PayStatus'] == 1,
  445. isCheck: f['Status'] == 0,
  446. ));
  447. });
  448. List<Widget> list = [];
  449. imgList[year][month].forEach((data) {
  450. bool isWatch = data['IsCheck'] == 1;
  451. double raduis = 10;
  452. list.add(CustomUI.buildImgCover(data['Id'], pisc, data['ImgUrl'],
  453. imgWidth, raduis, isWatch, context, data['Type'],
  454. isMyself: isMyself,
  455. payStatus: data['PayStatus'],
  456. state: isMan ? 1 : data['Status']));
  457. });
  458. return Row(
  459. crossAxisAlignment: CrossAxisAlignment.start,
  460. children: <Widget>[
  461. Container(
  462. alignment: Alignment.centerRight,
  463. margin: EdgeInsets.only(right: 15, top: 1),
  464. width: LeftSize,
  465. child: Text(
  466. '$month${I18n.of(context).month}',
  467. style: TextStyle(fontSize: 15, fontWeight: FontWeight.w600),
  468. )),
  469. Container(
  470. width: Screen.width - LeftSize - 15,
  471. child: Wrap(
  472. crossAxisAlignment: WrapCrossAlignment.start,
  473. children: list,
  474. ))
  475. ],
  476. );
  477. }
  478. @override
  479. void dispose() {
  480. super.dispose();
  481. MessageMgr().off('refresh_photo', msgRefreshPhoto);
  482. }
  483. }