2022-09-22 14:06:13 +08:00
|
|
|
<template>
|
|
|
|
<div :class="{'comment-active': commentActive}" style="border: 1px solid #eee; margin: 0; position: relative" @click="handleClickBlank">
|
|
|
|
<textarea ref="commentRef" v-model="myComment" @input="handleCommentChange" @blur="handleBlur" class="comment-content" :rows="3" placeholder="请输入你的评论,可以@成员" />
|
|
|
|
<div class="comment-content comment-html-shower" :class="{'no-content':noConent, 'top-div': showHtml, 'bottom-div': showHtml == false }" v-html="commentHtml" @click="handleClickHtmlShower"></div>
|
|
|
|
<div class="comment-buttons" v-if="commentActive">
|
|
|
|
<div style="cursor: pointer">
|
|
|
|
<Tooltip title="选择@用户">
|
|
|
|
<user-add-outlined @click="openSelectUser" />
|
|
|
|
</Tooltip>
|
|
|
|
|
|
|
|
<Tooltip title="上传附件">
|
|
|
|
<PaperClipOutlined @click="uploadVisible = !uploadVisible" />
|
|
|
|
</Tooltip>
|
|
|
|
|
|
|
|
<span title="表情" style="display: inline-block">
|
|
|
|
<SmileOutlined ref="emojiButton" @click="handleShowEmoji" />
|
|
|
|
<div style="position: relative" v-show=""> </div>
|
|
|
|
</span>
|
|
|
|
</div>
|
|
|
|
<div v-if="commentActive">
|
|
|
|
<a-button v-if="inner" @click="noComment" style="margin-right: 10px">取消</a-button>
|
|
|
|
<a-button type="primary" @click="sendComment" :loading="buttonLoading" :disabled="disabledButton">发 送</a-button>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<upload-chunk ref="uploadRef" :visible="uploadVisible" @select="selectFirstFile"></upload-chunk>
|
|
|
|
</div>
|
|
|
|
<UserSelectModal labelKey="realname" rowKey="username" @register="registerModal" @getSelectResult="setValue" isRadioSelection></UserSelectModal>
|
|
|
|
<a-modal v-model:visible="visibleEmoji" :footer="null" wrapClassName="emoji-modal" :closable="false" :width="490">
|
|
|
|
<template #title>
|
|
|
|
<span></span>
|
|
|
|
</template>
|
|
|
|
<Picker
|
|
|
|
:pickerStyles="pickerStyles"
|
|
|
|
:i18n="optionsName"
|
|
|
|
:data="emojiIndex"
|
|
|
|
emoji="grinning"
|
|
|
|
:showPreview="false"
|
|
|
|
:infiniteScroll="false"
|
|
|
|
:showSearch="false"
|
|
|
|
:showSkinTones="false"
|
|
|
|
set="apple"
|
|
|
|
@select="showEmoji">
|
|
|
|
</Picker>
|
|
|
|
</a-modal>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<script lang="ts">
|
2022-10-24 18:39:36 +08:00
|
|
|
import {ref, watch, computed, inject} from 'vue';
|
2022-09-22 14:06:13 +08:00
|
|
|
import { propTypes } from '/@/utils/propTypes';
|
|
|
|
import { UserAddOutlined, PaperClipOutlined, SmileOutlined } from '@ant-design/icons-vue';
|
|
|
|
import { Tooltip } from 'ant-design-vue';
|
|
|
|
import UserSelectModal from '/@/components/Form/src/jeecg/components/modal/UserSelectModal.vue';
|
|
|
|
import { useModal } from '/@/components/Modal';
|
|
|
|
import UploadChunk from './UploadChunk.vue';
|
|
|
|
import 'emoji-mart-vue-fast/css/emoji-mart.css';
|
|
|
|
import { useEmojiHtml } from './useComment';
|
|
|
|
|
|
|
|
const optionsName = {
|
|
|
|
categories: {
|
|
|
|
recent: '最常用的',
|
|
|
|
smileys: '表情选择',
|
|
|
|
people: '人物&身体',
|
|
|
|
nature: '动物&自然',
|
|
|
|
foods: '食物&饮料',
|
|
|
|
activity: '活动',
|
|
|
|
places: '旅行&地点',
|
|
|
|
objects: '物品',
|
|
|
|
symbols: '符号',
|
|
|
|
flags: '旗帜',
|
|
|
|
},
|
|
|
|
};
|
|
|
|
export default {
|
|
|
|
name: 'MyComment',
|
|
|
|
components: {
|
|
|
|
UserAddOutlined,
|
|
|
|
Tooltip,
|
|
|
|
UserSelectModal,
|
|
|
|
PaperClipOutlined,
|
|
|
|
UploadChunk,
|
|
|
|
SmileOutlined,
|
|
|
|
},
|
|
|
|
props: {
|
|
|
|
inner: propTypes.bool.def(false),
|
|
|
|
inputFocus: {
|
|
|
|
type: Boolean,
|
|
|
|
default: false,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
emits: ['cancel', 'comment'],
|
|
|
|
setup(props, { emit }) {
|
|
|
|
const uploadVisible = ref(false);
|
|
|
|
const uploadRef = ref();
|
|
|
|
//注册model
|
|
|
|
const [registerModal, { openModal }] = useModal();
|
|
|
|
const buttonLoading = ref(false);
|
|
|
|
const myComment = ref<string>('');
|
|
|
|
function sendComment() {
|
|
|
|
console.log(myComment.value);
|
|
|
|
let content = myComment.value;
|
|
|
|
if (!content && content !== '0') {
|
|
|
|
disabledButton.value = true;
|
|
|
|
} else {
|
|
|
|
buttonLoading.value = true;
|
|
|
|
let fileList = [];
|
|
|
|
if (uploadVisible.value == true) {
|
|
|
|
fileList = uploadRef.value.getUploadFileList();
|
|
|
|
}
|
|
|
|
emit('comment', content, fileList);
|
|
|
|
setTimeout(() => {
|
|
|
|
buttonLoading.value = false;
|
|
|
|
}, 350);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
const disabledButton = ref(false);
|
|
|
|
watch(myComment, () => {
|
|
|
|
let content = myComment.value;
|
|
|
|
if (!content && content !== '0') {
|
|
|
|
disabledButton.value = true;
|
|
|
|
} else {
|
|
|
|
disabledButton.value = false;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
function noComment() {
|
|
|
|
emit('cancel');
|
|
|
|
}
|
|
|
|
|
|
|
|
const commentRef = ref();
|
|
|
|
watch(
|
|
|
|
() => props.inputFocus,
|
|
|
|
(val) => {
|
|
|
|
if (val == true) {
|
|
|
|
// commentRef.value.focus()
|
|
|
|
myComment.value = '';
|
|
|
|
if (uploadVisible.value == true) {
|
|
|
|
uploadRef.value.clear();
|
|
|
|
uploadVisible.value = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{ deep: true, immediate: true }
|
|
|
|
);
|
|
|
|
|
|
|
|
function openSelectUser() {
|
|
|
|
openModal(true, {
|
|
|
|
isUpdate: false,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
function setValue(options) {
|
|
|
|
console.log('setValue', options);
|
|
|
|
if (options && options.length > 0) {
|
|
|
|
const { label, value } = options[0];
|
|
|
|
if (label && value) {
|
|
|
|
let str = `${label}[${value}]`;
|
|
|
|
let temp = myComment.value;
|
|
|
|
if (!temp) {
|
|
|
|
myComment.value = '@' + str;
|
|
|
|
} else {
|
|
|
|
if (temp.endsWith('@')) {
|
|
|
|
myComment.value = temp + str;
|
|
|
|
} else {
|
|
|
|
myComment.value = '@' + str + ' ' + temp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function handleCommentChange() {
|
|
|
|
//console.log(1,e)
|
|
|
|
}
|
|
|
|
watch(
|
|
|
|
() => myComment.value,
|
|
|
|
(val) => {
|
|
|
|
if (val && val.endsWith('@')) {
|
|
|
|
openSelectUser();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
|
|
|
const emojiButton = ref();
|
|
|
|
function onSelectEmoji(emoji) {
|
|
|
|
let temp = myComment.value || '';
|
|
|
|
temp += emoji;
|
|
|
|
myComment.value = temp;
|
|
|
|
emojiButton.value.click();
|
|
|
|
}
|
|
|
|
|
|
|
|
const visibleEmoji = ref(false);
|
|
|
|
function showEmoji(e) {
|
|
|
|
let temp = myComment.value || '';
|
|
|
|
let str = e.colons;
|
|
|
|
if (str.indexOf('::') > 0) {
|
|
|
|
str = str.substring(0, str.indexOf(':') + 1);
|
|
|
|
}
|
|
|
|
myComment.value = temp + str;
|
|
|
|
visibleEmoji.value = false;
|
|
|
|
handleBlur();
|
|
|
|
}
|
|
|
|
|
|
|
|
const pickerStyles = {
|
|
|
|
width: '490px'
|
|
|
|
/* height: '350px',
|
|
|
|
top: '0px',
|
|
|
|
left: '-75px',
|
|
|
|
position: 'absolute',
|
|
|
|
'z-index': 9999*/
|
|
|
|
};
|
|
|
|
function handleClickBlank(e) {
|
|
|
|
console.log('handleClickBlank');
|
|
|
|
e.preventDefault();
|
|
|
|
e.stopPropagation();
|
|
|
|
visibleEmoji.value = false;
|
|
|
|
commentActive.value = true;
|
|
|
|
}
|
|
|
|
function handleShowEmoji(e) {
|
|
|
|
console.log('handleShowEmoji');
|
|
|
|
e.preventDefault();
|
|
|
|
e.stopPropagation();
|
|
|
|
visibleEmoji.value = !visibleEmoji.value;
|
|
|
|
}
|
2022-10-24 18:39:36 +08:00
|
|
|
|
|
|
|
const emojiIndex = inject('$globalEmojiIndex')
|
|
|
|
const { getHtml } = useEmojiHtml(emojiIndex);
|
2022-09-22 14:06:13 +08:00
|
|
|
|
|
|
|
const commentHtml = computed(() => {
|
|
|
|
let temp = myComment.value;
|
|
|
|
if (!temp) {
|
|
|
|
return '请输入你的评论,可以@成员';
|
|
|
|
}
|
|
|
|
return getHtml(temp);
|
|
|
|
});
|
|
|
|
|
|
|
|
const showHtml = ref(false);
|
|
|
|
function handleClickHtmlShower(e) {
|
|
|
|
e.preventDefault();
|
|
|
|
e.stopPropagation();
|
|
|
|
showHtml.value = false;
|
|
|
|
commentRef.value.focus();
|
|
|
|
console.log(234);
|
|
|
|
commentActive.value = true;
|
|
|
|
}
|
|
|
|
function handleBlur() {
|
|
|
|
showHtml.value = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
const commentActive = ref(false);
|
|
|
|
const noConent = computed(()=>{
|
|
|
|
if(myComment.value.length>0){
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
});
|
|
|
|
function changeActive(){
|
|
|
|
if(myComment.value.length==0){
|
|
|
|
commentActive.value = false
|
|
|
|
uploadVisible.value = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function selectFirstFile(fileName){
|
|
|
|
if(myComment.value.length==0){
|
|
|
|
myComment.value = fileName;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return {
|
|
|
|
myComment,
|
|
|
|
sendComment,
|
|
|
|
noComment,
|
|
|
|
disabledButton,
|
|
|
|
buttonLoading,
|
|
|
|
commentRef,
|
|
|
|
registerModal,
|
|
|
|
openSelectUser,
|
|
|
|
setValue,
|
|
|
|
handleCommentChange,
|
|
|
|
uploadRef,
|
|
|
|
uploadVisible,
|
|
|
|
onSelectEmoji,
|
|
|
|
optionsName,
|
|
|
|
emojiButton,
|
|
|
|
emojiIndex,
|
|
|
|
showEmoji,
|
|
|
|
pickerStyles,
|
|
|
|
visibleEmoji,
|
|
|
|
handleClickBlank,
|
|
|
|
handleShowEmoji,
|
|
|
|
commentHtml,
|
|
|
|
showHtml,
|
|
|
|
handleClickHtmlShower,
|
|
|
|
handleBlur,
|
|
|
|
commentActive,
|
|
|
|
noConent,
|
|
|
|
changeActive,
|
|
|
|
selectFirstFile
|
|
|
|
};
|
|
|
|
},
|
|
|
|
};
|
|
|
|
</script>
|
|
|
|
|
|
|
|
<style lang="less">
|
|
|
|
.comment-content {
|
|
|
|
box-sizing: border-box;
|
|
|
|
margin: 0;
|
|
|
|
padding: 0;
|
|
|
|
font-variant: tabular-nums;
|
|
|
|
list-style: none;
|
|
|
|
font-feature-settings: tnum;
|
|
|
|
position: relative;
|
|
|
|
display: inline-block;
|
|
|
|
width: 100%;
|
|
|
|
padding: 4px 11px;
|
|
|
|
color: rgba(0, 0, 0, 0.85);
|
|
|
|
font-size: 15px;
|
|
|
|
line-height: 1.5715;
|
|
|
|
background-color: #fff;
|
|
|
|
background-image: none;
|
|
|
|
border: 1px solid #d9d9d9;
|
|
|
|
border-radius: 2px;
|
|
|
|
transition: all 0.3s;
|
|
|
|
width: 100%;
|
|
|
|
border: solid 0px;
|
|
|
|
outline: none;
|
|
|
|
|
|
|
|
.emoji-item {
|
|
|
|
display: inline-block !important;
|
|
|
|
width: 0 !important;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
.comment-buttons {
|
|
|
|
padding: 10px;
|
|
|
|
display: flex;
|
|
|
|
justify-content: space-between;
|
|
|
|
border-top: 1px solid #d9d9d9;
|
|
|
|
.anticon {
|
|
|
|
margin: 5px;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
.comment-html-shower {
|
|
|
|
position: absolute;
|
|
|
|
top: 0;
|
|
|
|
left: 0;
|
|
|
|
height: 70px;
|
|
|
|
&.bottom-div {
|
|
|
|
z-index: -99;
|
|
|
|
}
|
|
|
|
&.top-div {
|
|
|
|
z-index: 9;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.emoji-modal {
|
|
|
|
> .ant-modal{
|
|
|
|
right: 25% !important;
|
|
|
|
margin-right: 16px !important;
|
|
|
|
}
|
|
|
|
.ant-modal-header{
|
|
|
|
padding: 0 !important;
|
|
|
|
}
|
|
|
|
.emoji-mart-bar{
|
|
|
|
display: none;
|
|
|
|
}
|
|
|
|
h3.emoji-mart-category-label{
|
|
|
|
/* display: none;*/
|
|
|
|
border-bottom: 1px solid #eee;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.comment-active{
|
|
|
|
border-color: #1e88e5 !important;
|
|
|
|
box-shadow: 0 1px 1px 0 #90caf9, 0 1px 6px 0 #90caf9;
|
|
|
|
}
|
|
|
|
.no-content{
|
|
|
|
color: #a1a1a1
|
|
|
|
}
|
|
|
|
|
|
|
|
/**聊天表情本地化*/
|
|
|
|
.emoji-type-image.emoji-set-apple {
|
|
|
|
background-image: url("./image/emoji.png");
|
|
|
|
}
|
|
|
|
</style>
|