msg_page.dart 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692
  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: SvgPicture.asset(
  370. 'images/svg/平台助手.svg',
  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,
  390. fontSize: 15),
  391. ),
  392. ),
  393. Text(
  394. '',
  395. style: TextStyle(
  396. color: MyColors.c888888, fontSize: 12),
  397. ),
  398. ],
  399. ),
  400. Row(
  401. children: [
  402. Expanded(
  403. child: Text(
  404. data.content,
  405. style: TextStyle(
  406. color: MyColors.c888888,
  407. fontSize: 12),
  408. maxLines: 1,
  409. overflow: TextOverflow.ellipsis,
  410. softWrap: true,
  411. ),
  412. ),
  413. ],
  414. )
  415. ],
  416. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  417. ),
  418. ),
  419. )
  420. ],
  421. ),
  422. ),
  423. Container(
  424. margin: EdgeInsets.only(left: 73, right: 14),
  425. height: 0.5,
  426. color: MyColors.cE7E7E7,
  427. )
  428. ],
  429. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  430. ),
  431. ),
  432. ),
  433. secondaryActions: <Widget>[
  434. SlideAction(
  435. child: Container(
  436. child: Container(
  437. decoration: BoxDecoration(
  438. borderRadius: BorderRadius.circular(30),
  439. color: MyColors.cFF4233,
  440. ),
  441. height: 40,
  442. width: 40,
  443. child: SvgPicture.asset(
  444. 'images/svg/del.svg',
  445. height: 25,
  446. width: 25,
  447. ),
  448. alignment: Alignment.center,
  449. ),
  450. ),
  451. onTap: () {
  452. showSimpleDialog('是否删除系统消息', context, () async {
  453. Navigator.pop(context);
  454. MyCookie().prefs.remove('${MyCookie().getUID()}系统消息');
  455. chatRoom.remove('系统消息');
  456. lastMsg.remove(data);
  457. setState(() {});
  458. queryChatRoom();
  459. });
  460. },
  461. )
  462. ],
  463. );
  464. } else {
  465. return Slidable(
  466. actionPane: SlidableDrawerActionPane(),
  467. actionExtentRatio: 0.25,
  468. child: GestureDetector(
  469. onTap: () {
  470. MyTools().toPage(context, ChatPage(chatWith, null), (then) {
  471. var now = new DateTime.now();
  472. MyCookie().prefs.setString(
  473. '${MyCookie().getUID()}_${chatWith.userUid}',
  474. now.toString().substring(0, 19));
  475. queryChatRoom();
  476. });
  477. },
  478. behavior: HitTestBehavior.translucent,
  479. child: Container(
  480. height: 73,
  481. child: Column(
  482. children: [
  483. Expanded(
  484. child: Row(
  485. children: [
  486. Container(
  487. margin: EdgeInsets.only(left: 14, right: 14),
  488. child: ClipRRect(
  489. child: uid == 0
  490. ? Image.asset(
  491. 'images/app_logo.png',
  492. height: 45,
  493. width: 45,
  494. )
  495. : MyViews().netImg(imgURL(pic), 45, 45,
  496. placeholder: 'images/svg/占位图.svg'),
  497. borderRadius: BorderRadius.all(Radius.circular(4)),
  498. ),
  499. ),
  500. Expanded(
  501. child: Container(
  502. height: 45,
  503. padding: EdgeInsets.only(right: 14),
  504. child: Column(
  505. children: [
  506. Row(
  507. children: [
  508. Expanded(
  509. child: Text(
  510. uid == 0 ? '客服' : name,
  511. style: TextStyle(
  512. color: MyColors.c333333, fontSize: 15),
  513. )),
  514. Text(
  515. data.sentAt,
  516. style: TextStyle(
  517. color: MyColors.c888888, fontSize: 12),
  518. ),
  519. ],
  520. ),
  521. Row(
  522. children: [
  523. Expanded(
  524. child: Text(
  525. data.type != chatMsgTypeText
  526. ? '[${data.type}]'
  527. : data.content,
  528. style: TextStyle(
  529. color: MyColors.c888888,
  530. fontSize: 12),
  531. maxLines: 1,
  532. overflow: TextOverflow.ellipsis,
  533. softWrap: true,
  534. ),
  535. ),
  536. Visibility(
  537. visible: showRedPoint(
  538. chatWith.userUid, data.sentAt),
  539. child: Container(
  540. decoration: BoxDecoration(
  541. color: MyColors.cFF4233,
  542. borderRadius: BorderRadius.all(
  543. Radius.circular(4))),
  544. height: 8,
  545. width: 8,
  546. padding:
  547. EdgeInsets.only(left: 5, right: 5),
  548. alignment: Alignment.center,
  549. ),
  550. )
  551. ],
  552. )
  553. ],
  554. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  555. ),
  556. ),
  557. )
  558. ],
  559. ),
  560. ),
  561. Container(
  562. margin: EdgeInsets.only(left: 73, right: 14),
  563. height: 0.5,
  564. color: MyColors.cE7E7E7,
  565. )
  566. ],
  567. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  568. ),
  569. ),
  570. ),
  571. secondaryActions: <Widget>[
  572. SlideAction(
  573. child: Container(
  574. child: Container(
  575. decoration: BoxDecoration(
  576. borderRadius: BorderRadius.circular(30),
  577. color: MyColors.cFF4233,
  578. ),
  579. height: 40,
  580. width: 40,
  581. child: SvgPicture.asset(
  582. 'images/svg/del.svg',
  583. height: 25,
  584. width: 25,
  585. ),
  586. alignment: Alignment.center,
  587. ),
  588. ),
  589. onTap: () {
  590. showSimpleDialog(
  591. '将删除与(${name.isEmpty ? '客服' : name})的聊天记录,确认删除?', context,
  592. () async {
  593. Navigator.pop(context);
  594. MsgDB msgDB = MsgDB('table${MyCookie().getUID()}_$uid');
  595. await msgDB.deleteTableData();
  596. chatRoom.remove(uid);
  597. lastMsg.remove(data);
  598. setState(() {});
  599. queryChatRoom();
  600. });
  601. },
  602. )
  603. ],
  604. );
  605. }
  606. // }
  607. }
  608. Map chatRoom = Map();
  609. List<MessageBeanContent> lastMsg = [];
  610. queryChatRoom() async {
  611. List<Map<String, dynamic>> map = await SqlManager.allTables();
  612. map.forEach((element) async {
  613. TableBeanEntity table =
  614. TableBeanEntity().fromJson(json.decode(json.encode(element)));
  615. if (table.name.contains('table${MyCookie().getUID()}_')) {
  616. MsgDB msgDB = MsgDB(table.name);
  617. List<Map<String, dynamic>> maps = await msgDB.queryTableData(1, 1);
  618. maps.forEach((element) {
  619. print(json.encode(element));
  620. MessageBeanContent msg =
  621. MessageBeanContent().fromJson(json.decode(json.encode(element)));
  622. if (msg.senderUid == MyCookie().getUID()) {
  623. print(msg.receiverUid);
  624. chatRoom[msg.receiverUid] = msg;
  625. } else {
  626. print(msg.senderUid);
  627. chatRoom[msg.senderUid] = msg;
  628. }
  629. lastMsg.clear();
  630. chatRoom.forEach((key, value) {
  631. lastMsg.add(value);
  632. });
  633. lastMsg.sort((left, right) {
  634. if (left.senderUid == -1) {
  635. return -1;
  636. } else if (right.senderUid == -1) {
  637. return 1;
  638. } else {
  639. return right.sentAt.compareTo(left.sentAt);
  640. }
  641. });
  642. systemInformation =
  643. MyCookie().prefs.getString('${MyCookie().getUID()}系统消息');
  644. if (systemInformation != null) {
  645. print(systemInformation);
  646. MessageBeanContent sysMsg = MessageBeanContent();
  647. sysMsg.senderName = '系统消息';
  648. sysMsg.senderUid = -1;
  649. sysMsg.content = systemInformation.split('!@##@!')[0];
  650. chatRoom['系统消息'] = sysMsg;
  651. if (!lastMsg.any((element) => element.senderUid == -1)) {
  652. lastMsg.insert(0, chatRoom['系统消息']);
  653. }
  654. }
  655. setState(() {});
  656. });
  657. }
  658. });
  659. endRe(controller);
  660. }
  661. void onRefresh() {
  662. queryChatRoom();
  663. }
  664. showRedPoint(int userUid, String sentAt) {
  665. try {
  666. String lastTime =
  667. MyCookie().prefs.getString('${MyCookie().getUID()}_$userUid');
  668. print('--------------');
  669. print(lastTime);
  670. print(sentAt);
  671. print('--------------');
  672. return lastTime.compareTo(sentAt) == -1;
  673. } catch (e) {
  674. return true;
  675. }
  676. }
  677. }