Browse Source

feat(im_chat_info): 增加图片消息功能

- 新增 AQUplodeImage 组件用于上传图片
- 在聊天界面添加发送图片的功能
- 实现图片消息的展示和预览
-优化聊天界面布局和样式
master
liutong 10 months ago
parent
commit
57a54d14c8
  1. 56
      components/AQ/AQUplodeImage.vue
  2. 196
      pages/common/im_chat_info.vue

56
components/AQ/AQUplodeImage.vue

@ -0,0 +1,56 @@
<template>
<view @click="chooseImage">
<slot></slot>
</view>
</template>
<script>
export default {
props: {
multiple: { type: Boolean, default: false },
limit: { type: Number, default: 1 },
uploadUrl: { type: String, default: '' },
extraData: { type: Object, default: () => ({}) }
},
methods: {
chooseImage() {
uni.chooseImage({
count: this.multiple ? this.limit : 1,
sizeType: ['compressed'],
sourceType: ['album', 'camera'],
success: (res) => {
const tempFilePath = res.tempFilePaths[0];
this.uploadFile(tempFilePath);
}
});
},
uploadFile(filePath) {
let token = uni.getStorageSync('token');
uni.uploadFile({
url: this.uploadUrl,
filePath: filePath,
name: 'file',
header: {
'token': token
},
formData: this.extraData.formData || {},
success: (e) => {
try {
let res = JSON.parse(e.data.replace(/\ufeff/g, "") || "{}");
if (res.code === 1) {
this.$emit('uplodeImageRes', res.data, this.extraData);
} else {
uni.showToast({ title: res.msg, icon: 'none' });
}
} catch (error) {
uni.showToast({ title: '解析失败', icon: 'none' });
}
},
fail: () => {
uni.showToast({ title: '上传失败', icon: 'none' });
}
});
}
}
}
</script>

196
pages/common/im_chat_info.vue

@ -15,16 +15,25 @@
<view class="time_section" v-if="v.created_at">{{v.created_at}}</view> <view class="time_section" v-if="v.created_at">{{v.created_at}}</view>
<view class="li" v-if="v.direction == `left`"> <view class="li" v-if="v.direction == `left`">
<view class="item left_item"> <view class="item left_item" :style="v.message_type == 'text' ? { backgroundColor: '#f4f6f9' } : {}">
<view class="text_box">{{v.content}}</view> <!--文本内容-->
<view class="text_box" v-if="v.message_type == 'text'">{{v.content}}</view>
<!-- 图片内容 -->
<view class="img_box" v-if="v.message_type == 'img'" @click="previewImage(v.content)">
<image class="chat_img" :src="v.content" mode="aspectFill"></image>
</view>
</view> </view>
<view class="item"></view> <view class="item"></view>
</view> </view>
<view class="li" v-if="v.direction == `right`"> <view class="li" v-if="v.direction == `right`">
<view class="item"></view> <view class="item"></view>
<view class="item right_item"> <view class="item right_item" :style="v.message_type == 'text' ? { backgroundColor: '#1684fc' } : {}">
<view class="text_box">{{v.content}}</view> <view class="text_box" v-if="v.message_type == 'text'">{{v.content}}</view>
<!-- 图片内容 -->
<view class="img_box" v-if="v.message_type == 'img'" @click="previewImage(v.content)">
<image class="chat_img" :src="v.content" mode="aspectFill"></image>
</view>
</view> </view>
</view> </view>
</view> </view>
@ -36,27 +45,66 @@
<input class="input" v-model="formData.content" type="text" placeholder="请输入"> <input class="input" v-model="formData.content" type="text" placeholder="请输入">
</view> </view>
<view class="right_box"> <view class="right_box">
<image @click="submitForm()" class="send_img" src="@/static/images/common/fa_song.png"></image> <!--发送-->
<view class="img_box">
<image @click="submitTextForm()" class="send_img" src="@/static/images/common/fa_song.png"></image>
</view>
<!--更多选择-->
<view class="img_box">
<image @click="openMore()" class="send_img" src="@/static/images/common/jia_hao.png"></image>
</view>
</view>
</view>
<!--更多选择-->
<fui-bottom-popup :show="moreShow" @close="closeMore">
<view class="more_section">
<view class="fui-scroll__wrap">
<scroll-view scroll-y class="fui-scroll__view">
<view class="ul">
<view class="li" @click="">
<AQUplodeImage
:uploadUrl=uploadUrl
:extraData="{ input_name: 'img_uplode', formData:{} }"
@uplodeImageRes="uplodeImageRes"
>
<view class="icon_box">
<fui-icon name="picture-fill" :size="80"></fui-icon>
</view>
<view class="title">相册</view>
</AQUplodeImage>
</view> </view>
</view> </view>
</scroll-view>
</view>
</view>
</fui-bottom-popup>
</view> </view>
</template> </template>
<script> <script>
import apiRoute from '@/api/apiRoute.js'; import apiRoute from '@/api/apiRoute.js';
import memberApi from '@/api/member.js';
import commonApi from '@/api/common.js'; import {
import AQUplodeImgMulti from '@/components/AQ/AQUplodeImgMulti'; Api_url
} from "@/common/config.js";
import AQUplodeImage from '@/components/AQ/AQUplodeImage';//
import AQTabber from "@/components/AQ/AQTabber" import AQTabber from "@/components/AQ/AQTabber"
export default { export default {
components: { components: {
AQTabber, AQTabber,
AQUplodeImgMulti, AQUplodeImage,
}, },
data() { data() {
return { return {
uploadUrl: `${Api_url}/uploadImage`,
scrollTop:'',//,
loading:false,// loading:false,//
lowerThreshold: 100,// lowerThreshold: 100,//
isReachedBottom: false,//|true=|false= isReachedBottom: false,//|true=|false=
@ -91,8 +139,8 @@ export default {
content: '',//JSON ,=,= content: '',//JSON ,=,=
}, },
isFirstLoad: true, // //
scrollTop:'', moreShow:false,
} }
}, },
onLoad(options) { onLoad(options) {
@ -261,6 +309,12 @@ export default {
// console.log('AQxxx2',this.formData.member_store_certification_arr) // console.log('AQxxx2',this.formData.member_store_certification_arr)
}, },
//
submitTextForm(){
this.formData.message_type = 'text'
this.submitForm()
},
// //
async submitForm() { async submitForm() {
let data = {...this.formData} let data = {...this.formData}
@ -281,18 +335,18 @@ export default {
} else { } else {
let content = this.formData.content let content = this.formData.content
this.formData.content = ''// this.formData.content = ''//
let msgData = { let msgData = {
"id": '', id:'',
"hair_staff_id": this.filteredData.hair_staff_id, from_type:data.from_type,//|personnel=,customer=()
"closed_staff_id": '', from_id:data.from_id,//ID
"content": content, to_id:data.to_id,//ID
"status": 1, friend_id:data.friend_id,//chat_friendsid
"type": 2, message_type: data.message_type,//|text=,img=
"create_time": "", content: data.content,//JSON ,=,=
"redirect": null, direction:'right'
"title": null,
"direction": "right",
"show_time": ""
} }
// //
this.tableList = this.tableList.concat(msgData); this.tableList = this.tableList.concat(msgData);
@ -301,11 +355,40 @@ export default {
// //
scrollToBottom() { scrollToBottom() {
alert(1)
this.$nextTick(() => { this.$nextTick(() => {
this.scrollTop = 999999 // this.scrollTop = 999999 //
}) })
}, },
//
openMore(){
this.moreShow = true
},
//
closeMore(){
this.moreShow = false
},
//
uplodeImageRes(resData,extraData){
console.log('上传成功回调',resData,extraData)
//
if(extraData.input_name == 'img_uplode'){
this.closeMore()//
this.formData.content = resData.url
this.formData.message_type = 'img'
this.submitForm()
}
},
//
previewImage(url){
uni.previewImage({
current: url, //
urls: [url] //
});
},
} }
} }
</script> </script>
@ -369,13 +452,20 @@ export default {
word-wrap: break-word; /* 允许长单词或 URL 换行 */ word-wrap: break-word; /* 允许长单词或 URL 换行 */
word-break: break-all; /* 强制所有字符换行 */ word-break: break-all; /* 强制所有字符换行 */
.text_box{} .text_box{}
.img_box {
.chat_img {
width: 200rpx;
height: 200rpx;
border-radius: 16rpx;
}
}
} }
.left_item{ .left_item{
background-color: #f4f6f9; //background-color: #f4f6f9;
color: #343434; color: #343434;
} }
.right_item{ .right_item{
background-color: #1684fc; //background-color: #1684fc;
color: #fff; color: #fff;
} }
} }
@ -390,12 +480,12 @@ export default {
position: fixed; position: fixed;
bottom: 0; bottom: 0;
padding: 50rpx 50rpx; padding: 50rpx 30rpx;
display: flex; display: flex;
justify-content:space-between; justify-content:space-between;
align-items: center; align-items: center;
gap: 20rpx;
.left_box{ .left_box{
width: 70%;
.input{ .input{
background-color: #f4f6f9; background-color: #f4f6f9;
height: 88rpx; height: 88rpx;
@ -403,16 +493,21 @@ export default {
font-size: 28rpx; font-size: 28rpx;
border-radius: 32rpx; border-radius: 32rpx;
width: 532rpx; width: 480rpx;
color: #292929; color: #292929;
font-size: 28rpx; font-size: 28rpx;
} }
} }
.right_box{ .right_box{
border-radius: 50%; width: 100%;
background-color: #a2cefe; display: flex;
justify-content: space-between;
align-items: center;
.img_box{
width: 88rpx; width: 88rpx;
height: 88rpx; height: 88rpx;
border-radius: 50%;
background-color: #a2cefe;
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
@ -421,6 +516,7 @@ export default {
height: 36rpx; height: 36rpx;
} }
} }
}
} }
@ -428,4 +524,44 @@ export default {
color: #999999; color: #999999;
padding-left: 30rpx; padding-left: 30rpx;
} }
/* 更多选项相关 自定义内容区样式需自行控制 */
.more_section{
.fui-scroll__wrap {
padding-top: 30rpx;
position: relative;
}
.fui-title {
font-size: 30rpx;
font-weight: bold;
text-align: center;
padding-bottom: 24rpx;
}
.fui-icon__close {
position: absolute;
top: 24rpx;
left: 24rpx;
}
.fui-scroll__view {
width: 100%;
height: 350rpx;
}
.ul{
padding: 10rpx 40rpx;
display: flex;
.li{
display: flex;
flex-direction: column;
align-items: center;
.icon_box{
}
.title{
font-size: 28rpx;
text-align: center;
}
}
}
}
</style> </style>
Loading…
Cancel
Save