Hibok
Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.
 
 
 
 
 
 

439 Zeilen
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) || (widget.type == 2 && data['Status'] ==2),
  308. isInCome: widget.type == 2,
  309. money: isAdd(data['DetailType']) ? data['Value'] : -data['Value'],
  310. title: RichTitle.getRichTitleWidget(data, context,
  311. widget.type == 1 ? InfoType.MyMoney : InfoType.IncomeMoney,
  312. titleStyle: TextStyle(fontSize: 12, color: const Color(0XFF7F7F7F)),
  313. nameStyle: TextStyle(
  314. fontWeight: FontWeight.normal,
  315. fontSize: 13,
  316. color: Constants.BlackTextColor)),
  317. callback: () {
  318. if (data['ChangeUserId'] != 0) {
  319. Navigator.of(context).push(
  320. new MaterialPageRoute(
  321. builder: (context) {
  322. return ProfilePage(
  323. userId: data['UserId'] == UserData().basicInfo.userId
  324. ? data['ChangeUserId']
  325. : data['UserId'],
  326. );
  327. },
  328. ),
  329. );
  330. }
  331. },
  332. );
  333. }
  334. Widget _renderRow(BuildContext context, int index) {
  335. if (index < list.length) {
  336. var userInfo = list[index];
  337. Widget result = _buildMoneyInfo(userInfo);
  338. if (index == 0) {
  339. result = Padding(padding: EdgeInsets.only(top: 10), child: result);
  340. }
  341. return result;
  342. }
  343. return Container();
  344. }
  345. Widget _buildCoinBody() {
  346. return SmartRefresher(
  347. enablePullDown: true,
  348. enablePullUp: true,
  349. header: MaterialClassicHeader(),
  350. footer: CustomUI.buildLoadingFooter(),
  351. controller: _refreshController,
  352. onRefresh: _onRefresh,
  353. onLoading: _onLoading,
  354. child: (_refreshController.headerStatus == RefreshStatus.completed &&
  355. list.length == 0)
  356. ? CustomUI.buildNoData(context)
  357. : ListView.builder(
  358. itemBuilder: _renderRow,
  359. itemCount: list.length,
  360. ),
  361. );
  362. }
  363. static String currentGoodsId = '';
  364. static StreamSubscription _conectionSubscription,
  365. _purchaseUpdatedSubscription,
  366. _purchaseErrorSubscription;
  367. ///ios 内购初始化
  368. static Future initPayConf(BuildContext context) async {
  369. if (_purchaseErrorSubscription != null) {
  370. return;
  371. }
  372. // prepare
  373. print('initPayConf -------- start: ');
  374. var result = await FlutterInappPurchase.instance.initConnection;
  375. print('initPayConf -------- result: $result');
  376. FlutterInappPurchase.instance.clearTransactionIOS();
  377. _conectionSubscription =
  378. FlutterInappPurchase.connectionUpdated.listen((connected) {
  379. print('connected: $connected');
  380. });
  381. _purchaseUpdatedSubscription =
  382. FlutterInappPurchase.purchaseUpdated.listen((productItem) {
  383. print('支付成功,成功回调 ------ purchase-updated: $productItem');
  384. // showToast('支付成功,成功回调 ------ purchase-updated: $productItem');
  385. if (productItem.transactionReceipt != null &&
  386. productItem.transactionReceipt.isNotEmpty) {
  387. HttpUtil().createOrder(currentGoodsId, productItem.transactionReceipt,
  388. productItem.purchaseToken,
  389. context: context);
  390. showToast(I18n.of(context).payment_successful);
  391. }
  392. Navigator.of(context).pop();
  393. });
  394. _purchaseErrorSubscription =
  395. FlutterInappPurchase.purchaseError.listen((purchaseError) {
  396. // showToast('支付失败回调 -------- purchase-error: $purchaseError');
  397. FlutterInappPurchase.instance.clearTransactionIOS();
  398. Navigator.of(context).pop();
  399. });
  400. }
  401. }