Hibok
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
 
 
 
 
 
 

440 lignes
14 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: const EdgeInsets.only(
  81. 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. textScaleFactor: 1.0,
  127. style: TextStyle(
  128. fontSize: 14,
  129. fontWeight: FontWeight.w500,
  130. color:
  131. money > 0 ? Color(0xFFFE4624) : Color(0xFF5498FF)),
  132. ),
  133. showReturn
  134. ? Padding(
  135. padding: EdgeInsets.only(top: 3),
  136. child: Text(
  137. I18n.of(context).alreay_back,
  138. textScaleFactor: 1.0,
  139. style: TextStyle(
  140. fontSize: 12,
  141. fontWeight: FontWeight.normal,
  142. color: Constants.BlackTextColor),
  143. ))
  144. : Container()
  145. ],
  146. ),
  147. alignment: Alignment.center,
  148. ),
  149. ],
  150. ),
  151. ),
  152. onTap: () {
  153. callback();
  154. },
  155. );
  156. }
  157. }
  158. class MoneyDetailPage extends StatefulWidget {
  159. final int type;
  160. MoneyDetailPage({Key key, this.type}) : super(key: key);
  161. MoneyDetailPageState createState() => MoneyDetailPageState();
  162. }
  163. class MoneyDetailPageState extends State<MoneyDetailPage>
  164. with SingleTickerProviderStateMixin {
  165. List list = new List(); //列表要展示的数据
  166. RefreshController _refreshController =
  167. RefreshController(initialRefresh: true);
  168. int _page = 1; //加载的页数
  169. int rows = 20;
  170. TabController tabCtrl;
  171. var bindAccount;
  172. @override
  173. void initState() {
  174. super.initState();
  175. tabCtrl = TabController(length: 2, vsync: this);
  176. fluwx.responseFromPayment.listen((data) {
  177. if (data.errCode == 0) {
  178. Navigator.of(context).pop();
  179. setState(() {});
  180. showToast(I18n.of(context).payment_successful);
  181. }
  182. });
  183. }
  184. void addList(data) {
  185. if (data == null || data.length == 0) {
  186. _page--;
  187. _refreshController.loadNoData();
  188. } else {
  189. list.addAll(data);
  190. _refreshController.loadComplete();
  191. }
  192. setState(() {});
  193. }
  194. void _onLoading() async {
  195. _page++;
  196. getNewData(addList);
  197. }
  198. @override
  199. void dispose() {
  200. tabCtrl.dispose();
  201. _refreshController.dispose();
  202. if (_conectionSubscription != null) {
  203. _conectionSubscription.cancel();
  204. _conectionSubscription = null;
  205. }
  206. if (_purchaseUpdatedSubscription != null) {
  207. _purchaseUpdatedSubscription.cancel();
  208. _purchaseUpdatedSubscription = null;
  209. }
  210. if (_purchaseErrorSubscription != null) {
  211. _purchaseErrorSubscription.cancel();
  212. _purchaseErrorSubscription = null;
  213. }
  214. super.dispose();
  215. }
  216. @override
  217. Widget build(BuildContext context) {
  218. Widget content = Scaffold(
  219. resizeToAvoidBottomPadding: false,
  220. appBar: AppBar(
  221. leading: CustomUI.buildCustomLeading(context),
  222. backgroundColor: AppColors.NewAppbarBgColor,
  223. title: Text(
  224. widget.type == 1
  225. ? I18n.of(context).my_money_info
  226. : I18n.of(context).get_money_detail,
  227. textScaleFactor: 1.0,
  228. ),
  229. centerTitle: true,
  230. ),
  231. body: SafeArea(child: showCoin()),
  232. );
  233. return content;
  234. //return CustomUI.buildPageLoading(context, content, !isLoadingFish);
  235. }
  236. Widget showCoin() {
  237. return Scaffold(
  238. body: SafeArea(
  239. child: Center(
  240. child: Container(
  241. height: MediaQuery.of(context).size.height,
  242. width: MediaQuery.of(context).size.width,
  243. child: _buildCoinBody(),
  244. ),
  245. )));
  246. }
  247. void _onRefresh() async {
  248. _page = 1;
  249. getNewData(initList);
  250. }
  251. void initList(data) {
  252. list.clear();
  253. if (data != null) {
  254. list.addAll(data);
  255. }
  256. setState(() {});
  257. }
  258. getNewData(callback) async {
  259. Map data = {
  260. "userId": UserData().basicInfo.userId,
  261. 'type': widget.type,
  262. };
  263. data['sign'] = TokenMgr().getSign(data);
  264. data["page"] = _page;
  265. data['rows'] = rows;
  266. Response res = await HttpUtil().post('wallet/balance/detail', data: data);
  267. var resData = res.data;
  268. _refreshController.refreshCompleted();
  269. print(resData);
  270. if (resData['code'] == 0) {
  271. callback(resData['data']);
  272. } else {
  273. showToast(resData['msg']);
  274. }
  275. }
  276. bool isAdd(int type) {
  277. if (widget.type == 1) {
  278. return type == 1 ||
  279. type == 2 ||
  280. type == 3 ||
  281. type == 12 ||
  282. type == 13 ||
  283. type == 14;
  284. } else {
  285. return !(type == 1 || type == 2);
  286. }
  287. }
  288. //钱包通知
  289. Widget _buildMoneyInfo(data) {
  290. print(data);
  291. String imgUrl = data['HeadImg'] == null ||
  292. data['HeadImg'] == '' ||
  293. data['ChangeUserId'] == 0
  294. ? UserData().basicInfo.headimgurl
  295. : data['HeadImg'];
  296. return _ConversationItem(
  297. conversation: Conversation(
  298. avatar: imgUrl,
  299. title: '',
  300. desc: WebData().getLoginTime(context, data['CreateTime']),
  301. updateAt: '',
  302. ),
  303. bgColor: Constants.MoneyGradient,
  304. //余额Status 0=交易成功,1=系统退回
  305. //收入 0=冻结 ,1=成功 ,2= 退回
  306. //冻结和成功,你都可以表示成功
  307. showReturn: (widget.type == 1 && data['Status'] == 1) ||
  308. (widget.type == 2 && data['Status'] == 2 && data['DetailType'] != 1),
  309. isInCome: widget.type == 2,
  310. money: isAdd(data['DetailType']) ? data['Value'] : -data['Value'],
  311. title: RichTitle.getRichTitleWidget(data, context,
  312. widget.type == 1 ? InfoType.MyMoney : InfoType.IncomeMoney,
  313. titleStyle: TextStyle(fontSize: 12, color: const Color(0XFF7F7F7F)),
  314. nameStyle: TextStyle(
  315. fontWeight: FontWeight.normal,
  316. fontSize: 13,
  317. color: Constants.BlackTextColor)),
  318. callback: () {
  319. if (data['ChangeUserId'] != 0) {
  320. Navigator.of(context).push(
  321. new MaterialPageRoute(
  322. builder: (context) {
  323. return ProfilePage(
  324. userId: data['UserId'] == UserData().basicInfo.userId
  325. ? data['ChangeUserId']
  326. : data['UserId'],
  327. );
  328. },
  329. ),
  330. );
  331. }
  332. },
  333. );
  334. }
  335. Widget _renderRow(BuildContext context, int index) {
  336. if (index < list.length) {
  337. var userInfo = list[index];
  338. Widget result = _buildMoneyInfo(userInfo);
  339. if (index == 0) {
  340. result = Padding(padding: EdgeInsets.only(top: 10), child: result);
  341. }
  342. return result;
  343. }
  344. return Container();
  345. }
  346. Widget _buildCoinBody() {
  347. return SmartRefresher(
  348. enablePullDown: true,
  349. enablePullUp: true,
  350. header: MaterialClassicHeader(),
  351. footer: CustomUI.buildLoadingFooter(),
  352. controller: _refreshController,
  353. onRefresh: _onRefresh,
  354. onLoading: _onLoading,
  355. child: (_refreshController.headerStatus == RefreshStatus.completed &&
  356. list.length == 0)
  357. ? CustomUI.buildNoData(context)
  358. : ListView.builder(
  359. itemBuilder: _renderRow,
  360. itemCount: list.length,
  361. ),
  362. );
  363. }
  364. static String currentGoodsId = '';
  365. static StreamSubscription _conectionSubscription,
  366. _purchaseUpdatedSubscription,
  367. _purchaseErrorSubscription;
  368. ///ios 内购初始化
  369. static Future initPayConf(BuildContext context) async {
  370. if (_purchaseErrorSubscription != null) {
  371. return;
  372. }
  373. // prepare
  374. print('initPayConf -------- start: ');
  375. var result = await FlutterInappPurchase.instance.initConnection;
  376. print('initPayConf -------- result: $result');
  377. FlutterInappPurchase.instance.clearTransactionIOS();
  378. _conectionSubscription =
  379. FlutterInappPurchase.connectionUpdated.listen((connected) {
  380. print('connected: $connected');
  381. });
  382. _purchaseUpdatedSubscription =
  383. FlutterInappPurchase.purchaseUpdated.listen((productItem) {
  384. print('支付成功,成功回调 ------ purchase-updated: $productItem');
  385. // showToast('支付成功,成功回调 ------ purchase-updated: $productItem');
  386. if (productItem.transactionReceipt != null &&
  387. productItem.transactionReceipt.isNotEmpty) {
  388. HttpUtil().createOrder(currentGoodsId, productItem.transactionReceipt,
  389. productItem.purchaseToken,
  390. context: context);
  391. showToast(I18n.of(context).payment_successful);
  392. }
  393. Navigator.of(context).pop();
  394. });
  395. _purchaseErrorSubscription =
  396. FlutterInappPurchase.purchaseError.listen((purchaseError) {
  397. // showToast('支付失败回调 -------- purchase-error: $purchaseError');
  398. FlutterInappPurchase.instance.clearTransactionIOS();
  399. Navigator.of(context).pop();
  400. });
  401. }
  402. }