sender.vue 31 KB

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