index.vue 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. <template>
  2. <view class="box">
  3. <view class="flex-common-css ">
  4. <Nav title="AI助手" titleColor="#333" bgckgroundBox='#fff'></Nav>
  5. <scroll-view :scroll-y="true" id="scroll-view-css" class="scroll-view-css" :scroll-top="scrollTop"
  6. :scroll-with-animation="true" @scroll="scrolll">
  7. <view class="chat-box" id="chat-box">
  8. <msgItem v-for="(item,index) in chatData" :key="index" :item="item" :showType="item.showType"
  9. :msgText="item.content" @selectStyle="selectStyle" @refresh="refresh"></msgItem>
  10. </view>
  11. </scroll-view>
  12. <view class="bottom-box iPhone-bottom box-border-box">
  13. <view class="input-box">
  14. <!-- <view class="uni-input"> -->
  15. <!-- <view class="input-left"> -->
  16. <input type="text" v-model="chatText" placeholder="有问题尽管问我" class="input" @confirm="confirm"
  17. :disabled='!sendControl'>
  18. <!-- </view> -->
  19. <!-- </view> -->
  20. </view>
  21. </view>
  22. </view>
  23. </view>
  24. </template>
  25. <script>
  26. import tools from "@/service/tools.js";
  27. import msgItem from "./msg-item.vue";
  28. // import {
  29. // qianfanSend,
  30. // qianfanMsg_list,
  31. // } from "@/api/qianfan.js"
  32. import {
  33. aiSend,
  34. aiMsgList
  35. } from "@/api/ai.js"
  36. export default {
  37. components: {
  38. msgItem
  39. },
  40. data() {
  41. return {
  42. chatText: '',
  43. chatType: 1,
  44. scrollTop: 0,
  45. chatData: [],
  46. initialData: [],
  47. // loadingStyle: false,
  48. Ajax: false,
  49. timer: null, //settimeout
  50. showText: "",
  51. typeName: '',
  52. isScrolll: false,
  53. scrolllTimeServe: null,
  54. imgUrl: '',
  55. fileUrl: '',
  56. voiceUrl: '',
  57. inputHeadShow: true,
  58. sendControl: true
  59. };
  60. },
  61. onShow() {
  62. this.aiMsgList()
  63. },
  64. onLoad() {},
  65. mounted() {},
  66. methods: {
  67. selectStyle(e) {
  68. this.chatType = e
  69. this.initialData.forEach((item) => {
  70. if (this.chatType === item.type) {
  71. this.typeName = item.name
  72. let data = {
  73. msg_type: 2,
  74. content: '您好,我是' + this.typeName + 'AI小助手,有什么能帮助您吗?',
  75. created_at: tools.getDate(),
  76. }
  77. this.chatData.push(data)
  78. setTimeout(() => {
  79. this.scrollToBottom()
  80. }, 50)
  81. }
  82. })
  83. // console.log(e);
  84. },
  85. aiSend() {
  86. let that = this
  87. let data = {
  88. msg_type: 2,
  89. content: '',
  90. created_at: tools.getDate(),
  91. showType: true,
  92. }
  93. this.chatData.push(data)
  94. let key = this.chatData.length - 1
  95. aiSend({
  96. content: this.chatText,
  97. }).then((res) => {
  98. if (res.code == 1) {
  99. this.imgUrl = ''
  100. this.fileUrl = ''
  101. this.voice_url = ''
  102. this.chatText = ''
  103. this.sendControl = true
  104. // this.chatData[key].voice_url = res.data.voice_url
  105. this.chatData[key].content = res.data.content
  106. this.$nextTick(() => {
  107. this.scrollToBottom()
  108. })
  109. } else {
  110. this.chatData[key].content = msg
  111. }
  112. })
  113. },
  114. refresh(num) {
  115. // this.$nextTick(() => {
  116. if (num) {
  117. // console.log("高度");
  118. // this.scrollTop = 99999
  119. console.log('最终')
  120. setTimeout(() => {
  121. this.scrollToBottom(50)
  122. }, 50)
  123. } else {
  124. console.log('回调执行')
  125. this.scrollToBottom(0)
  126. // setTimeout(()=>{
  127. // this.scrollToBottom()
  128. // },10)
  129. }
  130. // })
  131. },
  132. aiMsgList() {
  133. this.chatData = []
  134. aiMsgList().then((res) => {
  135. if (res.code == 1) {
  136. let data = res.data.items.reverse()
  137. data.forEach((itm) => {
  138. itm.showType = false
  139. })
  140. this.chatData.push(...data)
  141. }
  142. })
  143. },
  144. onTabItemTap() {
  145. uni.hideTabBar()
  146. },
  147. leftClick() {
  148. uni.switchTab({
  149. url: 'pages/index/index'
  150. })
  151. uni.showTabBar()
  152. },
  153. confirm(event) {
  154. if (this.sendControl) {
  155. if (event.target.value) {
  156. let timeData = tools.getDate()
  157. let text = {
  158. created_at: timeData,
  159. msg_type: 1,
  160. content: event.target.value,
  161. img_url: this.imgUrl,
  162. file_url: this.fileUrl
  163. }
  164. this.chatData.push(text)
  165. this.inputHeadShow = false
  166. this.sendControl = false
  167. this.$nextTick(() => {
  168. this.scrollToBottom()
  169. })
  170. this.aiSend()
  171. // this.lading()
  172. this.chatText = ''
  173. } else {
  174. uni.showToast({
  175. title: '请输入问题',
  176. icon: 'none',
  177. duration: 1000
  178. });
  179. }
  180. }
  181. },
  182. scrolll(e) {
  183. console.log(e,'eeee');
  184. },
  185. scrollToBottom(num) {
  186. let query = uni.createSelectorQuery().in(this)
  187. query.select('#scroll-view-css').boundingClientRect()
  188. query.select('#chat-box').boundingClientRect()
  189. query.exec((res) => {
  190. //如果子元素高度大于父元素高度(显示高度)
  191. if (res[1].height > res[0].height) {
  192. //计算出二者差值就是需要滚动的距离
  193. let scrollTop = res[1].height - res[0].height
  194. let differenceNum = scrollTop - this.scrollTop
  195. console.log(differenceNum, 'differenceNum');
  196. console.log(scrollTop, 'scrollTop');
  197. if (differenceNum > 50) {
  198. this.scrollTop = scrollTop + 50
  199. console.log('differenceNum > 50');
  200. } else if (num > 0) {
  201. this.scrollTop = scrollTop + num
  202. console.log('num > 0');
  203. }
  204. }
  205. })
  206. },
  207. },
  208. }
  209. </script>
  210. <style lang="scss" scoped>
  211. .box {
  212. background: #fff;
  213. position: relative;
  214. .popup-block {
  215. border-radius: 20rpx 20rpx 0rpx 0rpx;
  216. overflow: hidden;
  217. background-color: #f5f5f5;
  218. .popup-row {
  219. height: 100rpx;
  220. background-color: #fff;
  221. text-align: center;
  222. line-height: 100rpx;
  223. border-bottom: 2rpx solid #f5f5f5;
  224. &:nth-child(4) {
  225. margin-bottom: 20rpx;
  226. }
  227. &:last-child {
  228. height: 112rpx;
  229. border: none;
  230. line-height: 112rpx;
  231. }
  232. &:active {
  233. background-color: rgb(244, 244, 244);
  234. }
  235. }
  236. }
  237. .chat-box {
  238. padding: 22rpx 32rpx 1rpx;
  239. box-sizing: border-box;
  240. .dialogue-box {
  241. // width: 100%;
  242. height: auto;
  243. margin: 0 0 40rpx 0;
  244. display: flex;
  245. flex-direction: column;
  246. .time {
  247. font-size: 24rpx;
  248. color: #999999;
  249. margin: 0 0 8rpx 0;
  250. }
  251. .dialogue {
  252. padding: 24rpx;
  253. box-sizing: border-box;
  254. word-break: break-all;
  255. font-size: 30rpx;
  256. .dialogue-text {}
  257. .dialogue-text-one {
  258. color: #333333;
  259. }
  260. .dialogue-text-two {
  261. color: #FFFFFF;
  262. }
  263. .initial-box {
  264. .initial-title {
  265. font-size: 30rpx;
  266. font-weight: 600;
  267. color: #333333;
  268. margin: 0 0 12rpx 0;
  269. }
  270. .initial-style {
  271. font-size: 30rpx;
  272. color: #2F80ED;
  273. margin: 0 0 12rpx 0;
  274. }
  275. .initial-style:last-child {
  276. margin: 0;
  277. }
  278. }
  279. }
  280. .dialogue-one {
  281. background: #F7F8FC;
  282. border-radius: 10rpx 10rpx 10rpx 0;
  283. }
  284. .dialogue-two {
  285. background: #FDAB26;
  286. border-radius: 10rpx 10rpx 0 10rpx;
  287. }
  288. }
  289. .dialogue-box-one {
  290. align-items: flex-start;
  291. }
  292. }
  293. .bottom-box {
  294. position: relative;
  295. .input-box {
  296. width: 100%;
  297. height: 100rpx;
  298. height: auto;
  299. background: #fff;
  300. padding: 10rpx 32rpx;
  301. box-sizing: border-box;
  302. border-top: 1rpx solid #EEEEEE;
  303. transition: all .1s linear;
  304. }
  305. }
  306. }
  307. .input {
  308. background: #F2F2F2;
  309. border-radius: 200rpx;
  310. width: 100%;
  311. height: 80rpx;
  312. padding: 20rpx 170rpx 20rpx 24rpx;
  313. box-sizing: border-box;
  314. }
  315. </style>