Hibok
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

488 lines
15 KiB

  1. import 'dart:io';
  2. import 'dart:typed_data';
  3. import 'package:cached_network_image/cached_network_image.dart';
  4. import 'package:chat/data/UserData.dart';
  5. import 'package:chat/data/WebData.dart';
  6. import 'package:chat/data/constants.dart';
  7. import 'package:chat/generated/i18n.dart';
  8. import 'package:chat/utils/CustomUI.dart';
  9. import 'package:chat/utils/HttpUtil.dart';
  10. import 'package:chat/utils/PicSwiper.dart';
  11. import 'package:chat/utils/file_cache_mgr.dart';
  12. import 'package:chat/utils/screen.dart';
  13. import 'package:dio/dio.dart';
  14. import 'package:flutter/material.dart';
  15. import 'package:multi_image_picker/multi_image_picker.dart';
  16. import 'package:oktoast/oktoast.dart';
  17. import '../data/UserData.dart';
  18. import '../utils/TokenMgr.dart';
  19. enum reason {
  20. advertising,
  21. rail,
  22. breakAppointment,
  23. sex,
  24. liar,
  25. }
  26. const int MaxImgNum = 4;
  27. class InformUserPage extends StatefulWidget {
  28. @required
  29. final userId;
  30. final programId;
  31. final isProgram;
  32. @required
  33. final bool isMan;
  34. InformUserPage(
  35. {Key key,
  36. this.userId,
  37. this.programId,
  38. this.isMan = false,
  39. this.isProgram = false})
  40. : super(key: key);
  41. _InformUserPageState createState() => _InformUserPageState();
  42. }
  43. class _InformUserPageState extends State<InformUserPage> {
  44. int _socialType = 0;
  45. bool parkHidden = false;
  46. bool distanceHidden = false;
  47. bool msgHidden = false;
  48. String explain = '';
  49. //List imgFileList = [];
  50. //上传图片地址
  51. List<String> imgUrlList = [];
  52. BoxDecoration _getCardDecoration() {
  53. return new BoxDecoration(color: Colors.white);
  54. }
  55. @override
  56. void initState() {
  57. super.initState();
  58. print('InformUserPage initState');
  59. }
  60. @override
  61. Widget build(BuildContext context) {
  62. Widget appBar = new AppBar(
  63. title: Text(
  64. I18n.of(context).anonymous_report,
  65. textScaleFactor: 1.0,
  66. ),
  67. leading: CustomUI.buildCustomLeading(context),
  68. centerTitle: true,
  69. actions: <Widget>[
  70. new Container(
  71. alignment: Alignment.center,
  72. child: new InkWell(
  73. child: new Padding(
  74. padding:
  75. EdgeInsets.only(right: 15, left: 15, top: 10, bottom: 10),
  76. child: new Text(I18n.of(context).submit,
  77. textScaleFactor: 1.0, style: Constants.AppBarActionTextStyle),
  78. ),
  79. onTap: () async {
  80. if (imgUrlList == null || imgUrlList.length == 0) {
  81. showToast(I18n.of(context).bad_evaluate);
  82. return;
  83. }
  84. var data = {
  85. "reportuserId": UserData().basicInfo.userId,
  86. "userid": widget.userId,
  87. };
  88. data['sign'] = TokenMgr().getSign(data);
  89. data['type'] =
  90. widget.programId == null ? 1 : (widget.isProgram ? 2 : 3);
  91. data['objectId'] =
  92. widget.programId == null ? 0 : widget.programId;
  93. data['reason'] = _socialType + 1;
  94. String temp = "";
  95. imgUrlList.forEach((str) {
  96. temp += (temp == ""
  97. ? WebData().deleteDemain(str)
  98. : '|${WebData().deleteDemain(str)}');
  99. });
  100. data["imgurl"] = temp;
  101. data["explain"] = explain;
  102. Response res = await HttpUtil()
  103. .post('report/user/insert', data: data, isShowLoading: true);
  104. Map resData = res.data;
  105. if (resData['code'] == 0) {
  106. CustomUI.buildOneConfirm(context,
  107. I18n.of(context).waiting_results, I18n.of(context).ok, () {
  108. Navigator.of(context).pop();
  109. Navigator.of(context).pop();
  110. }, failcallbak: () {
  111. Navigator.of(context).pop();
  112. });
  113. } else {
  114. showToast(resData['msg']);
  115. }
  116. },
  117. ),
  118. )
  119. ],
  120. );
  121. return Scaffold(
  122. body: SafeArea(
  123. child: Center(
  124. child: Container(
  125. height: MediaQuery.of(context).size.height,
  126. width: MediaQuery.of(context).size.width,
  127. child: _buildBody(),
  128. ),
  129. )),
  130. appBar: appBar,
  131. );
  132. }
  133. Widget _buildBody() {
  134. return new ListView(
  135. children: <Widget>[
  136. _userDetail(),
  137. _buildMoreInfo(),
  138. _buildTips(),
  139. ],
  140. );
  141. }
  142. Widget _buildTips() {
  143. return Container(
  144. margin: EdgeInsets.only(top: 5, left: 30, right: 30),
  145. child: Text(
  146. I18n.of(context).if_something,
  147. textScaleFactor: 1.0,
  148. style: TextStyle(fontSize: 12, color: Colors.grey[700]),
  149. textAlign: TextAlign.center,
  150. ),
  151. );
  152. }
  153. //下划线
  154. Widget _buildDivider() {
  155. return new Container(
  156. margin: EdgeInsets.zero,
  157. padding: EdgeInsets.zero,
  158. height: 1,
  159. width: MediaQuery.of(context).size.width,
  160. child: new Divider(
  161. color: Colors.grey[300],
  162. ),
  163. );
  164. }
  165. void _sendPicture() async {
  166. List<Asset> resultList = List<Asset>();
  167. resultList = await MultiImagePicker.pickImages(
  168. maxImages: MaxImgNum - imgUrlList.length,
  169. enableCamera: false,
  170. selectedAssets: [],
  171. cupertinoOptions: CupertinoOptions(takePhotoIcon: "chat"),
  172. materialOptions: MaterialOptions(
  173. actionBarColor: "#50A7F9",
  174. actionBarTitle: "Hibok",
  175. allViewTitle: "",
  176. useDetailsView: false,
  177. selectCircleStrokeColor: "#000000",
  178. ),
  179. );
  180. if (resultList != null && resultList.length > 0) {
  181. List<File> fileList = [];
  182. for (var i = 0; i < resultList.length; i++) {
  183. Asset photoEntity = resultList[i];
  184. ByteData byteData = await photoEntity.getByteData();
  185. File file = await FileCacheMgr().writeFile(
  186. 'temp-photo-${DateTime.now().millisecondsSinceEpoch}.png',
  187. byteData.buffer.asInt8List(0));
  188. fileList.add(file);
  189. }
  190. Map data = {"type": 3, "userId": UserData().basicInfo.userId};
  191. data['sign'] = TokenMgr().getSign(data);
  192. Response res = await HttpUtil().uploadFiles(
  193. fileList, data, 'upload/post/postfiles', 'image',
  194. isShowLoading: true);
  195. var resData = res.data;
  196. if (resData['code'] == 0 && resData['msg'] != null) {
  197. var returnList = resData['msg'].split('|');
  198. imgUrlList.addAll(returnList);
  199. if (returnList.length != fileList.length) {
  200. showToast(I18n.of(context).hava_error_photo);
  201. }
  202. setState(() {});
  203. }
  204. }
  205. // var photos = await PhotoPicker.pickAsset(
  206. // context: context,
  207. // themeColor: Color(0xFFF0F0F0),
  208. // maxSelected: MaxImgNum - imgUrlList.length,
  209. // textColor: Color(0xFF3F3F3F),
  210. // pickType: PickType.onlyImage);
  211. //
  212. // if (photos != null && photos.length > 0) {
  213. // List<File> fileList = [];
  214. // for (var i = 0; i < photos.length; i++) {
  215. // AssetEntity photoEntity = photos[i];
  216. // fileList.add(await photoEntity.file);
  217. // }
  218. // Map data = {"type": 3, "userId": UserData().basicInfo.userId};
  219. // data['sign'] = TokenMgr().getSign(data);
  220. // Response res = await HttpUtil().uploadFiles(
  221. // fileList, data, 'upload/post/postfiles', 'image',
  222. // isShowLoading: true);
  223. // var resData = res.data;
  224. // if (resData['code'] == 0 && resData['msg'] != null) {
  225. // imgUrlList.addAll(resData['msg'].split("|"));
  226. // setState(() {});
  227. // }
  228. // }
  229. }
  230. Widget _buildRadioButtom(str, radio, callback) {
  231. Widget left = Text(
  232. str,
  233. textScaleFactor: 1.0,
  234. style: TextStyle(fontSize: 14),
  235. );
  236. Widget right = new Expanded(
  237. child: new Align(
  238. alignment: Alignment.centerRight,
  239. child: radio,
  240. ));
  241. return InkWell(
  242. onTap: () {
  243. callback();
  244. },
  245. child: Container(
  246. padding: EdgeInsets.only(left: 15),
  247. child: new Row(
  248. children: <Widget>[left, right],
  249. ),
  250. ),
  251. );
  252. }
  253. //个人详情
  254. Widget _userDetail() {
  255. Widget tip =
  256. CustomUI.buildTopTip(15, I18n.of(context).report_reason, fontSize: 16);
  257. Widget radio1 = new Radio(
  258. value: reason.advertising.index,
  259. groupValue: _socialType, //当value和groupValue一致的时候则选中
  260. onChanged: (T) {
  261. setState(() {
  262. _socialType = T;
  263. });
  264. });
  265. Widget radio2 = new Radio(
  266. value: reason.rail.index,
  267. groupValue: _socialType, //当value和groupValue一致的时候则选中
  268. onChanged: (T) {
  269. setState(() {
  270. _socialType = T;
  271. });
  272. });
  273. Widget radio3 = new Radio(
  274. value: reason.breakAppointment.index,
  275. groupValue: _socialType, //当value和groupValue一致的时候则选中
  276. onChanged: (T) {
  277. setState(() {
  278. _socialType = T;
  279. });
  280. });
  281. Widget radio4 = new Radio(
  282. value: reason.sex.index,
  283. groupValue: _socialType, //当value和groupValue一致的时候则选中
  284. onChanged: (T) {
  285. setState(() {
  286. _socialType = T;
  287. });
  288. });
  289. Widget radio5 = new Radio(
  290. value: reason.liar.index,
  291. groupValue: _socialType, //当value和groupValue一致的时候则选中
  292. onChanged: (T) {
  293. setState(() {
  294. _socialType = T;
  295. });
  296. });
  297. List<Widget> basicList = [
  298. _buildRadioButtom(I18n.of(context).advertise, radio1, () {
  299. setState(() {
  300. _socialType = reason.advertising.index;
  301. });
  302. }),
  303. _buildDivider(),
  304. _buildRadioButtom(I18n.of(context).harassment, radio2, () {
  305. setState(() {
  306. _socialType = reason.rail.index;
  307. });
  308. }),
  309. _buildDivider(),
  310. _buildRadioButtom(I18n.of(context).false_photo, radio3, () {
  311. setState(() {
  312. _socialType = reason.breakAppointment.index;
  313. });
  314. }),
  315. _buildDivider(),
  316. _buildRadioButtom(I18n.of(context).erotic_vulgarity, radio4, () {
  317. setState(() {
  318. _socialType = reason.sex.index;
  319. });
  320. }),
  321. _buildDivider(),
  322. _buildRadioButtom(
  323. widget.isMan ? I18n.of(context).he_liar : I18n.of(context).she_liar,
  324. radio5, () {
  325. setState(() {
  326. _socialType = reason.liar.index;
  327. });
  328. }),
  329. ];
  330. var socialCard = new Container(
  331. decoration: _getCardDecoration(),
  332. width: MediaQuery.of(context).size.width,
  333. child: new Column(
  334. children: basicList,
  335. ),
  336. );
  337. return new Column(
  338. children: <Widget>[tip, socialCard],
  339. );
  340. }
  341. Widget _buildMoreInfo() {
  342. Widget tip = CustomUI.buildTopTip(15, I18n.of(context).provide_screenshots,
  343. fontSize: 15);
  344. Widget upButton = Container(
  345. child: InkWell(
  346. onTap: _sendPicture,
  347. child: Container(
  348. margin: EdgeInsets.only(left: 5, right: 5, top: 5, bottom: 5),
  349. decoration: BoxDecoration(
  350. borderRadius: BorderRadius.circular(10.0),
  351. border: Border.all(color: Colors.grey)),
  352. width: 75,
  353. height: 75,
  354. child: ClipRRect(
  355. borderRadius: BorderRadius.circular(10),
  356. child: Icon(
  357. IconData(
  358. 0xe616,
  359. fontFamily: 'iconfont',
  360. ),
  361. color: Colors.grey,
  362. ),
  363. ))));
  364. List<Widget> list = imgUrlList.map((f) {
  365. return _buildImg(f);
  366. }).toList();
  367. if (list.length < MaxImgNum) {
  368. list.add(upButton);
  369. }
  370. var socialCard = new Container(
  371. width: MediaQuery.of(context).size.width,
  372. decoration: _getCardDecoration(),
  373. padding: EdgeInsets.only(bottom: 10),
  374. child: Column(
  375. crossAxisAlignment: CrossAxisAlignment.start,
  376. children: <Widget>[
  377. Padding(
  378. padding: EdgeInsets.only(left: 10, top: 10, bottom: 10),
  379. child: Wrap(
  380. crossAxisAlignment: WrapCrossAlignment.start,
  381. children: list)),
  382. _buildDivider(),
  383. Container(
  384. margin: EdgeInsets.only(top: 10, left: 14),
  385. child: fixedText(I18n.of(context).describe_details)),
  386. Container(
  387. padding: EdgeInsets.only(top: 2, left: 8, right: 14),
  388. child: TextField(
  389. keyboardAppearance: Brightness.light,
  390. style: TextStyle(textBaseline: TextBaseline.alphabetic),
  391. decoration: new InputDecoration(
  392. hintText: I18n.of(context).optional,
  393. hintStyle: TextStyle(fontSize: 14),
  394. border: InputBorder.none,
  395. ),
  396. maxLines: 5,
  397. maxLength: 200,
  398. onChanged: (str) {
  399. explain = str;
  400. },
  401. ),
  402. ),
  403. ],
  404. ),
  405. );
  406. return new Column(
  407. children: <Widget>[tip, socialCard],
  408. );
  409. }
  410. Widget _buildImg(f) {
  411. return Stack(
  412. children: <Widget>[
  413. InkWell(
  414. onTap: () {
  415. Navigator.of(context).push(
  416. new MaterialPageRoute(
  417. builder: (context) {
  418. return PicSwiper(
  419. id: imgUrlList.indexOf(f),
  420. pics: imgUrlList
  421. .map((f) => PicSwiperItem(
  422. f,
  423. id: imgUrlList.indexOf(f),
  424. ))
  425. .toList(),
  426. );
  427. },
  428. ),
  429. );
  430. },
  431. child: Container(
  432. height: 75,
  433. width: 75,
  434. margin: EdgeInsets.only(left: 5, right: 5, top: 5, bottom: 5),
  435. decoration:
  436. BoxDecoration(borderRadius: BorderRadius.circular(2.0)),
  437. child: ClipRRect(
  438. borderRadius: BorderRadius.circular(10),
  439. child: f == null
  440. ? Container()
  441. : CachedNetworkImage(
  442. imageUrl: f,
  443. fit: BoxFit.cover,
  444. ),
  445. ))),
  446. Positioned(
  447. right: 0,
  448. child: InkWell(
  449. onTap: () {
  450. imgUrlList.remove(f);
  451. setState(() {});
  452. },
  453. child: Image.asset(
  454. 'assets/images/login/delete.png',
  455. height: 20,
  456. )),
  457. )
  458. ],
  459. );
  460. }
  461. }