Commit 132301fa authored by songrui's avatar songrui

im图片文件上传预览

parent b2ddd492
<svg viewBox="64 64 896 896" focusable="false"><path d="M854.6 288.7c6 6 9.4 14.1 9.4 22.6V928c0 17.7-14.3 32-32 32H192c-17.7 0-32-14.3-32-32V96c0-17.7 14.3-32 32-32h424.7c8.5 0 16.7 3.4 22.7 9.4l215.2 215.3zM790.2 326L602 137.8V326h188.2z" /></svg>
\ No newline at end of file
<svg viewBox="64 64 896 896" focusable="false"><path d="M696 480H544V328c0-4.4-3.6-8-8-8h-48c-4.4 0-8 3.6-8 8v152H328c-4.4 0-8 3.6-8 8v48c0 4.4 3.6 8 8 8h152v152c0 4.4 3.6 8 8 8h48c4.4 0 8-3.6 8-8V544h152c4.4 0 8-3.6 8-8v-48c0-4.4-3.6-8-8-8z" /><path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm0 820c-205.4 0-372-166.6-372-372s166.6-372 372-372 372 166.6 372 372-166.6 372-372 372z" /></svg>
\ No newline at end of file
<template>
<div class="file-view">
<!-- 文件预览 -->
<div v-if="!isImage" class="flex items-center">
<doc-icon type="file-filled" style="color: #999; font-size: 20px"/>
<a class="ml-2" @click.prevent="onDown">下载</a>
</div>
<van-image :src="file.url" v-else @click="viewImage">
<template v-slot:loading>
<van-loading type="spinner" size="20" />
</template>
</van-image>
</div>
</template>
<script>
export default {
props: {
file: {
type: Object,
default: () => ({})
}
},
emits: ['view-image'],
computed: {
isImage() {
const array = ['JPG', 'PNG', 'JEPG', 'GIF']
return array.includes(this.file.type) || array.includes(this.file.ext.toLocaleUpperCase())
}
},
methods: {
onDown() {
window.open(this.file.url, '_blank')
},
viewImage() {
this.$emit('view-image', this.file)
}
}
}
</script>
<style lang="less" scoped>
.file-view {
width: 100px;
}
</style>
......@@ -10,7 +10,7 @@
<van-list
v-model:loading="loading"
:finished="finished"
finished-text="没有更多了"
finished-text="没有更多消息了"
direction="up"
:disabled="scrollDisabled"
@load="loadHistory"
......@@ -20,7 +20,11 @@
<div class="shrink-0 avatar">
<img src="@/assets/image/nim/avatar-doctor.svg" alt="" v-show="item.from !== accountId">
</div>
<div class="msg-cont">{{ item.text }}</div>
<div class="msg-cont">
<span v-if="item.type === 'text'">{{ item.text }}</span>
<FileView v-else-if="['image', 'file'].includes(item.type)" :file="item.file"
@viewImage="viewImage"/>
</div>
<div class="shrink-0 avatar">
<img src="@/assets/image/nim/avatar-man.png" alt="" v-show="item.from === accountId">
</div>
......@@ -29,26 +33,50 @@
<div ref="bottom"></div>
</div>
<div class="shrink-0 px-3 py-2 footer">
<van-cell-group>
<van-field
<van-field type="textarea" rows="1"
:autosize="{ minHeight: 24, maxHeight: 76 }"
maxlength="500"
v-model="inputValue"
center
>
<template #left-icon>
<div style="color: #555; font-size: .2rem" class="mr-1"
@click="() => visible = true">
<doc-icon type="plus-circle"/>
</div>
</template>
<template #button>
<van-button size="small" type="primary"
@click="sendMsg">发送</van-button>
</template>
</van-field>
</van-cell-group>
</div>
<input type="file"
:accept="sendType == 'image' ? '.jpg,.jpeg,.png,.gif' : '*'"
ref="fileElem"
style="display: none;"
@change="handleFiles"
:key="inputKey">
<van-action-sheet
v-model:show="visible"
:actions="actionsList"
cancel-text="取消"
close-on-click-action
@select="fileSelect"
/>
</div>
</template>
<script>
import NIM from '@yxim/nim-web-sdk/dist/SDK/NIM_Web_NIM.js'
import { showNotify, showToast } from 'vant'
import { showNotify, showToast, showImagePreview, showSuccessToast, showFailToast } from 'vant'
import FileView from './FileView.vue'
export default {
components: {
FileView
},
data() {
return {
msgs: [],
......@@ -62,6 +90,15 @@ export default {
// 是否加载完成
finished: false,
scrollDisabled: true,
// image file
sendType: 'image',
inputKey: 1,
// 上传功能面板
visible: false,
actionsList: [
{ name: '上传图片', type: 'image' },
{ name: '上传文件', type: 'file' }
]
}
},
computed: {
......@@ -70,6 +107,7 @@ export default {
},
// 聊天对象
targetId() {
return '2000050903'
return this.accountId === '18487350810' ? '18987175004' : '18487350810'
}
},
......@@ -124,18 +162,19 @@ export default {
console.log('sendText ================>', error, msg)
}
})
this.msgs.push(msg)
this.pushMsg(msg)
this.inputValue = ''
this.toBottom()
},
pushMsg(msg) {
this.msgs.push(msg)
this.toBottom()
},
toBottom(behavior = 'smooth') {
const dom = this.$refs.bottom
setTimeout(() => {
dom && dom.scrollIntoView({block: 'start', behavior})
}, 100)
}, 300)
},
// 加载本地消息
getLocalMsgs() {
......@@ -163,9 +202,128 @@ export default {
loadHistory() {
this.getLocalMsgs()
},
handleFiles() {
let files = this.$refs['fileElem'].files
if (files.length <= 0) {
this.$message.info('未选中文件,请尝试重新选择')
return
}
if (files[0].size / 1024 / 1024 > 100) {
this.$message.info('文件大小不能超过100M')
return
}
this.upload(files[0])
},
upload(file, hash) {
// 先上传再发送
const tempMsg = {
from: this.accountId,
text: '上传中...',
time: +new Date(),
percentage: 0,
type: 'text'
}
this.pushMsg(tempMsg)
this.nim.previewFile({
type: this.sendType,
blob: file,
// fastPass: { md5: hash },
uploadprogress: function(obj) {
console.log('文件总大小: ' + obj.total + 'bytes');
console.log('已经上传的大小: ' + obj.loaded + 'bytes');
console.log('上传进度: ' + obj.percentage);
console.log('上传进度文本: ' + obj.percentageText);
tempMsg.percentage = obj.percentage
},
done: (error, file) => {
this.inputKey = Math.random().toString(16).substring(2, 6)
if (!error) {
const msg = this.nim.sendFile({
scene: 'p2p',
to: this.targetId,
file: file
})
console.log('正在发送p2p image消息, id=' + msg.idClient)
this.pushMsg(msg)
this.msgs = this.msgs.filter(e => e.time !== tempMsg.time)
} else {
const msg = this.nim.sendText({
scene: 'p2p',
to: this.targetId,
text: '文件上传失败!',
isLocal: true,
custom: { type: 'file', status: 'fail' }
})
this.pushMsg(msg)
}
}
})
},
fileSelect(action) {
this.sendType = action.type
const dom = this.$refs['fileElem']
setTimeout(() => {
dom && dom.click()
}, 100)
},
// 图片查看
viewImage(file) {
const currt = file.url
const tempList = this.msgs.filter(e => ['file', 'image'].includes(e.type)).map(e => e.file)
const imageList = []
tempList.forEach(e => {
const array = ['JPG', 'PNG', 'JEPG', 'GIF']
if (array.includes(e.type) || array.includes(e.ext.toLocaleUpperCase())) {
imageList.push(e.url)
}
})
console.log('imageList', imageList)
const index = imageList.indexOf(currt) || 0
showImagePreview({
images: imageList,
startPosition: index,
closeable: true
})
},
clearMsg() {
this.nim.deleteLocalMsgsBySession({
scene: 'p2p',
to: this.targetId,
delLastMsg: true,
done: (error) => {
if (error) {
showFailToast('删除失败')
} else {
showSuccessToast('删除成功')
}
}
});
},
clearAllMsg() {
this.nim.deleteAllLocalMsgs({
done: (error) => {
if (error) {
showFailToast('删除失败')
} else {
showSuccessToast('删除成功')
}
}
})
},
onBack() {
}
},
beforeUnmount() {
if (this.nim) {
this.nim.destroy({
done: function (err) {
console.log('nim 断开连接')
}
})
}
}
}
</script>
......
......@@ -2,6 +2,7 @@
import 'vant/es/toast/style/index'
import 'vant/es/notify/style/index'
import 'vant/es/dialog/style/index'
import 'vant/es/image-preview/style/index'
// 自定义svg 图标组件
import DocIcon from '@/components/docIcon/index'
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment