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.
 
 
 
 
 
 

485 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('temp-photo-${DateTime.now().millisecondsSinceEpoch}-${photoEntity.name}', byteData.buffer.asInt8List(0));
  186. fileList.add(file);
  187. }
  188. Map data = {"type": 3, "userId": UserData().basicInfo.userId};
  189. data['sign'] = TokenMgr().getSign(data);
  190. Response res = await HttpUtil().uploadFiles(
  191. fileList, data, 'upload/post/postfiles', 'image',
  192. isShowLoading: true);
  193. var resData = res.data;
  194. if (resData['code'] == 0 && resData['msg'] != null) {
  195. imgUrlList.addAll(resData['msg'].split("|"));
  196. setState(() {});
  197. }
  198. }
  199. // var photos = await PhotoPicker.pickAsset(
  200. // context: context,
  201. // themeColor: Color(0xFFF0F0F0),
  202. // maxSelected: MaxImgNum - imgUrlList.length,
  203. // textColor: Color(0xFF3F3F3F),
  204. // pickType: PickType.onlyImage);
  205. //
  206. // if (photos != null && photos.length > 0) {
  207. // List<File> fileList = [];
  208. // for (var i = 0; i < photos.length; i++) {
  209. // AssetEntity photoEntity = photos[i];
  210. // fileList.add(await photoEntity.file);
  211. // }
  212. // Map data = {"type": 3, "userId": UserData().basicInfo.userId};
  213. // data['sign'] = TokenMgr().getSign(data);
  214. // Response res = await HttpUtil().uploadFiles(
  215. // fileList, data, 'upload/post/postfiles', 'image',
  216. // isShowLoading: true);
  217. // var resData = res.data;
  218. // if (resData['code'] == 0 && resData['msg'] != null) {
  219. // imgUrlList.addAll(resData['msg'].split("|"));
  220. // setState(() {});
  221. // }
  222. // }
  223. }
  224. Widget _buildRadioButtom(str, radio, callback) {
  225. Widget left = Text(
  226. str,
  227. textScaleFactor: 1.0,
  228. style: TextStyle(fontSize: 14),
  229. );
  230. Widget right = new Expanded(
  231. child: new Align(
  232. alignment: Alignment.centerRight,
  233. child: radio,
  234. ));
  235. return InkWell(
  236. onTap: () {
  237. callback();
  238. },
  239. child: Container(
  240. padding: EdgeInsets.only(left: 15),
  241. child: new Row(
  242. children: <Widget>[left, right],
  243. ),
  244. ),
  245. );
  246. }
  247. //个人详情
  248. Widget _userDetail() {
  249. Widget tip =
  250. CustomUI.buildTopTip(15, I18n.of(context).report_reason, fontSize: 16);
  251. Widget radio1 = new Radio(
  252. value: reason.advertising.index,
  253. groupValue: _socialType, //当value和groupValue一致的时候则选中
  254. onChanged: (T) {
  255. setState(() {
  256. _socialType = T;
  257. });
  258. });
  259. Widget radio2 = new Radio(
  260. value: reason.rail.index,
  261. groupValue: _socialType, //当value和groupValue一致的时候则选中
  262. onChanged: (T) {
  263. setState(() {
  264. _socialType = T;
  265. });
  266. });
  267. Widget radio3 = new Radio(
  268. value: reason.breakAppointment.index,
  269. groupValue: _socialType, //当value和groupValue一致的时候则选中
  270. onChanged: (T) {
  271. setState(() {
  272. _socialType = T;
  273. });
  274. });
  275. Widget radio4 = new Radio(
  276. value: reason.sex.index,
  277. groupValue: _socialType, //当value和groupValue一致的时候则选中
  278. onChanged: (T) {
  279. setState(() {
  280. _socialType = T;
  281. });
  282. });
  283. Widget radio5 = new Radio(
  284. value: reason.liar.index,
  285. groupValue: _socialType, //当value和groupValue一致的时候则选中
  286. onChanged: (T) {
  287. setState(() {
  288. _socialType = T;
  289. });
  290. });
  291. List<Widget> basicList = [
  292. _buildRadioButtom(I18n.of(context).advertise, radio1, () {
  293. setState(() {
  294. _socialType = reason.advertising.index;
  295. });
  296. }),
  297. _buildDivider(),
  298. _buildRadioButtom(I18n.of(context).harassment, radio2, () {
  299. setState(() {
  300. _socialType = reason.rail.index;
  301. });
  302. }),
  303. _buildDivider(),
  304. _buildRadioButtom(I18n.of(context).false_photo, radio3, () {
  305. setState(() {
  306. _socialType = reason.breakAppointment.index;
  307. });
  308. }),
  309. _buildDivider(),
  310. _buildRadioButtom(I18n.of(context).erotic_vulgarity, radio4, () {
  311. setState(() {
  312. _socialType = reason.sex.index;
  313. });
  314. }),
  315. _buildDivider(),
  316. _buildRadioButtom(
  317. widget.isMan ? I18n.of(context).he_liar : I18n.of(context).she_liar,
  318. radio5, () {
  319. setState(() {
  320. _socialType = reason.liar.index;
  321. });
  322. }),
  323. ];
  324. var socialCard = new Container(
  325. decoration: _getCardDecoration(),
  326. width: MediaQuery.of(context).size.width,
  327. child: new Column(
  328. children: basicList,
  329. ),
  330. );
  331. return new Column(
  332. children: <Widget>[tip, socialCard],
  333. );
  334. }
  335. Widget _buildMoreInfo() {
  336. Widget tip = CustomUI.buildTopTip(15, I18n.of(context).provide_screenshots,
  337. fontSize: 15);
  338. Widget upButton = Container(
  339. child: InkWell(
  340. onTap: _sendPicture,
  341. child: Container(
  342. margin: EdgeInsets.only(left: 5, right: 5, top: 5, bottom: 5),
  343. decoration: BoxDecoration(
  344. borderRadius: BorderRadius.circular(10.0),
  345. border: Border.all(color: Colors.grey)),
  346. width: 75,
  347. height: 75,
  348. child: ClipRRect(
  349. borderRadius: BorderRadius.circular(10),
  350. child: Icon(
  351. IconData(
  352. 0xe616,
  353. fontFamily: 'iconfont',
  354. ),
  355. color: Colors.grey,
  356. ),
  357. ))));
  358. List<Widget> list = imgUrlList.map((f) {
  359. return _buildImg(f);
  360. }).toList();
  361. if (list.length < MaxImgNum) {
  362. list.add(upButton);
  363. }
  364. var socialCard = new Container(
  365. width: MediaQuery.of(context).size.width,
  366. decoration: _getCardDecoration(),
  367. padding: EdgeInsets.only(bottom: 10),
  368. child: Column(
  369. crossAxisAlignment: CrossAxisAlignment.start,
  370. children: <Widget>[
  371. Padding(
  372. padding: EdgeInsets.only(left: 10, top: 10, bottom: 10),
  373. child: Wrap(
  374. crossAxisAlignment: WrapCrossAlignment.start,
  375. children: list)),
  376. _buildDivider(),
  377. Container(
  378. margin: EdgeInsets.only(top: 10, left: 14),
  379. child: fixedText(I18n.of(context).describe_details)),
  380. Container(
  381. padding: EdgeInsets.only(top: 2, left: 8, right: 14),
  382. child: TextField(
  383. keyboardAppearance: Brightness.light,
  384. style: TextStyle(textBaseline: TextBaseline.alphabetic),
  385. decoration: new InputDecoration(
  386. hintText: I18n.of(context).optional,
  387. hintStyle: TextStyle(fontSize: 14),
  388. border: InputBorder.none,
  389. ),
  390. maxLines: 5,
  391. maxLength: 200,
  392. onChanged: (str) {
  393. explain = str;
  394. },
  395. ),
  396. ),
  397. ],
  398. ),
  399. );
  400. return new Column(
  401. children: <Widget>[tip, socialCard],
  402. );
  403. }
  404. Widget _buildImg(f) {
  405. return Stack(
  406. children: <Widget>[
  407. InkWell(
  408. onTap: () {
  409. Navigator.of(context).push(
  410. new MaterialPageRoute(
  411. builder: (context) {
  412. return PicSwiper(
  413. id: imgUrlList.indexOf(f),
  414. pics: imgUrlList
  415. .map((f) => PicSwiperItem(
  416. f,
  417. id: imgUrlList.indexOf(f),
  418. ))
  419. .toList(),
  420. );
  421. },
  422. ),
  423. );
  424. },
  425. child: Container(
  426. height: 75,
  427. width: 75,
  428. margin: EdgeInsets.only(left: 5, right: 5, top: 5, bottom: 5),
  429. decoration:
  430. BoxDecoration(borderRadius: BorderRadius.circular(2.0)),
  431. child: ClipRRect(
  432. borderRadius: BorderRadius.circular(10),
  433. child: f == null
  434. ? Container()
  435. : CachedNetworkImage(
  436. imageUrl: f,
  437. fit: BoxFit.cover,
  438. ),
  439. ))),
  440. Positioned(
  441. right: 0,
  442. child: InkWell(
  443. onTap: () {
  444. imgUrlList.remove(f);
  445. setState(() {});
  446. },
  447. child: Image.asset(
  448. 'assets/images/login/delete.png',
  449. height: 20,
  450. )),
  451. )
  452. ],
  453. );
  454. }
  455. }