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.
 
 
 
 
 
 

585 line
19 KiB

  1. import 'package:cached_network_image/cached_network_image.dart';
  2. import 'package:chat/data/constants.dart';
  3. import 'package:chat/generated/i18n.dart';
  4. import 'package:chat/home/InformUser.dart';
  5. import 'package:chat/models/ref_name_provider.dart';
  6. import 'package:chat/utils/CustomUI.dart';
  7. import 'package:chat/utils/MessageBox.dart';
  8. import 'package:chat/utils/MessageMgr.dart';
  9. import 'package:chat/utils/PicSwiper.dart';
  10. import 'package:chat/utils/app_navigator.dart';
  11. import 'package:chat/utils/msgHandler.dart';
  12. import 'package:flutter/material.dart';
  13. import 'package:oktoast/oktoast.dart';
  14. import 'package:provider/provider.dart';
  15. import '../utils/HttpUtil.dart';
  16. import 'package:dio/dio.dart';
  17. import "../data/UserData.dart";
  18. import '../utils/TokenMgr.dart';
  19. class ProgramDetailPage extends StatefulWidget {
  20. @required
  21. final int programId;
  22. ProgramDetailPage({Key key, this.programId}) : super(key: key);
  23. @override
  24. _ProgramDetailPageState createState() => new _ProgramDetailPageState();
  25. }
  26. class _ProgramDetailPageState extends State<ProgramDetailPage> {
  27. GlobalKey<ScaffoldState> registKey = new GlobalKey();
  28. List fabulousList = [];
  29. bool isMyself = false;
  30. List evaluateList = [];
  31. List enrollList = [];
  32. bool showAllContent = false;
  33. bool isMan = false;
  34. bool isProgram = false;
  35. Map programInfo = {};
  36. bool isLoadingFish = false;
  37. bool isNonContent = false;
  38. bool isJoin = false;
  39. msgRefresh(data) {
  40. getData();
  41. }
  42. msgUpdateDy(data) {
  43. setState(() {
  44. isNonContent = data;
  45. });
  46. }
  47. @override
  48. void initState() {
  49. super.initState();
  50. MessageMgr().on('delete_program', msgDeleteProgram);
  51. MessageMgr().on('update_dy', msgUpdateDy);
  52. MessageMgr().on('refresh_list', msgRefreshList);
  53. getData();
  54. }
  55. msgRefreshList(data) {
  56. getData();
  57. }
  58. msgDeleteProgram(data) {
  59. Navigator.of(context).pop();
  60. }
  61. Future getData() async {
  62. Map data = {
  63. "userId": UserData().basicInfo.userId,
  64. "id": widget.programId,
  65. };
  66. data['sign'] = TokenMgr().getSign(data);
  67. Response res = await HttpUtil().post('station/evaluate/detail',
  68. data: data, failback: () => Navigator.of(context).pop());
  69. var resData = res.data;
  70. print(resData);
  71. if (resData['code'] == 0) {
  72. if (resData['data']['FabulousList'] != null)
  73. fabulousList = resData['data']['FabulousList'];
  74. if (resData['data']['EvaluateList'] != null) {
  75. evaluateList = resData['data']['EvaluateList'];
  76. }
  77. enrollList = resData['data']['EnrollList'];
  78. isMyself = resData['data']['UserId'] == UserData().basicInfo.userId;
  79. isMan = resData['data']['Sex'] == 1;
  80. isProgram = resData['data']['Type'] == 0;
  81. programInfo = resData['data'];
  82. programInfo['Id'] = widget.programId;
  83. isNonContent = resData['data']['EvaluateStatus'] == 1;
  84. isJoin = resData['data']['IsEnroll'] == 1;
  85. isLoadingFish = true;
  86. setState(() {});
  87. } else {
  88. showToast(resData['msg']);
  89. }
  90. }
  91. @override
  92. Widget build(BuildContext context) {
  93. Widget appBar = new AppBar(
  94. backgroundColor: AppColors.NewAppbarBgColor,
  95. title: new Text(
  96. isProgram
  97. ? I18n.of(context).program_details
  98. : I18n.of(context).dynamic_details,
  99. textScaleFactor: 1.0,
  100. style: TextStyle(color: AppColors.NewAppbarTextColor),
  101. ),
  102. leading: CustomUI.buildCustomLeading(context),
  103. centerTitle: true,
  104. );
  105. var content = new Scaffold(
  106. key: registKey,
  107. appBar: appBar,
  108. backgroundColor: Colors.white,
  109. body: SafeArea(
  110. child: Center(
  111. child: Container(
  112. height: MediaQuery.of(context).size.height,
  113. width: MediaQuery.of(context).size.width,
  114. child: _buildBody(),
  115. ),
  116. ),
  117. ));
  118. return CustomUI.buildPageLoading(context, content, !isLoadingFish);
  119. }
  120. Widget _buildBottomSheetItem(str, height, callback) {
  121. return InkWell(
  122. child: Container(
  123. height: height,
  124. decoration:
  125. BoxDecoration(border: Border(bottom: Constants.GreyBorderSide)),
  126. alignment: Alignment.center,
  127. child: Text(
  128. str,
  129. textScaleFactor: 1.0,
  130. style: TextStyle(fontSize: 18, color: Constants.BlackTextColor),
  131. ),
  132. ),
  133. onTap: callback,
  134. );
  135. }
  136. Widget _buildReply(data) {
  137. const TextColor = Constants.BlackTextColor;
  138. const BlueColor = Constants.GreyTextColor;
  139. bool isWriter =
  140. programInfo['UserId'] == UserData().basicInfo.userId; //是否发布者
  141. bool isReplyer = data['UserId'] == UserData().basicInfo.userId; //是否评论者
  142. replay() {
  143. Navigator.of(context).pop();
  144. CustomUI.showContentDialog(
  145. registKey.currentContext, programInfo['Id'], data['Pid'], 1, (data) {
  146. programInfo['EvaluateNum']++;
  147. evaluateList.add(data);
  148. setState(() {});
  149. },
  150. replyUserId: data['UserId'],
  151. replyUserName: Provider.of<RefNameProvider>(context)
  152. .getRefName(data['UserId'], data['NickName']),
  153. isMyself: isMyself);
  154. }
  155. inform() async {
  156. var resdata = {
  157. "reportuserId": UserData().basicInfo.userId,
  158. "userid": data['UserId'],
  159. };
  160. resdata['sign'] = TokenMgr().getSign(resdata);
  161. resdata['type'] = 4;
  162. resdata['objectId'] = data['Pid'];
  163. resdata['reason'] = 0;
  164. resdata["imgurl"] = '';
  165. resdata["explain"] = '';
  166. Response res = await HttpUtil().post('report/user/insert', data: resdata);
  167. Map resData = res.data;
  168. showToast(resData['msg']);
  169. if (resData['code'] == 0) {
  170. Navigator.of(context).pop();
  171. }
  172. }
  173. delete() async {
  174. var resdata = {
  175. "userId": UserData().basicInfo.userId,
  176. "pId": data['Pid'],
  177. };
  178. resdata['sign'] = TokenMgr().getSign(resdata);
  179. Response res = await HttpUtil()
  180. .post('station/delete/evaluate', data: resdata, isShowLoading: true);
  181. Map resData = res.data;
  182. if (resData['code'] == 0) {
  183. Navigator.of(context).pop();
  184. programInfo['EvaluateNum']--;
  185. getData();
  186. }
  187. }
  188. double fontSize = 13.5;
  189. //1.不是发布者
  190. //1.1是评论者则没有选项
  191. //1.2不是评论者则有回复和举报
  192. //2.是发布者
  193. //2.1是评论者则有删除
  194. //2.2不是评论者则有删除,回复和举报
  195. return InkWell(
  196. onTap: !isWriter && isReplyer
  197. ? null
  198. : () {
  199. double height = 50.0;
  200. List<Widget> list = [];
  201. if (!isWriter && !isReplyer)
  202. list = [
  203. _buildBottomSheetItem(
  204. I18n.of(context).reply, height, replay),
  205. _buildBottomSheetItem(
  206. I18n.of(context).report, height, inform),
  207. ];
  208. if (isWriter && isReplyer)
  209. list = [
  210. _buildBottomSheetItem(
  211. I18n.of(context).delete, height, delete),
  212. ];
  213. if (isWriter && !isReplyer)
  214. list = [
  215. _buildBottomSheetItem(
  216. I18n.of(context).delete, height, delete),
  217. _buildBottomSheetItem(
  218. I18n.of(context).reply, height, replay),
  219. _buildBottomSheetItem(
  220. I18n.of(context).report, height, inform),
  221. ];
  222. //回复不能回复自己 ,只有发布者才能删除评论
  223. showModalBottomSheet(
  224. context: registKey.currentContext,
  225. builder: (BuildContext context) {
  226. return new Container(
  227. height: height * list.length,
  228. child: Column(
  229. children: list,
  230. ),
  231. );
  232. },
  233. ).then((val) {});
  234. },
  235. child: Container(
  236. padding: EdgeInsets.only(bottom: 3),
  237. child: RichText(
  238. text: TextSpan(
  239. children: data['ReplyUserId'] == 0
  240. ? [
  241. TextSpan(
  242. text: Provider.of<RefNameProvider>(context)
  243. .getRefName(data['UserId'], data['NickName']),
  244. style: TextStyle(
  245. fontSize: fontSize,
  246. textBaseline: TextBaseline.alphabetic,
  247. color: BlueColor,
  248. fontWeight: FontWeight.w500),
  249. ),
  250. TextSpan(
  251. text: ': ${data['Content']}',
  252. style: TextStyle(
  253. color: TextColor,
  254. textBaseline: TextBaseline.alphabetic,
  255. fontSize: fontSize),
  256. )
  257. ]
  258. : [
  259. TextSpan(
  260. text: Provider.of<RefNameProvider>(context)
  261. .getRefName(data['UserId'], data['NickName']),
  262. style: TextStyle(
  263. fontSize: fontSize,
  264. textBaseline: TextBaseline.alphabetic,
  265. color: BlueColor,
  266. fontWeight: FontWeight.w500),
  267. ),
  268. TextSpan(
  269. text: ' ${I18n.of(context).reply} ',
  270. style: TextStyle(
  271. fontSize: fontSize,
  272. textBaseline: TextBaseline.alphabetic,
  273. color: TextColor,
  274. fontWeight: FontWeight.w500),
  275. ),
  276. TextSpan(
  277. text: data['ReplyNickName'],
  278. style: TextStyle(
  279. fontSize: fontSize,
  280. textBaseline: TextBaseline.alphabetic,
  281. color: BlueColor,
  282. fontWeight: FontWeight.w500),
  283. ),
  284. TextSpan(
  285. text: ': ${data['Content']}',
  286. style: TextStyle(
  287. color: TextColor,
  288. textBaseline: TextBaseline.alphabetic,
  289. fontSize: fontSize),
  290. )
  291. ]),
  292. ),
  293. ));
  294. }
  295. Widget _buildJoinItem(data) {
  296. Widget basicInfo = Row(children: <Widget>[
  297. Padding(
  298. padding: EdgeInsets.only(left: 10, right: 5),
  299. child: Stack(
  300. children: <Widget>[
  301. Padding(
  302. padding: EdgeInsets.only(right: 10),
  303. child: ClipRRect(
  304. borderRadius: BorderRadius.circular(6.0),
  305. child: CachedNetworkImage(
  306. height: 45,
  307. width: 45,
  308. imageUrl:
  309. data['Headimgurl'] == null ? "" : data['Headimgurl'],
  310. placeholder: CustomUI.buildImgLoding,
  311. fit: BoxFit.cover,
  312. ),
  313. ),
  314. ),
  315. Positioned(
  316. right: 5,
  317. bottom: 0,
  318. child: Container(
  319. padding: EdgeInsets.only(bottom: 1.3, left: 0.5),
  320. decoration: BoxDecoration(
  321. color: Colors.white,
  322. borderRadius: BorderRadius.all(Radius.circular(20))),
  323. child: Icon(
  324. IconData(
  325. !isMan ? 0xe639 : 0xe638,
  326. fontFamily: 'iconfont',
  327. ),
  328. color: !isMan
  329. ? const Color(0xff0072ff)
  330. : const Color(0xffff0486),
  331. size: 12,
  332. ),
  333. ))
  334. ],
  335. )),
  336. Expanded(
  337. child: Column(
  338. crossAxisAlignment: CrossAxisAlignment.start,
  339. children: <Widget>[
  340. Container(
  341. child: RichText(
  342. text: TextSpan(children: [
  343. TextSpan(
  344. text: Provider.of<RefNameProvider>(context)
  345. .getRefName(data['UserId'], data['NickName']),
  346. style:
  347. TextStyle(fontSize: 14, color: Constants.BlackTextColor)),
  348. TextSpan(
  349. text: I18n.of(context).signed_up.replaceFirst('/s1', ''),
  350. style:
  351. TextStyle(fontSize: 13, color: Constants.GreyTextColor)),
  352. ])),
  353. ),
  354. Text(
  355. '${data['CreateTime']}',
  356. textScaleFactor: 1.0,
  357. style: TextStyle(color: Constants.LightGreyTextColor, fontSize: 12),
  358. ),
  359. ],
  360. )),
  361. InkWell(
  362. onTap: () {
  363. Navigator.of(context).push(
  364. new MaterialPageRoute(
  365. builder: (context) {
  366. return InformUserPage(
  367. isMan: !isMan,
  368. userId: data['UserId'],
  369. );
  370. },
  371. ),
  372. );
  373. },
  374. child: Container(
  375. padding: EdgeInsets.only(left: 10, right: 10, bottom: 10),
  376. alignment: Alignment.topRight,
  377. child: Text(
  378. I18n.of(context).report,
  379. textScaleFactor: 1.0,
  380. style: TextStyle(color: Constants.BlackTextColor),
  381. )))
  382. ]);
  383. Widget img = Container(
  384. child: Row(
  385. children: <Widget>[
  386. InkWell(
  387. onTap: () {
  388. Navigator.of(context).push(
  389. new MaterialPageRoute(
  390. builder: (context) {
  391. return PicSwiper(
  392. id: 0, pics: [PicSwiperItem(data['ImgUrl'], id: 0)]);
  393. },
  394. ),
  395. );
  396. },
  397. child: Container(
  398. margin: EdgeInsets.only(top: 10, left: 60),
  399. height: 80,
  400. width: 100,
  401. decoration:
  402. BoxDecoration(borderRadius: BorderRadius.circular(2.0)),
  403. child: ClipRRect(
  404. borderRadius: BorderRadius.circular(8),
  405. child: CachedNetworkImage(
  406. imageUrl: data['ImgUrl'] == null ? "" : data['ImgUrl'],
  407. placeholder: CustomUI.buildImgLoding,
  408. fit: BoxFit.cover,
  409. ),
  410. ))),
  411. Expanded(
  412. child: Container(
  413. height: 90,
  414. alignment: Alignment.bottomRight,
  415. child: InkWell(
  416. child: Container(
  417. margin: EdgeInsets.only(right: 10),
  418. decoration: BoxDecoration(
  419. color: const Color(0xFF547CFF),
  420. borderRadius: BorderRadius.all(Radius.circular(5))),
  421. padding:
  422. EdgeInsets.only(left: 15, right: 15, top: 5, bottom: 5),
  423. child: Text(
  424. !isMan
  425. ? I18n.of(context).talk_him
  426. : I18n.of(context).contact_her,
  427. textScaleFactor: 1.0,
  428. style: TextStyle(color: Colors.white, fontSize: 13),
  429. ),
  430. ),
  431. onTap: () {
  432. int fdId = data['UserId'];
  433. int sessionId = UserData().getSessionId(fdId);
  434. MsgHandler.updateActiveSesstion(sessionId);
  435. AppNavigator.pushChatPage(context, fdId);
  436. },
  437. ),
  438. ),
  439. )
  440. ],
  441. ),
  442. );
  443. return Container(
  444. padding: EdgeInsets.only(top: 10, bottom: 10),
  445. decoration: BoxDecoration(
  446. color: Colors.grey[100],
  447. borderRadius: BorderRadius.all(Radius.circular(10))),
  448. margin: EdgeInsets.only(top: 10),
  449. width: MediaQuery.of(context).size.width * 0.95,
  450. child: Column(
  451. children: <Widget>[basicInfo, img],
  452. ));
  453. }
  454. Widget _buildJoinList() {
  455. if (enrollList == null || enrollList.length == 0) {
  456. return Container();
  457. }
  458. return isMyself
  459. ? Container(
  460. child: Column(
  461. children: enrollList.map((data) {
  462. return _buildJoinItem(data);
  463. }).toList(),
  464. ),
  465. )
  466. : Container();
  467. }
  468. Widget _buildContent() {
  469. if (evaluateList == null || evaluateList.length == 0) {
  470. return Container();
  471. }
  472. const maxNum = 2;
  473. Widget button = InkWell(
  474. highlightColor: Colors.transparent,
  475. radius: 0,
  476. onTap: () {
  477. setState(() {
  478. showAllContent = !showAllContent;
  479. });
  480. },
  481. child: Padding(
  482. padding: EdgeInsets.only(top: 5, bottom: 5),
  483. child: Row(
  484. children: <Widget>[
  485. Text(
  486. !showAllContent
  487. ? I18n.of(context).expand
  488. : I18n.of(context).collapse,
  489. textScaleFactor: 1.0,
  490. style: TextStyle(fontSize: 12, color: Colors.grey),
  491. ),
  492. Icon(
  493. !showAllContent
  494. ? Icons.keyboard_arrow_down
  495. : Icons.keyboard_arrow_up,
  496. size: 18,
  497. color: Colors.grey,
  498. )
  499. ],
  500. ),
  501. ),
  502. );
  503. List<Widget> list = [];
  504. int showNum = evaluateList.length;
  505. if (evaluateList.length >= maxNum && !showAllContent) {
  506. showNum = maxNum;
  507. }
  508. for (int i = 0; i < showNum; i++) {
  509. var data = evaluateList[i];
  510. list.add(_buildReply(data));
  511. }
  512. if (evaluateList.length > maxNum) {
  513. list.add(button);
  514. }
  515. return Container(
  516. margin: EdgeInsets.only(left: 23, top: 10, right: 8, bottom: 10),
  517. child: Column(
  518. crossAxisAlignment: CrossAxisAlignment.start,
  519. children: list,
  520. ));
  521. }
  522. Widget _buildBody() {
  523. return new ListView(
  524. children: isLoadingFish
  525. ? <Widget>[
  526. MessageBox(isDetail: true, programInfo: programInfo),
  527. // _buildBigImg(programInfo),
  528. // _buildImgList(),
  529. _buildContent(),
  530. _buildJoinList(),
  531. ]
  532. : [],
  533. );
  534. }
  535. @override
  536. void dispose() {
  537. registKey = null;
  538. MessageMgr().off('update_dy', msgUpdateDy);
  539. MessageMgr().off('delete_program', msgDeleteProgram);
  540. MessageMgr().off('refresh_list', msgRefreshList);
  541. super.dispose();
  542. }
  543. }