留言板表情包

This commit is contained in:
fan 2020-11-19 14:17:01 +08:00
parent 4c7e601406
commit 11b54cef43
4 changed files with 171 additions and 87 deletions

View File

@ -29,6 +29,7 @@
"path-to-regexp": "2.4.0",
"qrcode.vue": "^1.6.2",
"qs": "^6.9.3",
"quill-emoji": "^0.1.8",
"quill-image-extend-module": "^1.1.2",
"recordrtc": "^5.5.9",
"script-loader": "^0.7.2",

View File

@ -1,5 +1,5 @@
<template>
<div>
<div :class="className">
<quill-editor
ref="editor"
v-model="content"
@ -16,8 +16,11 @@
<script>
import { quillEditor, Quill } from 'vue-quill-editor';
import 'quill/dist/quill.snow.css';
import QuillEmoji from 'quill-emoji';
import 'quill-emoji/dist/quill-emoji.css';
import { ImageExtend, QuillWatch} from 'quill-image-extend-module';
Quill.register('modules/ImageExtend', ImageExtend);
Quill.register('modules/quillEmoji', QuillEmoji);
export default {
components: {
quillEditor
@ -39,13 +42,17 @@ export default {
type: Number,
default: 80
},
unloadImg: {
type: Boolean,
default: false
},
noHandleP: {
type: Boolean,
type: Boolean,
defalut: false
},
editorType: {
type: String,
default: 'default'
},
className: {
type: String,
default: 'commonClass'
}
},
data() {
@ -59,21 +66,66 @@ export default {
},
options() {
const that = this;
return this.unloadImg ? {
modules: {
ImageExtend: {
loading: true,
name: 'file',
size: 3,
action: `https://test.joylink.club/jlfile/api/upload/PICTURE?appId=00001&appSecret=joylink00001`,
response: (res) => {
return `https://test.joylink.club/oss/joylink${res.data}`;
let optionValue = {};
switch (this.editorType) {
case 'imgEmoji':
optionValue = {
modules: {
ImageExtend: {
loading: true,
name: 'file',
size: 3,
action: `https://test.joylink.club/jlfile/api/upload/PICTURE?appId=00001&appSecret=joylink00001`,
response: (res) => {
return `https://test.joylink.club/oss/joylink${res.data}`;
},
error: () => { that.$message.error('图片上传失败,请检查网络状态'); },
sizeError: () => { that.$message.error('图片上传失败图片大小限制3MB'); } //
},
error: () => { that.$message.error('图片上传失败,请检查网络状态'); },
sizeError: () => { that.$message.error('图片上传失败图片大小限制3MB'); } //
'emoji-toolbar': true,
'emoji-shortname': true,
toolbar: {
container: [
['bold', 'italic', 'underline', 'strike'],
[],
[],
[{'list': 'ordered'}, {'list': 'bullet'}],
[{'script': 'sub'}, {'script': 'super'}],
[{'indent': '-1'}, {'indent': '+1'}],
[{'direction': 'rtl'}],
[{'size': ['small', 'large', 'huge']}],
[{'color': [], 'background': []}],
[{'font': []}],
[{'align': []}],
['clean'],
['image', 'emoji']
],
handlers: {
'image': function () {
QuillWatch.emit(this.quill.id);
}
}
}
},
toolbar: {
container: [
placeholder: '请输入'
};
break;
case 'onlyEmoji':
optionValue = {
modules: {
'emoji-toolbar': true,
'emoji-shortname': true,
toolbar: {
container: [['emoji']]
}
},
placeholder: this.placeholder
};
break;
case 'default':
optionValue = {
modules: {
toolbar: [
['bold', 'italic', 'underline', 'strike'],
[],
[],
@ -85,35 +137,13 @@ export default {
[{'color': [], 'background': []}],
[{'font': []}],
[{'align': []}],
['clean'],
['image']
],
handlers: {
'image': function () {
QuillWatch.emit(this.quill.id);
}
}
['clean']
]
}
},
placeholder: '请输入'
} : {
modules: {
toolbar: [
['bold', 'italic', 'underline', 'strike'],
[],
[],
[{'list': 'ordered'}, {'list': 'bullet'}],
[{'script': 'sub'}, {'script': 'super'}],
[{'indent': '-1'}, {'indent': '+1'}],
[{'direction': 'rtl'}],
[{'size': ['small', 'large', 'huge']}],
[{'color': [], 'background': []}],
[{'font': []}],
[{'align': []}],
['clean']
]
}
};
};
break;
}
return optionValue;
},
titleConfig () {
return {
@ -161,7 +191,7 @@ export default {
},
methods: {
onChange(e) {
if (!this.noHandleP) {
if (!this.noHandleP) {
this.$emit('input', this.$escapeHTML(this.content));
} else {
this.$emit('input', this.content);
@ -173,7 +203,29 @@ export default {
},
getFocus() {
this.$refs.editor.quill.focus();
},
getText() {
return this.$refs.editor.quill.getText();
},
setContents(val) {
this.$refs.editor.quill.setContents(val);
}
}
};
</script>
<style rel="stylesheet/scss" lang="scss" scoped>
.answer_input{
/deep/ .ql-toolbar.ql-snow{
padding: 0;
border: 0;
border-top: 1px solid #c0c0c0;
height: 0;
text-align: left;
.ql-emoji{
position: relative;
left: -30px;
}
}
}
</style>

View File

@ -447,7 +447,3 @@ export const ProjectList = [
{value: 'bjd', label: '北交大'},
{value: 'urtss', label: '陪标项目'}
];
export const ProjectPostIdMap = {
drts: 1,
bjd: 2
};

View File

@ -29,7 +29,7 @@
<template v-for="(elem,j) in allCommentList">
<div :key="j" style="font-size: 14px;margin-top: 10px;">
<span style="margin-right: 5px;">{{ computedCommentName(elem) }}</span>
<span style="margin-right: 15px;">{{ elem.content }}</span>
<span style="margin-right: 15px;" v-html="$escapeHTML(`${elem.content}`)" />
<span style="margin-right: 10px;">{{ elem.commentTime }}</span>
<span style="color:#409EFF;cursor: pointer;margin-right: 10px;" @click="replyLeaveMessage(item.id, i,elem.id, elem.userNickname)">回复</span>
<span v-if="userId == elem.userId || superAdmin" style="color:#409EFF;cursor: pointer;" type="text" @click="deleteComment(item.id, i, elem.id)">删除</span>
@ -40,7 +40,7 @@
<template v-for="(elem,j) in item.comments.list">
<div :key="j" style="font-size: 14px;margin-top: 18px;">
<span style="margin-right: 5px;">{{ computedCommentName(elem) }}</span>
<span style="margin-right: 15px;">{{ elem.content }}</span>
<span style="margin-right: 15px;" v-html="$escapeHTML(`${elem.content}`)" />
<span style="margin-right: 10px;">{{ elem.commentTime }}</span>
<span style="color:#409EFF;cursor: pointer;margin-right: 10px;" @click="replyLeaveMessage(item.id, i,elem.id, elem.userNickname)">回复</span>
<span v-if="userId == elem.userId || superAdmin" style="color:#409EFF;cursor: pointer;" type="text" @click="deleteComment(item.id, i, elem.id)">删除</span>
@ -52,8 +52,18 @@
</div>
</div>
<div v-if="replyMessageId == item.id" style="width: 80%;margin-left: 10%;text-align: center;">
<el-input :id="'answerInput' + item.id" v-model="commentContent" type="textarea" placeholder="请输入内容" maxlength="300" style="margin-top: 10px;" :autosize="{ minRows: 2, maxRows: 4}" show-word-limit @input="changeCommentContent" />
<div style="margin-top: 10px;">
<quill-editor
:ref="'answerInput' + item.id"
v-model="commentContent"
style="width: 80%;margin-left: 10%;margin-top: 10px;"
class-name="answer_input"
:margin-bottom="20"
editor-type="onlyEmoji"
:no-handle-p="true"
:height="100"
:placeholder="replyUserName"
/>
<div>
<el-button type="danger" size="small" @click="commentMessage">回复</el-button>
<el-button size="small" @click="cancelComment">取消</el-button>
</div>
@ -74,11 +84,10 @@
/>
</div>
</el-card>
<quill-editor ref="quillEditor" v-model="content" style="width: 80%;margin-left: 10%;" placeholder="请输入内容" :margin-bottom="20" :unload-img="true" :no-handle-p="true" />
<quill-editor ref="quillEditor" v-model="content" style="width: 80%;margin-left: 10%;" :margin-bottom="20" editor-type="imgEmoji" :no-handle-p="true" />
<span id="boardBottom" class="dialog-footer">
<el-button @click="handleClear">清空</el-button>
<el-button type="danger" @click="commitComment">留言</el-button>
<!--<el-button type="danger" @click="dialogVisible = false">返回</el-button>-->
</span>
<el-button size="mini" type="danger" style="position: fixed; right: 100px;top: 80px;width: 90px;" @click="goSlide">我要留言</el-button>
<el-button size="mini" style="position: fixed; right: 100px;top: 120px;width: 90px;" @click="dialogVisible = false">退出留言板</el-button>
@ -89,7 +98,8 @@
</template>
<script>
import { answerPost, queryMessagePagingByProjectCode, deleteMessageByAdmin, deleteMessageBySelf, commentLevelMessage, commentComents, queryMessageCommentList, deleteCommentByAdmin, deleteCommentBySelf, getPostByProjectCode } from '@/api/learn';
import { answerPost, queryMessagePagingByProjectCode, deleteMessageByAdmin, deleteMessageBySelf, commentLevelMessage, commentComents,
queryMessageCommentList, deleteCommentByAdmin, deleteCommentBySelf, getPostByProjectCode } from '@/api/learn';
import lick_icon from '@/assets/like.png';
import unlike_icon from '@/assets/unlike.png';
import reply_icon from '@/assets/reply.png';
@ -119,7 +129,6 @@ export default {
allCommentList: [],
moreMessageId: '',
replyUserName: '',
commentContentNoName: '',
postId: ''
};
},
@ -159,19 +168,20 @@ export default {
},
commitComment() {
const images = this.content.match(/<img/g);
const answerContent = this.handleEmojiContent(this.content);
if (images && images.length > 3) {
this.$message.error('留言内容使用图片应小于三张!');
return;
}
if (this.content.length > 1000) {
if (answerContent.length > 1000) {
this.$message.error('留言内容超出最大长度!');
return;
}
if (!this.content) {
if (!answerContent) {
this.$message.error('留言内容不能为空!');
return;
}
answerPost({postId: this.postId, content: this.content}).then(resp => {
answerPost({postId: this.postId, content: answerContent}).then(resp => {
this.pageNum = 1;
this.handleCurrentChange();
this.content = '';
@ -184,13 +194,25 @@ export default {
queryMessagePagingByProjectCode(this.projectCode, {pageSize: this.pageSize, pageNum: this.pageNum}).then(resp => {
this.postCommentList = [];
(resp.data.list || []).forEach(item => {
const value = item.content.replace(/<img/g, '<img style="width: 100px;height: auto;cursor: zoom-in;" onclick="handleZoomImg()"');
item.content = value;
item.content = this.replaceEmoji(item.content);
item.comments && item.comments.list && item.comments.list.forEach(elem => {
elem.content = this.replaceEmoji(elem.content);
});
this.postCommentList.push(item);
});
this.total = resp.data.total;
});
},
replaceEmoji(content) {
let value = content.replace(/<img/g, '<img style="width: 100px;height: auto;cursor: zoom-in;" onclick="handleZoomImg()"');
const list = value.match(/<<<([^>]*)>>>/g);
(list || []).forEach(elem => {
const targetValue = elem.substring(3, elem.length - 3);
value = value.replace(elem, `<span class="ql-emojiblot" data-name="${targetValue}"><span contenteditable="false"><span class="ap ap-${targetValue}">ss</span></span></span>`);
});
console.log(content, list, list);
return value;
},
goSlide() {
const bottom = document.getElementById('boardBottom');
const element = document.getElementById('elDialog').childNodes[0];
@ -219,10 +241,10 @@ export default {
this.replyMessageIndex = messageIndex;
if (commentId) {
this.replyUserName = '@' + userNickname + ' ';
this.commentContent = this.replyUserName + this.commentContentNoName;
this.commentContent = '';
}
this.$nextTick(()=>{
document.getElementById('answerInput' + messageId).focus();
this.$refs['answerInput' + messageId][0].getFocus();
});
},
cancelComment() {
@ -231,38 +253,47 @@ export default {
this.replyCommentId = '';
this.replyMessageIndex = '';
this.replyUserName = '';
this.commentContentNoName = '';
},
commentMessage() {
const contentValue = this.handleEmojiContent(this.commentContent);
if (contentValue.length > 300) {
this.$message.error('回复内容超出最大长度!');
return;
}
if (this.replyCommentId) {
commentComents(this.replyMessageId, this.replyCommentId, {content:this.commentContentNoName}).then(resp => {
commentComents(this.replyMessageId, this.replyCommentId, {content:contentValue}).then(resp => {
this.getCommentList(this.replyMessageId, this.replyMessageIndex);
this.cancelComment();
}).catch(error => {
this.$message.error('评论留言失败!');
this.$message.error('评论回复失败!');
console.error(error);
});
} else {
commentLevelMessage(this.replyMessageId, {content:this.commentContentNoName}).then(resp => {
commentLevelMessage(this.replyMessageId, {content:contentValue}).then(resp => {
this.getCommentList(this.replyMessageId, this.replyMessageIndex);
this.cancelComment();
}).catch(error => {
this.$message.error('评论留言失败!');
this.$message.error('评论回复失败!');
console.error(error);
});
}
},
getCommentList(messageId, messageIndex) {
queryMessageCommentList(messageId).then(resp => {
const replaceValue = [];
resp.data && resp.data.forEach(item => {
item.content = this.replaceEmoji(item.content);
replaceValue.push(item);
});
if (this.moreMessageId == messageId) {
this.allCommentList = resp.data;
this.allCommentList = replaceValue;
}
if (resp.data.length > 3) {
this.postCommentList[messageIndex].comments.list = resp.data.slice(0, 3);
this.postCommentList[messageIndex].comments.total = resp.data.length;
if (replaceValue.length > 3) {
this.postCommentList[messageIndex].comments.list = replaceValue.slice(0, 3);
this.postCommentList[messageIndex].comments.total = replaceValue.length;
} else {
this.postCommentList[messageIndex].comments.list = resp.data;
this.postCommentList[messageIndex].comments.total = resp.data.length;
this.postCommentList[messageIndex].comments.list = replaceValue;
this.postCommentList[messageIndex].comments.total = replaceValue.length;
}
}).catch(error => {
this.$message.error('更新回复失败!');
@ -314,20 +345,24 @@ export default {
},
viewMoreComment(data) {
queryMessageCommentList(data.id).then(resp => {
this.allCommentList = resp.data;
this.allCommentList = [];
resp.data && resp.data.forEach(item => {
item.content = this.replaceEmoji(item.content);
this.allCommentList.push(item);
});
this.moreMessageId = data.id;
}).catch(error => {
console.error(error);
});
},
changeCommentContent(val) {
if (this.replyUserName && val.startsWith(this.replyUserName)) {
this.commentContentNoName = val.slice(this.replyUserName.length);
} else if (this.replyUserName) {
this.commentContent = this.replyUserName + this.commentContentNoName;
} else {
this.commentContentNoName = this.commentContent;
}
handleEmojiContent(content) {
const list = content.match(/<span class="ql-emojiblot" data-name="(\S*)"><span contenteditable="false"><span class="ap ap-(\S*)<\/span><\/span><\/span>/g);
(list || []).forEach(item => {
let targetValue = item.split(' ')[2];
targetValue = targetValue.substring(11, targetValue.length - 8);
content = content.replace(item, '<<<' + targetValue + '>>>');
});
return content;
}
}
};