index.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449
  1. <template>
  2. <view class="main">
  3. <view class="one">
  4. <!-- 聊天内容 -->
  5. <scroll-view class="scroll-view" scroll-y="true" scroll-with-animation="true"
  6. :scroll-into-view="scrollToView" refresher-enabled="true" :refresher-triggered="triggered"
  7. @refresherrefresh="getFresh">
  8. <view class="list-scroll-view">
  9. <view class="chat-ls" v-for="(item,index) in msgList" :key="index" :id="'msg'+ item._id">
  10. <view class="chat-time" v-if="item.time != ''">
  11. {{item.time}}
  12. </view>
  13. <view class="msg-m msg-left" v-if="item.speaker !=  user._id">
  14. <image class="user-img"
  15. :src="config.logo_url&&config.logo_url.length>0?config.logo_url[0].url:''">
  16. </image>
  17. <!-- 文字 -->
  18. <view class="message" v-if="item.msg_type =='0'">                           
  19. <view class="msg-text">{{item.content}}</view>
  20. </view>
  21. <!-- 图像 -->
  22. <view class="message img" v-else-if="item.msg_type =='1'" @tap="previewImg(item.content)">
  23. <image :src="item.content" class="msg-img" mode="widthFix"></image>
  24. </view>
  25. </view>
  26. <view class="msg-m msg-right" v-else-if="item.speaker == user._id">
  27. <image class="user-img" :src="user.logo&&user.logo.length>0?user.logo[0].url:''">
  28. </image>
  29. <!-- 文字 -->
  30. <view class="message" v-if="item.msg_type =='0'">
  31. <view class="msg-text">{{item.content}}</view>
  32. </view>
  33. <!-- 图像 -->
  34. <view class="message img" v-else-if="item.msg_type =='1'" @tap="previewImg(item.content)">
  35. <image :src="item.content" class="msg-img" mode="widthFix"></image>
  36. </view>
  37. </view>
  38. </view>
  39. <view class="problem" v-if="problemList.length>0" id="msg123456789">
  40. <view class="list" v-for="(item,index) in problemList" :key="index" @tap="toProblem(item)">
  41. <text>{{item.question}}</text>
  42. <text class="iconfont icon-dayuhao"></text>
  43. </view>
  44. </view>
  45. </view>
  46. </scroll-view>
  47. </view>
  48. <view class="two">
  49. <submit_1 @choseImg="choseImg" @inputs="inputs" @heights="heights"></submit_1>
  50. </view>
  51. </view>
  52. </template>
  53. <script>
  54. import moment from 'moment';
  55. import submit_1 from './common/submit_1.vue';
  56. export default {
  57. components: {
  58. submit_1,
  59. },
  60. data() {
  61. return {
  62. config: {},
  63. user: {},
  64. // 常见问题
  65. problemList: [],
  66. // 聊天记录
  67. msgList: [],
  68. total: 0,
  69. skip: 0,
  70. limit: 6,
  71. page: 0,
  72. // 判断是否跳到最后一条
  73. is_bottom: true,
  74. // 判断是否下拉刷新复位
  75. triggered: false,
  76. scrollToView: '', //滑动最后一条信息
  77. // 判断是否是选择图片刷新
  78. is_img: false
  79. }
  80. },
  81. onShow: async function() {
  82. const that = this;
  83. that.searchToken();
  84. that.searchConfig();
  85. // 判断是否是选择图片刷新
  86. if (!that.is_img) {
  87. await that.clearPage();
  88. await that.search()
  89. }
  90. },
  91. onPullDownRefresh: async function() {
  92. const that = this;
  93. that.clearPage();
  94. await that.search();
  95. uni.stopPullDownRefresh();
  96. },
  97. methods: {
  98. searchToken() {
  99. const that = this;
  100. try {
  101. const res = uni.getStorageSync('token');
  102. if (res) that.$set(that, `user`, res);
  103. } catch (e) {
  104. uni.showToast({
  105. title: err.errmsg,
  106. icon: 'error',
  107. duration: 2000
  108. });
  109. }
  110. },
  111. searchConfig() {
  112. const that = this;
  113. try {
  114. const res = uni.getStorageSync('config');
  115. if (res) that.$set(that, `config`, res);
  116. } catch (e) {
  117. uni.showToast({
  118. title: err.errmsg,
  119. icon: 'error',
  120. duration: 2000
  121. });
  122. }
  123. },
  124. async search() {
  125. const that = this;
  126. if (!that.user._id) return
  127. let info = {
  128. skip: that.skip,
  129. limit: that.limit,
  130. user: that.user._id
  131. }
  132. const res = await that.$api(`/chat`, 'GET', {
  133. ...info,
  134. })
  135. if (res.errcode == '0') {
  136. let list = [...res.data.reverse(), ...that.msgList];
  137. that.$set(that, `msgList`, list)
  138. that.$set(that, `total`, res.total)
  139. } else {
  140. uni.showToast({
  141. title: res.errmsg,
  142. });
  143. }
  144. const arr = await that.$api(`/problem`, 'GET', {
  145. is_use: '0'
  146. })
  147. if (arr.errcode == '0') {
  148. that.$set(that, `problemList`, arr.data)
  149. } else {
  150. uni.showToast({
  151. title: arr.errmsg,
  152. });
  153. }
  154. // 跳转到最后一条数据 与前面的:id进行对照
  155. that.goBottom();
  156. },
  157. // 进行图片的预览
  158. previewImg(e) {
  159. const that = this;
  160. // 预览图片
  161. uni.previewImage({
  162. current: 0,
  163. urls: [e],
  164. longPressActions: {
  165. itemList: ['发送给朋友', '保存图片', '收藏'],
  166. success: function(data) {
  167. console.log('选中了第' + (data.tapIndex + 1) + '个按钮,第' + (data.index + 1) +
  168. '张图片');
  169. },
  170. fail: function(err) {
  171. console.log(err.errMsg);
  172. }
  173. }
  174. });
  175. },
  176. // 判断是否是选择图片刷新
  177. choseImg(e) {
  178. const that = this;
  179. that.$set(that, `is_img`, e)
  180. },
  181. //接受输入内容
  182. async inputs(e) {
  183. const that = this;
  184. let user = that.user
  185. if (user._id) {
  186. //时间间隔处理
  187. let data = {
  188. "user": user._id,
  189. "speaker": user._id,
  190. "content": e.message,
  191. "time": moment().format('YYYY-MM-DD HH:mm:ss'),
  192. "msg_type": e.type
  193. };
  194. // 发送给服务器消息
  195. let res = await that.$api(`/chat`, `POST`, data);
  196. if (res.errcode == '0') {
  197. that.msgList.push(res.data);
  198. } else {
  199. uni.showToast({
  200. title: res.errmsg,
  201. icon: 'none'
  202. })
  203. }
  204. // 跳转到最后一条数据 与前面的:id进行对照
  205. that.goBottom();
  206. } else {
  207. uni.navigateTo({
  208. url: `/pagesIndex/login/index`
  209. })
  210. }
  211. },
  212. // 点击问题
  213. async toProblem(item) {
  214. const that = this;
  215. let user = that.user
  216. if (user._id) {
  217. //时间间隔处理
  218. let data = {
  219. "user": user._id,
  220. "speaker": moment().valueOf().toString(),
  221. "content": item.answer,
  222. "time": moment().format('YYYY-MM-DD HH:mm:ss'),
  223. "msg_type": '0'
  224. };
  225. that.msgList.push(data);
  226. // 跳转到最后一条数据 与前面的:id进行对照
  227. that.goBottom();
  228. } else {
  229. uni.navigateTo({
  230. url: `/pagesIndex/login/index`
  231. })
  232. }
  233. },
  234. //输入框高度
  235. heights(e) {
  236. const that = this;
  237. that.goBottom();
  238. },
  239. // 滚动到底部
  240. async goBottom() {
  241. const that = this;
  242. that.scrollToView = ""
  243. that.$nextTick(function() {
  244. that.scrollToView = 'msg123456789'
  245. })
  246. },
  247. // 下拉刷新分页
  248. getFresh(e) {
  249. const that = this;
  250. that.$set(that, `triggered`, true)
  251. that.$set(that, `is_img`, false)
  252. let msgList = that.msgList;
  253. let limit = that.limit;
  254. setTimeout(() => {
  255. if (that.total > msgList.length) {
  256. uni.showLoading({
  257. title: '加载中',
  258. mask: true
  259. })
  260. let page = that.page + 1;
  261. that.$set(that, `page`, page)
  262. let skip = page * limit;
  263. that.$set(that, `skip`, skip)
  264. that.$set(that, `is_bottom`, false)
  265. that.search();
  266. uni.hideLoading();
  267. } else {
  268. uni.showToast({
  269. title: `没有更多聊天记录了`,
  270. icon: 'none'
  271. })
  272. }
  273. that.triggered = false;
  274. }, 1000)
  275. },
  276. // 分页
  277. toPage(e) {
  278. const that = this;
  279. let list = that.list;
  280. let limit = that.limit;
  281. if (that.total > list.length) {
  282. uni.showLoading({
  283. title: '加载中',
  284. mask: true
  285. })
  286. let page = that.page + 1;
  287. that.$set(that, `page`, page)
  288. let skip = page * limit;
  289. that.$set(that, `skip`, skip)
  290. that.search();
  291. uni.hideLoading();
  292. } else that.$set(that, `is_bottom`, true)
  293. },
  294. // 清空列表
  295. clearPage() {
  296. const that = this;
  297. that.$set(that, `msgList`, [])
  298. that.$set(that, `skip`, 0)
  299. that.$set(that, `limit`, 6)
  300. that.$set(that, `page`, 0)
  301. }
  302. }
  303. }
  304. </script>
  305. <style lang="scss" scoped>
  306. .main {
  307. display: flex;
  308. flex-direction: column;
  309. width: 100vw;
  310. height: 100vh;
  311. overflow: hidden;
  312. .one {
  313. position: relative;
  314. flex-grow: 1;
  315. .scroll-view {
  316. .chat-ls {
  317. padding: 2vw 2vw 0 2vw;
  318. .chat-time {
  319. font-size: 24rpx;
  320. color: rgba(39, 40, 50, 0.3);
  321. line-height: 34rpx;
  322. padding: 10rpx 0rpx;
  323. text-align: center;
  324. }
  325. .msg-m {
  326. display: flex;
  327. padding: 20rpx 0;
  328. .user-img {
  329. flex: none;
  330. width: 80rpx;
  331. height: 80rpx;
  332. border-radius: 40rpx;
  333. border: 1px solid #c0c0c0;
  334. }
  335. .message {
  336. flex: none;
  337. max-width: 480rpx;
  338. }
  339. .img {
  340. margin: 0 20rpx;
  341. }
  342. .msg-text {
  343. font-size: 32rpx;
  344. color: rgba(39, 40, 50, 1);
  345. line-height: 44rpx;
  346. padding: 18rpx 24rpx;
  347. word-break: break-all;
  348. }
  349. .msg-img {
  350. max-width: 400rpx;
  351. border-radius: 20rpx;
  352. }
  353. }
  354. .msg-left {
  355. flex-direction: row;
  356. .msg-text {
  357. word-break: break-all;
  358. margin-left: 16rpx;
  359. background-color: #f1f1f1;
  360. border-radius: 0rpx 20rpx 20rpx 20rpx;
  361. }
  362. .ms-img {
  363. margin-left: 16rpx;
  364. }
  365. }
  366. .msg-right {
  367. flex-direction: row-reverse;
  368. .msg-text {
  369. margin-right: 16rpx;
  370. background-color: var(--f3CColor);
  371. border-radius: 20rpx 0rpx 20rpx 20rpx;
  372. }
  373. .ms-img {
  374. margin-right: 16rpx;
  375. }
  376. }
  377. }
  378. }
  379. .problem {
  380. width: 60%;
  381. padding: 2vw;
  382. margin: 0 0 0 2vw;
  383. color: var(--mainColor);
  384. background-color: var(--f3CColor);
  385. border-radius: 10px;
  386. .list {
  387. display: flex;
  388. justify-content: space-between;
  389. padding: 2vw;
  390. border-bottom: 1px solid var(--f9Color);
  391. }
  392. }
  393. }
  394. .two {
  395. background-color: #f0f0f0;
  396. border-top: 1px solid rgba(39, 40, 50, 0.1);
  397. }
  398. }
  399. .scroll-view {
  400. position: absolute;
  401. top: 0;
  402. left: 0;
  403. right: 0;
  404. bottom: 0;
  405. .list-scroll-view {
  406. display: flex;
  407. flex-direction: column;
  408. }
  409. }
  410. .is_bottom {
  411. width: 100%;
  412. text-align: center;
  413. text {
  414. padding: 2vw 0;
  415. display: inline-block;
  416. color: var(--f85Color);
  417. font-size: var(--font14Size);
  418. }
  419. }
  420. </style>