chat.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  1. <template>
  2. <!-- <view style="padding-bottom: 248rpx;"> -->
  3. <view style="">
  4. <!-- #ifdef H5 -->
  5. <view style="color: #000;">
  6. <tn-nav-bar backgroundColor="#fff">GPT</tn-nav-bar>
  7. <view :style="{ height: tobheight + 'px' }"></view>
  8. </view>
  9. <!-- #endif -->
  10. <view class="content" @touchmove="touchmove">
  11. <view class="msg-list">
  12. <!-- <view v-if="!paintingmode" class="row"> -->
  13. <view v-if="true" class="row">
  14. <block>
  15. <view class="other">
  16. <!-- <view class="left" v-if="appInfo.is_show_gpt_avatar_nickname == 1"
  17. @click="switchmodel = true"> -->
  18. <view class="left" v-if="true" @click="switchmodel = true">
  19. <u-image src="
  20. /static/images/head.jpg
  21. " mode="widthFix" radius="5" width="40" height="40"></u-image>
  22. </view>
  23. <view class="right">
  24. <view class="username">
  25. <view class="name"></view>
  26. <view class="time"> ai问答机器人</view>
  27. </view>
  28. <view class="bubble">
  29. <view class="content">
  30. <view style="font-size: 32rpx;">您可以点击下方案例直接提问......</view>
  31. <!-- <block v-for="(item, index) in homeTemplate.hot" :key="index">
  32. <view class="ask" @click="send(item.text)">{{ item.text }}</view>
  33. </block> -->
  34. <view @click="commontemplate" class="tn-flex align-center"
  35. style="justify-content: flex-end;margin-top: 15rpx;margin-bottom: 15rpx;">
  36. <view style="color: #9e9e9e;margin-right: 10rpx;">换一换</view>
  37. <u-icon name="reload" color="#9e9e9e" size="18"></u-icon>
  38. </view>
  39. <u-button size="small" @click="switchmodel = true" type="primary"
  40. text="切换模型"></u-button>
  41. </view>
  42. </view>
  43. </view>
  44. </view>
  45. </block>
  46. </view>
  47. <!-- <block v-for="(row, index) in paintingmode?paintinglist:talkList" :key="index" :id="'msg' + row.id">
  48. <view class="row">
  49. <block>
  50. <view class="my" v-if="row.fromid == userInfo.id">
  51. <view class="left">
  52. <view class="username">
  53. <view class="name">{{ row.nickname }}</view>
  54. </view>
  55. <u-icon v-if="row.content !='该问题已被隐藏!'" @click="copyText(index)" name="file-text"
  56. color="#9e9e9e82" size="22"></u-icon>
  57. <view v-if="row.type == 1" class="bubble" style="color: #fff;margin-left: 15rpx;">
  58. <rich-text :nodes="row.content" @longtap="copy" :data-text="row.content"
  59. selectable="true"></rich-text>
  60. </view>
  61. </view>
  62. <view class="right">
  63. <u-image :src="row.avatar ? row.avatar : '/static/images/head.jpg'" mode="widthFix"
  64. radius="5" width="42" height="42"></u-image>
  65. </view>
  66. </view>
  67. <view class="other" v-if="row.fromid != userInfo.id">
  68. <view class="left" v-if="appInfo.is_show_gpt_avatar_nickname == 1"
  69. @click="switchmodel = paintingmode?false:true">
  70. <u-image :src="row.avatar" mode="widthFix" radius="5" width="42"
  71. height="42"></u-image>
  72. </view>
  73. <view class="right">
  74. <view class="username" v-if="appInfo.is_show_gpt_avatar_nickname == 1">
  75. <view class="name"></view>
  76. <view class="time">{{ row.nickname }}</view>
  77. </view>
  78. <view v-if="row.type == 1" class="bubble"
  79. style="display: block;position: relative;">
  80. <view>
  81. <zero-markdown-view
  82. v-if="(row.done && row.content.indexOf('```') != -1) || (row.done && row.content.indexOf('/*') != -1 || row.content.indexOf('---') != -1)"
  83. :themeColor="themeColor" :markdown="row.content"></zero-markdown-view>
  84. <text v-else @longtap="copy"
  85. :data-text="row.content">{{ row.content.replace(/^\s+|\s+$/g, '') }}</text>
  86. <text v-if="row.content == '正在思考中...'">{{ second }}s</text>
  87. <text class="flash" v-if="row.show_flash">│</text>
  88. </view>
  89. </view>
  90. <view v-if="row.type == 2" class="bubble"
  91. style="display: block;position: relative;">
  92. <view class="u-flex align-center">
  93. <text style="margin-right: 20rpx;">{{row.content}}</text>
  94. <u-loading-icon size="17"></u-loading-icon>
  95. </view>
  96. </view>
  97. <view v-if="row.type == 3" class="bubbleimg">
  98. <image @click="preview(index)" :src="row.img" mode="aspectFill"></image>
  99. </view>
  100. <view v-if="row.done && !row.donec"
  101. class="tn-flex align-center justify-between operate">
  102. <view @click="copyText(index)" hover-class="hoversubmit"
  103. class="tn-flex align-center">
  104. <u-icon name="file-text" top="1" color="#68d7bb" size="20"></u-icon>
  105. <view class="duplicate">复制回答</view>
  106. </view>
  107. <view @click="createPoster(index)" hover-class="hoversubmit"
  108. class="tn-flex align-center">
  109. <u-icon name="share-square" top="1" color="#68d7bb" size="20"></u-icon>
  110. <view class="share">分享对话</view>
  111. </view>
  112. <view v-if="appInfo.is_vop&&appInfo.is_vop == 1" class="eliseaudio">
  113. <elise-audio @aittsjob="aittsjob" :audioId="'audioId'+index"
  114. :url="row.audiolink" audioColor="#68d7bb" :durationS="5"
  115. :content="row.content" :index="index" :cancel="cancel"></elise-audio>
  116. </view>
  117. </view>
  118. </view>
  119. </view>
  120. </block>
  121. </view>
  122. </block> -->
  123. </view>
  124. <view class="bottomheight"></view>
  125. <view class="env"></view>
  126. </view>
  127. <view class="box-2">
  128. <view class="flex_col">
  129. <view class="flex_grow">
  130. <u--textarea height="45" @blur="blurinput" @focus="focusinput" fixed :showConfirmBar="false"
  131. v-model="content" :placeholder="paintingmode?'请输入您想绘制的图片内容...':'请输入您的问题...'"
  132. :maxlength="paintingmode?500:-1" border="none" :cursorSpacing="80"></u--textarea>
  133. </view>
  134. <!-- <u-icon v-if="appInfo.is_vop&&appInfo.is_vop == 1" @click="openmicrophone" name="mic" color="#ff9800"
  135. size="30"></u-icon> -->
  136. <!-- <button class="send"
  137. @click.prevent="paintingmode?sendpainting(content):send(content)">{{paintingmode?'绘制':'发送'}}</button> -->
  138. <button class="send" @click.prevent="">发送</button>
  139. </view>
  140. </view>
  141. <!-- <u-popup :show="showexpand" zIndex="1" mode="bottom" bgColor="transparent" :overlay="false"
  142. @close="showexpand = false">
  143. <scroll-view class="scroll-view_H" scroll-x="true">
  144. <view class="expand u-flex">
  145. <block v-if="appInfo.number_member">
  146. <navigator @click="getroute"
  147. :url="isLogin ?'/pages/user/member/member?id=1':'/pages/user/signin'"
  148. class="surplus u-flex align-center" v-if="appInfo.number_member == 1">
  149. <u-icon name="question-circle-fill" color="#ff9800" size="18" top="1"></u-icon>
  150. <view class="item">
  151. {{appInfo.number_alias?appInfo.number_alias+':':'点数:'}}{{ userData.coin ? userData.coin : 0 }}
  152. </view>
  153. </navigator>
  154. </block>
  155. <block v-else>
  156. <navigator @click="getroute"
  157. :url="isLogin ?'/pages/user/member/member?id=1':'/pages/user/signin'"
  158. class="surplus u-flex align-center">
  159. <u-icon name="question-circle-fill" color="#ff9800" size="18" top="1"></u-icon>
  160. <view class="item">
  161. {{appInfo.number_alias?appInfo.number_alias+':':'点数:'}}{{ userData.coin ? userData.coin : 0 }}
  162. </view>
  163. </navigator>
  164. </block>
  165. <blcok v-if="!paintingmode">
  166. <navigator @click="getroute"
  167. :url="isLogin ?'/pages/user/member/member?id=2':'/pages/user/signin'"
  168. class="surplus u-flex align-center" v-if="appInfo.time_member && appInfo.time_member == 1">
  169. <u-icon name="clock-fill" color="#607d8b" size="18" top="1"></u-icon>
  170. <view class="item">
  171. 会员时长:{{ userData.is_validity == 1 ? Math.round((userData.vip_time - Date.parse(new Date()) / 1000) / (3600 * 24)) : 0 }}天
  172. </view>
  173. </navigator>
  174. </blcok>
  175. <view v-if="appInfo.is_aipainting&&appInfo.is_aipainting == 1" @click="switcmode"
  176. class="surplus u-flex align-center">
  177. <u-icon :name="paintingmode?'chat-fill':'edit-pen-fill'" color="#f44336" size="18"
  178. top="1"></u-icon>
  179. <view class="item">{{paintingmode?'聊天模式':'Ai绘画'}}</view>
  180. </view>
  181. <navigator @click="getroute" :url="isLogin ?'/pages/user/member/member?id=3':'/pages/user/signin'"
  182. class="surplus u-flex align-center">
  183. <u-icon name="more-circle-fill" color="#2979ff" size="18" top="1"></u-icon>
  184. <view class="item">免费领{{appInfo.number_alias?appInfo.number_alias:'点数'}}</view>
  185. </navigator>
  186. <view class="surplus u-flex align-center" style="background: #fff0;padding: 1rpx;">
  187. </view>
  188. </view>
  189. </scroll-view>
  190. </u-popup> -->
  191. <!-- <wike-skeleton count="4" type="user" v-if="homeTemplate.length === 0"></wike-skeleton> -->
  192. <u-no-network></u-no-network>
  193. <!-- <navigator v-if="is_commission == 1" class="neckBtn_view" url="/pages/user/commission/index">
  194. <text class="free_view">分享</text>
  195. 赚佣金
  196. </navigator> -->
  197. <!-- <u-popup :show="showPoster" mode="bottom" :round="10" safeAreaInsetTop @close="showPoster = false">
  198. <view class="poster">
  199. <wike-painter :board="posterObj" @success="posterSuccess" ref="painter"></wike-painter>
  200. <view class="footer-btn">
  201. <view class="" @click="showPoster = false">退出</view>
  202. <view class="save" @click="toSave">保存/分享</view>
  203. </view>
  204. </view>
  205. </u-popup> -->
  206. <!-- <u-popup :show="soundrecording" mode="bottom" :round="20" safeAreaInsetTop @close="soundrecording = false">
  207. <view class="soundrecording u-flex justify-center">
  208. <view v-if="showlongpress" class="waveform">
  209. <image :src="'https://s1.voicecloud.cn/activity/imeVoiceShare/img/yuyin.gif'" mode="aspectFill">
  210. </image>
  211. </view>
  212. <view class="operation u-flex">
  213. <view @touchstart="startrecording" @touchend="stoprecording" class="longpress"
  214. hover-class="hoversubmit">
  215. <u-icon name="mic" color="#fff" size="35"></u-icon>
  216. </view>
  217. </view>
  218. <view class="discriminate">长按识别语音</view>
  219. </view>
  220. </u-popup> -->
  221. <!-- <wike-loading-page :isLoading="isLoading"></wike-loading-page> -->
  222. <!-- 生成的图片 -->
  223. <u-popup type="center" mode="center">
  224. <view class="poster-img">
  225. <text @click="closePopup"></text>
  226. <!-- #ifdef H5 -->
  227. <view class="">长按图片保存到手机</view>
  228. <!-- #endif -->
  229. <!-- #ifndef H5 -->
  230. <view class="">点击图片保存到手机</view>
  231. <!-- #endif -->
  232. </view>
  233. </u-popup>
  234. <!-- <u-popup :show="switchmodel" @close="switchmodel = false" :round="15" closeable>
  235. <view class="select u-flex justify-center"><text>选择模型</text></view>
  236. <scroll-view scroll-y="true" :style="{ height: homeTemplate.mode.length > 6 ? 700 + 'rpx' : 'auto' }">
  237. <block v-for="(item, index) in homeTemplate.mode" :key="index">
  238. <view class="u-flex justify-between model_view">
  239. <u-avatar :src="item.img_file.path" shape="square" mode="aspectFill" size="60"></u-avatar>
  240. <view class="modelname">
  241. <view class="name">{{ item.name }}</view>
  242. <view class="modeldetails">{{ item.intro }}</view>
  243. </view>
  244. <view @click="onselect(index)" class="modelselect"
  245. :style="{ background: selectornot == index ? '#9e9e9e' : '' }">
  246. {{ selectornot == index ? '已选择' : '选择' }}
  247. </view>
  248. </view>
  249. </block>
  250. <view style="height: 30rpx;"></view>
  251. </scroll-view>
  252. </u-popup> -->
  253. <!-- <wike-tabbar :onTabbar="true" :isShowAnimate="true"></wike-tabbar> -->
  254. </view>
  255. </template>
  256. <script>
  257. // import { indexOf } from 'core-js/js/array';
  258. import {
  259. Socket
  260. } from 'dgram';
  261. import {
  262. mapMutations,
  263. mapActions,
  264. mapState,
  265. mapGetters
  266. } from 'vuex';
  267. import {
  268. apiurl
  269. } from '@/common/request/request';
  270. import MumuRecorder from '@/uni_modules/mumu-recorder/components/mumu-recorder/mumu-recorder.vue';
  271. import eliseAudio from '@/components/elise-audio/elise-audio.vue';
  272. // #ifdef H5
  273. import Recorder from 'recorder-core';
  274. import 'recorder-core/src/engine/wav'
  275. // #endif
  276. let down, delay;
  277. let interstitialAd = null,
  278. timer,
  279. time2,
  280. timingr;
  281. // const innerAudioContext = uni.createInnerAudioContext();
  282. const recorderManager = uni.getRecorderManager();
  283. export default {
  284. components: {
  285. MumuRecorder,
  286. eliseAudio,
  287. // #ifdef H5
  288. Recorder
  289. // #endif
  290. },
  291. data() {
  292. return {
  293. gpt_mode_index: 0,
  294. talkList: [
  295. ],
  296. content: '',
  297. thecontent: '',
  298. image: '',
  299. hot: [],
  300. scrollTop: 999999,
  301. scrollAnimation: false,
  302. text1: ['您好,ChatGPT为您服务', '长按对话即可复制'],
  303. tobheight: 45,
  304. zhuangtai: 'AI智能问答机器人',
  305. platform: this.$platform.get(),
  306. // isFlash:false,
  307. showPoster: false,
  308. posterObj: {},
  309. switchmodel: false,
  310. selectornot: 0,
  311. modeldata: [],
  312. qrcode: '',
  313. haddressurl: '',
  314. haddresssk: '',
  315. scrollToView: '',
  316. question_index: 0,
  317. answer_index: 0,
  318. themeColor: '#007AFF',
  319. codeBgColor: '#26B3A0',
  320. showexpand: false,
  321. second: 15,
  322. showanswer: false,
  323. h5question: '',
  324. followornot: true,
  325. eights: false,
  326. spmplatform: 0,
  327. is_commission: 0,
  328. timing: 30,
  329. showcontext: true,
  330. showfetch: true,
  331. showdirect: true,
  332. //通道
  333. thoroughfare: 0,
  334. //绘画输入框
  335. drawcontent: '',
  336. //绘画模式
  337. paintingmode: false,
  338. //是否在绘画
  339. showdraw: false,
  340. //绘画id
  341. uuid: '',
  342. //绘画列表
  343. paintinglist: [],
  344. //弹出录音
  345. soundrecording: false,
  346. //是否长按
  347. showlongpress: false,
  348. //音频
  349. innerAudioContextsrc: '',
  350. //取消音频加载
  351. cancel: false,
  352. //第一次录
  353. firstrecording: 0,
  354. isLoading: true
  355. };
  356. },
  357. computed: {
  358. },
  359. mounted() {
  360. },
  361. onReady() {
  362. },
  363. onLoad() {
  364. },
  365. onShow: function() {
  366. },
  367. onUnload() {
  368. },
  369. onHide() {
  370. },
  371. onReachBottom() {},
  372. methods: {
  373. }
  374. };
  375. </script>
  376. <style lang="scss" scoped>
  377. @import '@/pages/chat/global.scss';
  378. @import './chat.scss';
  379. </style>