Hibok
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

373 line
11 KiB

  1. import 'package:cached_network_image/cached_network_image.dart';
  2. import 'package:chat/data/UserData.dart';
  3. import 'package:chat/data/constants.dart';
  4. import 'package:chat/generated/i18n.dart';
  5. import 'package:chat/models/list_msg_model.dart';
  6. import 'package:chat/r.dart';
  7. import 'package:chat/utils/CustomUI.dart';
  8. import 'package:chat/utils/HttpUtil.dart';
  9. import 'package:chat/utils/TokenMgr.dart';
  10. import 'package:chat/utils/screen.dart';
  11. import 'package:dio/dio.dart';
  12. import 'package:flutter/material.dart';
  13. import 'package:oktoast/oktoast.dart';
  14. import 'package:url_launcher/url_launcher.dart';
  15. class QuestionModel {
  16. final String question;
  17. final int index;
  18. QuestionModel({this.question, this.index});
  19. QuestionModel.fromJson(Map<String, dynamic> json)
  20. : question = json['Question'],
  21. index = json['Number'];
  22. }
  23. class ServiceMsgModel {
  24. final bool isMe;
  25. final List<String> msg;
  26. ServiceMsgModel({this.isMe, this.msg});
  27. }
  28. class ServiceCenterPage extends StatefulWidget {
  29. final int questionIndex;
  30. ServiceCenterPage({this.questionIndex = -1});
  31. @override
  32. _ServiceCenterPageState createState() => _ServiceCenterPageState();
  33. }
  34. class _ServiceCenterPageState extends State<ServiceCenterPage> {
  35. final TextEditingController _textCtrl = new TextEditingController();
  36. List<QuestionModel> questions = [];
  37. ScrollController _scrollCtrl = new ScrollController();
  38. ListModel<ServiceMsgModel> _list;
  39. GlobalKey<AnimatedListState> _listKey = GlobalKey<AnimatedListState>();
  40. @override
  41. void initState() {
  42. super.initState();
  43. _list = ListModel<ServiceMsgModel>(
  44. listKey: _listKey,
  45. initialItems: [],
  46. );
  47. getAllQuestions();
  48. }
  49. @override
  50. void dispose() {
  51. _listKey = null;
  52. _scrollCtrl.dispose();
  53. super.dispose();
  54. }
  55. @override
  56. Widget build(BuildContext context) {
  57. return Scaffold(
  58. appBar: AppBar(
  59. backgroundColor: AppColors.NewAppbarBgColor,
  60. leading: CustomUI.buildCustomLeading(context),
  61. title: Text(
  62. I18n.of(context).help,
  63. textScaleFactor: 1.0,
  64. style: TextStyle(color: AppColors.NewAppbarTextColor),
  65. ),
  66. centerTitle: true,
  67. ),
  68. body: SafeArea(
  69. child: Column(
  70. children: <Widget>[
  71. Expanded(
  72. child: GestureDetector(
  73. onTap: () {
  74. print('隐藏FocusNode');
  75. FocusScope.of(context).requestFocus(FocusNode());
  76. setState(() {});
  77. },
  78. child: _buildMessageList())),
  79. _buildTextComposer(),
  80. ],
  81. )),
  82. );
  83. }
  84. getAllQuestions() async {
  85. Map data = {
  86. "language": UserData().language,
  87. };
  88. data['sign'] = TokenMgr().getSign(data);
  89. Response res = await HttpUtil().post('message/staff/question', data: data);
  90. var resData = res.data;
  91. if (resData['code'] == 0) {
  92. questions = resData['data']
  93. .map<QuestionModel>((v) => QuestionModel.fromJson(v))
  94. .toList();
  95. String userName;
  96. if (UserData().isMan()) {
  97. userName = I18n.of(context).man_vi;
  98. } else {
  99. userName = I18n.of(context).women_vi;
  100. }
  101. var allTexts = ['$userName,${I18n.of(context).kf_tips}'];
  102. for (var i = 0; i < questions.length; i++) {
  103. allTexts.add(questions[i].question);
  104. }
  105. _list.add(ServiceMsgModel(isMe: false, msg: allTexts));
  106. ///自动发送提问
  107. if (widget.questionIndex != -1) {
  108. _textCtrl.text = widget.questionIndex.toString();
  109. sendMessage();
  110. }
  111. }
  112. }
  113. buildQuestions(msg) {
  114. if (questions == null) {
  115. return Container();
  116. }
  117. return Row(
  118. crossAxisAlignment: CrossAxisAlignment.start,
  119. children: <Widget>[
  120. ClipRRect(
  121. child: Image.asset(R.assetsImagesServiceIcon),
  122. borderRadius: BorderRadius.circular(8),
  123. ),
  124. SizedBox(width: 8),
  125. Container(
  126. width: Screen.width - 120,
  127. padding: EdgeInsets.symmetric(vertical: 10, horizontal: 5),
  128. decoration: BoxDecoration(
  129. color: Colors.white, borderRadius: BorderRadius.circular(10)),
  130. child: Column(
  131. crossAxisAlignment: CrossAxisAlignment.start,
  132. children: msg
  133. .map<Widget>((text) => Container(
  134. child: Text(text,
  135. textScaleFactor: 1.0,
  136. style: TextStyle(fontSize: 13)),
  137. ))
  138. .toList()))
  139. ],
  140. );
  141. }
  142. getAnswerWith(int index) async {
  143. Map data = {"language": UserData().language, "number": index};
  144. data['sign'] = TokenMgr().getSign(data);
  145. Response res = await HttpUtil().post('message/staff/answer', data: data);
  146. var resData = res.data;
  147. if (resData['code'] == 0) {
  148. _list.add(ServiceMsgModel(isMe: false, msg: [resData['data']]));
  149. } else {
  150. print(resData['msg']);
  151. }
  152. }
  153. buildAnswer(msg) {
  154. String answer = msg[0];
  155. print('anser a$answer');
  156. String sign = '';
  157. bool isHttp = answer.trim().startsWith('http');
  158. if (isHttp) {
  159. answer = I18n.of(context).service_withdraw_tips;
  160. Map data = {
  161. "userId": UserData().basicInfo.userId,
  162. "language": UserData().language,
  163. };
  164. sign = TokenMgr().getSign(data);
  165. print(
  166. '@@@@@@ sign $sign ${UserData().basicInfo.userId} ${UserData().language}');
  167. }
  168. return Row(
  169. crossAxisAlignment: CrossAxisAlignment.start,
  170. children: <Widget>[
  171. ClipRRect(
  172. child: Image.asset(R.assetsImagesServiceIcon),
  173. borderRadius: BorderRadius.circular(8),
  174. ),
  175. SizedBox(width: 8),
  176. Container(
  177. width: Screen.width - 120,
  178. padding: EdgeInsets.symmetric(vertical: 10, horizontal: 5),
  179. decoration: BoxDecoration(
  180. color: Colors.white, borderRadius: BorderRadius.circular(10)),
  181. child: isHttp
  182. ? Container(
  183. child: Column(
  184. children: <Widget>[
  185. Text(answer,
  186. textScaleFactor: 1.0,
  187. style: TextStyle(fontSize: 13)),
  188. SizedBox(
  189. height: 6,
  190. ),
  191. GestureDetector(
  192. child: Text(I18n.of(context).withdraw_tips,
  193. textScaleFactor: 1.0,
  194. style:
  195. TextStyle(fontSize: 13, color: Colors.blue)),
  196. onTap: () async {
  197. String url = msg[0] +
  198. '/Bank/Getlanguage?userId=${UserData().basicInfo.userId}&language=${UserData().language}&sign=$sign';
  199. print('url :$url');
  200. await launch(url);
  201. },
  202. ),
  203. ],
  204. ),
  205. )
  206. : Container(
  207. child: Text(msg[0],
  208. textScaleFactor: 1.0, style: TextStyle(fontSize: 13)),
  209. ))
  210. ],
  211. );
  212. }
  213. _buildMessageList() {
  214. return AnimatedList(
  215. key: _listKey,
  216. initialItemCount: _list.length,
  217. controller: _scrollCtrl,
  218. padding: EdgeInsets.symmetric(horizontal: 8, vertical: 10),
  219. itemBuilder: _buildItem,
  220. );
  221. }
  222. Widget _buildItem(
  223. BuildContext context, int index, Animation<double> animation) {
  224. ServiceMsgModel msg = _list[index];
  225. Widget item;
  226. if (index == 0) {
  227. item = buildQuestions(msg.msg);
  228. } else {
  229. if (msg.isMe) {
  230. item = buildSendMsg(msg.msg.first);
  231. } else {
  232. item = buildAnswer(msg.msg);
  233. }
  234. }
  235. return SizeTransition(
  236. sizeFactor:
  237. CurvedAnimation(parent: animation, curve: Curves.decelerate),
  238. axisAlignment: -2,
  239. child: Padding(padding: EdgeInsets.only(bottom: 10), child: item));
  240. }
  241. Future<Null> _textMessageSubmitted(String text) async {
  242. sendMessage();
  243. }
  244. buildSendMsg(msg) {
  245. return Row(
  246. mainAxisAlignment: MainAxisAlignment.end,
  247. crossAxisAlignment: CrossAxisAlignment.start,
  248. children: <Widget>[
  249. Container(
  250. constraints: BoxConstraints(maxWidth: Screen.width - 120),
  251. child: Text(msg,
  252. textScaleFactor: 1.0, style: TextStyle(color: Colors.white)),
  253. padding: EdgeInsets.symmetric(horizontal: 15, vertical: 12),
  254. decoration: BoxDecoration(
  255. boxShadow: [
  256. BoxShadow(
  257. color: Colors.blue[200],
  258. offset: Offset(0, 2),
  259. blurRadius: 3.0),
  260. ],
  261. color: Color(0xFF377dfe),
  262. borderRadius: BorderRadius.only(
  263. bottomLeft: Radius.circular(15),
  264. topLeft: Radius.circular(15),
  265. bottomRight: Radius.circular(15),
  266. )),
  267. ),
  268. SizedBox(width: 5),
  269. Container(
  270. width: 40,
  271. height: 40,
  272. child: ClipRRect(
  273. borderRadius: BorderRadius.circular(8),
  274. child: CachedNetworkImage(
  275. imageUrl: UserData().basicInfo.headimgurl,
  276. placeholder: (context, url) =>
  277. Image.asset(R.assetsImagesDefaultNorAvatar),
  278. ))),
  279. ],
  280. );
  281. }
  282. sendMessage() {
  283. var text = _textCtrl.text;
  284. if (text.length > 0) {
  285. int index = int.parse(text);
  286. if (index > 0 && index <= questions.length) {
  287. _list.add(ServiceMsgModel(isMe: true, msg: [text]));
  288. getAnswerWith(index);
  289. _textCtrl.clear();
  290. } else {
  291. showToast(I18n.of(context).reinput);
  292. }
  293. }
  294. }
  295. _buildTextComposer() {
  296. return Container(
  297. alignment: Alignment.center,
  298. width: Screen.width,
  299. child: Row(
  300. children: <Widget>[
  301. Expanded(
  302. child: Container(
  303. child: TextField(
  304. keyboardAppearance: Brightness.light,
  305. onSubmitted: _textMessageSubmitted,
  306. controller: _textCtrl,
  307. keyboardType: TextInputType.number,
  308. cursorColor: Color.fromARGB(255, 0, 189, 96),
  309. style: TextStyle(
  310. fontSize: fixedFontSize(15),
  311. textBaseline: TextBaseline.alphabetic),
  312. ),
  313. decoration: BoxDecoration(
  314. color: Colors.grey[200],
  315. borderRadius: BorderRadius.circular(10),
  316. ),
  317. ),
  318. ),
  319. SizedBox(width: 5),
  320. SizedBox(
  321. child: OutlineButton(
  322. child: Text(I18n.of(context).send, textScaleFactor: 1.0),
  323. onPressed: sendMessage,
  324. ))
  325. ],
  326. ),
  327. padding: EdgeInsets.symmetric(horizontal: 10, vertical: 8),
  328. decoration: BoxDecoration(
  329. color: Colors.white,
  330. borderRadius: BorderRadius.only(
  331. topLeft: Radius.circular(8), topRight: Radius.circular(8)),
  332. ),
  333. );
  334. }
  335. }