question_detail.dart 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716
  1. import 'dart:math';
  2. import 'package:flustars/flustars.dart' as FlutterStars;
  3. import 'package:flutter/material.dart';
  4. import 'package:flutter_screenutil/flutter_screenutil.dart';
  5. import 'package:liftmanager/common/common.dart';
  6. import 'package:liftmanager/internal/account/account_router.dart';
  7. import 'package:liftmanager/internal/bbs/model/question_detail.dart';
  8. import 'package:liftmanager/internal/bbs/page/tab/question/question_pay.dart';
  9. import 'package:liftmanager/internal/wode/wode_router.dart';
  10. import 'package:liftmanager/net/api_service.dart';
  11. import 'package:liftmanager/res/iconfont.dart';
  12. import 'package:liftmanager/res/resources.dart';
  13. import 'package:liftmanager/routers/fluro_navigator.dart';
  14. import 'package:liftmanager/utils/fast_notification.dart';
  15. import 'package:liftmanager/utils/theme_utils.dart';
  16. import 'package:liftmanager/utils/time_format.dart';
  17. import 'package:liftmanager/utils/toast.dart';
  18. import 'package:liftmanager/utils/utils.dart';
  19. import 'package:liftmanager/widgets/app_bar.dart';
  20. import 'package:liftmanager/widgets/bbs_content.dart';
  21. import 'package:liftmanager/widgets/load_image.dart';
  22. import 'package:liftmanager/widgets/preview_images.dart';
  23. import 'package:umeng_common_sdk/umeng_common_sdk.dart';
  24. class QuestionDetail extends StatefulWidget {
  25. QuestionDetail(this.id);
  26. final String id;
  27. @override
  28. State<StatefulWidget> createState() {
  29. return QuestionDetailState();
  30. }
  31. }
  32. class QuestionDetailState extends State<QuestionDetail> {
  33. bool _hasData = false;
  34. QuestionDetailModel detailObj;
  35. List<String> listPreview = [];
  36. double vipPrice;
  37. @override
  38. void initState() {
  39. super.initState();
  40. UmengCommonSdk.onPageStart("案例详情");
  41. getQuestionDetail();
  42. getVipPrice();
  43. FastNotification.addListener("initIsPay", (initThisUserMoney) {
  44. if (mounted) {
  45. getQuestionDetail();
  46. setState(() {});
  47. }
  48. });
  49. }
  50. @override
  51. void dispose() {
  52. UmengCommonSdk.onPageEnd("案例详情");
  53. super.dispose();
  54. }
  55. Future getQuestionDetail() async {
  56. await NewApiService().getQuestionDetail(int.parse(widget.id),
  57. onSuccess: (res) {
  58. if (res != null) {
  59. _hasData = true;
  60. detailObj = res;
  61. listPreview = [];
  62. setState(() {});
  63. detailObj.imgs?.split(",")?.forEach((element) {
  64. listPreview.add(Utils.getImagePath(element, isWater: true));
  65. });
  66. }
  67. }, onError: (code, msg) {
  68. toasts(msg);
  69. });
  70. }
  71. void getVipPrice() {
  72. NewApiService().getVipFeeList('1', onSuccess: (res) {
  73. setState(() {
  74. vipPrice = res.records[0].price;
  75. });
  76. }, onError: (code, msg) {
  77. toasts(msg);
  78. });
  79. }
  80. showAlertEvent() {
  81. showAlert(
  82. context,
  83. "提示",
  84. "确定登录?",
  85. "确定",
  86. () {
  87. NavigatorUtils.push(context, AccountRouter.loginPage, clearStack: true);
  88. },
  89. txt2: "取消",
  90. onPre2: () {
  91. NavigatorUtils.goBack(context);
  92. },
  93. );
  94. }
  95. Future changeLike() async {
  96. await NewApiService().questionLike(detailObj.id, 1, onSuccess: (res) {
  97. toasts("点赞成功");
  98. getQuestionDetail();
  99. }, onError: (code, msg) {
  100. toasts(msg);
  101. });
  102. }
  103. Future changeFav() async {
  104. await NewApiService().questionFav(detailObj.id, 1, onSuccess: (res) {
  105. toasts("收藏成功");
  106. initCollect();
  107. getQuestionDetail();
  108. }, onError: (code, msg) {
  109. toasts(msg);
  110. });
  111. }
  112. Future cancelLike() async {
  113. await NewApiService().questionLikeCancel(detailObj.id, 1, onSuccess: (res) {
  114. toasts("取消点赞成功");
  115. getQuestionDetail();
  116. }, onError: (code, msg) {
  117. toasts(msg);
  118. });
  119. }
  120. Future cancelFav() async {
  121. await NewApiService().questionFavCancel(detailObj.id, 1, onSuccess: (res) {
  122. toasts("取消收藏成功");
  123. initCollect();
  124. getQuestionDetail();
  125. }, onError: (code, msg) {
  126. toasts(msg);
  127. });
  128. }
  129. initCollect() {
  130. String collectInit = randomInt(1111, 9999).toString() +
  131. DateTime.now().millisecondsSinceEpoch.toString();
  132. FastNotification.push("collectAction", collectInit);
  133. }
  134. randomInt(int min, int max) {
  135. return new Random().nextInt(max) % (max - min + 1) + min;
  136. }
  137. @override
  138. Widget build(BuildContext context) {
  139. double width = MediaQuery.of(context).size.width;
  140. _clipText({title, bgcolor, textcolor}) {
  141. return ClipRRect(
  142. borderRadius: BorderRadius.all(Radius.circular(3)),
  143. child: Container(
  144. padding: EdgeInsets.only(left: 5, right: 5, top: 2, bottom: 2),
  145. color: bgcolor,
  146. alignment: Alignment.center,
  147. // color: Color(0xFD5D61),
  148. child: Text(
  149. title,
  150. style: TextStyle(fontSize: 11, color: textcolor),
  151. ),
  152. ),
  153. );
  154. }
  155. return Scaffold(
  156. resizeToAvoidBottomPadding: false, //不让键盘弹上去
  157. appBar: MyAppBar(
  158. centerTitle: "案例详情",
  159. ),
  160. body: _hasData
  161. ? Stack(
  162. children: <Widget>[
  163. Container(
  164. child: ListView(
  165. physics: detailObj.isTip != 1
  166. ? const NeverScrollableScrollPhysics()
  167. : null,
  168. children: <Widget>[
  169. Column(
  170. mainAxisAlignment: MainAxisAlignment.start,
  171. crossAxisAlignment: CrossAxisAlignment.start,
  172. children: <Widget>[
  173. Container(
  174. width: width,
  175. padding: EdgeInsets.symmetric(
  176. horizontal: 10, vertical: 10),
  177. decoration: BoxDecoration(
  178. border: Border(
  179. bottom:
  180. BorderSide(width: 0.5, color: Colours.line),
  181. ),
  182. ),
  183. child: Column(
  184. mainAxisAlignment: MainAxisAlignment.start,
  185. crossAxisAlignment: CrossAxisAlignment.start,
  186. children: <Widget>[
  187. Text(
  188. detailObj.title ?? "",
  189. style: TextStyle(
  190. fontSize: 16,
  191. fontWeight: FontWeight.w500,
  192. color: Color(0xff333333),
  193. ),
  194. textAlign: TextAlign.start,
  195. maxLines: 1,
  196. overflow: TextOverflow.ellipsis,
  197. ),
  198. SizedBox(
  199. height: 10,
  200. ),
  201. Row(
  202. children: [
  203. _clipText(
  204. title: detailObj.brandName ?? "",
  205. bgcolor:
  206. Color.fromRGBO(67, 141, 250, .16),
  207. textcolor: Color(0xFF5887FF)),
  208. Expanded(child: Container()),
  209. Text(
  210. "${detailObj.browseNum ?? "0"}浏览·${detailObj.likeNum ?? "0"}赞",
  211. textAlign: TextAlign.right,
  212. style: TextStyle(
  213. color: Color(0xFFCCCCCC),
  214. fontSize: 11,
  215. ),
  216. )
  217. ],
  218. ),
  219. ]),
  220. ),
  221. Container(
  222. padding: EdgeInsets.symmetric(
  223. horizontal: 10, vertical: 10),
  224. child: Row(
  225. children: <Widget>[
  226. Container(
  227. child: ClipRRect(
  228. borderRadius: BorderRadius.circular(16),
  229. child: LoadNetworkImage(
  230. detailObj.avatarUrl,
  231. // fit: BoxFit.cover,
  232. width: 32,
  233. height: 32,
  234. ),
  235. )),
  236. Container(
  237. padding: EdgeInsets.only(left: 5),
  238. child: Row(
  239. // crossAxisAlignment: CrossAxisAlignment.start,
  240. children: <Widget>[
  241. Text(
  242. detailObj.userName ?? "",
  243. style: TextStyle(
  244. fontSize: 14,
  245. color: Color(0xff555A64),
  246. ),
  247. ),
  248. SizedBox(
  249. width: 5,
  250. ),
  251. _clipText(
  252. title: 'lv1',
  253. bgcolor:
  254. Color.fromRGBO(253, 93, 97, 1),
  255. textcolor: Colors.white),
  256. ],
  257. ),
  258. )
  259. ],
  260. ),
  261. ),
  262. Container(
  263. padding: EdgeInsets.symmetric(horizontal: 10),
  264. child: Text(
  265. '${DateUtils().getFormartData(timeSamp: detailObj.createTime, format: 'yyyy-MM-dd HH:mm:ss')} 发布',
  266. style: TextStyle(
  267. fontSize: 12, color: Color(0xff989898)),
  268. ),
  269. ),
  270. SizedBox(
  271. height: 10,
  272. ),
  273. Divider(
  274. thickness: 0.5,
  275. ),
  276. Column(
  277. crossAxisAlignment: CrossAxisAlignment.start,
  278. mainAxisAlignment: MainAxisAlignment.start,
  279. children: <Widget>[
  280. Row(
  281. children: [
  282. Container(
  283. width: ScreenUtil().setWidth(2),
  284. height: ScreenUtil().setHeight(13),
  285. color: Color(0xFF568AFF),
  286. ),
  287. Container(
  288. padding: EdgeInsets.only(
  289. left: ScreenUtil().setWidth(10),
  290. top: ScreenUtil().setHeight(6),
  291. bottom: ScreenUtil().setWidth(5)),
  292. child: Text(
  293. "问题描述",
  294. style: TextStyle(
  295. fontSize: 15,
  296. color: Color(0xff333333),
  297. ),
  298. textAlign: TextAlign.left,
  299. ),
  300. ),
  301. ],
  302. ),
  303. Container(
  304. padding: EdgeInsets.symmetric(
  305. horizontal: 10, vertical: 10),
  306. child: Text(
  307. detailObj.expression ?? "",
  308. style: TextStyle(
  309. fontSize: 13,
  310. color: Color(0xff333333),
  311. ),
  312. textAlign: TextAlign.left,
  313. ),
  314. ),
  315. ],
  316. ),
  317. SizedBox(
  318. height: 6,
  319. child: Container(
  320. color: ThemeUtils.getDialogTextFieldColor(
  321. context)),
  322. ),
  323. Column(
  324. crossAxisAlignment: CrossAxisAlignment.start,
  325. mainAxisAlignment: MainAxisAlignment.start,
  326. children: <Widget>[
  327. Row(
  328. children: [
  329. Container(
  330. // margin: EdgeInsets.only(
  331. // top: ScreenUtil().setHeight(10)),
  332. width: ScreenUtil().setWidth(2),
  333. height: ScreenUtil().setHeight(13),
  334. color: Color(0xFF568AFF),
  335. ),
  336. Container(
  337. padding: EdgeInsets.only(
  338. left: ScreenUtil().setWidth(10),
  339. top: ScreenUtil().setHeight(6),
  340. bottom: ScreenUtil().setWidth(5)),
  341. child: Text(
  342. "解决方法",
  343. style: TextStyle(
  344. fontSize: 15,
  345. color: Color(0xff333333),
  346. ),
  347. textAlign: TextAlign.left,
  348. ),
  349. ),
  350. ],
  351. ),
  352. Container(
  353. padding: EdgeInsets.symmetric(
  354. horizontal: 10, vertical: 10),
  355. child: Text(
  356. detailObj.solution ?? "",
  357. style: TextStyle(
  358. fontSize: 13,
  359. color: Color(detailObj.isTip != 1
  360. ? 0x0c333333
  361. : 0xff333333),
  362. ),
  363. textAlign: TextAlign.left,
  364. ),
  365. )
  366. ],
  367. ),
  368. if (detailObj.isTip == 1)
  369. Container(
  370. padding: EdgeInsets.only(
  371. top: ScreenUtil().setWidth(5),
  372. left: ScreenUtil().setWidth(15),
  373. right: ScreenUtil().setWidth(15)),
  374. child: Wrap(
  375. spacing: 6,
  376. alignment: WrapAlignment.spaceBetween,
  377. crossAxisAlignment:
  378. WrapCrossAlignment.center,
  379. children: detailObj.imgs != null &&
  380. detailObj.imgs.isNotEmpty
  381. ? List<Widget>.from(detailObj.imgs
  382. .split(",")
  383. .asMap()
  384. .keys
  385. .map((subindex) {
  386. // print(item);
  387. return Container(
  388. padding: subindex <
  389. detailObj.imgs
  390. .split(",")
  391. .length -
  392. 1
  393. ? EdgeInsets.only(right: 6)
  394. : EdgeInsets.only(right: 0),
  395. // color:Colors.red,
  396. // decoration: BoxDecoration(
  397. // borderRadius: BorderRadius.circular(20.0),
  398. // ),
  399. child: GestureDetector(
  400. onTap: () {
  401. Navigator.of(context).push(
  402. new FadeRoute(
  403. page:
  404. PhotoViewGalleryScreen(
  405. images:
  406. listPreview, //传入图片list
  407. index:
  408. subindex, //传入当前点击的图片的index
  409. // heroTag: img,//传入当前点击的图片的hero tag (可选)
  410. ),
  411. ),
  412. );
  413. },
  414. child: ClipRRect(
  415. borderRadius:
  416. BorderRadius.circular(10),
  417. child: LoadNetworkImage(
  418. detailObj.imgs
  419. .split(",")[subindex],
  420. // height: width/375*75,
  421. height: ScreenUtil()
  422. .setWidth(80),
  423. width: ScreenUtil()
  424. .setWidth(80),
  425. isWater: true,
  426. ),
  427. ),
  428. ),
  429. );
  430. }).toList())
  431. : <Widget>[])),
  432. SizedBox(
  433. height: 70,
  434. ),
  435. ],
  436. ),
  437. ])),
  438. if (detailObj.isTip != 1)
  439. Positioned(
  440. bottom: ScreenUtil().setHeight(50),
  441. left: 0,
  442. height: ScreenUtil().setHeight(260),
  443. width: width,
  444. child: InkWell(
  445. child: Container(
  446. // color: Colors.red,
  447. decoration: BoxDecoration(
  448. gradient: LinearGradient(
  449. colors: [
  450. Color(0x66FFFFFF),
  451. Color(0xFFFFFFFF),
  452. ],
  453. begin: Alignment.topCenter,
  454. end: Alignment.bottomCenter),
  455. ),
  456. child: Column(
  457. mainAxisAlignment: MainAxisAlignment.center,
  458. children: [
  459. Stack(
  460. overflow: Overflow.visible,
  461. children: [
  462. GestureDetector(
  463. onTap: () {
  464. NavigatorUtils.push(
  465. context, '${WodeRouter.vip}?id=');
  466. },
  467. child: Container(
  468. width: 50,
  469. height: 50,
  470. decoration: BoxDecoration(
  471. gradient: LinearGradient(colors: [
  472. Color(0xffE6C8A0),
  473. Color(0xffDCB885)
  474. ]),
  475. borderRadius: BorderRadius.circular(25),
  476. ),
  477. child: Icon(
  478. Iconfont.huiyuan101,
  479. color: Colors.white,
  480. ),
  481. ),
  482. ),
  483. Positioned(
  484. top: 0,
  485. left: 30,
  486. child: Container(
  487. padding: EdgeInsets.all(2),
  488. color: Color(0xffF95046),
  489. child: Text(
  490. '最低仅需${vipPrice}元/月',
  491. style: TextStyle(
  492. color: Colors.white, fontSize: 9),
  493. ),
  494. ),
  495. ),
  496. ],
  497. ),
  498. Text(
  499. '立即成为会员,查看更多内容',
  500. style: TextStyle(
  501. fontSize: 13,
  502. color: Color(0xff333333),
  503. ),
  504. )
  505. ],
  506. )),
  507. ),
  508. ),
  509. Positioned(
  510. bottom: 0,
  511. left: 0,
  512. child: Container(
  513. height: ScreenUtil().setHeight(50),
  514. color: Colors.white,
  515. width: width,
  516. child: Row(children: <Widget>[
  517. Container(
  518. width: 60,
  519. child: GestureDetector(
  520. onTap: () {
  521. if (FlutterStars.SpUtil.getString(
  522. Constant.userId) ==
  523. "-1") {
  524. showAlertEvent();
  525. } else {
  526. if (detailObj.isLike == 1) {
  527. // cancelLike(2);
  528. cancelLike();
  529. } else {
  530. // changeLike(2);
  531. changeLike();
  532. }
  533. }
  534. },
  535. child: Column(
  536. mainAxisAlignment: MainAxisAlignment.center,
  537. children: <Widget>[
  538. Icon(
  539. // &#xe610;
  540. // : 0xe608,
  541. // &#xe6f8;
  542. detailObj.isLike == 1
  543. ? const IconData(0xe610,
  544. fontFamily: "Iconfont")
  545. : const IconData(0xe6f8,
  546. fontFamily: "Iconfont"),
  547. size: 20,
  548. color: Color(detailObj.isLike == 1
  549. ? 0xff5589FF
  550. : 0xff555A64),
  551. ),
  552. Text(
  553. detailObj.isLike == 1 ? "已点赞" : "点赞",
  554. style: TextStyle(
  555. color: Color(detailObj.isLike == 1
  556. ? 0xff5589FF
  557. : 0xff555A64),
  558. fontSize: 12),
  559. textAlign: TextAlign.start,
  560. ),
  561. ])),
  562. ),
  563. Container(
  564. width: 60,
  565. child: GestureDetector(
  566. onTap: () {
  567. if (FlutterStars.SpUtil.getString(
  568. Constant.userId) ==
  569. "-1") {
  570. showAlertEvent();
  571. } else {
  572. if (detailObj.isFavorite == 1) {
  573. // cancelLike(3);
  574. cancelFav();
  575. } else {
  576. // changeLike(3);
  577. changeFav();
  578. }
  579. }
  580. },
  581. child: Container(
  582. child: Column(
  583. mainAxisAlignment:
  584. MainAxisAlignment.center,
  585. children: <Widget>[
  586. Icon(
  587. // : 0xe604,
  588. detailObj.isFavorite == 1
  589. ? const IconData(0xe62a,
  590. fontFamily: "Iconfont")
  591. : const IconData(0xe6b7,
  592. fontFamily: "Iconfont"),
  593. size: 20,
  594. color: Color(detailObj.isFavorite == 1
  595. ? 0xff5589FF
  596. : 0xff555a64),
  597. ),
  598. Text(
  599. detailObj.isFavorite == 1 ? "已收藏" : "收藏",
  600. style: TextStyle(
  601. color: Color(detailObj.isFavorite == 1
  602. ? 0xff5589FF
  603. : 0xff555A64),
  604. fontSize: 12,
  605. ),
  606. textAlign: TextAlign.start,
  607. ),
  608. ])),
  609. ),
  610. ),
  611. Expanded(
  612. child: ClipRRect(
  613. borderRadius: BorderRadius.circular(22),
  614. child: Container(
  615. height: 44,
  616. // width: width / 2,
  617. color: Color(0xff5589FF),
  618. child: FlatButton(
  619. // padding: EdgeInsets.all(15.0),
  620. child: RichText(
  621. text: TextSpan(
  622. text: '打赏',
  623. style: TextStyle(
  624. fontSize: 16.0,
  625. fontWeight: FontWeight.w500),
  626. children: <TextSpan>[
  627. TextSpan(
  628. text: '(可查看全部内容)',
  629. style: TextStyle(
  630. fontSize: 11.0,
  631. )),
  632. ]),
  633. ),
  634. textColor: Colors.white,
  635. onPressed: () {
  636. if (FlutterStars.SpUtil.getString(
  637. Constant.userId) ==
  638. "-1") {
  639. showAlertEvent();
  640. } else {
  641. Navigator.push(
  642. context,
  643. MaterialPageRoute(
  644. builder: (context) => QuestionPay(
  645. detailObj.id.toString(),
  646. "question",
  647. detailObj.userName,
  648. detailObj.avatarUrl,
  649. expert: detailObj.expert
  650. .toString(),
  651. )));
  652. // NavigatorUtils.push(context,
  653. // "${BbsRouter.questionPay}?id=${detailObj.id}&userModel=${[detailObj.avatarUrl]}&type=question&name=${Uri.encodeComponent(detailObj.userName)}");
  654. }
  655. },
  656. ),
  657. ),
  658. )),
  659. SizedBox(
  660. width: 10,
  661. )
  662. ])))
  663. ],
  664. )
  665. : Center(
  666. child: Text("正在加载..."),
  667. ),
  668. );
  669. }
  670. }
  671. class FadeRoute extends PageRouteBuilder {
  672. final Widget page;
  673. FadeRoute({this.page})
  674. : super(
  675. pageBuilder: (
  676. BuildContext context,
  677. Animation<double> animation,
  678. Animation<double> secondaryAnimation,
  679. ) =>
  680. page,
  681. transitionsBuilder: (
  682. BuildContext context,
  683. Animation<double> animation,
  684. Animation<double> secondaryAnimation,
  685. Widget child,
  686. ) =>
  687. FadeTransition(
  688. opacity: animation,
  689. child: child,
  690. ),
  691. );
  692. }