Commit 2efb1ca6 authored by 以墨为白's avatar 以墨为白 🎧
parents bc07c430 f1c9d809
// 定义粘贴函数
const onPaste = (event) => {
// 剪贴板没数据,则直接返回
if (!event.clipboardData || !event.clipboardData.items) {
return;
}
// 封装Promise
return new Promise((resovle, reject) => {
for(let i = 0, len = event.clipboardData.items.length; i < len; i++) {
const item = event.clipboardData.items[i];
if (item.kind === 'string') {
// let str = event.clipboardData.getData('text');
// resovle({
// data: str
// });
let reg = /<\/?.+?\/?>/g; // 匹配粘贴文本中的html标签
item.getAsString(str => {
resovle({
data: str.replace(reg, '').replace(/(\r\n)|(\n)/g, '') // 去掉换行符
})
})
} else if (item.kind === 'file') {
const file = item.getAsFile();
if (item.type.match('^image/')) {
// 处理图片
handleImage(file, (data) => {
resovle(data)
})
} else {
// 其他文件直接返回
resovle({
data: file,
type: 'file'
})
}
} else {
reject(new Error('不支持粘贴该类型'));
}
}
})
}
/**
* 图片处理
* @param {*} file 图片
* @param {*} callback 回调
* @param {*} maxWidth
* @returns
*/
function handleImage(file, callback, maxWidth = 200) {
console.log('粘贴的图片', file);
if (!file || !/\/(?:png|jpg|jpeg|gif)/i.test(file.type)) {
console.log('图片格式不支持');
return;
}
const reader = new FileReader();
reader.onload = function () {
const result = this.result;
console.log('compressedDataUrl', result);
let img = new Image();
img.onload = function() {
let compressedDataUrl = compress(img, file.type, maxWidth, true);
let url = compress(img, file.type, maxWidth, false);
img = null;
callback({
data: file,
compressedDataUrl,
url,
type: 'image'
})
}
img.src = result;
};
reader.readAsDataURL(file);
}
/**
* 图片压缩
* @param {*} img 图片对象
* @param {*} type 图片类型
* @param {*} maxWidth 图片最大宽度
* @param {*} flag
*/
function compress(img, type, maxWidth, flag) {
let canvas = document.createElement('canvas');
let ctx2 = canvas.getContext('2d');
let ratio = img.width / img.height;
let width = img.width, height = img.height;
// 根据flag判断是否压缩图片
if (flag) {
// 压缩后的图片展示在输入框
width = maxWidth;
height = maxWidth / ratio; // 维持图片宽高比
}
canvas.width = width;
canvas.height = height;
ctx2.fillStyle = '#fff';
ctx2.fillRect(0, 0, canvas.width, canvas.height);
ctx2.drawImage(img, 0, 0, width, height);
let base64Data = canvas.toDataURL(type, 0.75);
if (type === 'image/gif') {
let regx = /(?<=data:image).*?(?=;base64)/; // 正则表示时在用于replace时,根据浏览器的不同,有的需要为字符串
base64Data = base64Data.replace(regx, '/gif');
}
canvas = null;
ctx2 = null;
return base64Data;
}
export default onPaste;
\ No newline at end of file
<template>
<el-dialog v-if="dialogVisible" v-el-drag-dialog title="聊天室" :visible.sync="dialogVisible" width="40%" :before-close="handleClose" :close-on-click-modal="false">
<el-dialog v-el-drag-dialog title="聊天室" :visible.sync="dialogVisible" width="40%" :before-close="handleClose"
@open="handleDialogOpen">
<div class="info-messageInfo">
<div class="messageInfo-content">
<div class="chatPerson">
<span :style="{ backgroundColor: chatPerson.isLine ? '#30d64d' : '#686a6b' }"
v-show="chatPerson.isLine != undefined"></span>&nbsp;
<span v-text="chatPerson.name"></span>
</div>
<div id="chatContent" class="chatContent" ref="chatContent">
<div v-for="item in chatMessageList" class="everyMessage">
<div :style="{ justifyContent: item.fromUserId == userInfo.account ? 'flex-end' : 'flex-start' }">
<template v-if="item.fromUserId != userInfo.account">
<img :src="avatar" alt="">
<div v-text="item.content" style="background-color:white"></div>
<img class="avatarImg" :src="avatar" alt="">
<!-- <div v-text="item.content" style="background-color:white"></div> -->
<div v-if="item.messageForm == 'TEXT'" v-html="item.content" style="background-color: white;">
</div>
<el-image v-else-if="item.messageForm == 'PICTURE'" style="width: 150px; height: 100px"
:src="item.content" :preview-src-list="[item.content]">
</el-image>
</template>
<template v-else-if="item.fromUserId == userInfo.account">
<div v-text="item.content" style="background-color: #85ce61;"></div>
<img :src="avatar" alt="">
<div v-if="item.messageForm == 'TEXT'" v-html="item.content"
style="background-color: #85ce61;">
</div>
<el-image v-else-if="item.messageForm == 'PICTURE'" style="width: 150px; height: 100px"
:src="item.content" :preview-src-list="[item.content]">
</el-image>
<img class="avatarImg" :src="avatar" alt="">
</template>
</div>
</div>
</div>
<div class="chatSendMessage">
<div class="messageContent">
<el-input type="textarea" autosize placeholder="请输入内容" v-model="sendMessage">
</el-input>
<div ref="editor" class="preview" contenteditable @paste.prevent="onPaste" @input="inputText"></div>
<!-- <el-input type="textarea" autosize placeholder="请输入内容" v-model="sendMessage">
</el-input> -->
</div>
<div class="sendMessageButtonList">
<el-button size="mini" type="success" @click="sendMessageFn">发送</el-button>
......@@ -40,22 +47,24 @@
import avatar from '../../../assets/img/ddkz/headPhoto.jpg';
import { getRecordsByPagingTeam } from '../../../api/chat/chatRecords';
import elDragDialog from "@/util/directive/el-dragDialog";
import onPaste from '@/util/onPaste.js';
import { upLoadFiles } from '@/api/chat/chatRoom';
import { getTime_extent, download } from '@/util/http_util.js';
export default {
data() {
return {
dialogVisible: false,
avatar: avatar,
chatPerson: {
name: '',
isLine: undefined
},
sendMessage: '',
sendMessage: [],
chatMessageList: [],
// stompClient: '',
// ws: null,
analogDataList: [],
currentChatRoom: {},
myStompClient: null
myStompClient: null,
file: null,
imgList: [],
noticeMessage: ''
}
},
directives: {
......@@ -66,28 +75,75 @@ export default {
analogData: Array,
stompClient: Object,
currentChatRoomInfo: Object
},
methods: {
handleClose() {
// this.dialogVisible = false;
this.$emit('handleCancel');
this.dialogVisible = false;
// this.$emit('handleCancel');
},
showDialog(){
showDialog() {
this.dialogVisible = true;
},
sendMessageFn() {
if (this.sendMessage.trim().length > 0) {
this.myStompClient.send("/app/sendToChatRoomTeam/" + this.currentChatRoom.id + '/' + this.currentChatRoom.teamId, {}, JSON.stringify({
'content': this.sendMessage
}));
base64ImgtoFile(dataurl, filename = 'file') {
const arr = dataurl.split(',')
const mime = arr[0].match(/:(.*?);/)[1]
const suffix = mime.split('/')[1]
const bstr = atob(arr[1])
let n = bstr.length
const u8arr = new Uint8Array(n)
while (n--) {
u8arr[n] = bstr.charCodeAt(n)
}
return new File([u8arr], `${filename}.${suffix}`, {
type: mime
})
},
upLoadImg() {
setTimeout(() => {
this.keepBottom();
this.sendMessage = '';
}, 100);
},
sendMessageFn() {
if (this.$refs.editor.innerHTML.trim().length > 0) {
this.sendMessage = []
let tmpArr = this.$refs.editor.innerHTML.trim().split(/\<img\s*src=\"([^\"]*?)\"[^>]*>/gi).filter(item => item.length !== 0);
this.imgList = [];
tmpArr.forEach((item, index) => {
let tmpObj = { content: item, messageForm: 'TEXT' }
if (item.indexOf('data:image/jpeg;base64') == 0) {
let obj = { index: index, url: item }
this.imgList.push(obj);
tmpObj.messageForm = 'PICTURE';
}
this.sendMessage.push(tmpObj);
})
let promiseArr = [];
for (let i = 0; i < this.imgList.length; i++) {
let p = new Promise((resolve, reject) => {
let fd = new FormData();
fd.append('file', this.base64ImgtoFile(this.imgList[i].url));
upLoadFiles('CHAT', fd).then(res => {
this.sendMessage[this.imgList[i].index].content = 'api/rest/file/viewPicture/CHAT?objectName=' + res;
resolve();
})
})
promiseArr.push(p);
}
Promise.all(promiseArr).then(res => {
for (let i = 0; i < this.sendMessage.length; i++) {
this.myStompClient.send("/app/sendToChatRoomTeam/" + this.currentChatRoom.id + '/' + this.currentChatRoom.teamId, {}, JSON.stringify({
'content': this.sendMessage[i].content,
messageForm: this.sendMessage[i].messageForm,
}));
}
})
} else {
this.$message.warning('不能发送空白信息');
}
setTimeout(() => {
this.keepBottom();
this.sendMessage = [];
this.$refs.editor.innerHTML = '';
}, 100);
},
keepBottom() {
this.$refs.chatContent.scrollTop = this.$refs.chatContent.scrollHeight;
......@@ -104,7 +160,8 @@ export default {
this.stompClient.subscribe('/topic/multicast/' + e.id + '/' + e.teamId, data => {
this.chatMessageList.push({
content: JSON.parse(data.body).content,
fromUserId: data.headers.fromUserId
fromUserId: data.headers.fromUserId,
messageForm: JSON.parse(data.body).messageForm
});
this.$nextTick(() => {
this.keepBottom();
......@@ -115,12 +172,50 @@ export default {
},
getCurrentMessageList(item) {
//查询我方聊天记录
getRecordsByPagingTeam(item.id, 1, 100, '2020-01-01 00:00:00', '2024-10-01 00:00:00', null, item.teamId).then(res1 => {
getRecordsByPagingTeam(item.id, 1, 500, '2023-10-01 00:00:00', getTime_extent(0).pre_rq_end, null, item.teamId).then(res1 => {
this.chatMessageList = res1.records;
this.$nextTick(() => {
this.keepBottom();
});
})
},
handleDialogOpen() {
this.analogDataList = this.$props.analogData;
this.currentChatRoom = this.$props.currentChatRoomInfo;
this.myStompClient = this.$props.stompClient;
//订阅
this.listChatroom(this.analogDataList);
this.getCurrentMessageList(this.$props.currentChatRoomInfo);
},
// 监听输入框内容
inputText(event) {
},
onPaste(event) {
new Promise((resolve, reject) => {
const result = onPaste(event);
result.then(res => {
const imgRegx = /^data:image\/png|jpg|jpeg|gif|svg|bmp|tif/; // 支持的图片格式
if (res.type) {
if (imgRegx.test(res.compressedDataUrl)) {
const sel = window.getSelection(); // 获取当前光标位置
if (sel && sel.rangeCount === 1 && sel.isCollapsed) {
const range = sel.getRangeAt(0);
const img = new Image();
img.src = res.compressedDataUrl; // 使用压缩后的图片
range.insertNode(img);
range.collapse(false);
sel.removeAllRanges();
sel.addRange(range);
resolve('hi');
}
}
} else {
document.execCommand('insertText', false, res.data);
}
})
})
}
},
computed: {
......@@ -131,15 +226,6 @@ export default {
return { account: "" };
}
}
},
mounted() {
this.dialogVisible = this.$props.visible;
this.analogDataList = this.$props.analogData;
this.currentChatRoom = this.$props.currentChatRoomInfo;
this.myStompClient = this.$props.stompClient;
//订阅
this.listChatroom(this.analogDataList);
this.getCurrentMessageList(this.$props.currentChatRoomInfo);
}
}
</script>
......@@ -172,39 +258,12 @@ export default {
height: calc(100% - 40px);
margin-top: 10px;
padding: 0px 10px;
border: 1px solid #254751;
border: 1px solid #515151c9;
box-sizing: border-box;
.chatPerson {
width: 100%;
height: 40px;
line-height: 40px;
display: flex;
justify-content: center;
font-size: 13px;
border-bottom: 1px solid #37383f;
display: none;
&>span:first-child {
width: 10px;
height: 10px;
border-radius: 50%;
display: block;
float: left;
margin-top: 15px;
margin-left: 5px;
}
&>span:last-child {
float: left;
margin-left: 10px;
}
}
.chatContent {
width: 100%;
height: 60%;
height: 64%;
border-bottom: 1px solid #37383f;
padding: 10px 0px;
box-sizing: border-box;
......@@ -217,16 +276,25 @@ export default {
&>div {
width: 100%;
display: flex;
align-items: center;
align-items: flex-start;
margin-top: 10px;
font-size: 13px;
img {
.avatarImg {
width: 20px;
height: 20px;
margin: 0px 10px;
}
.el-imgage {
img {
width: 100%;
height: 100%;
}
}
&>div {
max-width: 50%;
padding: 5px 10px;
......@@ -239,15 +307,30 @@ export default {
.chatSendMessage {
width: 100%;
height: calc(40% - 42px);
height: 35%;
position: relative;
.messageContent {
width: 100%;
height: 100%;
padding: 5px;
padding: 5px 0px;
box-sizing: border-box;
.preview {
width: 100%;
height: 100%;
padding: 10px;
box-sizing: border-box;
color: white;
border: 1px solid #474748;
outline: none;
/* 隐藏聚焦时外边框 */
white-space: pre-wrap;
overflow: hidden;
overflow-y: auto;
word-break: break-all;
}
.el-textarea__inner {
height: 100% !important;
color: white !important;
......@@ -259,7 +342,7 @@ export default {
.sendMessageButtonList {
position: absolute;
right: 10px;
bottom: 10px;
bottom: 15px;
}
}
}
......
......@@ -25,26 +25,19 @@ export default {
elDragDialog
},
props: {
// visible: Boolean,
peopleList: Array
},
methods: {
handleClose() {
this.dialogVisible = false;
// this.$emit('handleCancel');
},
showDialog() {
this.dialogVisible = true;
},
handleDialogOpen() {
// this.dialogVisible = this.$props.visible;
this.personList = this.$props.peopleList;
}
},
// mounted() {
// this.dialogVisible = this.$props.visible;
// this.personList = this.$props.peopleList;
// }
}
}
</script>
......
<template>
<el-dialog v-el-drag-dialog title="发送公告" :visible.sync="dialogVisible" width="30%" :before-close="handleClose">
<el-dialog v-el-drag-dialog title="发送公告" :visible.sync="dialogVisible" width="30%" :before-close="handleClose"
@open="handleDialogOpen">
<div class="notice">
<el-form ref="form" :model="form" label-width="80px">
<el-form-item label="标题">
......@@ -37,7 +38,7 @@ export default {
title: '',
content: '',
attachment: '',
messageForm:null
messageForm: null
},
formatFile: format_file(),
myStompClient: null,
......@@ -59,7 +60,7 @@ export default {
this.dialogVisible = false;
// this.$emit('handleCancel');
},
showDialog(){
showDialog() {
this.dialogVisible = true;
},
handleChange(file, fileList) {
......@@ -68,16 +69,16 @@ export default {
upLoadFiles('CHAT', fd).then(res => {
this.form.attachment = res;
let type = file.name.split('.')[1];
if(type=='png'||type=='jpg'){
if (type == 'png' || type == 'jpg') {
this.form.messageForm = 'PICTURE';
}else if(type=='mp4'){
} else if (type == 'mp4') {
this.form.messageForm = 'VIDEO';
}else if(type=='xlsx'||type=='xls'){
} else if (type == 'xlsx' || type == 'xls') {
this.form.messageForm = 'EXCEL';
}else{
} else {
this.form.messageForm = 'TEXT';
}
});
},
handleRemove() { },
......@@ -95,18 +96,24 @@ export default {
//订阅聊天室主题,订阅功能中设置ID:
this.stompClient.subscribe('/topic/multicast/' + e.id, data => {
this.$emit('handleCancel');
this.$emit('showInfo',true, this.currentChatRoom);
this.$emit('showInfo', true, this.currentChatRoom);
}, { id: "multicast" + e.id + new Date().getTime() });
})
},
handleDialogOpen() {
this.myStompClient = this.$props.stompClient;
this.currentChatRoom = this.$props.currentChatRoomInfo;
this.analogDataList = this.$props.analogData;
this.listChatroom(this.analogDataList);
}
},
mounted() {
this.dialogVisible = this.$props.visible;
this.myStompClient = this.$props.stompClient;
this.currentChatRoom = this.$props.currentChatRoomInfo;
this.analogDataList = this.$props.analogData;
this.listChatroom(this.analogDataList);
}
// mounted() {
// this.dialogVisible = this.$props.visible;
// this.myStompClient = this.$props.stompClient;
// this.currentChatRoom = this.$props.currentChatRoomInfo;
// this.analogDataList = this.$props.analogData;
// this.listChatroom(this.analogDataList);
// }
}
</script>
......
......@@ -73,7 +73,8 @@
:class="['everyDayNewCard', 'cardType' + item1.teamInfo.teamType]">
<div class="everyDayNewCardTitle" v-text="item1.title"></div>
<div class="everyDayNewCardContent">
<div class="left-everyDayNew" :style="{ width: item1.attachment ? '50%' : '100%' }">
<div class="left-everyDayNew"
:style="{ width: item1.attachment ? '50%' : '100%' }">
<div class="everyDayNewCardInfo">
<span v-text="item1.time"></span>&emsp;
来源:<span class="newsSource" v-text="item1.from"></span>
......@@ -86,7 +87,7 @@
</el-image>
</template>
<template v-else-if="item1.type == 'VIDEO'">
<video :src="item1.url" controls loop>
<video :src="item1.url" controls loop>
</video>
</template>
<template v-else-if="item1.type == 'EXCEL'">
......@@ -107,14 +108,11 @@
</div>
</div>
</transition>
<NoticeDialog v-if="visible" ref="myNotice" @handleCancel="closeDialog" :stompClient="stompClient"
<NoticeDialog ref="myNotice" :stompClient="stompClient"
:currentChatRoomInfo="currentChatRoomInfo" :analogData="analogData" @showInfo="showInfo"></NoticeDialog>
<ChatRoomDialog v-if="chatRoomVisible" :visible="chatRoomVisible" ref="myChatRoom"
@handleCancel="closeDialogChatRoom" :analogData="analogData" :currentChatRoomInfo="currentChatRoomInfo"
:stompClient="stompClient">
<ChatRoomDialog ref="myChatRoom" :analogData="analogData" :currentChatRoomInfo="currentChatRoomInfo" :stompClient="stompClient">
</ChatRoomDialog>
<ChatRoomPeople ref="myChatRoomPeople" @handleCancel="closeDialogChatRoomPeople"
:peopleList="peopleList"></ChatRoomPeople>
<ChatRoomPeople ref="myChatRoomPeople" :peopleList="peopleList"></ChatRoomPeople>
<el-tooltip placement="left" class="myButtonList" v-if="isInfo">
<div class="myTools" slot="content">
<div>
......@@ -183,9 +181,9 @@ export default {
],
avatar: avatar,
sendMessage: '',
visible: false,
chatRoomVisible: false,
chatRoomPeopleVisible: false,
// visible: false,
// chatRoomVisible: false,
// chatRoomPeopleVisible: false,
peopleList: [],
// chatMessageList: [],
currentChatRoomInfo: {},
......@@ -254,7 +252,6 @@ export default {
tmpArr = this.publicNoticeList.filter(item => { return item.fromUserId == user && item.createTime.slice(0, 10) == day });
}
tmpArr.forEach(item => {
console.log(item);
let obj = { time: '', news: [] };
let fileUrl = null;
fileUrl = item.attachment ? 'api/rest/file/viewPicture/CHAT?objectName=' + item.attachment : null;
......@@ -290,11 +287,11 @@ export default {
const divscll = document.getElementById('chatContent');
divscll.scrollTop = divscll.scrollHeight;
},
closeDialog() {
this.visible = false;
},
// closeDialog() {
// this.visible = false;
// },
sendNotice() {
this.visible = true;
// this.visible = true;
this.$nextTick(() => {
this.$refs.myNotice.showDialog();
})
......@@ -302,29 +299,25 @@ export default {
// this.$refs.myNotice.showDialog();
// }
},
closeDialogChatRoom() {
this.chatRoomVisible = false;
},
// closeDialogChatRoom() {
// this.chatRoomVisible = false;
// },
showChatRoom() {
this.chatRoomVisible = true;
// this.$nextTick(() => {
// this.$refs.myChatRoom.showDialog();
// })
// this.chatRoomVisible = true;
this.$nextTick(() => {
this.$refs.myChatRoom.showDialog();
})
// if (this.$refs.myChatRoom) {
// this.$refs.myChatRoom.showDialog();
// }
},
closeDialogChatRoomPeople() {
this.chatRoomPeopleVisible = false;
},
// closeDialogChatRoomPeople() {
// this.chatRoomPeopleVisible = false;
// },
showPeopleList() {
// this.chatRoomPeopleVisible = true;
this.$nextTick(() => {
this.$refs.myChatRoomPeople.showDialog();
})
// if (this.$refs.myChatRoomPeople) {
// this.$refs.myChatRoomPeople.showDialog();
// }
},
queryChatRoomListFn(params) {
getChatRoomList(params).then(res => {
......
......@@ -100,7 +100,7 @@ module.exports = {
}
},
'/websocket/**': {
target: 'ws://192.168.168.106:8081',
target: 'ws://192.168.168.213:8081',
ws: true,
secure: false,
logLevel: 'debug',
......
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