留言板表情包

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", "path-to-regexp": "2.4.0",
"qrcode.vue": "^1.6.2", "qrcode.vue": "^1.6.2",
"qs": "^6.9.3", "qs": "^6.9.3",
"quill-emoji": "^0.1.8",
"quill-image-extend-module": "^1.1.2", "quill-image-extend-module": "^1.1.2",
"recordrtc": "^5.5.9", "recordrtc": "^5.5.9",
"script-loader": "^0.7.2", "script-loader": "^0.7.2",

View File

@ -1,5 +1,5 @@
<template> <template>
<div> <div :class="className">
<quill-editor <quill-editor
ref="editor" ref="editor"
v-model="content" v-model="content"
@ -16,8 +16,11 @@
<script> <script>
import { quillEditor, Quill } from 'vue-quill-editor'; import { quillEditor, Quill } from 'vue-quill-editor';
import 'quill/dist/quill.snow.css'; 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'; import { ImageExtend, QuillWatch} from 'quill-image-extend-module';
Quill.register('modules/ImageExtend', ImageExtend); Quill.register('modules/ImageExtend', ImageExtend);
Quill.register('modules/quillEmoji', QuillEmoji);
export default { export default {
components: { components: {
quillEditor quillEditor
@ -39,13 +42,17 @@ export default {
type: Number, type: Number,
default: 80 default: 80
}, },
unloadImg: {
type: Boolean,
default: false
},
noHandleP: { noHandleP: {
type: Boolean, type: Boolean,
defalut: false defalut: false
},
editorType: {
type: String,
default: 'default'
},
className: {
type: String,
default: 'commonClass'
} }
}, },
data() { data() {
@ -59,7 +66,10 @@ export default {
}, },
options() { options() {
const that = this; const that = this;
return this.unloadImg ? { let optionValue = {};
switch (this.editorType) {
case 'imgEmoji':
optionValue = {
modules: { modules: {
ImageExtend: { ImageExtend: {
loading: true, loading: true,
@ -72,6 +82,8 @@ export default {
error: () => { that.$message.error('图片上传失败,请检查网络状态'); }, error: () => { that.$message.error('图片上传失败,请检查网络状态'); },
sizeError: () => { that.$message.error('图片上传失败图片大小限制3MB'); } // sizeError: () => { that.$message.error('图片上传失败图片大小限制3MB'); } //
}, },
'emoji-toolbar': true,
'emoji-shortname': true,
toolbar: { toolbar: {
container: [ container: [
['bold', 'italic', 'underline', 'strike'], ['bold', 'italic', 'underline', 'strike'],
@ -86,7 +98,7 @@ export default {
[{'font': []}], [{'font': []}],
[{'align': []}], [{'align': []}],
['clean'], ['clean'],
['image'] ['image', 'emoji']
], ],
handlers: { handlers: {
'image': function () { 'image': function () {
@ -96,7 +108,22 @@ export default {
} }
}, },
placeholder: '请输入' placeholder: '请输入'
} : { };
break;
case 'onlyEmoji':
optionValue = {
modules: {
'emoji-toolbar': true,
'emoji-shortname': true,
toolbar: {
container: [['emoji']]
}
},
placeholder: this.placeholder
};
break;
case 'default':
optionValue = {
modules: { modules: {
toolbar: [ toolbar: [
['bold', 'italic', 'underline', 'strike'], ['bold', 'italic', 'underline', 'strike'],
@ -114,6 +141,9 @@ export default {
] ]
} }
}; };
break;
}
return optionValue;
}, },
titleConfig () { titleConfig () {
return { return {
@ -173,7 +203,29 @@ export default {
}, },
getFocus() { getFocus() {
this.$refs.editor.quill.focus(); this.$refs.editor.quill.focus();
},
getText() {
return this.$refs.editor.quill.getText();
},
setContents(val) {
this.$refs.editor.quill.setContents(val);
} }
} }
}; };
</script> </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: 'bjd', label: '北交大'},
{value: 'urtss', label: '陪标项目'} {value: 'urtss', label: '陪标项目'}
]; ];
export const ProjectPostIdMap = {
drts: 1,
bjd: 2
};

View File

@ -29,7 +29,7 @@
<template v-for="(elem,j) in allCommentList"> <template v-for="(elem,j) in allCommentList">
<div :key="j" style="font-size: 14px;margin-top: 10px;"> <div :key="j" style="font-size: 14px;margin-top: 10px;">
<span style="margin-right: 5px;">{{ computedCommentName(elem) }}</span> <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="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 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> <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"> <template v-for="(elem,j) in item.comments.list">
<div :key="j" style="font-size: 14px;margin-top: 18px;"> <div :key="j" style="font-size: 14px;margin-top: 18px;">
<span style="margin-right: 5px;">{{ computedCommentName(elem) }}</span> <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="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 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> <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> </div>
<div v-if="replyMessageId == item.id" style="width: 80%;margin-left: 10%;text-align: center;"> <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" /> <quill-editor
<div style="margin-top: 10px;"> :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 type="danger" size="small" @click="commentMessage">回复</el-button>
<el-button size="small" @click="cancelComment">取消</el-button> <el-button size="small" @click="cancelComment">取消</el-button>
</div> </div>
@ -74,11 +84,10 @@
/> />
</div> </div>
</el-card> </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"> <span id="boardBottom" class="dialog-footer">
<el-button @click="handleClear">清空</el-button> <el-button @click="handleClear">清空</el-button>
<el-button type="danger" @click="commitComment">留言</el-button> <el-button type="danger" @click="commitComment">留言</el-button>
<!--<el-button type="danger" @click="dialogVisible = false">返回</el-button>-->
</span> </span>
<el-button size="mini" type="danger" style="position: fixed; right: 100px;top: 80px;width: 90px;" @click="goSlide">我要留言</el-button> <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> <el-button size="mini" style="position: fixed; right: 100px;top: 120px;width: 90px;" @click="dialogVisible = false">退出留言板</el-button>
@ -89,7 +98,8 @@
</template> </template>
<script> <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 lick_icon from '@/assets/like.png';
import unlike_icon from '@/assets/unlike.png'; import unlike_icon from '@/assets/unlike.png';
import reply_icon from '@/assets/reply.png'; import reply_icon from '@/assets/reply.png';
@ -119,7 +129,6 @@ export default {
allCommentList: [], allCommentList: [],
moreMessageId: '', moreMessageId: '',
replyUserName: '', replyUserName: '',
commentContentNoName: '',
postId: '' postId: ''
}; };
}, },
@ -159,19 +168,20 @@ export default {
}, },
commitComment() { commitComment() {
const images = this.content.match(/<img/g); const images = this.content.match(/<img/g);
const answerContent = this.handleEmojiContent(this.content);
if (images && images.length > 3) { if (images && images.length > 3) {
this.$message.error('留言内容使用图片应小于三张!'); this.$message.error('留言内容使用图片应小于三张!');
return; return;
} }
if (this.content.length > 1000) { if (answerContent.length > 1000) {
this.$message.error('留言内容超出最大长度!'); this.$message.error('留言内容超出最大长度!');
return; return;
} }
if (!this.content) { if (!answerContent) {
this.$message.error('留言内容不能为空!'); this.$message.error('留言内容不能为空!');
return; return;
} }
answerPost({postId: this.postId, content: this.content}).then(resp => { answerPost({postId: this.postId, content: answerContent}).then(resp => {
this.pageNum = 1; this.pageNum = 1;
this.handleCurrentChange(); this.handleCurrentChange();
this.content = ''; this.content = '';
@ -184,13 +194,25 @@ export default {
queryMessagePagingByProjectCode(this.projectCode, {pageSize: this.pageSize, pageNum: this.pageNum}).then(resp => { queryMessagePagingByProjectCode(this.projectCode, {pageSize: this.pageSize, pageNum: this.pageNum}).then(resp => {
this.postCommentList = []; this.postCommentList = [];
(resp.data.list || []).forEach(item => { (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 = this.replaceEmoji(item.content);
item.content = value; item.comments && item.comments.list && item.comments.list.forEach(elem => {
elem.content = this.replaceEmoji(elem.content);
});
this.postCommentList.push(item); this.postCommentList.push(item);
}); });
this.total = resp.data.total; 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() { goSlide() {
const bottom = document.getElementById('boardBottom'); const bottom = document.getElementById('boardBottom');
const element = document.getElementById('elDialog').childNodes[0]; const element = document.getElementById('elDialog').childNodes[0];
@ -219,10 +241,10 @@ export default {
this.replyMessageIndex = messageIndex; this.replyMessageIndex = messageIndex;
if (commentId) { if (commentId) {
this.replyUserName = '@' + userNickname + ' '; this.replyUserName = '@' + userNickname + ' ';
this.commentContent = this.replyUserName + this.commentContentNoName; this.commentContent = '';
} }
this.$nextTick(()=>{ this.$nextTick(()=>{
document.getElementById('answerInput' + messageId).focus(); this.$refs['answerInput' + messageId][0].getFocus();
}); });
}, },
cancelComment() { cancelComment() {
@ -231,38 +253,47 @@ export default {
this.replyCommentId = ''; this.replyCommentId = '';
this.replyMessageIndex = ''; this.replyMessageIndex = '';
this.replyUserName = ''; this.replyUserName = '';
this.commentContentNoName = '';
}, },
commentMessage() { commentMessage() {
const contentValue = this.handleEmojiContent(this.commentContent);
if (contentValue.length > 300) {
this.$message.error('回复内容超出最大长度!');
return;
}
if (this.replyCommentId) { 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.getCommentList(this.replyMessageId, this.replyMessageIndex);
this.cancelComment(); this.cancelComment();
}).catch(error => { }).catch(error => {
this.$message.error('评论留言失败!'); this.$message.error('评论回复失败!');
console.error(error); console.error(error);
}); });
} else { } else {
commentLevelMessage(this.replyMessageId, {content:this.commentContentNoName}).then(resp => { commentLevelMessage(this.replyMessageId, {content:contentValue}).then(resp => {
this.getCommentList(this.replyMessageId, this.replyMessageIndex); this.getCommentList(this.replyMessageId, this.replyMessageIndex);
this.cancelComment(); this.cancelComment();
}).catch(error => { }).catch(error => {
this.$message.error('评论留言失败!'); this.$message.error('评论回复失败!');
console.error(error); console.error(error);
}); });
} }
}, },
getCommentList(messageId, messageIndex) { getCommentList(messageId, messageIndex) {
queryMessageCommentList(messageId).then(resp => { 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) { if (this.moreMessageId == messageId) {
this.allCommentList = resp.data; this.allCommentList = replaceValue;
} }
if (resp.data.length > 3) { if (replaceValue.length > 3) {
this.postCommentList[messageIndex].comments.list = resp.data.slice(0, 3); this.postCommentList[messageIndex].comments.list = replaceValue.slice(0, 3);
this.postCommentList[messageIndex].comments.total = resp.data.length; this.postCommentList[messageIndex].comments.total = replaceValue.length;
} else { } else {
this.postCommentList[messageIndex].comments.list = resp.data; this.postCommentList[messageIndex].comments.list = replaceValue;
this.postCommentList[messageIndex].comments.total = resp.data.length; this.postCommentList[messageIndex].comments.total = replaceValue.length;
} }
}).catch(error => { }).catch(error => {
this.$message.error('更新回复失败!'); this.$message.error('更新回复失败!');
@ -314,20 +345,24 @@ export default {
}, },
viewMoreComment(data) { viewMoreComment(data) {
queryMessageCommentList(data.id).then(resp => { 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; this.moreMessageId = data.id;
}).catch(error => { }).catch(error => {
console.error(error); console.error(error);
}); });
}, },
changeCommentContent(val) { handleEmojiContent(content) {
if (this.replyUserName && val.startsWith(this.replyUserName)) { const list = content.match(/<span class="ql-emojiblot" data-name="(\S*)"><span contenteditable="false"><span class="ap ap-(\S*)<\/span><\/span><\/span>/g);
this.commentContentNoName = val.slice(this.replyUserName.length); (list || []).forEach(item => {
} else if (this.replyUserName) { let targetValue = item.split(' ')[2];
this.commentContent = this.replyUserName + this.commentContentNoName; targetValue = targetValue.substring(11, targetValue.length - 8);
} else { content = content.replace(item, '<<<' + targetValue + '>>>');
this.commentContentNoName = this.commentContent; });
} return content;
} }
} }
}; };