index.vue 10 KB

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