msg_page.dart 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690
  1. import 'dart:convert';
  2. import 'package:bbyyy/beans/message_bean_entity.dart';
  3. import 'package:bbyyy/beans/my_shop_bean_entity.dart';
  4. import 'package:bbyyy/beans/table_bean_entity.dart';
  5. import 'package:bbyyy/https/url.dart';
  6. import 'package:bbyyy/msgDB/my_msg_db.dart';
  7. import 'package:bbyyy/msgDB/sql_manager.dart';
  8. import 'package:bbyyy/my_tools/const.dart';
  9. import 'package:bbyyy/my_tools/event_bus.dart';
  10. import 'package:bbyyy/my_tools/my_colors.dart';
  11. import 'package:bbyyy/my_tools/my_cookie.dart';
  12. import 'package:bbyyy/my_tools/my_tools.dart';
  13. import 'package:bbyyy/my_tools/my_views.dart';
  14. import 'package:bbyyy/paegs/chat_page/chat_page.dart';
  15. import 'package:bbyyy/paegs/system_information_page/system_information_page.dart';
  16. import 'package:flutter/cupertino.dart';
  17. import 'package:flutter/material.dart';
  18. import 'package:flutter_slidable/flutter_slidable.dart';
  19. import 'package:flutter_svg/svg.dart';
  20. import 'package:pull_to_refresh/pull_to_refresh.dart';
  21. class MsgPage extends StatefulWidget {
  22. @override
  23. _MsgPageState createState() => _MsgPageState();
  24. }
  25. class _MsgPageState extends State<MsgPage> with AutomaticKeepAliveClientMixin {
  26. var types = ['商品', '对象'];
  27. List<DropdownMenuItem<String>> sortItems = [];
  28. int typeIndex = 0;
  29. bool showInput = false;
  30. TextEditingController _description = TextEditingController();
  31. FocusNode _descriptionFocus = FocusNode();
  32. RefreshController controller = RefreshController(initialRefresh: true);
  33. bool haveSysMsg = false;
  34. var sysMsgRead = false;
  35. String systemInformation;
  36. @override
  37. void initState() {
  38. // TODO: implement initState
  39. super.initState();
  40. types.forEach((element) {
  41. sortItems.add(DropdownMenuItem(
  42. child: Text(
  43. element,
  44. style: TextStyle(color: MyColors.c666666, fontSize: 14),
  45. ),
  46. value: element,
  47. ));
  48. });
  49. _descriptionFocus.addListener(() {
  50. if (_descriptionFocus.hasFocus) {
  51. } else {
  52. if (_description.text.isEmpty) {
  53. setState(() {
  54. showInput = false;
  55. });
  56. }
  57. }
  58. });
  59. EventBus().on('hasNewMsgInMsgPage', (arg) {
  60. queryChatRoom();
  61. });
  62. EventBus().on('haveSysMsg', (arg) {
  63. haveSysMsg = true;
  64. setState(() {});
  65. });
  66. }
  67. @override
  68. void dispose() {
  69. // TODO: implement dispose
  70. super.dispose();
  71. EventBus().off('hasNewMsgInMsgPage');
  72. EventBus().off('haveSysMsg');
  73. }
  74. @override
  75. Widget build(BuildContext context) {
  76. return GestureDetector(
  77. onTap: () {
  78. MyTools().hideKeyboard(context);
  79. },
  80. behavior: HitTestBehavior.translucent,
  81. child: Scaffold(
  82. body: Stack(
  83. children: [
  84. Container(
  85. decoration: BoxDecoration(
  86. gradient: LinearGradient(
  87. colors: MyColors.lg,
  88. ),
  89. ),
  90. height: 152,
  91. // child: SafeArea(
  92. // child: Container(
  93. // decoration: BoxDecoration(
  94. // color: Colors.white,
  95. // borderRadius: BorderRadius.all(
  96. // Radius.circular(17),
  97. // ),
  98. // ),
  99. // height: 34,
  100. // child: Row(
  101. // children: [
  102. // DropdownButtonHideUnderline(
  103. // child: DropdownButton(
  104. // items: sortItems,
  105. // onChanged: (v) {
  106. // setState(() {
  107. // typeIndex = types.indexOf(v);
  108. // });
  109. // },
  110. // value: types[typeIndex],
  111. // ),
  112. // ),
  113. // Container(
  114. // height: 13,
  115. // width: 1,
  116. // decoration: BoxDecoration(
  117. // borderRadius: BorderRadius.all(
  118. // Radius.circular(0.5),
  119. // ),
  120. // color: MyColors.c979797),
  121. // ),
  122. // Expanded(
  123. // child: showInput
  124. // ? TextField(
  125. // controller: _description,
  126. // focusNode: _descriptionFocus,
  127. // cursorColor: MyColors.cFF4233,
  128. // cursorWidth: 1.0,
  129. // decoration: InputDecoration(
  130. // border: InputBorder.none,
  131. // disabledBorder: InputBorder.none,
  132. // enabledBorder: InputBorder.none,
  133. // focusedBorder: InputBorder.none,
  134. // isDense: true,
  135. // hintText: '请输入描述',
  136. // hintStyle: TextStyle(
  137. // color: MyColors.c999999, fontSize: 14),
  138. // contentPadding: const EdgeInsets.fromLTRB(
  139. // 14, 4.5, 8, 4.5),
  140. // ),
  141. // maxLines: 1,
  142. // style: TextStyle(
  143. // color: MyColors.c333333,
  144. // fontSize: 14,
  145. // height: 1.3,
  146. // letterSpacing: 0.2),
  147. // keyboardType: TextInputType.text,
  148. // onChanged: (t) {},
  149. // )
  150. // : GestureDetector(
  151. // onTap: () {
  152. // setState(() {
  153. // showInput = true;
  154. // });
  155. // Timer(Duration(milliseconds: 100), () {
  156. // FocusScope.of(context)
  157. // .requestFocus(_descriptionFocus);
  158. // });
  159. // },
  160. // behavior: HitTestBehavior.translucent,
  161. // child: Row(
  162. // children: [
  163. // Container(
  164. // child:
  165. // SvgPicture.asset('images/svg/搜索.svg'),
  166. // margin: EdgeInsets.only(right: 5),
  167. // ),
  168. // Text(
  169. // '请输入',
  170. // style: TextStyle(
  171. // color: MyColors.cBFBFBF,
  172. // fontSize: 14),
  173. // )
  174. // ],
  175. // mainAxisAlignment: MainAxisAlignment.center,
  176. // ),
  177. // ),
  178. // ),
  179. // Container(
  180. // decoration: BoxDecoration(
  181. // color: MyColors.cFF4233,
  182. // borderRadius: BorderRadius.all(
  183. // Radius.circular(17),
  184. // ),
  185. // ),
  186. // height: 34,
  187. // width: 76,
  188. // child: Text(
  189. // '搜索',
  190. // style: TextStyle(color: Colors.white, fontSize: 14),
  191. // ),
  192. // alignment: Alignment.center,
  193. // padding: EdgeInsets.only(bottom: 2),
  194. // )
  195. // ],
  196. // ),
  197. // margin: EdgeInsets.only(
  198. // left: 15,
  199. // right: 15,
  200. // top: 72 - MediaQuery.of(context).padding.top),
  201. // padding: EdgeInsets.only(left: 16),
  202. // ),
  203. // ),
  204. child: SafeArea(
  205. child: Stack(
  206. children: [
  207. Container(
  208. height: 50,
  209. child: Text(
  210. '消息',
  211. style: TextStyle(color: Colors.white, fontSize: 16),
  212. ),
  213. alignment: Alignment.center,
  214. ),
  215. ],
  216. alignment: Alignment.topCenter,
  217. ),
  218. ),
  219. alignment: Alignment.topCenter,
  220. ),
  221. Container(
  222. decoration: BoxDecoration(
  223. color: Colors.white,
  224. borderRadius: BorderRadius.only(
  225. topLeft: Radius.circular(16),
  226. topRight: Radius.circular(16),
  227. ),
  228. ),
  229. margin:
  230. EdgeInsets.only(top: MediaQuery.of(context).padding.top + 50),
  231. child: SmartRefresher(
  232. onRefresh: onRefresh,
  233. controller: controller,
  234. child: lastMsg.length == 0 && !haveSysMsg
  235. ? noData()
  236. : ListView.builder(
  237. itemBuilder: (c, index) {
  238. // if (index == 0) {
  239. // return msgItems(null);
  240. // } else {
  241. return msgItems(lastMsg[index]);
  242. // }
  243. },
  244. itemCount: lastMsg.length,
  245. padding: EdgeInsets.only(bottom: 65),
  246. ),
  247. ),
  248. )
  249. ],
  250. ),
  251. ),
  252. );
  253. }
  254. @override
  255. // TODO: implement wantKeepAlive
  256. bool get wantKeepAlive => true;
  257. Widget msgItems(MessageBeanContent data) {
  258. // if (data == null) {
  259. // return GestureDetector(
  260. // onTap: () {
  261. // MyTools().toPage(context, PlatformAssistantPage(), (then) {});
  262. // },
  263. // behavior: HitTestBehavior.translucent,
  264. // child: Container(
  265. // height: 73,
  266. // child: Column(
  267. // children: [
  268. // Expanded(
  269. // child: Row(
  270. // children: [
  271. // Container(
  272. // margin: EdgeInsets.only(left: 14, right: 14),
  273. // child: SvgPicture.asset(
  274. // 'images/svg/平台助手.svg',
  275. // height: 45,
  276. // width: 45,
  277. // ),
  278. // ),
  279. // Expanded(
  280. // child: Container(
  281. // height: 45,
  282. // padding: EdgeInsets.only(right: 14),
  283. // child: Column(
  284. // children: [
  285. // Text(
  286. // '平台助手',
  287. // style: TextStyle(
  288. // color: MyColors.c333333, fontSize: 15),
  289. // ),
  290. // Row(
  291. // children: [
  292. // Expanded(
  293. // child: Text(
  294. // '你有一条新的申请消息',
  295. // style: TextStyle(
  296. // color: MyColors.c888888, fontSize: 12),
  297. // ),
  298. // ),
  299. // Container(
  300. // decoration: BoxDecoration(
  301. // color: MyColors.cFF4233,
  302. // borderRadius:
  303. // BorderRadius.all(Radius.circular(4))),
  304. // height: 8,
  305. // width: 8,
  306. // padding: EdgeInsets.only(left: 5, right: 5),
  307. // alignment: Alignment.center,
  308. // )
  309. // ],
  310. // )
  311. // ],
  312. // mainAxisAlignment: MainAxisAlignment.spaceBetween,
  313. // crossAxisAlignment: CrossAxisAlignment.start,
  314. // ),
  315. // ),
  316. // )
  317. // ],
  318. // ),
  319. // ),
  320. // Container(
  321. // margin: EdgeInsets.only(left: 73, right: 14),
  322. // height: 0.5,
  323. // color: MyColors.cE7E7E7,
  324. // )
  325. // ],
  326. // mainAxisAlignment: MainAxisAlignment.spaceBetween,
  327. // ),
  328. // ),
  329. // );
  330. // } else {
  331. String pic;
  332. String name;
  333. int uid;
  334. MyShopBeanDataData chatWith = MyShopBeanDataData();
  335. if (data.senderUid == MyCookie().getUID()) {
  336. pic = data.receiverPic;
  337. name = data.receiverName;
  338. uid = data.receiverUid;
  339. chatWith.userName = data.receiverName;
  340. chatWith.userUid = data.receiverUid;
  341. chatWith.userPic = data.receiverPic;
  342. } else {
  343. pic = data.senderPic;
  344. name = data.senderName;
  345. uid = data.senderUid;
  346. chatWith.userName = data.senderName;
  347. chatWith.userUid = data.senderUid;
  348. chatWith.userPic = data.senderPic;
  349. }
  350. if (data.senderUid == -1) {
  351. return Slidable(
  352. actionPane: SlidableDrawerActionPane(),
  353. actionExtentRatio: 0.25,
  354. child: GestureDetector(
  355. onTap: () {
  356. MyTools().toPage(context, SystemInformationPage(), (then) {});
  357. },
  358. behavior: HitTestBehavior.translucent,
  359. child: Container(
  360. height: 73,
  361. child: Column(
  362. children: [
  363. Expanded(
  364. child: Row(
  365. children: [
  366. Container(
  367. margin: EdgeInsets.only(left: 14, right: 14),
  368. child: ClipRRect(
  369. child: Image.asset(
  370. 'images/app_logo.png',
  371. height: 45,
  372. width: 45,
  373. ),
  374. borderRadius: BorderRadius.all(Radius.circular(4)),
  375. ),
  376. ),
  377. Expanded(
  378. child: Container(
  379. height: 45,
  380. padding: EdgeInsets.only(right: 14),
  381. child: Column(
  382. children: [
  383. Row(
  384. children: [
  385. Expanded(
  386. child: Text(
  387. '系统消息',
  388. style: TextStyle(
  389. color: MyColors.c333333, fontSize: 15),
  390. )),
  391. Text(
  392. '',
  393. style: TextStyle(
  394. color: MyColors.c888888, fontSize: 12),
  395. ),
  396. ],
  397. ),
  398. Row(
  399. children: [
  400. Expanded(
  401. child: Text(
  402. data.content,
  403. style: TextStyle(
  404. color: MyColors.c888888,
  405. fontSize: 12),
  406. maxLines: 1,
  407. overflow: TextOverflow.ellipsis,
  408. softWrap: true,
  409. ),
  410. ),
  411. ],
  412. )
  413. ],
  414. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  415. ),
  416. ),
  417. )
  418. ],
  419. ),
  420. ),
  421. Container(
  422. margin: EdgeInsets.only(left: 73, right: 14),
  423. height: 0.5,
  424. color: MyColors.cE7E7E7,
  425. )
  426. ],
  427. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  428. ),
  429. ),
  430. ),
  431. secondaryActions: <Widget>[
  432. SlideAction(
  433. child: Container(
  434. child: Container(
  435. decoration: BoxDecoration(
  436. borderRadius: BorderRadius.circular(30),
  437. color: MyColors.cFF4233,
  438. ),
  439. height: 40,
  440. width: 40,
  441. child: SvgPicture.asset(
  442. 'images/svg/del.svg',
  443. height: 25,
  444. width: 25,
  445. ),
  446. alignment: Alignment.center,
  447. ),
  448. ),
  449. onTap: () {
  450. showSimpleDialog('是否删除系统消息', context, () async {
  451. Navigator.pop(context);
  452. MyCookie().prefs.remove('${MyCookie().getUID()}系统消息');
  453. chatRoom.remove('系统消息');
  454. lastMsg.remove(data);
  455. setState(() {});
  456. queryChatRoom();
  457. });
  458. },
  459. )
  460. ],
  461. );
  462. } else {
  463. return Slidable(
  464. actionPane: SlidableDrawerActionPane(),
  465. actionExtentRatio: 0.25,
  466. child: GestureDetector(
  467. onTap: () {
  468. MyTools().toPage(context, ChatPage(chatWith, null), (then) {
  469. var now = new DateTime.now();
  470. MyCookie().prefs.setString(
  471. '${MyCookie().getUID()}_${chatWith.userUid}',
  472. now.toString().substring(0, 19));
  473. queryChatRoom();
  474. });
  475. },
  476. behavior: HitTestBehavior.translucent,
  477. child: Container(
  478. height: 73,
  479. child: Column(
  480. children: [
  481. Expanded(
  482. child: Row(
  483. children: [
  484. Container(
  485. margin: EdgeInsets.only(left: 14, right: 14),
  486. child: ClipRRect(
  487. child: uid == 0
  488. ? Image.asset(
  489. 'images/app_logo.png',
  490. height: 45,
  491. width: 45,
  492. )
  493. : MyViews().netImg(imgURL(pic), 45, 45,
  494. placeholder: 'images/svg/占位图.svg'),
  495. borderRadius: BorderRadius.all(Radius.circular(4)),
  496. ),
  497. ),
  498. Expanded(
  499. child: Container(
  500. height: 45,
  501. padding: EdgeInsets.only(right: 14),
  502. child: Column(
  503. children: [
  504. Row(
  505. children: [
  506. Expanded(
  507. child: Text(
  508. uid == 0 ? '客服' : name,
  509. style: TextStyle(
  510. color: MyColors.c333333, fontSize: 15),
  511. )),
  512. Text(
  513. data.sentAt,
  514. style: TextStyle(
  515. color: MyColors.c888888, fontSize: 12),
  516. ),
  517. ],
  518. ),
  519. Row(
  520. children: [
  521. Expanded(
  522. child: Text(
  523. data.type != chatMsgTypeText
  524. ? '[${data.type}]'
  525. : data.content,
  526. style: TextStyle(
  527. color: MyColors.c888888,
  528. fontSize: 12),
  529. maxLines: 1,
  530. overflow: TextOverflow.ellipsis,
  531. softWrap: true,
  532. ),
  533. ),
  534. Visibility(
  535. visible: showRedPoint(
  536. chatWith.userUid, data.sentAt),
  537. child: Container(
  538. decoration: BoxDecoration(
  539. color: MyColors.cFF4233,
  540. borderRadius: BorderRadius.all(
  541. Radius.circular(4))),
  542. height: 8,
  543. width: 8,
  544. padding:
  545. EdgeInsets.only(left: 5, right: 5),
  546. alignment: Alignment.center,
  547. ),
  548. )
  549. ],
  550. )
  551. ],
  552. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  553. ),
  554. ),
  555. )
  556. ],
  557. ),
  558. ),
  559. Container(
  560. margin: EdgeInsets.only(left: 73, right: 14),
  561. height: 0.5,
  562. color: MyColors.cE7E7E7,
  563. )
  564. ],
  565. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  566. ),
  567. ),
  568. ),
  569. secondaryActions: <Widget>[
  570. SlideAction(
  571. child: Container(
  572. child: Container(
  573. decoration: BoxDecoration(
  574. borderRadius: BorderRadius.circular(30),
  575. color: MyColors.cFF4233,
  576. ),
  577. height: 40,
  578. width: 40,
  579. child: SvgPicture.asset(
  580. 'images/svg/del.svg',
  581. height: 25,
  582. width: 25,
  583. ),
  584. alignment: Alignment.center,
  585. ),
  586. ),
  587. onTap: () {
  588. showSimpleDialog(
  589. '将删除与(${name.isEmpty ? '客服' : name})的聊天记录,确认删除?', context,
  590. () async {
  591. Navigator.pop(context);
  592. MsgDB msgDB = MsgDB('table${MyCookie().getUID()}_$uid');
  593. await msgDB.deleteTableData();
  594. chatRoom.remove(uid);
  595. lastMsg.remove(data);
  596. setState(() {});
  597. queryChatRoom();
  598. });
  599. },
  600. )
  601. ],
  602. );
  603. }
  604. // }
  605. }
  606. Map chatRoom = Map();
  607. List<MessageBeanContent> lastMsg = [];
  608. queryChatRoom() async {
  609. List<Map<String, dynamic>> map = await SqlManager.allTables();
  610. map.forEach((element) async {
  611. TableBeanEntity table =
  612. TableBeanEntity().fromJson(json.decode(json.encode(element)));
  613. if (table.name.contains('table${MyCookie().getUID()}_')) {
  614. MsgDB msgDB = MsgDB(table.name);
  615. List<Map<String, dynamic>> maps = await msgDB.queryTableData(1, 1);
  616. maps.forEach((element) {
  617. print(json.encode(element));
  618. MessageBeanContent msg =
  619. MessageBeanContent().fromJson(json.decode(json.encode(element)));
  620. if (msg.senderUid == MyCookie().getUID()) {
  621. print(msg.receiverUid);
  622. chatRoom[msg.receiverUid] = msg;
  623. } else {
  624. print(msg.senderUid);
  625. chatRoom[msg.senderUid] = msg;
  626. }
  627. lastMsg.clear();
  628. chatRoom.forEach((key, value) {
  629. lastMsg.add(value);
  630. });
  631. lastMsg.sort((left, right) {
  632. if (left.senderUid == -1) {
  633. return -1;
  634. } else if (right.senderUid == -1) {
  635. return 1;
  636. } else {
  637. return right.sentAt.compareTo(left.sentAt);
  638. }
  639. });
  640. systemInformation =
  641. MyCookie().prefs.getString('${MyCookie().getUID()}系统消息');
  642. if (systemInformation != null) {
  643. print(systemInformation);
  644. MessageBeanContent sysMsg = MessageBeanContent();
  645. sysMsg.senderName = '系统消息';
  646. sysMsg.senderUid = -1;
  647. sysMsg.content = systemInformation.split('!@##@!')[0];
  648. chatRoom['系统消息'] = sysMsg;
  649. if (!lastMsg.any((element) => element.senderUid == -1)) {
  650. lastMsg.insert(0, chatRoom['系统消息']);
  651. }
  652. }
  653. setState(() {});
  654. });
  655. }
  656. });
  657. endRe(controller);
  658. }
  659. void onRefresh() {
  660. queryChatRoom();
  661. }
  662. showRedPoint(int userUid, String sentAt) {
  663. try {
  664. String lastTime =
  665. MyCookie().prefs.getString('${MyCookie().getUID()}_$userUid');
  666. print('--------------');
  667. print(lastTime);
  668. print(sentAt);
  669. print('--------------');
  670. return lastTime.compareTo(sentAt) == -1;
  671. } catch (e) {
  672. return true;
  673. }
  674. }
  675. }