product_detail.dart 22 KB

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