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

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<!--
* @Author: ch
* @Date: 2022-05-11 11:45:08
* @LastEditors: ch
* @LastEditTime: 2022-05-21 11:38:36
* @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 {Im} from '@/common/utils';
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 (){
const {
orderId,
payTypeDesc,
payAmount,
orderStatusDesc,
orderNo,
products
} = this.orderInfo;
return {orderId, payTypeDesc, payAmount, orderStatusDesc, orderNo, ...(products ? products[0] : {})};
}
},
watch:{
simpleOrder(val){
if(val.orderId){
this.sendOrder();
}
}
},
methods:{
/**
* 统一发送函数
*/
async send(val, type){
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;
}
let res = await Im.sendMsg({
fromId : this.$store.state.userInfo.id,
content: {
toSessionId : this.$Route.query.sessionId,
payload : payload,
toId : 1,
type : type
}
})
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>