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.
 
 
 
 
 
 

432 regels
13 KiB

  1. import 'dart:async';
  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/data/conversation.dart';
  7. import 'package:chat/generated/i18n.dart';
  8. import 'package:chat/home/ProfilePage.dart';
  9. import 'package:chat/home/rich_title.dart';
  10. import 'package:chat/utils/CustomUI.dart';
  11. import 'package:chat/utils/HttpUtil.dart';
  12. import 'package:chat/utils/TokenMgr.dart';
  13. import 'package:dio/dio.dart';
  14. import 'package:flutter/cupertino.dart';
  15. import 'package:flutter/material.dart';
  16. import 'package:flutter_inapp_purchase/flutter_inapp_purchase.dart';
  17. import 'package:fluwx_no_pay/fluwx_no_pay.dart' as fluwx;
  18. import 'package:oktoast/oktoast.dart';
  19. import 'package:pull_to_refresh/pull_to_refresh.dart';
  20. class _ConversationItem extends StatelessWidget {
  21. const _ConversationItem(
  22. {Key key,
  23. this.conversation,
  24. this.callback,
  25. this.showRight = true,
  26. this.rightButton,
  27. this.showReturn = false,
  28. this.applyInfo,
  29. this.bgColor,
  30. this.isInCome = false,
  31. this.money,
  32. this.title})
  33. : assert(conversation != null),
  34. super(key: key);
  35. final Widget rightButton;
  36. final Conversation conversation;
  37. final callback;
  38. final int money;
  39. final bool showRight;
  40. final title;
  41. final applyInfo;
  42. final bgColor;
  43. final bool showReturn;
  44. final bool isInCome;
  45. @override
  46. Widget build(BuildContext context) {
  47. Widget avatar;
  48. double width = 44.55;
  49. if (conversation.isAvatarFromNet()) {
  50. avatar = ClipRRect(
  51. borderRadius: BorderRadius.circular(10),
  52. child: CachedNetworkImage(
  53. imageUrl: conversation.avatar,
  54. placeholder: (context, url) => Image.asset(
  55. Constants.DefaultHeadImgUrl,
  56. width: width,
  57. height: width,
  58. ),
  59. fit: BoxFit.cover,
  60. width: width,
  61. height: width,
  62. ));
  63. } else {
  64. avatar = ClipRRect(
  65. borderRadius: BorderRadius.circular(10),
  66. child: Container(
  67. width: width,
  68. height: width,
  69. alignment: Alignment.center,
  70. decoration: BoxDecoration(
  71. gradient: this.bgColor,
  72. borderRadius: BorderRadius.all(Radius.circular(50))),
  73. child: Image.asset(
  74. conversation.avatar,
  75. height: 27,
  76. )));
  77. }
  78. return InkWell(
  79. child: Container(
  80. padding:
  81. const EdgeInsets.only(left: 21, top: 12.5, bottom: 12.5, right: 24.5),
  82. decoration: BoxDecoration(
  83. color: Color(AppColors.ConversationItemBgColor),
  84. border: Border(
  85. bottom: BorderSide(
  86. color: AppColors.DividerColor,
  87. width: Constants.DividerWidth))),
  88. child: Row(
  89. crossAxisAlignment: CrossAxisAlignment.center,
  90. children: <Widget>[
  91. avatar,
  92. Container(width: 14.0),
  93. Expanded(
  94. child: Container(
  95. padding: EdgeInsets.only(top: 3),
  96. child: Column(
  97. crossAxisAlignment: CrossAxisAlignment.start,
  98. children: <Widget>[
  99. Container(
  100. child: title == null
  101. ? Text(conversation.title,
  102. textScaleFactor: 1.0,
  103. style: TextStyle(
  104. fontSize: 11,
  105. color: Constants.LightGreyTextColor))
  106. : title),
  107. Container(
  108. padding: EdgeInsets.only(top: 10),
  109. child: Text(conversation.desc,
  110. textScaleFactor: 1.0,
  111. style: TextStyle(
  112. fontSize: 11, color: Constants.LightGreyTextColor)),
  113. )
  114. ],
  115. ),
  116. )),
  117. Container(
  118. height: width,
  119. margin: EdgeInsets.only(left: 10),
  120. child: Column(
  121. crossAxisAlignment: CrossAxisAlignment.end,
  122. mainAxisAlignment: MainAxisAlignment.center,
  123. children: <Widget>[
  124. Text(
  125. '${money > 0 ? '+' : ''}${this.isInCome ? money * 1000 : (money.toString() + I18n.of(context).mask_coin)}',
  126. style: TextStyle(
  127. fontSize: 14,
  128. fontWeight: FontWeight.w500,
  129. color:
  130. money > 0 ? Color(0xFFFE4624) : Color(0xFF5498FF)),
  131. ),
  132. showReturn
  133. ? Padding(
  134. padding: EdgeInsets.only(top: 3),
  135. child: Text(
  136. I18n.of(context).alreay_back,
  137. style: TextStyle(
  138. fontSize: 12,
  139. fontWeight: FontWeight.normal,
  140. color: Constants.BlackTextColor),
  141. ))
  142. : Container()
  143. ],
  144. ),
  145. alignment: Alignment.center,
  146. ),
  147. ],
  148. ),
  149. ),
  150. onTap: () {
  151. callback();
  152. },
  153. );
  154. }
  155. }
  156. class MoneyDetailPage extends StatefulWidget {
  157. final int type;
  158. MoneyDetailPage({Key key, this.type}) : super(key: key);
  159. MoneyDetailPageState createState() => MoneyDetailPageState();
  160. }
  161. class MoneyDetailPageState extends State<MoneyDetailPage>
  162. with SingleTickerProviderStateMixin {
  163. List list = new List(); //列表要展示的数据
  164. RefreshController _refreshController =
  165. RefreshController(initialRefresh: true);
  166. int _page = 1; //加载的页数
  167. int rows = 20;
  168. TabController tabCtrl;
  169. var bindAccount;
  170. @override
  171. void initState() {
  172. super.initState();
  173. tabCtrl = TabController(length: 2, vsync: this);
  174. fluwx.responseFromPayment.listen((data) {
  175. if (data.errCode == 0) {
  176. Navigator.of(context).pop();
  177. setState(() {});
  178. showToast(I18n.of(context).payment_successful);
  179. }
  180. });
  181. }
  182. void addList(data) {
  183. if (data == null || data.length == 0) {
  184. _page--;
  185. _refreshController.loadNoData();
  186. } else {
  187. list.addAll(data);
  188. _refreshController.loadComplete();
  189. }
  190. setState(() {});
  191. }
  192. void _onLoading() async {
  193. _page++;
  194. getNewData(addList);
  195. }
  196. @override
  197. void dispose() {
  198. tabCtrl.dispose();
  199. _refreshController.dispose();
  200. if (_conectionSubscription != null) {
  201. _conectionSubscription.cancel();
  202. _conectionSubscription = null;
  203. }
  204. if (_purchaseUpdatedSubscription != null) {
  205. _purchaseUpdatedSubscription.cancel();
  206. _purchaseUpdatedSubscription = null;
  207. }
  208. if (_purchaseErrorSubscription != null) {
  209. _purchaseErrorSubscription.cancel();
  210. _purchaseErrorSubscription = null;
  211. }
  212. super.dispose();
  213. }
  214. @override
  215. Widget build(BuildContext context) {
  216. Widget content = Scaffold(
  217. resizeToAvoidBottomPadding: false,
  218. appBar: AppBar(
  219. leading: CustomUI.buildCustomLeading(context),
  220. backgroundColor: AppColors.NewAppbarBgColor,
  221. title: Text(
  222. widget.type == 1
  223. ? I18n.of(context).my_money_info
  224. : I18n.of(context).get_money_detail,
  225. textScaleFactor: 1.0,
  226. ),
  227. centerTitle: true,
  228. ),
  229. body: SafeArea(child: showCoin()),
  230. );
  231. return content;
  232. //return CustomUI.buildPageLoading(context, content, !isLoadingFish);
  233. }
  234. Widget showCoin() {
  235. return Scaffold(
  236. body: SafeArea(
  237. child: Center(
  238. child: Container(
  239. height: MediaQuery.of(context).size.height,
  240. width: MediaQuery.of(context).size.width,
  241. child: _buildCoinBody(),
  242. ),
  243. )));
  244. }
  245. void _onRefresh() async {
  246. _page = 1;
  247. getNewData(initList);
  248. }
  249. void initList(data) {
  250. list.clear();
  251. if (data != null) {
  252. list.addAll(data);
  253. }
  254. setState(() {});
  255. }
  256. getNewData(callback) async {
  257. Map data = {
  258. "userId": UserData().basicInfo.userId,
  259. 'type': widget.type,
  260. };
  261. data['sign'] = TokenMgr().getSign(data);
  262. data["page"] = _page;
  263. data['rows'] = rows;
  264. Response res = await HttpUtil().post('wallet/balance/detail', data: data);
  265. var resData = res.data;
  266. _refreshController.refreshCompleted();
  267. print(resData);
  268. if (resData['code'] == 0) {
  269. callback(resData['data']);
  270. } else {
  271. showToast(resData['msg']);
  272. }
  273. }
  274. bool isAdd(int type) {
  275. if (widget.type == 1) {
  276. return type == 1 ||
  277. type == 2 ||
  278. type == 3 ||
  279. type == 12 ||
  280. type == 13 ||
  281. type == 14;
  282. } else {
  283. return !(type == 1 || type == 2);
  284. }
  285. }
  286. //钱包通知
  287. Widget _buildMoneyInfo(data) {
  288. String imgUrl = data['HeadImg'] == null ||
  289. data['HeadImg'] == '' ||
  290. data['ChangeUserId'] == 0
  291. ? UserData().basicInfo.headimgurl
  292. : data['HeadImg'];
  293. return _ConversationItem(
  294. conversation: Conversation(
  295. avatar: imgUrl,
  296. title: '',
  297. desc: WebData().getLoginTime(context, data['CreateTime']),
  298. updateAt: '',
  299. ),
  300. bgColor: Constants.MoneyGradient,
  301. isInCome: widget.type == 2,
  302. money: isAdd(data['DetailType']) ? data['Value'] : -data['Value'],
  303. title: RichTitle.getRichTitleWidget(data, context,
  304. widget.type == 1 ? InfoType.MyMoney : InfoType.IncomeMoney,
  305. titleStyle: TextStyle(fontSize: 12, color: const Color(0XFF7F7F7F)),
  306. nameStyle: TextStyle(
  307. fontWeight: FontWeight.normal,
  308. fontSize: 13,
  309. color: Constants.BlackTextColor)),
  310. callback: () {
  311. if (data['ChangeUserId'] != 0) {
  312. Navigator.of(context).push(
  313. new MaterialPageRoute(
  314. builder: (context) {
  315. return ProfilePage(
  316. userId: data['UserId'] == UserData().basicInfo.userId
  317. ? data['ChangeUserId']
  318. : data['UserId'],
  319. );
  320. },
  321. ),
  322. );
  323. }
  324. },
  325. );
  326. }
  327. Widget _renderRow(BuildContext context, int index) {
  328. if (index < list.length) {
  329. var userInfo = list[index];
  330. Widget result = _buildMoneyInfo(userInfo);
  331. if (index == 0) {
  332. result = Padding(padding: EdgeInsets.only(top: 10), child: result);
  333. }
  334. return result;
  335. }
  336. return Container();
  337. }
  338. Widget _buildCoinBody() {
  339. return SmartRefresher(
  340. enablePullDown: true,
  341. enablePullUp: true,
  342. header: MaterialClassicHeader(),
  343. footer: CustomUI.buildLoadingFooter(),
  344. controller: _refreshController,
  345. onRefresh: _onRefresh,
  346. onLoading: _onLoading,
  347. child: (_refreshController.headerStatus == RefreshStatus.completed &&
  348. list.length == 0)
  349. ? CustomUI.buildNoData(context)
  350. : ListView.builder(
  351. itemBuilder: _renderRow,
  352. itemCount: list.length,
  353. ),
  354. );
  355. }
  356. static String currentGoodsId = '';
  357. static StreamSubscription _conectionSubscription,
  358. _purchaseUpdatedSubscription,
  359. _purchaseErrorSubscription;
  360. ///ios 内购初始化
  361. static Future initPayConf(BuildContext context) async {
  362. if (_purchaseErrorSubscription != null) {
  363. return;
  364. }
  365. // prepare
  366. print('initPayConf -------- start: ');
  367. var result = await FlutterInappPurchase.instance.initConnection;
  368. print('initPayConf -------- result: $result');
  369. FlutterInappPurchase.instance.clearTransactionIOS();
  370. _conectionSubscription =
  371. FlutterInappPurchase.connectionUpdated.listen((connected) {
  372. print('connected: $connected');
  373. });
  374. _purchaseUpdatedSubscription =
  375. FlutterInappPurchase.purchaseUpdated.listen((productItem) {
  376. print('支付成功,成功回调 ------ purchase-updated: $productItem');
  377. // showToast('支付成功,成功回调 ------ purchase-updated: $productItem');
  378. if (productItem.transactionReceipt != null &&
  379. productItem.transactionReceipt.isNotEmpty) {
  380. HttpUtil().createOrder(currentGoodsId, productItem.transactionReceipt,
  381. productItem.purchaseToken,
  382. context: context);
  383. showToast(I18n.of(context).payment_successful);
  384. }
  385. Navigator.of(context).pop();
  386. });
  387. _purchaseErrorSubscription =
  388. FlutterInappPurchase.purchaseError.listen((purchaseError) {
  389. // showToast('支付失败回调 -------- purchase-error: $purchaseError');
  390. FlutterInappPurchase.instance.clearTransactionIOS();
  391. Navigator.of(context).pop();
  392. });
  393. }
  394. }