msg_page.dart 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695
  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. bottom: false,
  206. child: Stack(
  207. children: [
  208. Container(
  209. height: 50,
  210. child: Text(
  211. '消息',
  212. style: TextStyle(color: Colors.white, fontSize: 16),
  213. ),
  214. alignment: Alignment.center,
  215. ),
  216. ],
  217. alignment: Alignment.topCenter,
  218. ),
  219. ),
  220. alignment: Alignment.topCenter,
  221. ),
  222. Container(
  223. decoration: BoxDecoration(
  224. color: Colors.white,
  225. borderRadius: BorderRadius.only(
  226. topLeft: Radius.circular(16),
  227. topRight: Radius.circular(16),
  228. ),
  229. ),
  230. margin:
  231. EdgeInsets.only(top: MediaQuery.of(context).padding.top + 50),
  232. child: SmartRefresher(
  233. onRefresh: onRefresh,
  234. controller: controller,
  235. child: lastMsg.length == 0 && !haveSysMsg
  236. ? SingleChildScrollView(child: noData())
  237. : ListView.builder(
  238. itemBuilder: (c, index) {
  239. // if (index == 0) {
  240. // return msgItems(null);
  241. // } else {
  242. return msgItems(lastMsg[index]);
  243. // }
  244. },
  245. itemCount: lastMsg.length,
  246. padding: EdgeInsets.only(bottom: 65),
  247. ),
  248. ),
  249. )
  250. ],
  251. ),
  252. ),
  253. );
  254. }
  255. @override
  256. // TODO: implement wantKeepAlive
  257. bool get wantKeepAlive => true;
  258. Widget msgItems(MessageBeanContent data) {
  259. // if (data == null) {
  260. // return GestureDetector(
  261. // onTap: () {
  262. // MyTools().toPage(context, PlatformAssistantPage(), (then) {});
  263. // },
  264. // behavior: HitTestBehavior.translucent,
  265. // child: Container(
  266. // height: 73,
  267. // child: Column(
  268. // children: [
  269. // Expanded(
  270. // child: Row(
  271. // children: [
  272. // Container(
  273. // margin: EdgeInsets.only(left: 14, right: 14),
  274. // child: SvgPicture.asset(
  275. // 'images/svg/平台助手.svg',
  276. // height: 45,
  277. // width: 45,
  278. // ),
  279. // ),
  280. // Expanded(
  281. // child: Container(
  282. // height: 45,
  283. // padding: EdgeInsets.only(right: 14),
  284. // child: Column(
  285. // children: [
  286. // Text(
  287. // '平台助手',
  288. // style: TextStyle(
  289. // color: MyColors.c333333, fontSize: 15),
  290. // ),
  291. // Row(
  292. // children: [
  293. // Expanded(
  294. // child: Text(
  295. // '你有一条新的申请消息',
  296. // style: TextStyle(
  297. // color: MyColors.c888888, fontSize: 12),
  298. // ),
  299. // ),
  300. // Container(
  301. // decoration: BoxDecoration(
  302. // color: MyColors.cFF4233,
  303. // borderRadius:
  304. // BorderRadius.all(Radius.circular(4))),
  305. // height: 8,
  306. // width: 8,
  307. // padding: EdgeInsets.only(left: 5, right: 5),
  308. // alignment: Alignment.center,
  309. // )
  310. // ],
  311. // )
  312. // ],
  313. // mainAxisAlignment: MainAxisAlignment.spaceBetween,
  314. // crossAxisAlignment: CrossAxisAlignment.start,
  315. // ),
  316. // ),
  317. // )
  318. // ],
  319. // ),
  320. // ),
  321. // Container(
  322. // margin: EdgeInsets.only(left: 73, right: 14),
  323. // height: 0.5,
  324. // color: MyColors.cE7E7E7,
  325. // )
  326. // ],
  327. // mainAxisAlignment: MainAxisAlignment.spaceBetween,
  328. // ),
  329. // ),
  330. // );
  331. // } else {
  332. String pic;
  333. String name;
  334. int uid;
  335. MyShopBeanDataData chatWith = MyShopBeanDataData();
  336. if (data.senderUid == MyCookie().getUID()) {
  337. pic = data.receiverPic;
  338. name = data.receiverName;
  339. uid = data.receiverUid;
  340. chatWith.userName = data.receiverName;
  341. chatWith.userUid = data.receiverUid;
  342. chatWith.userPic = data.receiverPic;
  343. } else {
  344. pic = data.senderPic;
  345. name = data.senderName;
  346. uid = data.senderUid;
  347. chatWith.userName = data.senderName;
  348. chatWith.userUid = data.senderUid;
  349. chatWith.userPic = data.senderPic;
  350. }
  351. if (data.senderUid == -1) {
  352. return Slidable(
  353. actionPane: SlidableDrawerActionPane(),
  354. actionExtentRatio: 0.25,
  355. child: GestureDetector(
  356. onTap: () {
  357. MyTools().toPage(context, SystemInformationPage(), (then) {});
  358. },
  359. behavior: HitTestBehavior.translucent,
  360. child: Container(
  361. height: 73,
  362. child: Column(
  363. children: [
  364. Expanded(
  365. child: Row(
  366. children: [
  367. Container(
  368. margin: EdgeInsets.only(left: 14, right: 14),
  369. child: ClipRRect(
  370. child: SvgPicture.asset(
  371. 'images/svg/平台助手.svg',
  372. height: 45,
  373. width: 45,
  374. ),
  375. borderRadius: BorderRadius.all(Radius.circular(4)),
  376. ),
  377. ),
  378. Expanded(
  379. child: Container(
  380. height: 45,
  381. padding: EdgeInsets.only(right: 14),
  382. child: Column(
  383. children: [
  384. Row(
  385. children: [
  386. Expanded(
  387. child: Text(
  388. '系统消息',
  389. style: TextStyle(
  390. color: MyColors.c333333,
  391. fontSize: 15),
  392. ),
  393. ),
  394. Text(
  395. '',
  396. style: TextStyle(
  397. color: MyColors.c888888, fontSize: 12),
  398. ),
  399. ],
  400. ),
  401. Row(
  402. children: [
  403. Expanded(
  404. child: Text(
  405. data.content,
  406. style: TextStyle(
  407. color: MyColors.c888888,
  408. fontSize: 12),
  409. maxLines: 1,
  410. overflow: TextOverflow.ellipsis,
  411. softWrap: true,
  412. ),
  413. ),
  414. ],
  415. )
  416. ],
  417. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  418. ),
  419. ),
  420. )
  421. ],
  422. ),
  423. ),
  424. Container(
  425. margin: EdgeInsets.only(left: 73, right: 14),
  426. height: 0.5,
  427. color: MyColors.cE7E7E7,
  428. )
  429. ],
  430. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  431. ),
  432. ),
  433. ),
  434. secondaryActions: <Widget>[
  435. SlideAction(
  436. child: Container(
  437. child: Container(
  438. decoration: BoxDecoration(
  439. borderRadius: BorderRadius.circular(30),
  440. color: MyColors.cFF4233,
  441. ),
  442. height: 40,
  443. width: 40,
  444. child: SvgPicture.asset(
  445. 'images/svg/del.svg',
  446. height: 25,
  447. width: 25,
  448. ),
  449. alignment: Alignment.center,
  450. ),
  451. ),
  452. onTap: () {
  453. showSimpleDialog('是否删除系统消息', context, () async {
  454. Navigator.pop(context);
  455. MyCookie().prefs.remove('${MyCookie().getUID()}系统消息');
  456. chatRoom.remove('系统消息');
  457. lastMsg.remove(data);
  458. setState(() {});
  459. queryChatRoom();
  460. });
  461. },
  462. )
  463. ],
  464. );
  465. } else {
  466. return Slidable(
  467. actionPane: SlidableDrawerActionPane(),
  468. actionExtentRatio: 0.25,
  469. child: GestureDetector(
  470. onTap: () {
  471. MyTools().toPage(context, ChatPage(chatWith, null), (then) {
  472. var now = new DateTime.now();
  473. MyCookie().prefs.setString(
  474. '${MyCookie().getUID()}_${chatWith.userUid}',
  475. now.toString().substring(0, 19));
  476. queryChatRoom();
  477. });
  478. },
  479. behavior: HitTestBehavior.translucent,
  480. child: Container(
  481. height: 73,
  482. child: Column(
  483. children: [
  484. Expanded(
  485. child: Row(
  486. children: [
  487. Container(
  488. margin: EdgeInsets.only(left: 14, right: 14),
  489. child: ClipRRect(
  490. child: uid == 0
  491. ? Image.asset(
  492. 'images/app_logo.png',
  493. height: 45,
  494. width: 45,
  495. )
  496. : MyViews().netImg(imgURL(pic), 45, 45,
  497. placeholder: 'images/svg/占位图.svg'),
  498. borderRadius: BorderRadius.all(Radius.circular(4)),
  499. ),
  500. ),
  501. Expanded(
  502. child: Container(
  503. height: 45,
  504. padding: EdgeInsets.only(right: 14),
  505. child: Column(
  506. children: [
  507. Row(
  508. children: [
  509. Expanded(
  510. child: Text(
  511. uid == 0 ? '客服' : name,
  512. style: TextStyle(
  513. color: MyColors.c333333, fontSize: 15),
  514. )),
  515. Text(
  516. data.sentAt,
  517. style: TextStyle(
  518. color: MyColors.c888888, fontSize: 12),
  519. ),
  520. ],
  521. ),
  522. Row(
  523. children: [
  524. Expanded(
  525. child: Text(
  526. data.type != chatMsgTypeText
  527. ? '[${data.type}]'
  528. : data.content,
  529. style: TextStyle(
  530. color: MyColors.c888888,
  531. fontSize: 12),
  532. maxLines: 1,
  533. overflow: TextOverflow.ellipsis,
  534. softWrap: true,
  535. ),
  536. ),
  537. Visibility(
  538. visible: showRedPoint(
  539. chatWith.userUid, data.sentAt),
  540. child: Container(
  541. decoration: BoxDecoration(
  542. color: MyColors.cFF4233,
  543. borderRadius: BorderRadius.all(
  544. Radius.circular(4))),
  545. height: 8,
  546. width: 8,
  547. padding:
  548. EdgeInsets.only(left: 5, right: 5),
  549. alignment: Alignment.center,
  550. ),
  551. )
  552. ],
  553. )
  554. ],
  555. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  556. ),
  557. ),
  558. )
  559. ],
  560. ),
  561. ),
  562. Container(
  563. margin: EdgeInsets.only(left: 73, right: 14),
  564. height: 0.5,
  565. color: MyColors.cE7E7E7,
  566. )
  567. ],
  568. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  569. ),
  570. ),
  571. ),
  572. secondaryActions: <Widget>[
  573. SlideAction(
  574. child: Container(
  575. child: Container(
  576. decoration: BoxDecoration(
  577. borderRadius: BorderRadius.circular(30),
  578. color: MyColors.cFF4233,
  579. ),
  580. height: 40,
  581. width: 40,
  582. child: SvgPicture.asset(
  583. 'images/svg/del.svg',
  584. height: 25,
  585. width: 25,
  586. ),
  587. alignment: Alignment.center,
  588. ),
  589. ),
  590. onTap: () {
  591. showSimpleDialog(
  592. '将删除与(${name.isEmpty ? '客服' : name})的聊天记录,确认删除?', context,
  593. () async {
  594. Navigator.pop(context);
  595. MsgDB msgDB = MsgDB('table${MyCookie().getUID()}_$uid');
  596. await msgDB.deleteTableData();
  597. chatRoom.remove(uid);
  598. lastMsg.remove(data);
  599. setState(() {});
  600. queryChatRoom();
  601. });
  602. },
  603. )
  604. ],
  605. );
  606. }
  607. // }
  608. }
  609. Map chatRoom = Map();
  610. List<MessageBeanContent> lastMsg = [];
  611. queryChatRoom() async {
  612. List<Map<String, dynamic>> map = await SqlManager.allTables();
  613. map.forEach((element) async {
  614. TableBeanEntity table =
  615. TableBeanEntity().fromJson(json.decode(json.encode(element)));
  616. if (table.name.contains('table${MyCookie().getUID()}_')) {
  617. MsgDB msgDB = MsgDB(table.name);
  618. List<Map<String, dynamic>> maps = await msgDB.queryTableData(1, 1);
  619. maps.forEach((element) {
  620. print(json.encode(element));
  621. MessageBeanContent msg =
  622. MessageBeanContent().fromJson(json.decode(json.encode(element)));
  623. if (msg.senderUid == MyCookie().getUID()) {
  624. print(msg.receiverUid);
  625. chatRoom[msg.receiverUid] = msg;
  626. } else {
  627. print(msg.senderUid);
  628. chatRoom[msg.senderUid] = msg;
  629. }
  630. lastMsg.clear();
  631. chatRoom.forEach((key, value) {
  632. lastMsg.add(value);
  633. });
  634. lastMsg.sort((left, right) {
  635. if (left.senderUid == -1) {
  636. return -1;
  637. } else if (right.senderUid == -1) {
  638. return 1;
  639. } else {
  640. return right.sentAt.compareTo(left.sentAt);
  641. }
  642. });
  643. setState(() {});
  644. });
  645. }
  646. });
  647. systemInformation =
  648. MyCookie().prefs.getString('${MyCookie().getUID()}系统消息');
  649. if (systemInformation != null) {
  650. print(systemInformation);
  651. MessageBeanContent sysMsg = MessageBeanContent();
  652. sysMsg.senderName = '系统消息';
  653. sysMsg.senderUid = -1;
  654. sysMsg.content = systemInformation.split('!@##@!')[0];
  655. chatRoom['系统消息'] = sysMsg;
  656. if (!lastMsg.any((element) => element.senderUid == -1)) {
  657. lastMsg.insert(0, chatRoom['系统消息']);
  658. }
  659. }
  660. setState(() {
  661. });
  662. endRe(controller);
  663. }
  664. void onRefresh() {
  665. queryChatRoom();
  666. }
  667. showRedPoint(int userUid, String sentAt) {
  668. try {
  669. String lastTime =
  670. MyCookie().prefs.getString('${MyCookie().getUID()}_$userUid');
  671. print('--------------');
  672. print(lastTime);
  673. print(sentAt);
  674. print('--------------');
  675. return lastTime.compareTo(sentAt) == -1;
  676. } catch (e) {
  677. return true;
  678. }
  679. }
  680. }