Hibok
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 
 
 

446 行
13 KiB

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