You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1372 lines
37 KiB
1372 lines
37 KiB
<!--
|
|
版本声明:
|
|
* 由于 WanlLive、WanlChat、以下代码开发难度较大,已将相关代码独立申请著作权,受法律保护!!!
|
|
* 无论你购买任何版本,均不允许复制到第三方直接、间接使用,且也不能以学习为目的参考和借鉴!!
|
|
* 你仅有在 WanlShop 中使用、二次开发权利,否则我们会追究法律责任
|
|
* 深圳前海万联科技有限公司 @www.i36k.com
|
|
-->
|
|
<template>
|
|
<view class="wanl-chat">
|
|
<view class="edgeInsetTop"></view>
|
|
<view @touchstart="hideDrawer">
|
|
<scroll-view class="cu-chat" scroll-y="true" :scroll-with-animation="scrollAnimation" :scroll-top="scrollTop"
|
|
:scroll-into-view="scrollToView" @scrolltoupper="loadHistory" upper-threshold="50">
|
|
<!-- 加载历史数据waitingUI -->
|
|
<view class="loading" v-show="isHistoryLoading">
|
|
<view class="spinner">
|
|
<view class="rect1"></view>
|
|
<view class="rect2"></view>
|
|
<view class="rect3"></view>
|
|
<view class="rect4"></view>
|
|
<view class="rect5"></view>
|
|
</view>
|
|
</view>
|
|
<view v-for="(row, index) in msgList" :key="index" :id="'msg' + row.id">
|
|
<view v-if="row.type == 'chat'">
|
|
<view class="cu-item self" v-if="row.to_id == to_id">
|
|
<view class="main" v-if="row.message.type == 'text'">
|
|
<view class="content bg-green">
|
|
<rich-text :nodes="row.message.content.text"></rich-text>
|
|
</view>
|
|
</view>
|
|
<!-- 图片消息 -->
|
|
<view class="main" v-if="row.message.type == 'img'">
|
|
<image :src="row.message.content.url" @tap="showPic(row.message)" :style="{ width: row.message.content.w + 'px', height: row.message.content.h + 'px' }"></image>
|
|
</view>
|
|
<!-- 语音消息 -->
|
|
<view class="main" v-if="row.message.type == 'voice'" @tap="playVoice(row.message)" :class="playMsgid == row.message.id ? 'play' : ''">
|
|
<view class="action text-bold text-grey" style="padding-right: 2rpx;">
|
|
{{ row.message.content.length }}
|
|
<text class="wlIcon-miao"></text>
|
|
</view>
|
|
<view class="content bg-green">
|
|
<text :style="{ width: row.message.content.length * 6 + 'rpx' }"></text>
|
|
<text class="wlIcon-yuyinyou text-xxl padding-left-xl"></text>
|
|
</view>
|
|
</view>
|
|
<!-- 商品消息 1.0.2升级 -->
|
|
<view class="main goods" v-if="row.message.type == 'goods'">
|
|
<view class="content" @tap="onGoods(goods.id)">
|
|
<image :src="$wanlshop.oss(row.message.content.image, 100, 0)" mode="widthFix"></image>
|
|
<view class="text-price text-orange text-lg margin-tb-xs">
|
|
{{row.message.content.price}}
|
|
</view>
|
|
<view>
|
|
{{row.message.content.title}}
|
|
</view>
|
|
</view>
|
|
</view>
|
|
<!-- 订单消息 1.0.2升级 -->
|
|
<view class="main order" v-if="row.message.type == 'order'">
|
|
<view class="content" @tap="orderDetails(row.message.content.id)">
|
|
<view class="">
|
|
<text>订单详情:</text>
|
|
</view>
|
|
<view class="margin-tb-bj radius product padding-sm">
|
|
<view class="item" v-for="(item, index) in row.message.content.goods" :key="index">
|
|
<view class="image">
|
|
<image :src="$wanlshop.oss(item.image, 50, 50)" mode="aspectFill"></image>
|
|
</view>
|
|
<view class="details text-sm">
|
|
<view class="text-cut wanl-gray-dark">
|
|
<text>{{item.title}}</text>
|
|
</view>
|
|
<view class="wanl-gray-light flex justify-between" style="width: 100%;">
|
|
<view class="text-price text-orange">
|
|
{{item.price * item.number}}
|
|
</view>
|
|
<view>
|
|
<text>{{item.difference}} x {{item.number}}</text>
|
|
<text v-if="item.refund_status != 0">({{refundStatusText[item.refund_status]}})</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
<view class="text-sm flex justify-between ">
|
|
<view>
|
|
<text class="">{{stateText[row.message.content.state-1]}}</text>
|
|
</view>
|
|
<view>
|
|
<text>ID:</text>
|
|
<text>{{row.message.content.order_no}}</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="cu-avatar radius" :style="{ backgroundImage: 'url(' + $wanlshop.oss(row.form.avatar, 100, 100) + ')' }"></view>
|
|
<view class="date">{{ $wanlshop.timeToChat(row.createtime) }}</view>
|
|
</view>
|
|
<view class="cu-item" v-else>
|
|
<view class="cu-avatar radius" :style="{ backgroundImage: 'url(' + $wanlshop.oss(row.form.avatar, 100, 100) + ')' }"></view>
|
|
<view class="main" v-if="row.message.type == 'text'">
|
|
<view class="content">
|
|
<rich-text :nodes="row.message.content.text"></rich-text>
|
|
</view>
|
|
</view>
|
|
<!-- 图片消息 -->
|
|
<view class="main" v-if="row.message.type == 'img'">
|
|
<image :src="row.message.content.url" @tap="showPic(row.message)" :style="{ width: row.message.content.w + 'px', height: row.message.content.h + 'px' }"></image>
|
|
</view>
|
|
<!-- 语音消息 -->
|
|
<view class="main" v-if="row.message.type == 'voice'" @tap="playVoice(row.message)" :class="playMsgid == row.message.id ? 'play' : ''">
|
|
<view class="content">
|
|
<text class="wlIcon-yuyinzuo text-xxl padding-right-xl"></text>
|
|
<text :style="{ width: row.message.content.length * 6 + 'rpx' }"></text>
|
|
</view>
|
|
<view class="action text-bold text-grey">
|
|
{{ row.message.content.length }}
|
|
<text class="wlIcon-miao"></text>
|
|
</view>
|
|
</view>
|
|
<view class="date ">{{ $wanlshop.timeToChat(row.createtime) }}</view>
|
|
</view>
|
|
</view>
|
|
<view v-if="row.type == 'sys'">
|
|
<!-- 系统消息 -->
|
|
<view class="cu-info round">对方撤回一条消息!</view>
|
|
</view>
|
|
</view>
|
|
</scroll-view>
|
|
</view>
|
|
<!-- 抽屉栏 -->
|
|
<view class="popup-layer" :class="{showLayer: popupLayerClass}" @touchmove.stop.prevent="discard">
|
|
<!-- 表情 -->
|
|
<view :class="{ hidden: hideEmoji }">
|
|
<view class="emoji">
|
|
<scroll-view class="emojinav" scroll-x scroll-with-animation>
|
|
<view class="item">
|
|
<view :class="item == TabCur ? 'emojibg' : ''" v-for="(item, index) in emojiList.categories" :key="index" @tap="tabSelect"
|
|
:data-id="item" :style="{ backgroundImage: 'url(' + emojiList.groups[item][0].url + ')' }"></view>
|
|
</view>
|
|
</scroll-view>
|
|
<!-- 列表 -->
|
|
<scroll-view v-for="(emoji, groups) in emojiList.groups" :key="groups" v-if="TabCur == groups" class="subject"
|
|
scroll-y scroll-with-animation>
|
|
<view class="item grid margin-bottom text-center col-5">
|
|
<view v-for="(item, index) in emoji" :key="index" @tap="addEmoji(item.value)" :style="{ backgroundImage: 'url(' + item.url + ')' }"></view>
|
|
</view>
|
|
</scroll-view>
|
|
</view>
|
|
</view>
|
|
<!-- 更多功能 1.0.2升级 -->
|
|
<view class="solid-top" :class="{ hidden: hideMore }">
|
|
<view class="opmenu solid-top">
|
|
<view class="box" @tap="browsing">
|
|
<view class="icon wanl-gray"><text class="wlIcon-shangpin"></text></view>
|
|
<text class="text-sm">商品</text>
|
|
</view>
|
|
<view class="box" @tap="order">
|
|
<view class="icon wanl-gray"><text class="wlIcon-dingdan1"></text></view>
|
|
<text class="text-sm">订单</text>
|
|
</view>
|
|
<!-- #ifndef H5 -->
|
|
<view class="box" @tap="camera">
|
|
<view class="icon wanl-gray"><text class="wlIcon-31paishexuanzhong"></text></view>
|
|
<text class="text-sm">拍摄</text>
|
|
</view>
|
|
<!-- #endif -->
|
|
<view class="box" @tap="chooseImage">
|
|
<view class="icon wanl-gray"><text class="wlIcon-tupian1"></text></view>
|
|
<text class="text-sm">照片</text>
|
|
</view>
|
|
<view class="box" @tap="complaint">
|
|
<view class="icon wanl-gray"><text class="wlIcon-zhuyidapx"></text></view>
|
|
<text class="text-sm">投诉</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
<!-- 底部输入栏 -->
|
|
<view class="input-box" :class="{ emptybottom: emptybottom, showLayer: popupLayerClass}" @touchmove.stop.prevent="discard">
|
|
<!-- H5下不能录音,输入栏布局改动一下 -->
|
|
<!-- #ifndef H5 -->
|
|
<view class="voice">
|
|
<view :class="isVoice ? 'wlIcon-jianpanqiehuan' : 'wlIcon-yuyin'" @tap="switchVoice"></view>
|
|
</view>
|
|
<!-- #endif -->
|
|
|
|
<!-- #ifdef H5 -->
|
|
<view class="more" @tap="showMore">
|
|
<view class="wlIcon-yuanquanjiahao"></view>
|
|
</view>
|
|
<!-- #endif -->
|
|
<view class="textbox">
|
|
<view class="voice-mode" :class="[isVoice ? '' : 'hidden', recording ? 'recording' : '']" @touchstart="voiceBegin"
|
|
@touchmove.stop.prevent="voiceIng" @touchend="voiceEnd" @touchcancel="voiceCancel">
|
|
{{ voiceTis }}
|
|
</view>
|
|
<view class="text-mode" :class="isVoice ? 'hidden' : ''">
|
|
<view class="box">
|
|
<textarea auto-height="true" maxlength="300" :show-confirm-bar="false" cursor-spacing="90" v-model="textMsg"
|
|
@focus="textareaFocus" @blur="textareaBlur" @confirm="sendText" />
|
|
</view>
|
|
<view class="em" @tap="chooseEmoji"><view class="wlIcon-biaoqing2"></view></view>
|
|
</view>
|
|
</view>
|
|
<!-- #ifndef H5 -->
|
|
<view class="more" @tap="showMore" style="margin-right: -12rpx;"><view class="wlIcon-yuanquanjiahao"></view></view>
|
|
<!-- #endif -->
|
|
<view class="send" :class="isVoice ? 'hidden' : ''" @tap="sendText">
|
|
<text class="wlIcon-zhifeiji" v-if="textMsg"></text>
|
|
<text class="wlIcon-fasong" v-else></text>
|
|
</view>
|
|
</view>
|
|
<!-- 提示 1.0.2升级 -->
|
|
<view class="chatTips bg-white radius-bock margin-lr-bj padding-sm" v-if="goods && isGoods">
|
|
<image class="radius" :src="$wanlshop.oss(goods.image,100,100)" mode="aspectFill"></image>
|
|
<view class="details">
|
|
<view class="flex justify-between margin-bottom-sm">
|
|
<view class="text-cut title">
|
|
<text>{{goods.title}}</text>
|
|
</view>
|
|
<view @tap="closeTips()">
|
|
<text class="wlIcon-31guanbi"></text>
|
|
</view>
|
|
</view>
|
|
<view class="flex justify-between">
|
|
<view class="text-lg text-orange">
|
|
<text class="text-price">{{goods.price}}</text>
|
|
</view>
|
|
<view>
|
|
<button class="cu-btn round bg-orange sm" @tap="sendGoods(goods)">发送商家</button>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
<!-- 录音UI效果 -->
|
|
<view class="record" :class="recording ? '' : 'hidden'">
|
|
<view class="ing" :class="willStop ? 'hidden' : ''"><view class="wlIcon-huatong01"></view></view>
|
|
<view class="cancel" :class="willStop ? '' : 'hidden'"><view class="wlIcon-shanchu2"></view></view>
|
|
<view class="tis" :class="willStop ? 'change' : ''">{{ recordTis }}</view>
|
|
</view>
|
|
<!-- 模态框 -->
|
|
<view class="WANL-MODAL">
|
|
<!-- 商品列表 -->
|
|
<view class="cu-modal bottom-modal" :class="modalName == 'goods' ? 'show' : ''" @tap="hideModal">
|
|
<view class="cu-dialog bg-white" @tap.stop="">
|
|
<view class="wanl-modal">
|
|
<view class="head padding-bj">
|
|
<view class="content"><view class="text-lg">浏览过的商品</view></view>
|
|
<view class="close wlIcon-31guanbi" @tap="hideModal"></view>
|
|
</view>
|
|
<scroll-view class="scroll-y" scroll-y="true">
|
|
<view class="item goods" v-for="(item, index) in goodsData" :key="index">
|
|
<!-- 1.0.8升级 -->
|
|
<block v-if="item.goods !== null">
|
|
<image class="radius" :src="$wanlshop.oss(item.goods.image,100,100)" mode="aspectFill"></image>
|
|
<view class="details">
|
|
<view class="text-cut-2 title">
|
|
<text>{{item.goods.title}}</text>
|
|
</view>
|
|
<view class="flex justify-between info">
|
|
<view class="text-lg text-orange">
|
|
<text class="text-price">{{item.goods.price}}</text>
|
|
</view>
|
|
<button class="cu-btn round line-orange sm" @tap="sendGoods(item.goods)">发送商品</button>
|
|
</view>
|
|
</view>
|
|
</block>
|
|
</view>
|
|
</scroll-view>
|
|
<view class="foot padding-lr-bj"><button class="cu-btn bg-gradual-orange round text-bold complete" @tap="hideModal">完成</button></view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
<!-- 订单列表 -->
|
|
<view class="cu-modal bottom-modal" :class="modalName == 'order' ? 'show' : ''" @tap="hideModal">
|
|
<view class="cu-dialog bg-bgcolor" @tap.stop="">
|
|
<view class="wanl-modal">
|
|
<view class="head padding-bj">
|
|
<view class="content"><view class="text-lg">购买过的订单</view></view>
|
|
<view class="close wlIcon-31guanbi" @tap="hideModal"></view>
|
|
</view>
|
|
<scroll-view class="scroll-y" scroll-y="true">
|
|
<view class="item bg-white radius-bock margin-tb-sm padding-bj" v-for="(item, index) in orderData" :key="item.id" @tap="sendOrder(item)">
|
|
<view class="flex justify-between">
|
|
<text>订单号:{{item.order_no}}</text>
|
|
<text class="wanl-gray-dark text-sm">{{stateText[item.state-1]}}</text>
|
|
</view>
|
|
<view class="goods" v-for="(goods, key) in item.goods" :key="key">
|
|
<image class="radius" :src="$wanlshop.oss(goods.image,100,100)" mode="aspectFill"></image>
|
|
<view class="details">
|
|
<view class="text-cut-2 title wanl-gray-dark">
|
|
<text>{{goods.title}}</text>
|
|
</view>
|
|
<view class="flex justify-between info">
|
|
<view class="text-lg text-orange">
|
|
<text class="text-price">{{goods.price}}</text>
|
|
</view>
|
|
<!-- <button v-if="goods.refund_status != 0" class="cu-btn round sm" :class="refundStatusBg[goods.refund_status]">{{refundStatusText[goods.refund_status]}}</button> -->
|
|
</view>
|
|
</view>
|
|
</view>
|
|
<view class="flex justify-end">
|
|
<button class="cu-btn round sm line-orange">发送订单</button>
|
|
</view>
|
|
</view>
|
|
</scroll-view>
|
|
<view class="foot padding-lr-bj"><button class="cu-btn bg-gradual-orange round text-bold complete" @tap="hideModal">完成</button></view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
<script>
|
|
const emotions = require('@/static/json/emotions.json');
|
|
import { mapMutations } from 'vuex';
|
|
export default {
|
|
data() {
|
|
return {
|
|
user_id: this.$store.state.user.id,
|
|
avatar: this.$store.state.user.avatar,
|
|
username: this.$store.state.user.username,
|
|
nickname: this.$store.state.user.nickname,
|
|
to_id: 0,
|
|
shop_id: 0,
|
|
shop_name: null,
|
|
shop_avatar: null,
|
|
textMsg: '', //文字消息
|
|
isHistoryLoading: false, //消息列表
|
|
reload: false,
|
|
current_page: 1,
|
|
scrollAnimation: false,
|
|
scrollTop: 0,
|
|
scrollToView: '',
|
|
msgList: [],
|
|
msgImgList: [],
|
|
goods: null,
|
|
isGoods: true,
|
|
goodsData: [],
|
|
orderData: [],
|
|
// 取消底部
|
|
emptybottom: false,
|
|
//录音相关参数
|
|
// #ifndef H5
|
|
//H5不能录音
|
|
RECORDER: uni.getRecorderManager(),
|
|
// #endif
|
|
isVoice: false,
|
|
voiceTis: '按住 说话',
|
|
recordTis: '手指上滑 取消发送',
|
|
recording: false,
|
|
willStop: false,
|
|
initPoint: { identifier: 0, Y: 0 },
|
|
recordTimer: null,
|
|
recordLength: 0,
|
|
//播放语音相关参数
|
|
AUDIO: uni.createInnerAudioContext(),
|
|
playMsgid: null,
|
|
VoiceTimer: null,
|
|
// 抽屉参数
|
|
popupLayerClass: false,
|
|
// more参数
|
|
hideMore: true,
|
|
modalName: null,
|
|
stateText: ["等待您付款", "付款成功", "待收货", "待评论", "退款订单", "订单已完成", "交易关闭"],
|
|
refundStatusText: ["未退款", "退款中", "待退货", "退款完成", "退款关闭", "退款被拒"],
|
|
refundStatusBg: ["", "bg-orange", "bg-red", "bg-green", "bg-grey", "bg-red"],
|
|
//表情定义
|
|
//表情
|
|
TabCur: '默认',
|
|
hideEmoji: true,
|
|
emojiList: this.emojiData(),
|
|
QnUrl: '',
|
|
Sysmodel: this.$wanlshop.wanlsys().model
|
|
};
|
|
},
|
|
async onLoad(option) {
|
|
// 判断是否通过商品进来 1.0.2升级
|
|
if (option.hasOwnProperty('goods')) {
|
|
this.goods = JSON.parse(option.goods);
|
|
setTimeout(()=> {
|
|
this.isGoods = false;
|
|
}, 5000);
|
|
}
|
|
// 临时关闭推送
|
|
this.$store.commit('chat/setIschat', {notice: false});
|
|
// 查看权限 1.0.2升级 追加商家在线状态
|
|
await uni.request({
|
|
url: '/wanlshop/chat/getShopChat',
|
|
method: 'POST',
|
|
data: {
|
|
id: option.shop_id,
|
|
type: 'chat'
|
|
},
|
|
success: res => {
|
|
this.to_id = res.data.user_id;
|
|
this.shop_id = res.data.id;
|
|
// 新版新追加
|
|
this.shop_name = res.data.shopname;
|
|
this.shop_avatar = res.data.avatar;
|
|
this.$wanlshop.title(res.data.shopname + (res.data.isOnline == 1 ? '-在线':'-离线'));
|
|
// 初始界面
|
|
this.getMsgList(res.data.user_id);
|
|
}
|
|
});
|
|
//语音自然播放结束
|
|
this.AUDIO.onEnded(res => {
|
|
this.playMsgid = null;
|
|
});
|
|
// #ifndef H5
|
|
//录音开始事件
|
|
this.RECORDER.onStart(e => {
|
|
this.recordBegin(e);
|
|
});
|
|
//录音结束事件
|
|
this.RECORDER.onStop(e => {
|
|
this.recordEnd(e);
|
|
});
|
|
// #endif
|
|
// 监听服务消息
|
|
uni.$on('onMessage', this.onSend);
|
|
},
|
|
// 店铺按钮
|
|
onNavigationBarButtonTap() {
|
|
this.onShop(this.shop_id);
|
|
},
|
|
// 监听返回
|
|
onUnload() {
|
|
this.$store.dispatch('chat/update', {type:'del', id:this.to_id});
|
|
// 恢复全局监听
|
|
this.$store.commit('chat/setIschat', {notice: true, number: 0});
|
|
},
|
|
onShow() {
|
|
this.scrollTop = 9999999;
|
|
},
|
|
methods: {
|
|
getMsgList(id) {
|
|
// 消息列表
|
|
uni.getStorage({
|
|
key: 'wanlchat:message_' + id,
|
|
success: res => {
|
|
var list = res.data;
|
|
for (let i = 0; i < list.length; i++) {
|
|
// 获取消息中的图片,并处理显示尺寸
|
|
if (list[i].type == 'chat' && list[i].message.type == 'img') {
|
|
list[i].message.content = this.setPicSize(list[i].message.content);
|
|
this.msgImgList.push(list[i].message.content.url);
|
|
}
|
|
// 获取消息中表情,并处理为图片
|
|
if (list[i].type == 'chat' && list[i].message.type == 'text') {
|
|
list[i].message.content.text = this.replaceEmoji(list[i].message.content.text);
|
|
}
|
|
}
|
|
this.msgList = list;
|
|
// 滚动到底部
|
|
this.$nextTick(() => {
|
|
//进入页面滚动到底部
|
|
this.scrollTop = 9999;
|
|
this.$nextTick(() => {
|
|
this.scrollAnimation = true;
|
|
});
|
|
});
|
|
}
|
|
});
|
|
},
|
|
// 接受本地消息
|
|
onChat(msg) {
|
|
if (msg.type == 'system') {
|
|
if (msg.msg.type == 'text') {
|
|
this.addSystemTextMsg(msg);
|
|
}
|
|
} else if (msg.type == 'chat') {
|
|
// 用户消息
|
|
if (msg.message.type == 'text') {
|
|
this.addTextMsg(msg);
|
|
}
|
|
if (msg.message.type == 'voice') {
|
|
this.addVoiceMsg(msg);
|
|
}
|
|
if (msg.message.type == 'img') {
|
|
this.addImgMsg(msg);
|
|
}
|
|
// 1.0.2升级
|
|
if (msg.message.type == 'goods') {
|
|
this.addGoodsMsg(msg);
|
|
}
|
|
if (msg.message.type == 'order') {
|
|
this.addOrderMsg(msg);
|
|
}
|
|
}
|
|
// 滚动到底
|
|
this.$nextTick(() => {
|
|
this.scrollToView = 'msg' + msg.id;
|
|
});
|
|
},
|
|
// 接受在线消息
|
|
onSend(msg) {
|
|
if (msg.form.id == this.to_id) {
|
|
if (msg.type == 'system') {
|
|
if (msg.msg.type == 'text') {
|
|
this.addSystemTextMsg(msg);
|
|
}
|
|
} else if (msg.type == 'chat') {
|
|
// 用户消息
|
|
if (msg.message.type == 'text') {
|
|
this.addTextMsg(msg);
|
|
}
|
|
if (msg.message.type == 'voice') {
|
|
this.addVoiceMsg(msg);
|
|
}
|
|
if (msg.message.type == 'img') {
|
|
this.addImgMsg(msg);
|
|
}
|
|
if (msg.message.type == 'goods') {
|
|
this.addGoodsMsg(msg);
|
|
}
|
|
if (msg.message.type == 'order') {
|
|
this.addOrderMsg(msg);
|
|
}
|
|
}
|
|
// 滚动到底
|
|
this.$nextTick(() => {
|
|
this.scrollToView = 'msg' + msg.id;
|
|
});
|
|
}
|
|
},
|
|
// 发送消息
|
|
sendMsg(content, type) {
|
|
let lastid = 1;
|
|
if (this.msgList.length) {
|
|
lastid = this.msgList[this.msgList.length - 1].id;
|
|
lastid++;
|
|
}
|
|
let data = {
|
|
id: lastid,
|
|
type: 'chat',
|
|
to_id: this.to_id,
|
|
form: {
|
|
id: this.user_id, //本人
|
|
avatar: this.avatar,
|
|
name: this.nickname
|
|
},
|
|
message: {
|
|
type: type,
|
|
content: content
|
|
},
|
|
createtime: parseInt(new Date().getTime() / 1000)
|
|
};
|
|
// 深拷贝移除数据绑定
|
|
this.onChat(JSON.parse(JSON.stringify(data)));
|
|
// 更新列表
|
|
this.$store.dispatch('chat/update', {type:'send', data:data, shop: {
|
|
id: this.shop_id,
|
|
user_id: this.to_id,
|
|
name: this.shop_name,
|
|
avatar: this.shop_avatar,
|
|
}});
|
|
// 发送消息
|
|
this.$wanlshop.send(data);
|
|
},
|
|
// 添加文字消息到列表
|
|
addTextMsg(msg) {
|
|
msg.message.content.text = this.replaceEmoji(msg.message.content.text);
|
|
this.msgList.push(msg);
|
|
},
|
|
// 添加语音消息到列表
|
|
addVoiceMsg(msg) {
|
|
this.msgList.push(msg);
|
|
},
|
|
// 添加图片消息到列表
|
|
addImgMsg(msg) {
|
|
msg.message.content = this.setPicSize(msg.message.content);
|
|
this.msgImgList.push(msg.message.content.url);
|
|
this.msgList.push(msg);
|
|
},
|
|
// 添加商品消息到列表 1.0.2升级
|
|
addGoodsMsg(msg) {
|
|
this.msgList.push(msg);
|
|
},
|
|
addOrderMsg(msg) {
|
|
this.msgList.push(msg);
|
|
},
|
|
// 添加系统文字消息到列表
|
|
addSystemTextMsg(msg) {
|
|
this.msgList.push(msg);
|
|
},
|
|
// 表情数据
|
|
emojiData() {
|
|
var groups = {},
|
|
categories = [],
|
|
map = {};
|
|
emotions.forEach(emotion => {
|
|
var cate = emotion.category.length > 0 ? emotion.category : '默认';
|
|
if (!groups[cate]) {
|
|
groups[cate] = [];
|
|
categories.push(cate);
|
|
}
|
|
groups[cate].push(emotion);
|
|
map[emotion.phrase] = emotion.icon;
|
|
});
|
|
return { groups, categories, map };
|
|
},
|
|
//替换表情符号为图片
|
|
replaceEmoji(str) {
|
|
// 这里处理 链接 换行符
|
|
let replacedStr = str.replace(/\[([^(\]|\[)]*)\]/g, (item, index) => {
|
|
return '<img src="' + this.emojiList.map[item] + '" width="18rpx">';
|
|
});
|
|
return replacedStr.replace(/(\r\n)|(\n)/g, '<br>');
|
|
},
|
|
// 表情tab
|
|
tabSelect(e) {
|
|
this.TabCur = e.currentTarget.dataset.id;
|
|
},
|
|
//触发滑动到顶部(加载历史信息记录)
|
|
async loadHistory(e) {
|
|
if (this.isHistoryLoading) {
|
|
return;
|
|
}
|
|
// 说明加载过一次,并且没有任何记录了
|
|
if (this.reload) {
|
|
return;
|
|
}
|
|
this.isHistoryLoading = true; //参数作为进入请求标识,防止重复请求
|
|
this.scrollAnimation = false; //关闭滑动动画
|
|
let view_id = this.msgList[0].id; //记住第一个信息ID
|
|
//请求历史记录效果
|
|
await uni.request({
|
|
url: '/wanlshop/chat/history',
|
|
method: 'POST',
|
|
data: {
|
|
to_id: this.to_id,
|
|
page: this.current_page
|
|
},
|
|
// 1.1.8升级
|
|
complete: res => {
|
|
if(res.res.code == 1){
|
|
// 消息列表
|
|
let list = res.data.data;
|
|
// 获取消息中的图片,并处理显示尺寸
|
|
for (let i = 0; i < list.length; i++) {
|
|
if (list[i].type == 'chat' && list[i].message.type == 'img') {
|
|
list[i].message.content = this.setPicSize(list[i].message.content);
|
|
this.msgImgList.unshift(list[i].message.content.url);
|
|
}
|
|
// 获取消息中表情,并处理为图片
|
|
if (list[i].type == 'chat' && list[i].message.type == 'text') {
|
|
list[i].message.content.text = this.replaceEmoji(list[i].message.content.text);
|
|
}
|
|
}
|
|
list.sort(function(a, b) {
|
|
return a.updatetime - b.updatetime;
|
|
});
|
|
this.msgList = res.data.current_page == 1 ? list : list.concat(this.msgList);
|
|
//这段代码很重要,不然每次加载历史数据都会跳到顶部
|
|
this.$nextTick(() => {
|
|
this.scrollToView = 'msg' + view_id;
|
|
this.$nextTick(() => {
|
|
this.scrollAnimation = true; //恢复滚动动画
|
|
});
|
|
});
|
|
// 判断尾页
|
|
if (res.data.current_page == res.data.last_page) {
|
|
// 下次不允许下拉加载数据了
|
|
this.reload = true;
|
|
} else {
|
|
this.current_page = res.data.current_page + 1;
|
|
}
|
|
}
|
|
this.isHistoryLoading = false;
|
|
}
|
|
});
|
|
},
|
|
|
|
//处理图片尺寸,如果不处理宽高,新进入页面加载图片时候会闪
|
|
setPicSize(content) {
|
|
// 让图片最长边等于设置的最大长度,短边等比例缩小,图片控件真实改变,区别于aspectFit方式。
|
|
let maxW = uni.upx2px(350); //350是定义消息图片最大宽度
|
|
let maxH = uni.upx2px(350); //350是定义消息图片最大高度
|
|
if (content.w > maxW || content.h > maxH) {
|
|
let scale = content.w / content.h;
|
|
content.w = scale > 1 ? maxW : maxH * scale;
|
|
content.h = scale > 1 ? maxW / scale : maxH;
|
|
}
|
|
return content;
|
|
},
|
|
//更多功能(点击+弹出)
|
|
showMore() {
|
|
this.isVoice = false;
|
|
this.hideEmoji = true;
|
|
if (this.hideMore) {
|
|
this.hideMore = false;
|
|
this.openDrawer();
|
|
} else {
|
|
this.hideDrawer();
|
|
}
|
|
},
|
|
// 打开抽屉
|
|
openDrawer() {
|
|
this.emptybottom = true;
|
|
this.popupLayerClass = true;
|
|
},
|
|
// 隐藏抽屉
|
|
hideDrawer() {
|
|
this.emptybottom = false;
|
|
this.popupLayerClass = false;
|
|
setTimeout(() => {
|
|
this.hideMore = true;
|
|
this.hideEmoji = true;
|
|
}, 150);
|
|
},
|
|
// 选择图片发送
|
|
chooseImage() {
|
|
this.getImage('album');
|
|
},
|
|
//拍照发送
|
|
camera() {
|
|
this.getImage('camera');
|
|
},
|
|
//选照片 or 拍照
|
|
getImage(type) {
|
|
this.hideDrawer();
|
|
uni.chooseImage({
|
|
sourceType: [type],
|
|
sizeType: ['original', 'compressed'], //可以指定是原图还是压缩图,默认二者都有
|
|
success: res => {
|
|
uni.request({
|
|
url: '/wanlshop/common/uploadData',
|
|
success: updata => {
|
|
for (let i = 0; i < res.tempFilePaths.length; i++) {
|
|
// 读取图片宽高
|
|
uni.getImageInfo({
|
|
src: res.tempFilePaths[i],
|
|
success: image => {
|
|
uni.uploadFile({
|
|
url: updata.data.uploadurl,
|
|
filePath: image.path,
|
|
name: 'file',
|
|
formData: updata.data.storage == 'local' ? null : updata.data.multipart,
|
|
success: data => {
|
|
this.sendMsg({ url: JSON.parse(data.data).data.fullurl, w: image.width, h: image.height }, 'img');
|
|
},
|
|
fail: error => {
|
|
uni.showToast({title: JSON.parse(error.data).msg, icon: 'error', position: true});
|
|
}
|
|
});
|
|
}
|
|
});
|
|
}
|
|
}
|
|
});
|
|
}
|
|
});
|
|
},
|
|
// 预览图片
|
|
showPic(message) {
|
|
uni.previewImage({
|
|
indicator: 'none',
|
|
current: message.content.url,
|
|
urls: this.msgImgList
|
|
});
|
|
},
|
|
// 选择表情
|
|
chooseEmoji() {
|
|
this.hideMore = true;
|
|
if (this.hideEmoji) {
|
|
this.hideEmoji = false;
|
|
this.openDrawer();
|
|
} else {
|
|
this.hideDrawer();
|
|
}
|
|
},
|
|
//添加表情
|
|
addEmoji(em) {
|
|
this.textMsg += em;
|
|
},
|
|
//获取焦点,如果不是选表情ing,则关闭抽屉
|
|
textareaFocus() {
|
|
this.emptybottom = true;
|
|
this.closeTips();
|
|
if (this.popupLayerClass && this.hideMore == false) {
|
|
this.hideDrawer();
|
|
}
|
|
},
|
|
// 失去焦点
|
|
textareaBlur() {
|
|
this.emptybottom = false;
|
|
},
|
|
|
|
// 发送文字消息
|
|
sendText() {
|
|
this.hideDrawer(); //隐藏抽屉
|
|
if (!this.textMsg) {
|
|
return;
|
|
}
|
|
let msg = { text: this.textMsg };
|
|
this.sendMsg(msg, 'text');
|
|
this.textMsg = ''; //清空输入框
|
|
},
|
|
// 发送商品消息
|
|
sendGoods(data){
|
|
this.sendMsg(data, 'goods');
|
|
this.closeTips();
|
|
this.hideModal();
|
|
},
|
|
// 发送订单消息
|
|
sendOrder(data){
|
|
this.sendMsg({id: data.id,order_no: data.order_no,goods: data.goods,state: data.state}, 'order');
|
|
this.closeTips();
|
|
this.hideModal();
|
|
},
|
|
// 关闭提示窗口
|
|
closeTips(){
|
|
this.isGoods = false;
|
|
},
|
|
// 投诉
|
|
complaint(){
|
|
this.$wanlshop.to(`/pages/user/complaint/complaint?id=${this.shop_id}&type=2`);
|
|
//隐藏抽屉
|
|
this.hideDrawer();
|
|
},
|
|
// 查询浏览商品
|
|
async browsing(){
|
|
//隐藏抽屉
|
|
this.hideDrawer();
|
|
await uni.request({
|
|
url: '/wanlshop/product/getBrowsingToShop',
|
|
method: 'POST',
|
|
data: {shop_id: this.shop_id},
|
|
success: res => {
|
|
this.goodsData = res.data;
|
|
this.modalName = 'goods';
|
|
}
|
|
});
|
|
},
|
|
// 查询订单
|
|
async order(){
|
|
//隐藏抽屉
|
|
this.hideDrawer();
|
|
await uni.request({
|
|
url: '/wanlshop/order/getOrderListToShop',
|
|
method: 'POST',
|
|
data: {shop_id: this.shop_id},
|
|
success: res => {
|
|
this.orderData = res.data;
|
|
this.modalName = 'order';
|
|
}
|
|
});
|
|
},
|
|
hideModal() {
|
|
this.modalName = null;
|
|
},
|
|
// 播放语音
|
|
playVoice(message) {
|
|
this.playMsgid = message.id;
|
|
this.AUDIO.src = message.content.url;
|
|
this.$nextTick(() => {
|
|
this.AUDIO.play();
|
|
});
|
|
},
|
|
// 录音开始
|
|
voiceBegin(e) {
|
|
if (e.touches.length > 1) {
|
|
return;
|
|
}
|
|
this.initPoint.Y = e.touches[0].clientY;
|
|
this.initPoint.identifier = e.touches[0].identifier;
|
|
this.RECORDER.start({ format: 'mp3' }); //录音开始,
|
|
},
|
|
//录音开始UI效果
|
|
recordBegin(e) {
|
|
this.recording = true;
|
|
this.voiceTis = '松开 结束';
|
|
this.recordLength = 0;
|
|
this.recordTimer = setInterval(() => {
|
|
this.recordLength++;
|
|
}, 1000);
|
|
},
|
|
// 录音被打断
|
|
voiceCancel() {
|
|
this.recording = false;
|
|
this.voiceTis = '按住 说话';
|
|
this.recordTis = '手指上滑 取消发送';
|
|
this.willStop = true; //不发送录音
|
|
this.RECORDER.stop(); //录音结束
|
|
},
|
|
// 录音中(判断是否触发上滑取消发送)
|
|
voiceIng(e) {
|
|
if (!this.recording) {
|
|
return;
|
|
}
|
|
let touche = e.touches[0];
|
|
//上滑一个导航栏的高度触发上滑取消发送
|
|
if (this.initPoint.Y - touche.clientY >= uni.upx2px(200)) {
|
|
this.willStop = true;
|
|
this.recordTis = '松开手指 取消发送';
|
|
} else {
|
|
this.willStop = false;
|
|
this.recordTis = '手指上滑 取消发送';
|
|
}
|
|
},
|
|
// 结束录音
|
|
voiceEnd(e) {
|
|
if (!this.recording) {
|
|
return;
|
|
}
|
|
this.recording = false;
|
|
this.voiceTis = '按住 说话';
|
|
this.recordTis = '手指上滑 取消发送';
|
|
this.RECORDER.stop(); //录音结束
|
|
},
|
|
//录音结束(回调文件)
|
|
recordEnd(e) {
|
|
clearInterval(this.recordTimer);
|
|
if (!this.willStop) {
|
|
uni.request({
|
|
url: '/wanlshop/common/uploadData',
|
|
success: updata => {
|
|
uni.uploadFile({
|
|
url: updata.data.uploadurl,
|
|
filePath: e.tempFilePath,
|
|
name: 'file',
|
|
formData: updata.data.storage == 'local' ? null : updata.data.multipart,
|
|
success: data => {
|
|
let msg = {length: 0, url: JSON.parse(data.data).data.fullurl};
|
|
msg.length = this.recordLength % 60;
|
|
if (msg.length > 0) {
|
|
this.sendMsg(msg, 'voice');
|
|
}
|
|
},
|
|
fail: error =>{
|
|
this.$wanlshop.msg(JSON.parse(error.data).msg);
|
|
}
|
|
});
|
|
}
|
|
});
|
|
} else {
|
|
console.log('取消发送录音');
|
|
}
|
|
this.willStop = false;
|
|
},
|
|
// 切换语音/文字输入
|
|
switchVoice() {
|
|
this.hideDrawer();
|
|
this.isVoice = this.isVoice ? false : true;
|
|
},
|
|
discard() {
|
|
return;
|
|
}
|
|
}
|
|
};
|
|
</script>
|
|
<style>
|
|
/* 1.0.2升级 */
|
|
.cu-btn.sm{
|
|
font-size: 26rpx;
|
|
}
|
|
.cu-modal{
|
|
z-index: 2001;
|
|
}
|
|
.chatTips{
|
|
display: inline-flex;
|
|
align-items: center;
|
|
position: absolute;
|
|
z-index: 101;
|
|
right: 0;
|
|
left: 0;
|
|
bottom: 120rpx;
|
|
bottom: calc(120rpx + env(safe-area-inset-bottom));
|
|
}
|
|
.chatTips image{
|
|
width: 100rpx;
|
|
height: 100rpx;
|
|
margin-right: 20rpx;
|
|
flex-shrink: 0;
|
|
}
|
|
.chatTips .details{
|
|
width: calc(100% - 100rpx - 20rpx);
|
|
}
|
|
.chatTips .details .title{
|
|
width: 90%;
|
|
}
|
|
.cu-chat .cu-item > .main.goods .content, .cu-chat .cu-item > .main.order .content {
|
|
display: block;
|
|
}
|
|
.cu-chat .cu-item > .main.order{
|
|
max-width: calc(100% - 200rpx);
|
|
}
|
|
.cu-chat .cu-item > .main.order .product {
|
|
background-color: #f9f9f9;
|
|
}
|
|
.cu-chat .cu-item > .main.order .product .item{
|
|
display: flex;
|
|
justify-content: space-between;
|
|
margin-bottom: 25rpx;
|
|
}
|
|
.cu-chat .cu-item > .main.order .product .item:last-of-type{
|
|
margin-bottom: 0;
|
|
}
|
|
|
|
.cu-chat .cu-item > .main.order .product .item .image, .product .item .image image{
|
|
width: 100rpx;
|
|
height: 100rpx;
|
|
border-radius: 10rpx;
|
|
}
|
|
|
|
|
|
.cu-chat .cu-item > .main.order .product .item .details{
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
width: calc(100% - 120rpx);
|
|
align-content: space-between;
|
|
}
|
|
/* 1.0.2升级 模态框 */
|
|
.wanl-modal .goods{
|
|
display: flex;
|
|
padding: 20rpx 0;
|
|
}
|
|
.wanl-modal .goods:last-of-type {
|
|
padding-bottom: 0;
|
|
}
|
|
|
|
.wanl-modal .goods image{
|
|
width: 180rpx;
|
|
height: 180rpx;
|
|
margin-right: 20rpx;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.wanl-modal .goods .details{
|
|
flex-wrap: wrap;
|
|
display: flex;
|
|
flex: 1;
|
|
align-content: space-between;
|
|
}
|
|
|
|
.wanl-modal .goods .details .info{
|
|
width: 100%;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.opmenu {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
margin-top: 2rpx;
|
|
color: #4c4c4c;
|
|
}
|
|
.opmenu .box {
|
|
padding-top: 35rpx;
|
|
padding-left: 50rpx;
|
|
text-align: center;
|
|
}
|
|
.opmenu .box .icon {
|
|
height: 120rpx;
|
|
width: 120rpx;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
justify-items: center;
|
|
background-color: #ffffff;
|
|
border-radius: 20rpx;
|
|
font-size: 68rpx;
|
|
margin-bottom: 10rpx;
|
|
}
|
|
.emptybottom{
|
|
padding-bottom: 0 !important;
|
|
}
|
|
.hidden {
|
|
display: none !important;
|
|
}
|
|
.cu-chat .cu-item > .main .content {
|
|
font-size: 30rpx;
|
|
border-radius: 17rpx;
|
|
}
|
|
.cu-chat .cu-item [class*='wlIcon-'] {
|
|
font-size: 34rpx;
|
|
}
|
|
|
|
|
|
|
|
.popup-layer {
|
|
transition: all 0.15s linear;
|
|
width: 100%;
|
|
height: 480rpx;
|
|
background-color: #f5f5f5;
|
|
position: fixed;
|
|
z-index: 2000;
|
|
top: 100%;
|
|
}
|
|
.popup-layer.showLayer {
|
|
transform: translate3d(0, -480rpx, 0);
|
|
}
|
|
.popup-layer .emoji .emojinav {
|
|
background-color: #f8f8f8;
|
|
}
|
|
.popup-layer .emoji .emojinav .item {
|
|
display: flex;
|
|
align-items: center;
|
|
height: 100rpx;
|
|
padding-left: 10rpx;
|
|
}
|
|
.popup-layer .emoji .emojinav .item .emojibg {
|
|
background-color: #dedede;
|
|
}
|
|
.popup-layer .emoji .emojinav .item > view {
|
|
margin: 0 25rpx;
|
|
width: 60rpx;
|
|
height: 60rpx;
|
|
border-radius: 18rpx;
|
|
background-repeat: no-repeat;
|
|
background-size: 80%;
|
|
background-position: center;
|
|
}
|
|
|
|
.popup-layer .emoji .subject {
|
|
height: 380rpx;
|
|
background-color: #f1f1f1;
|
|
}
|
|
.popup-layer .emoji .subject .item {
|
|
padding: 25rpx;
|
|
}
|
|
|
|
.popup-layer .emoji .subject .item > view {
|
|
background-repeat: no-repeat;
|
|
background-size: 56%;
|
|
background-position: center;
|
|
width: 12.5%;
|
|
height: 100rpx;
|
|
}
|
|
|
|
.input-box {
|
|
width: 100%;
|
|
min-height: 100rpx;
|
|
padding-bottom: env(safe-area-inset-bottom);
|
|
background-color: #f2f2f2;
|
|
display: flex;
|
|
align-items: flex-end;
|
|
position: fixed;
|
|
z-index: 2000;
|
|
bottom: -2rpx;
|
|
transition: all 0.15s linear;
|
|
}
|
|
.input-box [class*='wlIcon-'] {
|
|
font-size: 50rpx;
|
|
color: #323232;
|
|
}
|
|
|
|
.input-box .wlIcon-zhifeiji {
|
|
color: #fe6600;
|
|
}
|
|
|
|
.input-box.showLayer {
|
|
transform: translate3d(0, -480rpx, 0);
|
|
}
|
|
.input-box .voice,
|
|
.input-box .more {
|
|
flex-shrink: 0;
|
|
width: 90rpx;
|
|
height: 100rpx;
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
}
|
|
.input-box .send {
|
|
flex-shrink: 0;
|
|
width: 90rpx;
|
|
height: 100rpx;
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
}
|
|
.input-box .send .btn {
|
|
width: 110rpx;
|
|
height: 70rpx;
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
border-radius: 16rpx;
|
|
font-size: 32rpx;
|
|
}
|
|
.input-box .textbox {
|
|
width: 100%;
|
|
}
|
|
.input-box .textbox .voice-mode {
|
|
width: calc(100% - 2upx);
|
|
height: 80rpx;
|
|
margin: 10rpx 0;
|
|
border-radius: 16rpx;
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
font-size: 28rpx;
|
|
background-color: #fff;
|
|
color: #555;
|
|
}
|
|
.input-box .textbox .voice-mode.recording {
|
|
background-color: #e5e5e5;
|
|
}
|
|
.input-box .textbox .text-mode {
|
|
width: 100%;
|
|
min-height: 80rpx;
|
|
margin: 10rpx 0;
|
|
display: flex;
|
|
background-color: #ffffff;
|
|
border-radius: 16rpx;
|
|
}
|
|
.input-box .textbox .text-mode .box {
|
|
width: 100%;
|
|
padding-left: 30rpx;
|
|
min-height: 80rpx;
|
|
display: flex;
|
|
align-items: center;
|
|
}
|
|
.input-box .textbox .text-mode .box textarea {
|
|
width: 100%;
|
|
}
|
|
.input-box .textbox .text-mode .em {
|
|
flex-shrink: 0;
|
|
width: 80rpx;
|
|
padding-left: 10rpx;
|
|
height: 80rpx;
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
}
|
|
|
|
.record {
|
|
width: 39vw;
|
|
height: 39vw;
|
|
position: fixed;
|
|
top: 35%;
|
|
left: 30%;
|
|
background-color: rgba(0, 0, 0, 0.8);
|
|
border-radius: 40rpx;
|
|
}
|
|
.record .ing {
|
|
width: 100%;
|
|
height: 30vw;
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
}
|
|
@keyframes volatility {
|
|
0% {
|
|
background-position: 0% 130%;
|
|
}
|
|
20% {
|
|
background-position: 0% 150%;
|
|
}
|
|
30% {
|
|
background-position: 0% 155%;
|
|
}
|
|
40% {
|
|
background-position: 0% 160%;
|
|
}
|
|
50% {
|
|
background-position: 0% 145%;
|
|
}
|
|
70% {
|
|
background-position: 0% 150%;
|
|
}
|
|
80% {
|
|
background-position: 0% 170%;
|
|
}
|
|
90% {
|
|
background-position: 0% 160%;
|
|
}
|
|
100% {
|
|
background-position: 0% 135%;
|
|
}
|
|
}
|
|
.record .ing [class*='wlIcon'] {
|
|
background-image: linear-gradient(to bottom, #ffffff, #565656 50%);
|
|
background-size: 100% 200%;
|
|
animation: volatility 1.5s ease-in-out -1.5s infinite alternate;
|
|
-webkit-background-clip: text;
|
|
-webkit-text-fill-color: transparent;
|
|
font-size: 140rpx;
|
|
padding-top: 40rpx;
|
|
color: #f09b37;
|
|
}
|
|
.record .cancel {
|
|
width: 100%;
|
|
height: 30vw;
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
}
|
|
.record .cancel [class*='wlIcon'] {
|
|
color: #fff;
|
|
font-size: 150rpx;
|
|
}
|
|
.record .tis {
|
|
width: 100%;
|
|
height: 10vw;
|
|
display: flex;
|
|
justify-content: center;
|
|
font-size: 24rpx;
|
|
color: #fff;
|
|
}
|
|
.record .tis.change {
|
|
color: #f09b37;
|
|
}
|
|
|
|
.content {
|
|
width: 100%;
|
|
}
|
|
page{
|
|
background-color: #ececec;
|
|
}
|
|
.content .msg-list,
|
|
.cu-chat {
|
|
position: absolute;
|
|
top: 0;
|
|
bottom: 100rpx;
|
|
bottom: calc(env(safe-area-inset-bottom) + 100rpx);
|
|
background-color: #ececec;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.loading {
|
|
display: flex;
|
|
justify-content: center;
|
|
}
|
|
@keyframes stretchdelay {
|
|
0%,
|
|
40%,
|
|
100% {
|
|
transform: scaleY(0.6);
|
|
}
|
|
20% {
|
|
transform: scaleY(1);
|
|
}
|
|
}
|
|
.loading .spinner {
|
|
margin: 20upx 0;
|
|
width: 60upx;
|
|
height: 100upx;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
}
|
|
.loading .spinner view {
|
|
background-color: #dadada;
|
|
height: 50upx;
|
|
width: 6upx;
|
|
border-radius: 6upx;
|
|
animation: stretchdelay 1.2s infinite ease-in-out;
|
|
}
|
|
.loading .spinner .rect2 {
|
|
animation-delay: -1.1s;
|
|
}
|
|
.loading .spinner .rect3 {
|
|
animation-delay: -1s;
|
|
}
|
|
.loading .spinner .rect4 {
|
|
animation-delay: -0.9s;
|
|
}
|
|
.loading .spinner .rect5 {
|
|
animation-delay: -0.8s;
|
|
}
|
|
</style>
|
|
|