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.
shop-app/pages/account/message/chat/components/Footer.vue

320 lines
6.9 KiB

3 years ago
<!--
* @Author: ch
* @Date: 2022-05-11 11:45:08
* @LastEditors: ch
3 years ago
* @LastEditTime: 2022-05-19 14:07:03
3 years ago
* @Description: file content
-->
<template>
<view class="footer">
<GoodsInfo class="goods" v-if="simpleGoods.id && goodsShow" :goodsInfo="simpleGoods"
@send="sendGoods" @close="goodsShow=false" @click="$Router.back()"/>
<view class="operation">
<textarea class="operation--input" :focus="focus" v-model="msgCtx" @focus="moreShow = false" @click="emojiShow = false"/>
<view class="operation--btns">
<image class="operation--emoji" src="@/static/imxx/emoji.png" @click="emojiShow = !emojiShow"/>
<view class="operation--send" v-if="msgCtx.length" @click="send(msgCtx, MSG_TYPE.TXT)"></view>
<image class="operation--more" v-else src="@/static/imxx/more.png" @click="moreShow = true" />
</view>
</view>
<view class="emoji" v-if="emojiShow">
<view class="emoji--tab">
<text class="emoji--tab-item" :class="idx == curEmojiIdx && 'emoji--tab-item__active'"
v-for="(item, idx) in emojiData" :key="idx" @click="curEmojiIdx = idx">{{item.name}}</text>
</view>
<view class="emoji--icon">
<view class="emoji--icon-item" @click="handleAddEmoji(item)"
v-for="item in emojiData[curEmojiIdx].list" :key="item">{{emojiUtf16(item)}}</view>
</view>
</view>
<view class="other" v-if="moreShow">
<u-upload @afterRead="uploadImg" >
<view class="other--btn">
<image class="other--img" src="@/static/imxx/img.png"/>
<view>图片</view>
</view>
</u-upload>
<u-upload @afterRead="uploadVideo" compressed accept="video">
<view class="other--btn">
<image class="other--img" src="@/static/imxx/video.png"/>
<view>视频</view>
</view>
</u-upload>
</view>
</view>
</template>
<script>
import {MsbWebSkt, CreateUUID} from '@/common/utils';
3 years ago
import {MsbSktSendMsg} from '@/common/utils/webSkt';
3 years ago
import {MSG_TYPE} from '@/common/dicts/im';
import {Request} from '@/common/utils';
import {ApiPutUser} from '@/common/api/account';
import {ApiPostGetOssConfig} from '@/common/api/oss';
import UiButton from '@/components/UiButton.vue';
import {entitiestoUtf16, emojiData} from '@/common/plugins/emoji';
import GoodsInfo from './GoodsInfo.vue';
import OrderInfo from './OrderInfo.vue';
export default {
components: { UiButton, GoodsInfo, OrderInfo },
props: {
orderInfo : {
type : Object,
default : () => ({})
},
goodsInfo : {
type : Object,
default : () => ({})
}
},
data(){
return {
goodsShow : true,
orderShow : true,
moreShow : false,
focus : false,
msgCtx : '',
MSG_TYPE ,
emojiShow : false,
emojiData,
emojiUtf16 : entitiestoUtf16,
curEmojiIdx : 0
}
},
computed : {
simpleGoods (){
const {
startingPrice,
name,
id,
pictureList
} = this.goodsInfo;
const productImageUrl = pictureList ? pictureList[0] : '';
return {startingPrice,name,id, productImageUrl}
},
simpleOrder (){
3 years ago
const {
orderId,
payTypeDesc,
payAmount,
orderStatusDesc,
orderNo,
products
} = this.orderInfo;
3 years ago
return {orderId, payTypeDesc, payAmount, orderStatusDesc, orderNo, ...(products ? products[0] : {})};
}
},
watch:{
simpleOrder(val){
if(val.orderId){
this.sendOrder();
}
}
},
methods:{
/**
* 统一发送函数
*/
3 years ago
async send(val, type){
3 years ago
let payload = {};
switch(type){
case MSG_TYPE.CUSTOM :
payload = JSON.stringify(val)
break;
case MSG_TYPE.VIDEO:
case MSG_TYPE.IMG :
payload = {url : val};
break;
default:
payload = {text : val}
break;
}
3 years ago
let res = await MsbSktSendMsg({
content: {
toSessionId : this.$store.state.sessionMsgId,
payload : payload,
toId : 1,
type : type
}
})
3 years ago
this.msgCtx = '';
this.focus = false;
this.$nextTick(() => {
this.focus = true;
});
},
handleAddEmoji (data){
let str = ' ' + entitiestoUtf16(data) + ' ';
this.msgCtx += str;
},
sendGoods(){
this.send(this.simpleGoods, MSG_TYPE.CUSTOM);
this.goodsShow = false;
},
sendOrder(){
this.send(this.simpleOrder, MSG_TYPE.CUSTOM);
this.orderShow = false;
},
uploadImg(val){
const file = val.file;
this.uploadFile(file, MSG_TYPE.IMG);
},
uploadVideo(val){
const file = val.file;
this.uploadFile(file, MSG_TYPE.VIDEO);
},
/**
* 获取OSS鉴权信息
* configId 自定义文件夹 图片存储的文件夹名称
* serviceName 服务名
*/
async getOssCon(){
const {error, result} = await ApiPostGetOssConfig({
configId : 'im/',
serviceName : 'uc'
});
if(error){
uni.$u.toast(error.message);
return false
}
return result;
},
/**
* 上传文件
* 1拿到OSS信息上传
* 2成功后拼地址传发送消息
*/
async uploadFile(file, type){
const urlArr = file.url.split('/');
const fileName = file.name || urlArr[urlArr.length - 1];
const oss = await this.getOssCon();
uni.uploadFile({
name : 'file',
filePath : file.url,
url : oss.host,
formData : {
name : fileName,
key : `${oss.dir}${'${filename}'}`,
policy : oss.policy,
OSSAccessKeyId : oss.accessId,
success_action_status : 200,
signature : oss.signature
},
success : async (res)=>{
const fileUrl = `${oss.host}/${oss.dir}${fileName}`;
this.send(fileUrl, type);
}
})
}
}
}
</script>
<style lang="scss" scoped>
.footer{
position: fixed;
bottom: 0;
background: #fff;
left: 0;
right: 0;
margin-bottom: constant(safe-area-inset-bottom);
margin-bottom: env(safe-area-inset-bottom);
}
.goods{
width: 670rpx;
height: 200rpx;
position: absolute;
top: -220rpx;
left: 30rpx;
}
.operation{
display: flex;
height: 100rpx;
align-items: center;
padding: 0 40rpx;
&--input{
height: 70rpx;
padding: 18rpx 20rpx 10rpx;
line-height: 40rpx;
flex: 1;
background: #F3F4F6;
border-radius: 8rpx;
margin-right: 15rpx;
}
&--btns{
display: flex;
align-items: center;
}
&--more, &--emoji{
width: 50rpx;
height: 50rpx;
margin: 0 15rpx;
}
&--send{
width: 110rpx;
height: 60rpx;
line-height: 60rpx;
background: #FF875B;
color: #fff;
font-size: 30rpx;
text-align: center;
border-radius: 8rpx;
margin: 0 15rpx;
}
}
.emoji{
&--icon{
background: #f8f8f8;
padding: 10rpx 30rpx;
display: flex;
justify-content: flex-start;
flex-wrap: wrap;
height: 320rpx;
overflow-y: auto;
&-item{
margin:20rpx;
}
}
&--tab{
display: flex;
height: 50rpx;
line-height: 50rpx;
padding: 0 30rpx;
&-item{
padding: 0 20rpx;
font-size: $font-size-sm;
color: #999;
&__active{
background: #f8f8f8;
}
}
}
}
.other{
width: 100%;
display: flex;
justify-content: flex-start;
background: #f8f8f8;
padding: 30rpx 40rpx;
.u-upload{
flex: 0;
}
&--btn{
text-align: center;
margin-right: 60rpx;
color: #999;
}
&--img{
width: 120rpx;
height: 120rpx;
margin-bottom: 20rpx;
}
}
</style>