chat.vue 24 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043
  1. <template>
  2. <view class="chat-box" :style="colorStyle">
  3. <!-- #ifdef MP -->
  4. <view class="head-box">
  5. <view class="system-head" :style="{ height: sysHead }"></view>
  6. <view class="title-hd">
  7. <view class="iconfont icon-fanhui" @click="goBack"></view>
  8. <view>{{ titleName }}</view>
  9. </view>
  10. </view>
  11. <!-- #endif -->
  12. <view class="broadcast-details_order">
  13. <!-- 商品信息 -->
  14. <view class="broadcast-details_box" v-if="productId && productInfo.id">
  15. <view class="broadcast_details_img">
  16. <image class="goods-img" :src="productInfo.image" />
  17. </view>
  18. <view class="broadcast_details_picBox">
  19. <view class="broadcast_details_tit" v-text="productInfo.store_name"></view>
  20. <view class="bottom acea-row row-between">
  21. <view class="broadcast_details_pic">
  22. ¥{{ productInfo.price }}
  23. <text class="broadcast_details_pic_num"
  24. v-if="productInfo.ot_price">¥{{ productInfo.ot_price }}</text>
  25. </view>
  26. <view class="broadcast_details_btn" @click="sendProduct">发送客服</view>
  27. </view>
  28. </view>
  29. </view>
  30. <!-- 订单信息 -->
  31. <view class="broadcast_box" v-if="orderId && orderInfo.id">
  32. <view class="broadcast-details_num broadcast_num">
  33. <text>订单号:{{ orderInfo.order_id }}</text>
  34. <text>{{ orderInfo.add_time_y }} {{ orderInfo.add_time_h }}</text>
  35. </view>
  36. <view class="broadcast-details_box" v-if="orderInfo.cartInfo">
  37. <view class="broadcast_details_img">
  38. <image class="goods-img"
  39. :src="orderInfo.cartInfo[0].productInfo.attrInfo?orderInfo.cartInfo[0].productInfo.attrInfo.image:orderInfo.cartInfo[0].productInfo.image" />
  40. <view class="broadcast_details_model">
  41. {{ orderInfo.cartInfo ? orderInfo.cartInfo.length : 0 }}件商品
  42. </view>
  43. </view>
  44. <view class="broadcast_details_picBox">
  45. <view class="broadcast_details_tit">{{ orderInfo.cartInfo[0].productInfo.store_name }}</view>
  46. <view class="bottom acea-row row-between">
  47. <view class="broadcast_details_pic">
  48. ¥{{ orderInfo.cartInfo[0].productInfo.attrInfo?orderInfo.cartInfo[0].productInfo.attrInfo.price:orderInfo.cartInfo[0].productInfo.price }}
  49. <text class="broadcast_details_pic_num">¥{{ orderInfo.cartInfo[0].costPrice }}</text>
  50. </view>
  51. <view class="broadcast_details_btn" @click="sendOrder">发送客服</view>
  52. </view>
  53. </view>
  54. </view>
  55. </view>
  56. </view>
  57. <view class="chat-scroll-box">
  58. <scroll-view scroll-y="true" style="height: 100%;" :scroll-top="scrollTop" @scrolltoupper="scrollToTop">
  59. <Loading :loaded="status" :loading="loading"></Loading>
  60. <view id="box" class="chat" ref="chat">
  61. <view v-for="(item, index) in records" :key="index" :id="`msg-${item.id}`" class="msgItem">
  62. <view class="day-box" v-if="item.show">{{item._add_time}}</view>
  63. <view class="chat-item" :class="{ 'right-box': item.uid == myUid }">
  64. <image class="avatar" :src="item.avatar" mode=""></image>
  65. <!-- 消息 -->
  66. <view class="msg-box" v-if="item.msn_type <= 2" v-html="item.msn"></view>
  67. <!-- 图片 -->
  68. <view class="img-box" v-if="item.msn_type == 3">
  69. <image :src="item.msn" mode="widthFix" @tap="previewImage(item.msn)"></image>
  70. </view>
  71. <!-- 商品 -->
  72. <view class="product-box" v-if="item.msn_type == 5" @click="goProduct(item)">
  73. <image v-if="Array.isArray(item.productInfo)" src="../static/product-off.png" mode="aspectFit" class="product-off"></image>
  74. <template v-else>
  75. <image
  76. :src="item.productInfo.cartInfo?item.productInfo.cartInfo.image:item.productInfo.image"
  77. mode="widthFix"></image>
  78. <view class="info">
  79. <view class="price">
  80. <text>¥</text>
  81. {{ item.productInfo.cartInfo?item.productInfo.cartInfo.price:item.productInfo.price }}
  82. </view>
  83. <view class="name line2">{{ item.productInfo.store_name }}</view>
  84. </view>
  85. </template>
  86. </view>
  87. <!-- 订单 -->
  88. <view class="order-box"
  89. v-if="(item.msn_type == 6 || item.msn_type == 7) && item.orderInfo.cartInfo"
  90. @click="goOrder(item)">
  91. <view class="title">订单号: {{ item.orderInfo.order_id }}</view>
  92. <view class="info">
  93. <image
  94. :src="item.orderInfo.cartInfo[0].productInfo.attrInfo?item.orderInfo.cartInfo[0].productInfo.attrInfo.image:item.orderInfo.cartInfo[0].productInfo.image">
  95. </image>
  96. <view class="product-info">
  97. <view class="name line2">{{ item.orderInfo.cartInfo[0].productInfo.store_name }}
  98. </view>
  99. <view class="price">
  100. ¥{{ item.orderInfo.cartInfo[0].productInfo.attrInfo?item.orderInfo.cartInfo[0].productInfo.attrInfo.price:item.orderInfo.cartInfo[0].productInfo.price }}
  101. </view>
  102. </view>
  103. </view>
  104. </view>
  105. </view>
  106. </view>
  107. </view>
  108. </scroll-view>
  109. </view>
  110. <view class="pb-safe bg--w111-f5f5f5">
  111. <view class="footer-box">
  112. <view class="words" @click="uploadImg"><text class="iconfont icon-ic_picture"></text></view>
  113. <view class="input-box">
  114. <view class="flex-1 pl-20 h-full fs-28 text--w111-999 flex-y-center" @tap="showInputDrawer">请输入内容</view>
  115. <!-- <input type="text" placeholder="请输入内容" v-model="con" confirm-type="send" @confirm="sendText" /> -->
  116. <text class="iconfont icon-ic_send" @click="sendText" :class="{ isSend: isSend }"></text>
  117. </view>
  118. <view class="emoji" @click="isSwiper = !isSwiper"><span class="iconfont icon-ic_expression"></span></view>
  119. </view>
  120. </view>
  121. <!-- 表情 -->
  122. <view class="banner slider-banner" v-if="isSwiper && httpUrl">
  123. <swiper class="swiper-wrapper" :autoplay="autoplay" :circular="circular" :interval="interval"
  124. :duration="duration" v-if="emojiGroup.length > 0">
  125. <block v-for="(emojiList, index) in emojiGroup" :key="index">
  126. <swiper-item><i class="em" :class="emoji" :style="'background-image:url('+ httpUrl +')'"
  127. v-for="emoji in emojiList" :key="emoji" @click="addEmoji(emoji)"></i></swiper-item>
  128. </block>
  129. </swiper>
  130. </view>
  131. <canvas canvas-id="canvas" v-if="canvasStatus"
  132. :style="{width: canvasWidth + 'px', height: canvasHeight + 'px',position: 'absolute',left:'-100000px',top:'-100000px'}"></canvas>
  133. <tui-drawer mode="bottom" :visible="showInput" background-color="transparent" mask maskClosable @close="showInputDrawer">
  134. <view class="w-full bg--w111-fff drawer-text pt-32 pl-32 pr-32">
  135. <view class="bg--w111-f5f5f5 rd-32rpx pt-16 pr-14 pb-16 pl-24 relative">
  136. <textarea class="w-528 fs-28 h-auto"
  137. :auto-height="true"
  138. wrap-style="wrap"
  139. max-height="100px"
  140. placeholder-class='placeholder'
  141. placeholder="请输入内容"
  142. :always-embed="true"
  143. :adjust-position="true"
  144. cursor-spacing="85rpx"
  145. v-model="con"
  146. :maxlength="150"
  147. name="mark">
  148. </textarea>
  149. <view class="reply-confirm-btn w-96 h-48 rd-24rpx flex-center bg-color text--w111-fff fs-24 ml-24"
  150. @tap="sendText">发送</view>
  151. </view>
  152. </view>
  153. </tui-drawer>
  154. </view>
  155. </template>
  156. <script>
  157. const app = getApp();
  158. import {HTTP_REQUEST_URL} from "@/config/app.js";
  159. import {getChatRecord} from '@/api/user';
  160. import {getProductDetail} from '@/api/store';
  161. import {getOrderDetail,getRefundOrderDetail} from '@/api/order';
  162. let statusBarHeight = uni.getSystemInfoSync().statusBarHeight + 'px';
  163. const chunk = function(arr, num) {
  164. num = num * 1 || 1;
  165. var ret = [];
  166. arr.forEach(function(item, i) {
  167. if (i % num === 0) {
  168. ret.push([]);
  169. }
  170. ret[ret.length - 1].push(item);
  171. });
  172. return ret;
  173. };
  174. import emojiList from '@/utils/emoji';
  175. import Loading from '@/components/Loading';
  176. import tuiDrawer from "@/components/tui-drawer/tui-drawer.vue"
  177. import colors from "@/mixins/color";
  178. export default {
  179. name: 'adminChat_index',
  180. data() {
  181. return {
  182. httpUrl: '',
  183. status: false,
  184. loading: false,
  185. sysHead: statusBarHeight,
  186. isTool: false,
  187. isSwiper: false,
  188. isWords: false,
  189. autoplay: false,
  190. circular: true,
  191. interval: 3000,
  192. duration: 500,
  193. emojiGroup: chunk(emojiList, 21),
  194. wordsList: [],
  195. con: '',
  196. toUid: 0,
  197. limit: 15,
  198. upperId: 0,
  199. chatList: [],
  200. kefuInfo: {},
  201. scrollTop: 0,
  202. active: true,
  203. isScroll: true,
  204. oldHeight: 0,
  205. myUid: 0,
  206. productId: 0,
  207. productInfo: {},
  208. orderId: 0,
  209. page: 1,
  210. orderInfo: {},
  211. uidTo: 0,
  212. titleName: '',
  213. chatStatus: false,
  214. userType: 0,
  215. canvasWidth: "",
  216. canvasHeight: "",
  217. canvasStatus: false,
  218. isReturen: 0,
  219. showInput: false
  220. };
  221. },
  222. mixins: [colors],
  223. components: {
  224. Loading,
  225. tuiDrawer
  226. },
  227. computed: {
  228. isSend() {
  229. if (this.con.length == 0) {
  230. return false;
  231. } else {
  232. return true;
  233. }
  234. },
  235. records() {
  236. return this.chatList.map((item, index) => {
  237. if (index) {
  238. if (item.add_time - this.chatList[index - 1].add_time >= 300) {
  239. item.show = true;
  240. } else {
  241. item.show = false;
  242. }
  243. } else {
  244. item.show = true;
  245. }
  246. return item;
  247. });
  248. }
  249. },
  250. onLoad(options) {
  251. this.isReturen = options.isReturen;
  252. this.myUid = this.$store.state.app.uid;
  253. this.toUid = options.to_uid
  254. this.productId = parseInt(options.productId) || 0;
  255. this.orderId = options.orderId || 0;
  256. this.userType = options.type
  257. this.getproductInfo();
  258. this.getOrderInfo();
  259. this.getChatList();
  260. },
  261. onUnload() {
  262. this.$socket.clearPing();
  263. app.globalData.isWsOpen = false;
  264. uni.$off()
  265. },
  266. onReady() {
  267. this.httpUrl = `${HTTP_REQUEST_URL}/statics/images/look.png`;
  268. // #ifdef H5
  269. let dom = document.querySelector(".chat-box");
  270. dom.style.height = window.innerHeight + 'px'
  271. // #endif
  272. // 监听客服转接
  273. uni.$on('to_transfer', data => {
  274. this.toUid = data.toUid;
  275. this.$socket.send({
  276. data: {
  277. id: this.toUid
  278. },
  279. type: 'to_chat'
  280. });
  281. this.chatList.forEach(el => {
  282. if (el.uid != this.myUid) {
  283. el.avatar = data.avatar
  284. }
  285. })
  286. });
  287. // 链接成功
  288. uni.$on('success', () => {
  289. app.globalData.isWsOpen = true;
  290. uni.hideLoading();
  291. this.$socket.send({
  292. data: {
  293. id: this.toUid
  294. },
  295. type: 'to_chat'
  296. });
  297. });
  298. // 消息接收
  299. uni.$on(['reply', 'chat'], data => {
  300. if (data.msn_type == 1) {
  301. data.msn = this.replace_em(data.msn);
  302. }
  303. data._add_time = data._add_time.substring(0, data._add_time.length - 3);
  304. this.chatList.push(data);
  305. this.$nextTick(() => {
  306. this.height();
  307. });
  308. });
  309. uni.$on('socket_error', () => {
  310. this.$util.Tips({
  311. title: '连接失败'
  312. });
  313. });
  314. uni.$on('err_tip', (e) => {
  315. this.$util.Tips({
  316. title: e.msg
  317. });
  318. });
  319. uni.$on('online', data => {
  320. if (data.online == 0) {
  321. uni.showModal({
  322. title: '提示',
  323. content: '客服已下线,是否需要反馈?',
  324. success: function(res) {
  325. if (res.confirm) {
  326. uni.redirectTo({
  327. url: '/pages/extension/customer_list/feedback'
  328. });
  329. } else if (res.cancel) {}
  330. }
  331. });
  332. }
  333. });
  334. this.$nextTick(() => {
  335. this.height();
  336. });
  337. },
  338. onShow(){
  339. uni.removeStorageSync('form_type_cart');
  340. },
  341. methods: {
  342. previewImage(n) {
  343. uni.previewImage({
  344. urls: [n]
  345. });
  346. },
  347. // 返回
  348. goBack() {
  349. uni.navigateBack({
  350. delta: 1,
  351. fail(){
  352. uni.switchTab({
  353. url: '/pages/index/index'
  354. })
  355. }
  356. });
  357. },
  358. // 商品信息
  359. getproductInfo() {
  360. let that = this;
  361. if (!this.productId) return;
  362. getProductDetail(this.productId).then(res => {
  363. that.productInfo = res.data.storeInfo;
  364. });
  365. },
  366. // 商品信息
  367. goProduct(item) {
  368. uni.navigateTo({
  369. url: `/pages/goods_details/index?id=${item.msn}`
  370. });
  371. },
  372. // 订单详情
  373. goOrder(item) {
  374. if (this.userType) {
  375. if (item.msn_type == 7) {
  376. uni.navigateTo({
  377. url: `/pages/admin/orderDetail/index?id=${item.msn}&isReturen=1`
  378. });
  379. } else {
  380. uni.navigateTo({
  381. url: `/pages/admin/orderDetail/index?id=${item.msn}`
  382. });
  383. }
  384. } else {
  385. if (item.msn_type == 7) {
  386. uni.navigateTo({
  387. url: `/pages/goods/order_details/index?order_id=${item.msn}&isReturen=1`
  388. });
  389. } else {
  390. uni.navigateTo({
  391. url: `/pages/goods/order_details/index?order_id=${item.msn}`
  392. });
  393. }
  394. }
  395. },
  396. // 订单消息
  397. getOrderInfo() {
  398. if (!this.orderId) return;
  399. let obj = '';
  400. if (this.isReturen == 1) {
  401. obj = getRefundOrderDetail(this.orderId);
  402. } else {
  403. obj = getOrderDetail(this.orderId);
  404. }
  405. obj.then(res => {
  406. this.orderInfo = res.data;
  407. if (this.orderInfo.add_time_h) {
  408. this.orderInfo.add_time_h = this.orderInfo.add_time_h.substring(0, this.orderInfo
  409. .add_time_h.lastIndexOf(':'));
  410. }
  411. if (this.orderInfo.cartInfo.length) {
  412. this.cartInfo = this.orderInfo.cartInfo[0];
  413. }
  414. });
  415. },
  416. // 表情点击
  417. addEmoji(item) {
  418. let val = `[${item}]`;
  419. this.con += val;
  420. },
  421. // 聊天表情转换
  422. replace_em(str) {
  423. str = str.replace(/\[em-([\s\S]*?)\]/g, "<span class='em em-$1' style='background-image:url(" + this
  424. .httpUrl + ")'></span>");
  425. return str;
  426. },
  427. // 获取聊天列表
  428. getChatList() {
  429. let self = this;
  430. getChatRecord({
  431. limit: this.limit,
  432. uidTo: this.uidTo,
  433. toUid: this.toUid
  434. })
  435. .then(res => {
  436. let selector = '';
  437. if (res.data.serviceList.length) {
  438. if (this.uidTo == 0) {
  439. selector = `#msg-${res.data.serviceList[res.data.serviceList.length - 1].id}`;
  440. } else {
  441. selector = `#msg-${this.chatList[0].id}`;
  442. }
  443. }
  444. let arr = [];
  445. var sH = 0;
  446. uni.hideLoading();
  447. uni.setNavigationBarTitle({
  448. title: res.data.nickname
  449. });
  450. this.titleName = res.data.nickname;
  451. this.toUid = res.data.uid;
  452. res.data.serviceList.forEach(el => {
  453. el._add_time = el._add_time.substring(0, el._add_time.length - 3);
  454. if (el.msn_type == 1 || el.msn_type == 2) {
  455. el.msn = this.replace_em(el.msn);
  456. }
  457. });
  458. this.loading = false;
  459. this.chatList = [...res.data.serviceList, ...this.chatList];
  460. if (!app.globalData.isWsOpen) {
  461. uni.showLoading({
  462. title: '客服连接中...',
  463. });
  464. this.$socket.startConnect();
  465. //5秒后还是没有连接自动关闭
  466. setTimeout(() => {
  467. uni.hideLoading();
  468. }, 5000);
  469. }
  470. this.$nextTick(() => {
  471. this.setPageScrollTo(selector);
  472. this.isScroll = res.data.serviceList.length >= this.limit;
  473. });
  474. })
  475. .catch(error => {
  476. uni.hideLoading();
  477. this.$util.Tips({
  478. title: error
  479. });
  480. this.loading = false;
  481. this.isScroll = false
  482. uni.redirectTo({
  483. // url: '/pages/columnGoods/HotNewGoods/feedback'
  484. url: '/pages/extension/customer_list/feedback'
  485. });
  486. });
  487. },
  488. // 设置页面滚动位置
  489. setPageScrollTo(selector) {
  490. try {
  491. if (this.chatList.length) {
  492. let view = uni
  493. .createSelectorQuery()
  494. .in(this)
  495. .select(selector);
  496. view.boundingClientRect(res => {
  497. this.scrollTop = parseFloat(res.top) - 60;
  498. }).exec();
  499. }
  500. } catch (e) {
  501. console.log(e);
  502. }
  503. },
  504. showInputDrawer(){
  505. this.showInput = !this.showInput;
  506. },
  507. // 发送消息
  508. sendText() {
  509. if (!this.isSend || this.con.trim() === '') {
  510. return this.$util.Tips({
  511. title: '请输入内容'
  512. });
  513. }
  514. this.sendMsg(this.con, 1);
  515. this.con = '';
  516. },
  517. // ws发送
  518. sendMsg(msn, type) {
  519. this.$socket.send({
  520. data: {
  521. msn,
  522. type,
  523. to_uid: this.toUid
  524. },
  525. //#ifdef MP || APP-PLUS
  526. form_type: 2,
  527. //#endif
  528. //#ifdef H5
  529. form_type: this.$wechat.isWeixin() ? 1 : 3,
  530. //#endif
  531. type: 'chat'
  532. });
  533. this.showInput = false;
  534. },
  535. uploadImg() {
  536. let self = this;
  537. self.canvasStatus = true
  538. self.$util.uploadImageChange('upload/image', function(res) {
  539. if (res.status == 200) {
  540. self.sendMsg(res.data.url, 3);
  541. }
  542. }, (res) => {
  543. this.canvasStatus = false
  544. }, (res) => {
  545. this.canvasWidth = res.w
  546. this.canvasHeight = res.h
  547. });
  548. },
  549. // 发送商品
  550. sendProduct() {
  551. this.sendMsg(this.productId, 5);
  552. this.productId = 0;
  553. this.productInfo = {};
  554. },
  555. // 发送订单
  556. sendOrder() {
  557. let num = 0;
  558. if (this.isReturen == 1) {
  559. num = 7;
  560. } else {
  561. num = 6;
  562. }
  563. this.sendMsg(this.orderId, num);
  564. this.orderId = 0;
  565. this.orderInfo = {};
  566. },
  567. // 滚动到底部
  568. height() {
  569. let self = this;
  570. var scrollTop = 0;
  571. let info = uni.createSelectorQuery().select('.chat');
  572. setTimeout(res => {
  573. info.boundingClientRect(function(data) {
  574. //data - 各种参数
  575. scrollTop = data.height;
  576. if (self.active) {
  577. self.scrollTop = parseInt(scrollTop) + 500;
  578. } else {
  579. self.scrollTop = parseInt(scrollTop) + 100;
  580. }
  581. }).exec();
  582. }, 200);
  583. },
  584. // 滚动到顶部
  585. scrollToTop() {
  586. let self = this;
  587. if (this.isScroll) {
  588. this.loading = true;
  589. this.uidTo = this.chatList[0].id;
  590. this.isScroll = false;
  591. setTimeout(res => {
  592. this.getChatList();
  593. }, 800);
  594. }
  595. }
  596. }
  597. };
  598. </script>
  599. <style>
  600. /* #ifdef MP || APP-PLUS || H5 */
  601. page,
  602. uni-page-body,
  603. html,
  604. body {
  605. height: 100%;
  606. }
  607. /* #endif */
  608. .em {
  609. display: inline-block;
  610. width: 50rpx;
  611. height: 50rpx;
  612. margin: 40rpx 0 0 50rpx;
  613. /* background-size: 4100%!important;
  614. background-position: 2.5% 62.5%!important; */
  615. }
  616. .emoji-outer {
  617. position: absolute;
  618. right: 50rpx;
  619. bottom: 30rpx;
  620. width: 50rpx;
  621. height: 50rpx;
  622. }
  623. </style>
  624. <style lang="scss">
  625. .chat-box {
  626. display: flex;
  627. flex-direction: column;
  628. height: 100%;
  629. background: #f0f1f2;
  630. /* #ifdef H5 */
  631. height: 100vh;
  632. /* #endif */
  633. .head-box {
  634. /* #ifdef H5 */
  635. height: 86rpx;
  636. /* #endif */
  637. background: linear-gradient(85deg, $kf-star 0%, $kf-end 100%);
  638. .title-hd {
  639. display: flex;
  640. align-items: center;
  641. justify-content: center;
  642. position: relative;
  643. height: 43px;
  644. padding: 0 30rpx;
  645. color: #fff;
  646. .icon-fanhui {
  647. position: absolute;
  648. left: 30rpx;
  649. top: 50%;
  650. transform: translateY(-50%);
  651. }
  652. .icon-gengduo2 {
  653. /* #ifdef MP */
  654. position: absolute;
  655. right: 210rpx;
  656. top: 50%;
  657. transform: translateY(-50%);
  658. /* #endif */
  659. }
  660. }
  661. }
  662. .scroll-box {
  663. flex: 1;
  664. }
  665. .footer-box {
  666. display: flex;
  667. align-items: center;
  668. padding: 0 30rpx;
  669. color: rgba(0, 0, 0, 0.8);
  670. background: #f5f5f5;
  671. height: 100rpx;
  672. // height: calc(100rpx+ constant(safe-area-inset-bottom)); ///兼容 IOS<11.2/
  673. // height: calc(100rpx + env(safe-area-inset-bottom)); ///兼容 IOS>11.2/
  674. .words .icon-ic_picture {
  675. font-size: 50rpx;
  676. }
  677. .input-box {
  678. display: flex;
  679. align-items: center;
  680. flex: 1;
  681. height: 64rpx;
  682. padding-right: 5rpx;
  683. margin-left: 18rpx;
  684. background-color: #fff;
  685. border-radius: 32rpx;
  686. input {
  687. flex: 1;
  688. padding-left: 20rpx;
  689. height: 100%;
  690. font-size: 28rpx;
  691. font-weight: normal;
  692. }
  693. .icon-ic_send {
  694. font-size: 50rpx;
  695. color: #ccc;
  696. font-weight: normal;
  697. margin-left: 30rpx;
  698. }
  699. .isSend {
  700. color: $kf-theme;
  701. }
  702. }
  703. .emoji .icon-ic_expression {
  704. margin-left: 18rpx;
  705. font-size: 50rpx;
  706. }
  707. .more .icon-gengduozhankai {
  708. margin-left: 18rpx;
  709. font-size: 50rpx;
  710. }
  711. }
  712. }
  713. .tool-wrapper {
  714. display: flex;
  715. justify-content: space-between;
  716. padding: 45rpx 60rpx;
  717. background: #fff;
  718. font-size: 24rpx;
  719. .tool-item {
  720. text-align: center;
  721. image {
  722. width: 104rpx;
  723. height: 104rpx;
  724. }
  725. }
  726. }
  727. .slider-banner {
  728. background: #fff;
  729. padding-bottom: 25rpx;
  730. }
  731. .words-mask {
  732. z-index: 50;
  733. position: fixed;
  734. left: 0;
  735. top: 0;
  736. right: 0;
  737. bottom: 0;
  738. background: rgba(0, 0, 0, 0.5);
  739. .content {
  740. position: absolute;
  741. left: 0;
  742. right: 0;
  743. top: 114rpx;
  744. bottom: 0;
  745. display: flex;
  746. flex-direction: column;
  747. padding: 0 30rpx;
  748. background: #fff;
  749. border-radius: 6rpx 6rpx 0px 0px;
  750. .title-box {
  751. position: relative;
  752. height: 125rpx;
  753. line-height: 125rpx;
  754. text-align: center;
  755. font-size: 32rpx;
  756. .icon-cha1 {
  757. position: absolute;
  758. right: 0;
  759. top: 50%;
  760. transform: translateY(-50%);
  761. }
  762. }
  763. .scroll-box {
  764. flex: 1;
  765. overflow: hidden;
  766. .msg-item {
  767. padding: 25rpx 0;
  768. border-bottom: 1px solid #eceff8;
  769. }
  770. }
  771. }
  772. }
  773. .chat-scroll-box {
  774. flex: 1;
  775. padding: 0 30rpx 0;
  776. overflow: hidden;
  777. .chat-item {
  778. display: flex;
  779. margin-bottom: 16rpx;
  780. padding-bottom: 20rpx;
  781. .avatar {
  782. width: 80rpx;
  783. height: 80rpx;
  784. border-radius: 50%;
  785. }
  786. .msg-box {
  787. display: flex;
  788. align-items: center;
  789. max-width: 452rpx;
  790. margin-left: 22rpx;
  791. padding: 10rpx 24rpx;
  792. background: #fff;
  793. border-radius: 14rpx;
  794. word-break: break-all;
  795. }
  796. .img-box {
  797. width: 270rpx;
  798. margin-left: 22rpx;
  799. image {
  800. width: 270rpx;
  801. }
  802. }
  803. .product-box {
  804. width: 452rpx;
  805. margin-left: 22rpx;
  806. background-color: #fff;
  807. border-radius: 14rpx;
  808. overflow: hidden;
  809. image {
  810. width: 452rpx;
  811. }
  812. .info {
  813. padding: 16rpx 26rpx;
  814. .price {
  815. font-size: 36rpx;
  816. color: var(--view-priceColor);
  817. text {
  818. font-size: 28rpx;
  819. }
  820. }
  821. }
  822. }
  823. .order-box {
  824. width: 452rpx;
  825. margin-left: 22rpx;
  826. background-color: #fff;
  827. border-radius: 14rpx;
  828. .title {
  829. padding: 15rpx 20rpx;
  830. font-size: 26rpx;
  831. color: #282828;
  832. border-bottom: 1px solid #eceff8;
  833. }
  834. .info {
  835. display: flex;
  836. padding: 20rpx;
  837. image {
  838. width: 124rpx;
  839. height: 124rpx;
  840. border-radius: 6rpx;
  841. }
  842. .product-info {
  843. flex: 1;
  844. display: flex;
  845. flex-direction: column;
  846. justify-content: space-between;
  847. margin-left: 16rpx;
  848. .name {
  849. font-size: 26rpx;
  850. }
  851. .price {
  852. font-size: 30rpx;
  853. color: var(--view-priceColor);
  854. }
  855. }
  856. }
  857. }
  858. &.right-box {
  859. flex-direction: row-reverse;
  860. .msg-box {
  861. margin-left: 0;
  862. margin-right: 22rpx;
  863. background-color: #9cec60;
  864. }
  865. .img-box {
  866. margin-left: 0;
  867. margin-right: 22rpx;
  868. }
  869. .product-box {
  870. margin-left: 0;
  871. margin-right: 22rpx;
  872. }
  873. .order-box {
  874. margin-left: 0;
  875. margin-right: 22rpx;
  876. }
  877. }
  878. .em {
  879. margin: 0;
  880. }
  881. }
  882. }
  883. .broadcast-details_box {
  884. display: flex;
  885. background: #fff;
  886. border-radius: 6px;
  887. padding: 24rpx;
  888. }
  889. .broadcast_details_img {
  890. width: 140rpx;
  891. height: 140rpx;
  892. border-radius: 8px;
  893. overflow: hidden;
  894. position: relative;
  895. }
  896. .broadcast_details_img .goods-img {
  897. width: 100%;
  898. height: 100%;
  899. }
  900. .broadcast_details_picBox {
  901. width: 75%;
  902. margin-left: 24rpx;
  903. .bottom {
  904. margin-top: 12rpx;
  905. }
  906. }
  907. .broadcast_details_tit {
  908. font-size: 28rpx;
  909. color: #333333;
  910. height: 76rpx;
  911. font-weight: 800;
  912. overflow: hidden;
  913. text-overflow: ellipsis;
  914. display: -webkit-box;
  915. -webkit-line-clamp: 2;
  916. -webkit-box-orient: vertical;
  917. text-align: left !important;
  918. }
  919. .broadcast_details_pic {
  920. font-size: 36rpx;
  921. color: var(--view-priceColor);
  922. text-align: left;
  923. }
  924. .broadcast_details_pic_num {
  925. text-decoration: line-through;
  926. font-size: 28rpx;
  927. color: rgba(0, 0, 0, 0.5);
  928. margin-left: 0.1rem;
  929. }
  930. .broadcast_details_btn {
  931. width: 130rpx;
  932. height: 50rpx;
  933. background: var(--view-theme);
  934. opacity: 1;
  935. border-radius: 125rpx;
  936. color: #fff;
  937. font-size: 24rpx;
  938. text-align: center;
  939. line-height: 50rpx;
  940. }
  941. .broadcast-details_num {
  942. width: 100%;
  943. height: 80rpx;
  944. line-height: 80rpx;
  945. color: #000000;
  946. font-size: 26rpx;
  947. display: flex;
  948. justify-content: space-between;
  949. background: #fff;
  950. border-bottom: 1px dashed rgba(0, 0, 0, 0.2);
  951. padding: 0 24rpx;
  952. }
  953. .day-box {
  954. font-size: 24rpx;
  955. color: #999;
  956. text-align: center;
  957. margin-bottom: 36rpx;
  958. }
  959. .msgItem {
  960. &:first-child {
  961. .day-box {
  962. padding-top: 30rpx;
  963. }
  964. }
  965. }
  966. .reply-confirm-btn{
  967. position: absolute;
  968. bottom: 10rpx;
  969. right: 14rpx;
  970. }
  971. .drawer-text{
  972. padding-bottom: calc(32rpx + env(safe-area-inset-bottom));
  973. }
  974. </style>