product_detail.dart 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530
  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:flutter_swiper/flutter_swiper.dart';
  6. import 'package:fluwx/fluwx.dart' as fluwx;
  7. import 'package:liftmanager/common/common.dart';
  8. import 'package:liftmanager/internal/account/account_router.dart';
  9. import 'package:liftmanager/internal/bbs/model/shop_detail.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/toast.dart';
  17. import 'package:liftmanager/utils/url.dart';
  18. import 'package:liftmanager/widgets/app_bar.dart';
  19. import 'package:liftmanager/widgets/load_image.dart';
  20. import 'package:url_launcher/url_launcher.dart';
  21. import 'package:liftmanager/widgets/preview_images.dart';
  22. import '../../recommend_ask.dart';
  23. class ProductDetail extends StatefulWidget {
  24. ProductDetail(this.id);
  25. final String id;
  26. @override
  27. State<StatefulWidget> createState() {
  28. return ProductDetailState();
  29. }
  30. }
  31. class ProductDetailState extends State<ProductDetail> {
  32. @override
  33. void initState() {
  34. super.initState();
  35. getShopDetail();
  36. }
  37. bool _hasData = false;
  38. ShopDetailModel detailObj;
  39. Future getShopDetail() async {
  40. await NewApiService().getShopDetail(int.parse(widget.id), 1,
  41. onSuccess: (res) {
  42. if (res != null) {
  43. _hasData = true;
  44. detailObj = res;
  45. setState(() {});
  46. }
  47. }, onError: (code, msg) {
  48. toasts(msg);
  49. });
  50. }
  51. showAlertEvent() {
  52. showAlert(
  53. context,
  54. "提示",
  55. "确定登录?",
  56. "确定",
  57. () {
  58. NavigatorUtils.push(context, AccountRouter.loginPage, clearStack: true);
  59. },
  60. txt2: "取消",
  61. onPre2: () {
  62. NavigatorUtils.goBack(context);
  63. },
  64. );
  65. }
  66. Future changeFav(type) async {
  67. await NewApiService().shopFav(detailObj.id, type, 1, onSuccess: (res) {
  68. toasts("收藏成功");
  69. initCollect();
  70. getShopDetail();
  71. }, onError: (code, msg) {
  72. toasts(msg);
  73. });
  74. }
  75. Future cancelFav() async {
  76. await NewApiService().shopFavCancel(detailObj.favoriteId, onSuccess: (res) {
  77. toasts("取消收藏成功");
  78. initCollect();
  79. getShopDetail();
  80. }, onError: (code, msg) {
  81. toasts(msg);
  82. });
  83. }
  84. _launchPhone(url) async {
  85. if (await canLaunch(url)) {
  86. await launch(url);
  87. } else {
  88. throw 'Could not launch $url';
  89. }
  90. }
  91. initCollect() {
  92. String collectInit = randomInt(1111, 9999).toString() +
  93. DateTime.now().millisecondsSinceEpoch.toString();
  94. FastNotification.push("collectAction", collectInit);
  95. }
  96. randomInt(int min, int max) {
  97. return new Random().nextInt(max) % (max - min + 1) + min;
  98. }
  99. @override
  100. Widget build(BuildContext context) {
  101. double width = MediaQuery.of(context).size.width;
  102. return Scaffold(
  103. resizeToAvoidBottomPadding: false, //不让键盘弹上去
  104. appBar: MyAppBar(
  105. centerTitle: "商品详情",
  106. ),
  107. body: _hasData
  108. ? Stack(
  109. children: <Widget>[
  110. Container(
  111. child: ListView(children: <Widget>[
  112. Column(
  113. mainAxisAlignment: MainAxisAlignment.start,
  114. crossAxisAlignment: CrossAxisAlignment.start,
  115. children: <Widget>[
  116. Container(
  117. padding: EdgeInsets.symmetric(horizontal: 10),
  118. decoration: BoxDecoration(
  119. border: Border(
  120. bottom: BorderSide(width: 0.5, color: Colours.line),
  121. ),
  122. ),
  123. child: Column(
  124. mainAxisAlignment: MainAxisAlignment.start,
  125. crossAxisAlignment: CrossAxisAlignment.start,
  126. children: <Widget>[
  127. Container(
  128. width: width,
  129. height: ScreenUtil().setWidth(220),
  130. padding: EdgeInsets.only(bottom: 10),
  131. child: Container(
  132. child: Swiper(
  133. itemBuilder: (BuildContext context, index) {
  134. return Container(
  135. width: width,
  136. height: ScreenUtil().setWidth(220),
  137. key: Key(
  138. detailObj.imgs.split(",")[index]),
  139. child: LoadNetworkImage(
  140. detailObj.imgs.split(",")[index],
  141. width: width,
  142. height: ScreenUtil().setWidth(220),
  143. fit: BoxFit.fill,
  144. isWater: true,
  145. ),
  146. );
  147. },
  148. pagination: SwiperPagination(
  149. builder: DotSwiperPaginationBuilder(
  150. color: Colors.grey,
  151. activeColor: Colors.white,
  152. size: 6,
  153. activeSize: 6)),
  154. itemCount: detailObj.imgs.split(",").length,
  155. scrollDirection: Axis.horizontal,
  156. autoplay: false,
  157. onTap: (index) {
  158. Navigator.of(context).push(
  159. FadeRoute(
  160. page: PhotoViewGalleryScreen(
  161. images: detailObj.imgs
  162. .split(","), //传入图片list
  163. index: index, //传入当前点击的图片的index
  164. // heroTag: img,//传入当前点击的图片的hero tag (可选)
  165. ),
  166. ),
  167. );
  168. // print(index);
  169. },
  170. ),
  171. ),
  172. ),
  173. SizedBox(height: 5),
  174. Text(
  175. detailObj.name ?? "",
  176. style:
  177. TextStyle(fontSize: ScreenUtil().setSp(16)),
  178. textAlign: TextAlign.start,
  179. ),
  180. SizedBox(
  181. height: 10,
  182. ),
  183. if (detailObj.brandName != null)
  184. Container(
  185. padding: EdgeInsets.all(3),
  186. decoration: BoxDecoration(
  187. color: Color(0x33448EFA),
  188. ),
  189. child: Text(
  190. detailObj.brandName ?? "",
  191. style: TextStyle(
  192. color: Color(0xff5888FF),
  193. fontSize: 11,
  194. fontWeight: FontWeight.w500,
  195. ),
  196. textAlign: TextAlign.start,
  197. ),
  198. ),
  199. SizedBox(
  200. height: 10,
  201. ),
  202. Row(
  203. crossAxisAlignment: CrossAxisAlignment.baseline,
  204. children: <Widget>[
  205. if (detailObj.discountPrice != null)
  206. Text(
  207. '¥${detailObj.discountPrice.toInt()}',
  208. style: TextStyle(
  209. color: Color(0xffFF5C00),
  210. fontSize: 16,
  211. ),
  212. ),
  213. if (detailObj.discountPrice == null)
  214. Text(
  215. '¥${detailObj.price?.toInt() ?? '暂无'}',
  216. style: TextStyle(
  217. color: Color(0xffFF5C00),
  218. fontSize: 16,
  219. ),
  220. ),
  221. if (detailObj.discountPrice != null)
  222. Text(
  223. '¥${detailObj.price.toInt()}',
  224. style: TextStyle(
  225. color: Color(0xff999999),
  226. fontSize: 11,
  227. decoration: TextDecoration.lineThrough,
  228. ),
  229. ),
  230. // Text(
  231. // '¥${detailObj?.price?.toInt() ?? ""}',
  232. // style: TextStyle(
  233. // color: Color(0xffFF5B00),
  234. // fontSize: 16,
  235. // ),
  236. // textAlign: TextAlign.start,
  237. // ),
  238. ],
  239. ),
  240. SizedBox(height: 15),
  241. ]),
  242. ),
  243. Column(
  244. crossAxisAlignment: CrossAxisAlignment.start,
  245. mainAxisAlignment: MainAxisAlignment.start,
  246. children: <Widget>[
  247. SizedBox(
  248. height: 10,
  249. ),
  250. Container(
  251. padding: EdgeInsets.only(left: 10),
  252. decoration: BoxDecoration(
  253. border: Border(
  254. left: BorderSide(
  255. width: 2,
  256. color: Color(0xff568AFF),
  257. ),
  258. ),
  259. ),
  260. child: Text(
  261. "商品简介",
  262. style: TextStyle(
  263. fontSize: 15,
  264. color: Color(0xff333333),
  265. ),
  266. textAlign: TextAlign.left,
  267. ),
  268. ),
  269. SizedBox(
  270. height: 10,
  271. ),
  272. Container(
  273. padding: EdgeInsets.symmetric(horizontal: 10),
  274. child: Text(
  275. detailObj.descr,
  276. style: TextStyle(
  277. color: Color(0xff333333), fontSize: 13),
  278. textAlign: TextAlign.left,
  279. ),
  280. ),
  281. ],
  282. ),
  283. SizedBox(
  284. height: 10,
  285. ),
  286. Container(
  287. height: 1,
  288. color: ThemeUtils.getDialogTextFieldColor(context)),
  289. Column(
  290. crossAxisAlignment: CrossAxisAlignment.start,
  291. mainAxisAlignment: MainAxisAlignment.start,
  292. children: <Widget>[
  293. SizedBox(
  294. height: 10,
  295. ),
  296. Container(
  297. padding: EdgeInsets.only(left: 10),
  298. decoration: BoxDecoration(
  299. border: Border(
  300. left: BorderSide(
  301. width: 2,
  302. color: Color(0xff568AFF),
  303. ),
  304. ),
  305. ),
  306. child: Text(
  307. "商家信息",
  308. style: TextStyle(
  309. color: Color(0xff333333),
  310. fontSize: 15,
  311. ),
  312. textAlign: TextAlign.left,
  313. ),
  314. ),
  315. SizedBox(
  316. height: 10,
  317. ),
  318. Container(
  319. padding: EdgeInsets.symmetric(
  320. horizontal: 10,
  321. ),
  322. child: Column(children: [
  323. Row(
  324. children: [
  325. Icon(
  326. Iconfont.shangjia,
  327. color: Colors.orange,
  328. size: 13,
  329. ),
  330. SizedBox(
  331. width: 10,
  332. ),
  333. Text(
  334. "${detailObj.manufacturer}",
  335. style: TextStyle(
  336. color: Color(0xff666666),
  337. fontSize: 11,
  338. ),
  339. textAlign: TextAlign.left,
  340. ),
  341. ],
  342. ),
  343. SizedBox(
  344. height: 10,
  345. ),
  346. Row(
  347. children: [
  348. Icon(
  349. Iconfont.lianxi,
  350. color: Colors.orange,
  351. size: 13,
  352. ),
  353. SizedBox(
  354. width: 10,
  355. ),
  356. Text(
  357. "${detailObj.telephone} (${detailObj.contactPerson})",
  358. style: TextStyle(
  359. color: Color(0xff666666),
  360. fontSize: 11,
  361. ),
  362. textAlign: TextAlign.left,
  363. ),
  364. ],
  365. ),
  366. ]),
  367. ),
  368. ],
  369. ),
  370. SizedBox(height: ScreenUtil().setWidth(70))
  371. ],
  372. ),
  373. ])),
  374. Positioned(
  375. bottom: 0,
  376. left: 0,
  377. child: Container(
  378. width: width,
  379. color: Colors.white,
  380. padding: EdgeInsets.all(10),
  381. child: Row(
  382. crossAxisAlignment: CrossAxisAlignment.center,
  383. children: <Widget>[
  384. Expanded(
  385. child: Row(
  386. mainAxisAlignment: MainAxisAlignment.spaceAround,
  387. children: [
  388. GestureDetector(
  389. onTap: () {
  390. if (FlutterStars.SpUtil.getString(
  391. Constant.userId) ==
  392. "-1") {
  393. showAlertEvent();
  394. } else {
  395. String initThis =
  396. randomInt(1111, 9999).toString() +
  397. DateTime.now()
  398. .millisecondsSinceEpoch
  399. .toString();
  400. fluwx
  401. .shareToWeChat(
  402. fluwx.WeChatShareWebPageModel(
  403. scene: fluwx.WeChatScene.SESSION,
  404. webPage:
  405. "$jumpUrl/h5/index.html?num=$initThis&page=/bbs/productDetail&id=${widget.id}",
  406. title: detailObj.name,
  407. description: detailObj.descr,
  408. thumbnail: detailObj.imgs.split(",")[0],
  409. ))
  410. .then((result) {}, onError: (msg) {
  411. // print(msg);
  412. });
  413. }
  414. },
  415. child: Container(
  416. // padding: EdgeInsets.only(left:25,right:30),
  417. child: Column(children: <Widget>[
  418. Icon(
  419. Iconfont.fenxiang,
  420. size: 20.0,
  421. color: Color(0xff333333),
  422. ),
  423. Text(
  424. "分享",
  425. style: TextStyle(
  426. color: Color(0xff555A64),
  427. fontSize: 12,
  428. ),
  429. textAlign: TextAlign.start,
  430. ),
  431. ])),
  432. ),
  433. GestureDetector(
  434. onTap: () {
  435. if (FlutterStars.SpUtil.getString(
  436. Constant.userId) ==
  437. "-1") {
  438. showAlertEvent();
  439. } else {
  440. if (detailObj.isFavorite == 1) {
  441. cancelFav();
  442. } else {
  443. changeFav(3);
  444. }
  445. }
  446. },
  447. child: Container(
  448. child: Column(children: <Widget>[
  449. Icon(
  450. // : 0xe604,&#xe62a;
  451. detailObj.isFavorite == 1
  452. ? Iconfont.shoucang1
  453. : Iconfont.shoucang,
  454. size: 20.0,
  455. color: Color(detailObj.isFavorite == 1
  456. ? 0xff5589FF
  457. : 0xff555A64),
  458. ),
  459. Text(
  460. detailObj.isFavorite == 1 ? "已收藏" : "收藏",
  461. style: TextStyle(
  462. color: Color(detailObj.isFavorite == 1
  463. ? 0xff5589FF
  464. : 0xff555A64),
  465. fontSize: 12,
  466. ),
  467. textAlign: TextAlign.start,
  468. ),
  469. ])),
  470. ),
  471. ],
  472. ),
  473. ),
  474. Container(
  475. height: 45,
  476. width: 240,
  477. decoration: BoxDecoration(
  478. color: Color(0xff5589FF),
  479. borderRadius: BorderRadius.circular(30),
  480. ),
  481. child: FlatButton(
  482. // padding: EdgeInsets.all(15.0),
  483. child: Text(
  484. "联系商家",
  485. style: TextStyle(
  486. fontSize: 16,
  487. ),
  488. ),
  489. textColor: Colors.white,
  490. onPressed: () {
  491. if (FlutterStars.SpUtil.getString(
  492. Constant.userId) ==
  493. "-1") {
  494. showAlertEvent();
  495. } else {
  496. _launchPhone("tel:" + detailObj.telephone);
  497. }
  498. },
  499. ),
  500. ),
  501. ],
  502. ),
  503. ),
  504. )
  505. ],
  506. )
  507. : Center(
  508. child: Text("正在加载..."),
  509. ),
  510. );
  511. }
  512. }