sender.vue 34 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045
  1. <template>
  2. <view>
  3. <view v-if="showPanel" style="height:75px;display: block;">
  4. </view>
  5. <view class="v-sender" id="v-send">
  6. <view class="v-sender__control v-sender__control_t" v-if="qute && qute.id && !voice">
  7. <!-- #ifndef H5 -->
  8. <view class="emoji" style="width: 64rpx;">
  9. </view>
  10. <!-- #endif -->
  11. <!-- 引用 -->
  12. <view class=" textarea qute-wrap">
  13. <!-- 文本 -->
  14. <template v-if="qute.message.type == 'text'">
  15. <!-- @文本 -->
  16. <view class="content" v-if="qute.message.content.type && qute.message.content.type == 'remind'">
  17. {{qute.sender.nickname}}: <text v-html="qute.message.qute"></text>
  18. </view>
  19. <!-- 纯文本 -->
  20. <view class="content" v-else>
  21. {{qute.sender.nickname}}:{{qute.message && qute.message.qute ? qute.message.qute: ''}}
  22. </view>
  23. </template>
  24. <!-- -->
  25. <view class="content" v-if="qute.message.type == 'emotion'">
  26. {{qute.sender.nickname}}:
  27. <block v-for="(m1,index1) in qute.message.face" :key="index1">
  28. <block v-if="m1.type=='img'">
  29. <image :src="m1.content" class="emotion"></image>
  30. </block>
  31. <block v-else>{{m1.content}}</block>
  32. </block>
  33. </view>
  34. <view class="content" v-if="qute.message.type == 'image'">
  35. {{qute.sender.nickname}}:[图片]
  36. </view>
  37. <image src="../static/img/del.png" mode="" @click="clearQute"></image>
  38. </view>
  39. </view>
  40. <view class="v-sender__control">
  41. <!-- #ifndef H5 -->
  42. <view class="emoji" @tap="sendVoice">
  43. <text v-if="!voice && !noSpeaking" class="n-icon n-icon-voice"></text>
  44. <text v-else class="n-icon n-icon-keyboard"></text>
  45. </view>
  46. <!-- #endif -->
  47. <block v-if="noSpeaking">
  48. <view class="falseinput"
  49. style="text-align: center;color: #999;margin-left: 16upx;margin-right: 20upx;margin-left:10px;">
  50. {{speaking_tips}}
  51. </view>
  52. </block>
  53. <block v-else>
  54. <textarea v-if="!voice" ref="shuru" id="sendbox" maxlength="99999999999" auto-height="true"
  55. :class="{'textarea':true,'input':input_value && !voice}" v-model="input_value" type="text"
  56. @input="listen('input', $event.detail.value)" @confirm="set_focos()" @tap="sendertap();"
  57. confirmType="send" adjust-position="ture" :confirm-hold="true" cursor-spacing="15"
  58. style="overflow-y: auto;" :focus='focusState'>
  59. </textarea>
  60. <view v-if="voice" :class="{'falseinput':true,'press':setting}"
  61. style="text-align: center;color: #222;margin-right: 20upx;" @touchstart="startVoice"
  62. @touchend="endVoice" @touchmove.stop.prevent="voiceIng" @touchcancel="voiceCancel">{{voiceTis}}
  63. </view>
  64. <!-- 图片/表情 -->
  65. <view class="emoji" @tap="showemoji();" v-if="!emoji"><text class="n-icon n-icon-face"></text>
  66. </view>
  67. <view class="emoji" @tap="hideemoji();" v-if="emoji"><text class="n-icon n-icon-keyboard"></text>
  68. </view>
  69. <view class="btn sendbtn" v-if="input_value && !voice" @touchend.prevent="tapsender">发送</view>
  70. <view class="bigbox3" v-if="!input_value && !voice">
  71. <view class="emoji" @tap="show_panel();" v-if="!showPanel&&!input_value"><text>&#xe634;</text>
  72. </view>
  73. <view class="emoji" @tap="hide_panel();" v-else-if="showPanel&&!input_value">
  74. <text>&#xe603;</text>
  75. </view>
  76. </view>
  77. </block>
  78. </view>
  79. <view class="record" :class="setting?'':'hidden'">
  80. <view class="ing" :class="willStop?'hidden':''">
  81. <view class="icon luyin2"></view>
  82. </view>
  83. <view class="cancel" :class="willStop?'':'hidden'">
  84. <view class="icon chehui"></view>
  85. </view>
  86. <view class="tis" :class="willStop?'change':''">{{recordTis}}</view>
  87. </view>
  88. <view v-if="emoji" class="face_box">
  89. <view style="width: 100%;">
  90. <view class="emotion-box" style="height:200px">
  91. <view class="emotion-box-line" v-for="(line, i) in lists" :key="i">
  92. <view class="emotion-item" v-for="(item, index) in line" :key="index"
  93. @click="handleEmotion(item)">
  94. <image :src="'/static/emoji/'+item.name+'.gif'" style="width: 50rpx;height: 50rpx;">
  95. </image>
  96. </view>
  97. </view>
  98. </view>
  99. </view>
  100. </view>
  101. <view v-if="showPanel" class="v-sender__panel">
  102. <!-- <view @click="sendImg('album')"> -->
  103. <view @click="openAuth('sendImg','album','authpup')">
  104. <view class="icons"><text class="n-icon n-icon-image"></text></view>
  105. <view>图片</view>
  106. </view>
  107. <!-- <view class="box" @click="sendImg('camera')"> -->
  108. <view class="box" @click="openAuth('sendImg','camera','authpupCAMERA')">
  109. <view class="icons"><text class="n-icon n-icon-paizhao"></text></view>
  110. <view>拍照</view>
  111. </view>
  112. <!-- <view class="box" @click="sendVedio('album')"> -->
  113. <view class="box" @click="openAuth('sendVedio','album','authpup')">
  114. <view class="icons">
  115. <image src="../static/img/vedio.png"></image>
  116. </view>
  117. <view>视频</view>
  118. </view>
  119. <view class="box" @click="openAuth('sendVedio','camera','authpupCAMERA')">
  120. <view class="icons">
  121. <image src="../static/img/camera.png"></image>
  122. </view>
  123. <view>录像</view>
  124. </view>
  125. <!-- <view class="box" @click="sendRedpactet()">
  126. <view class="icons"><image src="../static/img/redpacket.png" style="width: 26px;" ></image></view>
  127. <view>红包</view>
  128. </view> -->
  129. </view>
  130. </view>
  131. <yk-authpup ref="authpup" type="top" @changeAuth="changeAuth"
  132. permissionID="WRITE_EXTERNAL_STORAGE"></yk-authpup>
  133. <!-- CAMERA -->
  134. <yk-authpup ref="authpupCAMERA" type="top" @changeAuth="changeAuth"
  135. permissionID="CAMERA"></yk-authpup>
  136. <!-- RECORD_AUDIO -->
  137. <yk-authpup ref="authpupRECORD_AUDIO" type="top" @changeAuth="changeAuths"
  138. permissionID="RECORD_AUDIO"></yk-authpup>
  139. </view>
  140. </template>
  141. <script>
  142. // #ifdef APP-PLUS
  143. const recorderManager = uni.getRecorderManager();
  144. // #endif
  145. import ykAuthpup from "@/components/yk-authpup/yk-authpup";
  146. const {
  147. windowWidth,
  148. windowHeight
  149. } = uni.getSystemInfoSync();
  150. import helper from "../library/helper.js"
  151. import api from "../library/index.js"
  152. import action from "../library/action.js"
  153. export default {
  154. components: {
  155. ykAuthpup
  156. },
  157. name: 'v-sender',
  158. props: {
  159. placeholder: {
  160. type: String,
  161. default: '说点什么吧'
  162. },
  163. value: {
  164. type: String,
  165. default: ''
  166. },
  167. noSpeaking: {
  168. type: Boolean,
  169. default: false
  170. },
  171. speaking_tips: {
  172. },
  173. forbidRedpack: {
  174. type: Boolean,
  175. default: false
  176. },
  177. showboard: {
  178. type: Boolean,
  179. default: false
  180. },
  181. groupid: {
  182. type: [Number, String],
  183. default: 0
  184. },
  185. isgroup: {
  186. default: 0
  187. },
  188. sendtype: {
  189. type: [Number, String],
  190. default: 'text'
  191. }
  192. },
  193. data() {
  194. return {
  195. confirmType: '发送',
  196. meth: '',
  197. openType: '',
  198. focusState: false,
  199. qute: {},
  200. showPanel: false,
  201. showPacket: false,
  202. voice: false,
  203. text: 'uni-app',
  204. voicePath: '',
  205. setting: false,
  206. emoji: false,
  207. faceImg: {},
  208. swipers: [],
  209. voiceTis: '按住 说话',
  210. recordTis: "手指上滑 取消发送",
  211. recording: false,
  212. willStop: false,
  213. initPoint: {
  214. identifier: 0,
  215. Y: 0
  216. },
  217. recordTimer: null,
  218. recordLength: 0,
  219. mids: {},
  220. uploadnum: 0,
  221. starttime: 0,
  222. endtime: 0,
  223. voice_mid: '',
  224. focus: false,
  225. input_value: '',
  226. area_value: '',
  227. inputclass: 'textarea',
  228. sendtime: 0,
  229. keyboardheight: 0,
  230. borderheight: 0,
  231. user: uni.getStorageSync('userInfo'),
  232. list: [
  233. ['微笑', '撇嘴', '色', '发呆', '得意', '流泪', '害羞', '闭嘴'],
  234. ['睡', '大哭', '尴尬', '发怒', '调皮', '呲牙', '惊讶', '难过'],
  235. ['酷', '冷汗', '抓狂', '吐', '偷笑', '可爱', '白眼', '傲慢'],
  236. ['饥饿', '困', '惊恐', '流汗', '憨笑', '大兵', '奋斗', '咒骂'],
  237. ['疑问', '嘘', '晕', '折磨', '衰', '骷髅', '敲打', '再见'],
  238. ['擦汗', '抠鼻', '鼓掌', '糗大了', '坏笑', '左哼哼', '右哼哼', '哈欠'],
  239. ['鄙视', '委屈', '快哭了', '阴险', '亲亲', '吓', '可怜', '菜刀'],
  240. ['西瓜', '啤酒', '篮球', '乒乓', '咖啡', '饭', '猪头', '玫瑰', ],
  241. ['凋谢', '示爱', '爱心', '心碎', '蛋糕', '闪电', '炸弹', '刀'],
  242. ['足球', '瓢虫', '便便', '月亮', '太阳', '礼物', '拥抱', '强'],
  243. ['弱', '握手', '胜利', '抱拳', '勾引', '拳头', '差劲', '爱你'],
  244. ['NO', 'OK', '爱情', '飞吻', '跳跳', '发抖', '怄火', '转圈'],
  245. ['磕头', '回头', '跳绳', '挥手', '激动', '闭嘴', '笑哭', '吐舌'],
  246. ['耶', '跳舞', '恐惧', '失望', '脸红', '无语', '奸笑', '嘿哈'],
  247. ['鬼混', '福', '合十', '强壮', '红包', '发财', '庆祝', '礼物']
  248. ],
  249. reg: /\S{1,3}/gi,
  250. lists: [],
  251. listss: []
  252. }
  253. },
  254. mounted() {
  255. let that = this;
  256. // #ifdef APP-PLUS
  257. recorderManager.onStart((e) => {
  258. this.recordBegin(e);
  259. })
  260. recorderManager.onStop(res => {
  261. this.recordStop(res);
  262. });
  263. // #endif
  264. var value = '';
  265. this.list = this.list.map((line, index) => {
  266. this.listss = [];
  267. line = line.map((item, idx) => {
  268. value = item;
  269. item = item.replace(/\S{1,3}/gi, this.emotion(item));
  270. this.listss.push({
  271. "name": item,
  272. "index": index,
  273. "value": value,
  274. "idx": idx
  275. })
  276. return item;
  277. })
  278. this.lists.push(this.listss);
  279. return line;
  280. })
  281. },
  282. computed: {
  283. sendShowing() {
  284. return this.value.length > 0
  285. },
  286. },
  287. methods: {
  288. showCall(val) {
  289. val = val + ''
  290. let str = ''
  291. if (val) {
  292. str = val.replace(/<span.*?>|<\/span>/g, "")
  293. }
  294. return str
  295. },
  296. // 清理引用
  297. clearQute() {
  298. this.qute = {}
  299. // 清理父的qute
  300. this.$emit('clearQute')
  301. },
  302. // 保存引用
  303. setQute(item) {
  304. let that = this
  305. that.qute = item
  306. console.log('that.qute', that.qute);
  307. let data = this.$refs.shuru
  308. that.focusState = false
  309. this.$nextTick(() => {
  310. that.focusState = true
  311. })
  312. },
  313. emotion(res) {
  314. //let word = res.replace(/\#|\;/gi,'')
  315. const list = ['微笑', '撇嘴', '色', '发呆', '得意', '流泪', '害羞', '闭嘴', '睡', '大哭', '尴尬', '发怒', '调皮', '呲牙', '惊讶',
  316. '难过', '酷', '冷汗', '抓狂', '吐', '偷笑', '可爱', '白眼', '傲慢', '饥饿', '困', '惊恐', '流汗', '憨笑', '大兵', '奋斗',
  317. '咒骂', '疑问', '嘘', '晕', '折磨', '衰', '骷髅', '敲打', '再见', '擦汗', '抠鼻', '鼓掌', '糗大了', '坏笑', '左哼哼', '右哼哼',
  318. '哈欠', '鄙视', '委屈', '快哭了', '阴险', '亲亲', '吓', '可怜', '菜刀', '西瓜', '啤酒', '篮球', '乒乓', '咖啡', '饭', '猪头',
  319. '玫瑰', '凋谢', '示爱', '爱心', '心碎', '蛋糕', '闪电', '炸弹', '刀', '足球', '瓢虫', '便便', '月亮', '太阳', '礼物', '拥抱',
  320. '强', '弱', '握手', '胜利', '抱拳', '勾引', '拳头', '差劲', '爱你', 'NO', 'OK', '爱情', '飞吻', '跳跳', '发抖', '怄火',
  321. '转圈', '磕头', '回头', '跳绳', '挥手', '激动', '闭嘴', '笑哭', '吐舌', '耶', '跳舞', '恐惧', '失望', '脸红', '无语', '奸笑',
  322. '嘿哈', '鬼混', '福', '合十', '强壮', '红包', '发财', '庆祝', '礼物'
  323. ]
  324. let index = list.indexOf(res)
  325. var index1 = index + 100;
  326. return index1
  327. },
  328. showemoji() {
  329. this.showPanel = false;
  330. this.emoji = true;
  331. // this.setChatHeight();
  332. },
  333. hideemoji() {
  334. this.showPanel = false;
  335. this.emoji = false;
  336. // this.setChatHeight();
  337. },
  338. show_panel() {
  339. this.showPanel = true;
  340. this.emoji = false;
  341. this.setChatHeight();
  342. },
  343. hide_panel() {
  344. this.showPanel = false;
  345. this.emoji = false;
  346. this.setChatHeight();
  347. },
  348. setChatHeight() {
  349. //
  350. // console.log(this.sendHeight);
  351. var that = this;
  352. setTimeout(() => {
  353. var that = this;
  354. var query = uni.createSelectorQuery(); // 这里要加上select
  355. query.in(that).select('#v-send').boundingClientRect(res => {
  356. var hh = (parseInt(res.height) - 60);
  357. this.$emit("senderheight", hh);
  358. }).exec();
  359. }, 100);
  360. },
  361. sendVedio(type) {
  362. let that = this
  363. uni.chooseVideo({
  364. sourceType: [type],
  365. maxDuration: 15,
  366. compressed: false,
  367. success(re) {
  368. // console.log(re.tempFilePath);
  369. //console.log(re.tempFilePaths[0]);
  370. that.sendertap();
  371. var mids = 'm' + Math.random().toString(36).substring(2);
  372. var duration = re.duration;
  373. that.$emit('sendVedio', {
  374. mid: mids,
  375. src: re.tempFilePath,
  376. time: duration
  377. });
  378. var _that = that;
  379. helper.uploadFiles([re.tempFilePath], 'Vedio', {
  380. type: 'vedio'
  381. }).then(res => {
  382. that.$emit('sendVedio', {
  383. mid: mids,
  384. src: res,
  385. time: duration
  386. });
  387. });
  388. },
  389. fail(e) {
  390. console.log(e)
  391. }
  392. })
  393. },
  394. changeAuth() {
  395. console.log('5555555555555555')
  396. this[this.meth](this.openType)
  397. },
  398. openAuth(meth,type,name) {
  399. this.openType = type
  400. this.meth = meth
  401. // #ifdef APP-PLUS
  402. if(plus.os.name =='Android') {
  403. this.$refs[name].open() //调起自定义权限目的弹框,具体可看示例里面很详细
  404. }else {
  405. this[meth](type)
  406. }
  407. // #endif
  408. // #ifdef H5
  409. this[meth](type)
  410. // #endif
  411. },
  412. sendImg(type) {
  413. let that = this
  414. uni.chooseImage({
  415. sourceType: [type],
  416. sizeType: ['original', 'compressed'],
  417. success(re) {
  418. //console.log(re.tempFilePaths.length);
  419. //console.log(re.tempFilePaths[0]);
  420. that.sendertap();
  421. that.uploadnum = 0;
  422. for (var i = 0; i < re.tempFilePaths.length; i++) {
  423. that.mids[i] = 'm' + Math.random().toString(36).substring(2);
  424. // that.$emit('sendImage', {mid:that.mids[i],src: re.tempFilePaths[i]});
  425. var _that = that;
  426. // console.log(re.tempFilePaths[i]);
  427. helper.uploadFiles([re.tempFilePaths[i]], 'images', {
  428. type: 'images'
  429. }).then(res => {
  430. that.$emit('sendImage', {
  431. mid: _that.mids[that.uploadnum],
  432. src: res
  433. });
  434. });
  435. }
  436. }
  437. })
  438. },
  439. sendRedpactet() {
  440. if (this.user.banknum < 1) {
  441. uni.showModal({
  442. title: '提示',
  443. content: "绑定银行卡后才可以发送红包",
  444. showCancel: true,
  445. cancelText: '关闭',
  446. confirmText: '立即绑定',
  447. success: res => {
  448. if (res.confirm) {
  449. uni.navigateTo({
  450. url: "/pages/mine/bank"
  451. })
  452. }
  453. }
  454. });
  455. return false;
  456. } else {
  457. uni.navigateTo({
  458. url: '../friend/readpacket?isgroup=' + this.isgroup + '&id=' + this.groupid
  459. })
  460. }
  461. this.hide_panel();
  462. },
  463. listen(name, eventOrValue) {
  464. this.$emit(name, eventOrValue);
  465. this.focus = false;
  466. },
  467. set_focos() {
  468. if (this.focus == false) this.focus = true;
  469. },
  470. getfocus(detail) {
  471. this.boardheight = detail.height;
  472. // #ifdef APP-PLUS
  473. if (plus.os.name == 'Android') this.$emit("keyboardheight", detail.height);
  474. // #endif
  475. },
  476. unfocus() {
  477. this.boardheight = 0;
  478. // console.log('sender失去焦点')
  479. this.$emit("keyboardheight", 0);
  480. },
  481. unfocus1() {
  482. // console.log('box失去焦点')
  483. this.$emit("keyboardheight", 0);
  484. },
  485. sendertap() {
  486. this.showPanel = false;
  487. this.emoji = false;
  488. // z uni.hideKeyboard();
  489. },
  490. setinputvalue(e) {
  491. this.input_value = this.input_value + e + ' ';
  492. this.$emit('input', this.input_value);
  493. },
  494. istap() {
  495. },
  496. tapsender() {
  497. //this.inputclass='textarea sending'
  498. if (this.input_value != '') {
  499. var that = this;
  500. // setTimeout(function(){that.$emit('send',that.$event);},1000)
  501. that.$emit('send', that.$event);
  502. this.area_value = '';
  503. this.input_value = '';
  504. //that.$emit("senderheight",0);
  505. //this.keyboardheight=this.boardheight;
  506. // this.$emit("senderheight",300);
  507. if (this.sendtype != 'text') {
  508. this.hideemoji();
  509. this.hide_panel();
  510. }
  511. // #ifdef APP-PLUS
  512. //if(plus.os.name=="iOS") uni.hideKeyboard();
  513. // #endif
  514. }
  515. },
  516. listen1(e) {
  517. // console.log(e);
  518. this.input_value = e;
  519. this.listen('input', e);
  520. // console.log(e);
  521. },
  522. clickbox(e) {
  523. var x = e.touches[0].clientX;
  524. var y = e.touches[0].clientY;
  525. // console.log( windowWidth-x, windowHeight-y)
  526. if (windowWidth - x < 65) this.tapsender();
  527. },
  528. startVoice(e) {
  529. this.setting = true;
  530. this.willStop = false;
  531. this.voiceTis = '手指上滑 取消发送'
  532. recorderManager.start({
  533. format: 'mp3',
  534. numberOfChannels: 2,
  535. duration: 6000
  536. });
  537. this.starttime = new Date().getTime();
  538. this.initPoint.Y = e.touches[0].clientY;
  539. this.initPoint.identifier = e.touches[0].identifier;
  540. console.log('start');
  541. },
  542. //录音开始UI效果
  543. recordBegin(e) {
  544. /** 暂停语音播放 */
  545. console.log('录音开始UI效果');
  546. recorderManager.pause();
  547. this.setting = true;
  548. this.voiceTis = '松开 结束';
  549. this.recordLength = 0;
  550. this.recordTimer = setInterval(() => {
  551. this.recordLength++;
  552. }, 1000)
  553. },
  554. //录音停止 上传到服务器
  555. recordStop(res) {
  556. var that = this;
  557. this.endtime = new Date().getTime();
  558. that.voicePath = res.tempFilePath;
  559. if (!this.willStop) {
  560. if (this.endtime - this.starttime < 1000) return that.$toast('时间太短了');
  561. var duration = (this.endtime - this.starttime) / 1000;
  562. this.voice_mid = 'm' + Math.random().toString(36).substring(2);
  563. that.$emit('face', {
  564. url: that.voicePath,
  565. time: duration.toFixed(2),
  566. mid: this.voice_mid
  567. })
  568. helper.uploadFiles([that.voicePath], 'audio', {
  569. type: 'audio'
  570. }).then(res => {
  571. that.$emit('face', {
  572. url: res,
  573. time: duration.toFixed(2),
  574. mid: this.voice_mid
  575. })
  576. });
  577. action.playVoice('/static/voice/voice.mp3');
  578. } else {
  579. console.log('取消发送录音');
  580. }
  581. },
  582. // 录音被打断
  583. voiceCancel() {
  584. this.setting = false;
  585. this.willStop = true; //不发送录音
  586. recorderManager.stop(); //录音结束
  587. this.voiceTis = '按住 说话';
  588. this.recordTis = '手指上滑 取消发送'
  589. },
  590. // 录音中(判断是否触发上滑取消发送)
  591. voiceIng(e) {
  592. if (!this.setting) {
  593. return;
  594. }
  595. let touche = e.touches[0];
  596. //上滑一个导航栏的高度触发上滑取消发送
  597. if (this.initPoint.Y - touche.clientY >= uni.upx2px(100)) {
  598. this.willStop = true;
  599. this.recordTis = '松开手指 取消发送'
  600. } else {
  601. this.willStop = false;
  602. this.recordTis = '手指上滑 取消发送'
  603. }
  604. },
  605. endVoice() {
  606. this.setting = false
  607. recorderManager.stop();
  608. this.voiceTis = '按住 说话';
  609. this.recordTis = '手指上滑 取消发送';
  610. },
  611. sendVoice() {
  612. if(!this.voice) {
  613. // #ifdef APP-PLUS
  614. if(plus.os.name =='Android') {
  615. this.$refs.authpupRECORD_AUDIO.open()
  616. }else {
  617. this.voice = !this.voice;
  618. }
  619. // #endif
  620. // #ifndef APP-PLUS
  621. this.voice = !this.voice;
  622. // #endif
  623. // this.$refs.authpupRECORD_AUDIO.open()
  624. }else {
  625. this.voice = !this.voice;
  626. }
  627. },
  628. changeAuths() {
  629. this.voice = !this.voice;
  630. },
  631. getEmoji() {
  632. },
  633. sendEmoji(e) {
  634. //this.showPanel = false;
  635. this.emoji = false
  636. this.$emit('emoji', e)
  637. },
  638. handleEmotion(item) {
  639. var v = item.value;
  640. this.input_value += '[' + v + ']';
  641. this.area_value = this.input_value
  642. this.listen1(this.input_value);
  643. this.$emit('handleEmotion', this.input_value);
  644. },
  645. },
  646. created() {
  647. this.getEmoji()
  648. },
  649. onLoad() {
  650. },
  651. }
  652. </script>
  653. <style lang="scss" scoped>
  654. @import "@/static/css/chat/style.scss";
  655. $control-height: 120upx;
  656. $input-height: $control-height - $uni-spacing-col-base * 2;
  657. .face_box {
  658. position: fixed;
  659. bottom: 60px;
  660. ;
  661. left: 1px;
  662. width: calc(100% - 4px);
  663. z-index: 99;
  664. background-color: #fff;
  665. border: 1px #ddd solid;
  666. padding-top: 5px;
  667. ;
  668. border-top-right-radius: 5px;
  669. border-top-left-radius: 5px;
  670. }
  671. .faceImg {
  672. width: 100upx;
  673. flex-basis: 100upx;
  674. }
  675. .n-icon {
  676. font-size: 33px;
  677. line-height: 33px;
  678. color: #333;
  679. vertical-align: middle;
  680. }
  681. .icons {
  682. height: 70upx;
  683. line-height: 70upx;
  684. vertical-align: middle;
  685. }
  686. .icons image {
  687. width: 65upx;
  688. height: 55upx;
  689. vertical-align: middle;
  690. }
  691. .bigbox {
  692. position: fixed;
  693. bottom: 0px;
  694. left: 110upx;
  695. width: calc(100vw - 100upx);
  696. height: 120upx;
  697. line-height: 120upx;
  698. padding: 0px;
  699. z-index: 0;
  700. border: 0px #eee solid;
  701. color: transparent !important;
  702. }
  703. .bigbox2 {
  704. position: absolute;
  705. top: 10px;
  706. right: 80upx;
  707. width: 84upx;
  708. height: 120upx;
  709. line-height: 120upx;
  710. padding: 0px;
  711. z-index: 10;
  712. border: 0px #eee solid;
  713. }
  714. .bigbox3 {
  715. position: absolute;
  716. top: 10px;
  717. right: 0upx;
  718. width: 80upx;
  719. height: 120upx;
  720. line-height: 120upx;
  721. padding: 0px;
  722. z-index: 0;
  723. text-align: right;
  724. justify-content: right;
  725. border: 0px #eee solid;
  726. }
  727. .sending {
  728. color: transparent !important;
  729. }
  730. .v-sender {
  731. z-index: 99999999;
  732. position: fixed;
  733. bottom: 0;
  734. left: 0;
  735. width: 99vw;
  736. padding-left: 1vw;
  737. background-color: #fafafa;
  738. border-top: 1px solid #ddd;
  739. &__panel,
  740. &__control {
  741. position: relative;
  742. width: 100%;
  743. &::before {
  744. display: block;
  745. content: '\20';
  746. position: absolute;
  747. top: 0;
  748. left: 0;
  749. width: 100%;
  750. // background-color: #ddd;
  751. height: 1upx;
  752. transform: scaleY(0.5);
  753. }
  754. }
  755. &__panel {
  756. width: 100%;
  757. display: table;
  758. padding: 20upx 0;
  759. font-size: 28upx;
  760. background: #fafafa;
  761. >view {
  762. .n-icon {
  763. font-size: 33px;
  764. color: #999;
  765. }
  766. text-align: center;
  767. display: table-cell;
  768. }
  769. }
  770. &__control {
  771. height: $control-height;
  772. padding: $uni-spacing-col-base 0px $uni-spacing-col-base 0;
  773. &,
  774. .emoji,
  775. .btn {
  776. display: flex;
  777. flex-direction: row;
  778. flex-wrap: nowrap;
  779. align-items: center;
  780. box-sizing: border-box;
  781. }
  782. >.emoji,
  783. >.btn,
  784. >input {
  785. margin-left: $uni-spacing-row-base;
  786. }
  787. view {
  788. height: $input-height;
  789. flex-shrink: 0;
  790. }
  791. .emoji {
  792. font-size: 64upx;
  793. line-height: $input-height;
  794. }
  795. input,
  796. .falseinput {
  797. flex: 1;
  798. height: $input-height;
  799. border-radius: $uni-border-radius-base;
  800. box-sizing: border-box;
  801. background-color: #ccc;
  802. height: 68upx;
  803. line-height: 68upx;
  804. margin-left: 10px;
  805. ;
  806. }
  807. .falseinput.press {
  808. background-color: #666;
  809. color: #fff !important;
  810. }
  811. .btn {
  812. line-height: $input-height - 10upx;
  813. height: $input-height - 10upx;
  814. color: #fff;
  815. text-align: center;
  816. background-color: $uni-color-primary;
  817. }
  818. }
  819. &__control_t {
  820. height: 80upx;
  821. padding: 0;
  822. .qute-wrap {
  823. border: none;
  824. background-color: #eaeaea;
  825. height: 40upx;
  826. font-size: 26upx;
  827. color: #6d6d6d;
  828. display: flex;
  829. justify-content: space-between;
  830. flex-wrap: nowrap;
  831. .content {
  832. flex-grow: 1;
  833. text-overflow: ellipsis;
  834. white-space: nowrap;
  835. overflow: hidden;
  836. max-width: 90%;
  837. height: 45rpx;
  838. }
  839. image {
  840. flex-shrink: 0;
  841. width: 28upx;
  842. height: 28upx;
  843. }
  844. }
  845. }
  846. }
  847. .textarea,
  848. .textareas {
  849. font-size: 32upx;
  850. background: #fff;
  851. border: 1px solid #ddd;
  852. max-height: 80upx;
  853. min-height: 40upx;
  854. line-height: 40upx;
  855. padding: 12upx 10upx;
  856. border-radius: 3px;
  857. ;
  858. }
  859. .textarea {
  860. margin-left: 10px;
  861. /* #ifndef H5 */
  862. width: calc(100% - 290upx);
  863. /* #endif */
  864. /* #ifdef H5 */
  865. width: calc(100% - 210upx);
  866. /* #endif */
  867. }
  868. .textarea.input {
  869. /* #ifndef H5 */
  870. width: calc(100% - 360upx);
  871. /* #endif */
  872. /* #ifdef H5 */
  873. width: calc(100% - 280upx);
  874. /* #endif */
  875. }
  876. .sendbtn {
  877. margin-left: 16upx !important;
  878. padding: 0px 40upx !important;
  879. }
  880. .emotion-box {
  881. margin: 0 auto;
  882. width: calc(100% - 4px);
  883. box-sizing: border-box;
  884. padding: 2px;
  885. overflow: hidden;
  886. overflow-y: auto;
  887. }
  888. .emotion-box-line {
  889. display: flex;
  890. }
  891. .emotion-item {
  892. flex: 1;
  893. text-align: center;
  894. cursor: pointer;
  895. }
  896. </style>