Files
learning-system-mobile/components/comments/comments.vue
2022-12-02 15:17:34 +08:00

686 lines
21 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view>
<u-toast ref="interactToast"></u-toast>
<view class="comments">
<view v-if="showTop" class="comments-top">
<view>
<text style="font-size: 32upx;font-weight: 500;">评论 </text>
<text style="font-size: 28upx;padding-left: 20upx;color: #333;font-weight: 400;"> ({{total}})</text></view>
<view>
<!-- <view v-if="showShare" class="share-btn" @click="addShare">
<view class="share-btn-icon"><img src="/static/images/icon/share.png" alt=""></view>
<view class="share-btn-name">分享</view>
</view> -->
</view>
</view>
<view class="comments-items">
<!--内容确定了这部分样式要移到class中-->
<view v-for="(comm,commidx) in list" :key="commidx" class="comment">
<view class="comment-top">
<author-img :avatar="comm.avatar" :sex="comm.sex" width="30px" height="30px" :size="30"></author-img>
<text style="font-size: 28upx;ont-weight: 500;color: #333333;margin-left: 22upx;">{{comm.sysCreateBy}}</text>
</view>
<view class="comment-body">
<view class="comment-content" v-html="comm.content"></view>
<view class="comment-btns">
<view class="comment-time">
<time-show :time="comm.sysCreateTime"></time-show>
</view>
<view class="" style="display: flex;">
<view style="font-size: 12px;color: #999999;line-height: 60upx;" @click="openInput(commidx)">
<image style="width: 36upx;height: 36upx;vertical-align: middle;margin-right: 10upx;" src="../../static/images/icon/bar-comment.png" size="24"></image>回复
<!-- <u-icon @click="openInput(commidx)" name="chat" color="#979797" size="18" label="回复"></u-icon> -->
</view>
<interact-bar :pageType="objType" :pageParams="objId" :type="praisesType" :data="comm" :comments="false" :favorites="false"></interact-bar>
</view>
<!-- <view>
<u-icon @click="openInput(commidx)" name="chat" color="#979797" size="18" label="回复"></u-icon>
</view> -->
<!-- <view>
<u-icon @click="openBtns(commidx,-1,comm)" name="more-dot-fill" size="20"></u-icon>
</view> -->
</view>
<view v-if="comm.replyList && comm.replyList.length>0" class="comment-replys">
<view v-for="(reply,replyIdx) in comm.replyList" :key="replyIdx" class="comment" v-if="comm.showAll || replyIdx<2">
<view class="comment-top">
<view style="display: flex;">
<author v-if="reply" :showInfo="true" :data="reply"></author>
<!-- <author-info :avatar="reply.avatar" :name="reply.sysCreateBy"></author-info> -->
<!-- <u-avatar shape="square" icon="account" :size="26" :src="reply.avatar"></u-avatar>
<text style="margin-left: 10upx;"> {{reply.sysCreateBy}}</text> -->
<text style="padding-left: 16upx;padding-top: 6upx;color: #979797;font-size: 20upx;"> 回复 </text>
<text style="padding-left: 16upx;padding-top: 6upx;font-size: 26upx;">{{reply.replyName}}</text>
</view>
</view>
<view class="comment-body" style="margin-left: 0;padding-left: 50upx;">
<view class="comment-content" v-html="reply.content"></view>
<view class="" style="display: flex;justify-content: space-between;">
<view class="comment-time">
<time-show :time="reply.sysCreateTime"></time-show>
</view>
<view class="comment-btns" style="line-height: 60upx;">
<view style="font-size: 12px;color: #999999;" @click="openInput(commidx,replyIdx)">
<image style="width: 36upx;height: 36upx;vertical-align: middle;margin-right: 10upx;" src="../../static/images/icon/bar-comment.png" size="24"></image>回复
<!-- <u-icon @click="openInput(commidx)" name="chat" color="#979797" size="18" label="回复"></u-icon> -->
</view>
<interact-bar :pageType="objType" :pageParams="objId" :data="reply" :type="praisesType" :comments="false" :favorites="false"></interact-bar>
<!-- <view>
<u-icon @click="openInput(commidx,replyIdx)" name="chat" color="#979797" size="18" label="回复"></u-icon>
</view>
<view>
<u-icon @click="openBtns(commidx,replyIdx,reply)" name="more-dot-fill" size="20"></u-icon>
</view> -->
</view>
</view>
</view>
</view>
<view v-if="comm.replyList.length>2" class="view-all-com" @click="loadReplyMore(comm)">
{{comm.showAll ? '收起':`查看全部${comm.replyList.length}条评论 >`}}
</view>
</view>
</view>
</view>
<view v-if="total==0 && loadStatus=='noMore'">
<!--提示-->
<view style="text-align: center;padding: 20px;color: #aaaaaa;min-height: 400upx; " >暂无评论</view>
</view>
</view>
<view style="height: 10px;"></view>
</view>
<view v-if="total>pageSize">
<uni-load-more :status="loadStatus"></uni-load-more>
</view>
<u-popup :show="inputShow" @close="closeInput" :round="16">
<view>
<view style="padding: 60upx 30upx;">
<view><u--textarea confirmType="done" style="border: none;background: #F4F4F4;" :height="50" v-model="inputValue" :placeholder="'回复 '+this.replyInfo.replyName" count ></u--textarea></view>
<view style="width:160upx;padding-top: 10px;line-height: 80upx;float: right;">
<view style="padding: 20upx;margin-top: 20upx;"><u-button style="padding: 2upx 30upx;height: 52upx;background: #87B3FF;border-color: #87B3FF;" @click="submitReply()" type="primary" text="发布"></u-button></view>
</view>
</view>
<view>
</view>
</view>
</u-popup>
<u-popup :show="btnsShow" @close="closeBtns">
<view>
<view @click="delShow()" class="big-button" v-if="userInfo.aid==commData.sysCreateAid" style="color: #db0000;">删除</view>
<view @click="copy()" class="big-button">复制</view>
<view @click="closeBtns()" class="big-button">取消</view>
</view>
</u-popup>
<u-popup :show="shareInfo.show" @close="closeShare" @open="addShare" mode="right">
<view style="padding: 10px 20px;line-height: 60upx;">
<view style="padding: 10upx;">请输入要分享给人的姓名</view>
<view style="padding: 10upx;">
<u--input placeholder="请输入人员姓名" border="surround" v-model="shareInfo.name"></u--input>
</view>
<view style="padding-top:20upx;">
<u-button @click="findUsers()" type="primary" text="查询"></u-button>
</view>
<view style="padding-top: 50upx;">
<!--查询内容列表-->
<view style="line-height: 60upx;" v-for="(su,suidx) in shareInfo.users" :key="suidx" @click="confirmShare(su)">{{suidx+1}}, {{su.name}} {{su.code}}</view>
</view>
</view>
</u-popup>
</view>
</template>
<script>
import apiComment from '@/api/modules/comments.js'
import apiUser from '@/api/system/user.js'
import apiShares from '@/api/modules/shares.js'
import apiStat from '@/api/phase2/stat.js'
import { mapGetters } from 'vuex';
export default {
props:{
showTop:{
type:Boolean,
default:true
},
showShare:{
type:Boolean,
default:true
},
objId:{
type:String,
required:true
},
objType:{
type:Number,
required:true
}
},
computed: {
...mapGetters(['userInfo'])
},
data(){
return {
loadStatus:'more',//more,loading,noMore
pageSize:20,
pageIndex:1,
total:0,
inputShow:false,
inputValue:'',
curCommentIndex:-1,
curReplyIndex:-1,
shareInfo:{
show:false,
name:'',
users:[],
},
btnsShow:false,
list:[],
replyParent:{},
// replyShow:false,
btnsShowRowId:'',
replyInfo:{
clevel:2,
parentId:'',
replyAid:'',
commentId:'',
replyName:'',
objType:'',
objId:'',
content:'',
sex:'',
},
replyDiaglog:{
show:false,
pageIndex:1,
pageSize:30,
count:0,
commentId:'',
list:[]
},
toUserDig:{
show:false,
name:'',
chooseUserId:'',
chooseUserName:'',
list:[]
},
commData:{},
praisesType:0,
}
},
mounted() {
this.loadData(false);
if(this.objType == 1) {
this.praisesType = 10;
}
if(this.objType == 2) {
this.praisesType = 20;
}
if(this.objType == 3) {
this.praisesType = 30;
}
},
methods: {
loadReplyMore(item){
item.showAll=!item.showAll;
},
loadData(append){ //加载数据
let params={
pageIndex:this.pageIndex,
pageSize:this.pageSize,
type:this.objType,
id:this.objId,
orderField:'praises'
}
let $this=this;
uni.showLoading({
title:'加载评论...'
})
apiComment.pageQuery(params).then(res=>{
setTimeout(function(){uni.hideLoading()},500);
if(res.status==200){
this.total=res.result.count;
let ids=[];
let allList=[];
res.result.list.forEach(item=>{
item.showAll = false;
item.avatar='';
item.orgInfo='';
item.sex = null;
item.content = item.content.replace(/(\n){2,}/,'<br>');
allList.push(item);
ids.push(item.sysCreateAid);
if(item.replyList && item.replyList!=''){
item.replyList.forEach(reply=>{
reply.avatar='';
reply.orgInfo='';
reply.sex = null;
reply.content = reply.content.replace(/(\n){2,}/,'<br>');
allList.push(reply);
ids.push(reply.sysCreateAid);
})
}
});
this.loadAuthorInfo(allList,ids);
if(append){
res.result.list.forEach(item=>{
$this.list.push(item);
});
}else{
$this.list=res.result.list;
}
if(this.total==0){
this.loadStatus='noMore';
}else if(this.pageIndex>=res.result.totalPages){
this.loadStatus='noMore';
}else{
this.loadStatus='more';
}
}else{
this.$refs.interactToast.show({message:'加载评论失败',type:'error'});
}
});
},
loadAuthorInfo(list,ids){ //加载作者信息,头像,机构信息
if(ids.length==0){
return;
}
const noReapetIds=[...new Set(ids)]
apiUser.getByIds(ids).then(res=>{
if(res.status==200){
list.forEach((item,index)=>{
res.result.some(author=>{
if(author.aid==item.sysCreateAid){
if(item.parentId == "-1" ) {
item.avatar= author.avatar;
} else if(author.avatar != ''){
item.avatar=this.$config.fileUrl + author.avatar;
}
// item.avatar= author.avatar;
item.sex=author.sex;
item.orgInfo=author.orgInfo;
return true;
}else{
return false;
}
})
});
}else{
//console.log('加载用户头像信息:'+res.error);
//this.$message.error(res.message);
}
});
},
submit(){
if(this.inputValue==''){
return;
}
this.inputValue=this.inputValue.replace(/^\s*|\s*$/g,"");
if(this.inputValue==''){
return;
}
if(this.inputValue!=''){
let cdata={
objType:this.objType,
objId:this.objId,
parentId:'-1',
content:this.inputValue,
clevel:1,
toAid:'',
toAname:'',
}
if(this.toUserDig.chooseUserId!=='' && this.toUserDig.chooseUserName!=''){
cdata.toAid=this.toUserDig.chooseUserId;
cdata.toAname=this.toUserDig.chooseUserName;
}
apiComment.add(cdata).then(res=>{
if(res.status==200){
this.list.push(res.result);
//this.$message.success('发布成功');
this.inputValue='';
this.toUserDig.chooseUserId='';
this.toUserDig.chooseUserName='';
}else{
//this.$message.error(res.message);
}
});
}
},
// showReply(item){
// this.replyInfo.objType=this.objType;
// this.replyInfo.objId=this.objId;
// this.replyInfo.parentId=item.id;
// this.replyInfo.replyAid=item.sysCreateAid;
// this.replyInfo.replyName=item.sysCreateBy;
// this.replyShow=true;
// //注意在这里并没有设置commentId,需要在下一步计算
// },
// cancelReply(){
// this.replyInfo.parentId='';
// },
submitReply(){
if(this.inputValue==''){
return;
}
this.inputValue=this.inputValue.replace(/^\s*|\s*$/g,"");
if(this.inputValue==''){
return;
}
this.replyInfo.content=this.inputValue;
let $this=this;
//console.log(this.curCommentIndex,'this.curCommentIndex')
apiComment.reply(this.replyInfo).then(res=>{
if(res.status==200){
this.replyInfo.parentId='';
this.replyInfo.content='';
// this.replyInfo.sex = null;
this.inputValue='';
this.loadData()
// this.loadAuthorInfo([this.result],[res.result.sysCreateAid])
res.result.content = res.result.content.replace(/(\n){2,}/,'<br>');
this.list[this.curCommentIndex].replyList.push(res.result);
this.$refs.interactToast.show({message:'发布成功',type:'success'});
this.inputShow=false;
let event = {
key: "ReplyComment",//后台的事件key 发布文章且审核通过
title: "回复评论",//事件的标题
parameters:"",//用户自定义参数 name:value,name:value
content: "每回一个评论",//事件的内容
objId: this.replyInfo.commentId,//关联的id
objType: "81",//关联的类型
objInfo: "回复评论",
aid: this.userInfo.aid, //当前登录人的id
aname: this.userInfo.name,//当前人的姓名
status: 1 ,//状态直接写1
source:2,
}
apiStat.sendEvent(event);
}else{
this.$refs.interactToast.show({message:'发布失败',type:'error'});
}
});
},
showMoreReply(comment){
this.replyDiaglog.show=true;
this.replyDiaglog.commnetId=comment.id;
this.loadReplyData(false);
},
loadReplyData(append){
let params={
pageIndex:this.replyDiaglog.pageIndex,
pageSize:this.replyDiaglog.pageSize,
type:this.objType,
commentId:this.replyDiaglog.commnetId
}
let $this=this;
apiComment.replyList(params).then(rs=>{
if(rs.status==200){
if(append){
rs.result.list.forEach(item=>{
$this.replyDiaglog.list.push(item);
})
}else{
$this.replyDiaglog.list=rs.result.list;
}
}else{
this.$refs.interactToast.show({message:'加载失败',type:'error'});
}
})
},
addShare(){
//分享
this.shareInfo.show=true;
//默认显示当前内容的作者最好
},
findUsers(){
this.shareInfo.users=[];
//模拟数据
var name=this.shareInfo.name;
if(name==''){
return;
}
apiUser.findByName(name).then(rs=>{
if(rs.status==200){
this.shareInfo.users=rs.result;
}else{
this.$refs.interactToast.show({message:'查询用户失败',type:'error'});
console.log(rs.message);
console.log(rs.error)
}
})
},
confirmShare(u){
let postData={
objType:this.objType,
objId:this.objId,
content:'',
isRead:false,
toAid:u.aid,
toAname:u.name
}
//console.log(postData,'选中的列表');
apiShares.save(postData).then(rs=>{
if(rs.status==200){
this.$refs.interactToast.show({message:'分享成功',type:'success'});
this.shareInfo.show=false;
}else{
console.log(rs.message);
this.$refs.interactToast.show({message:'分享处理失败',type:'error'});
}
});
},
closeShare(){
this.shareInfo.show=false;
},
//回复的事件
openInput(commIdx,replyIdx){
this.curCommentIndex=commIdx;
let comm=this.list[commIdx];
this.replyInfo.commentId=comm.id;
if(replyIdx !== undefined){
this.curReplyIndex=replyIdx;
let re=comm.replyList[replyIdx];
this.replyInfo.parentId=re.id;
this.replyInfo.replyAid=re.sysCreateAid;
this.replyInfo.replyName=re.sysCreateBy;
this.replyInfo.sex = re.sex;
}else{
this.curReplyIndex=-1;
this.replyInfo.parentId=comm.id;
this.replyInfo.replyAid=comm.sysCreateAid;
this.replyInfo.replyName=comm.sysCreateBy;
this.replyInfo.sex = comm.sex;
}
this.replyInfo.objType=this.objType;
this.replyInfo.objId=this.objId;
this.inputShow=true;
// this.loadAuthorInfo();
// this.loadData()
},
closeInput(){
this.inputShow=false;
},
openBtns(comIdx,itemIdx,com){
this.curCommentIndex=comIdx;
this.curReplyIndex=itemIdx;
this.commData = com;
this.btnsShow=true;
},
closeBtns(){
this.btnsShow=false;
},
delShow(){
this.btnsShow=false;
let $this=this;
uni.showModal({
title: '提示',
content: '您确定要删除所选评论吗?',
success: function (res) {
if (res.confirm) {
$this.del();
} else if (res.cancel) {
}
}
});
},
del(){
//删除
//console.log(this.userInfo);
let comm=this.list[this.curCommentIndex];
if(this.curReplyIndex==-1){
if(comm.replyList.length>0){
this.$refs.interactToast.show({message:'有回复不能删除',type:'error'});
return;
}
//删除评论
let $this=this;
apiComment.del(comm.id,this.userInfo.aid).then(res=>{
if(res.status==200){
this.list.splice(this.curCommentIndex,1);
this.$refs.interactToast.show({message:'删除成功',type:'success'});
this.btnsShow=false;
this.$emit('delSuccess');
}else{
console.log(res.error);
this.$refs.interactToast.show({message:'删除失败',type:'error'});
}
});
}else{
let re=comm.replyList[this.curReplyIndex];
let params={
id:re.id,
user:this.userInfo.aid,
pid:re.parentId
}
apiComment.delReply(params).then(res=>{
if(res.status==200){
comm.replyList.splice(this.curReplyIndex,1);
this.$refs.interactToast.show({message:'删除回复成功',type:'success'});
this.btnsShow=false;
}else{
this.$refs.interactToast.show({message:'删除回复失败',type:'error'});
}
});
}
},
copy(){
let comm=this.list[this.curCommentIndex];
let text=comm.content;
if(this.curReplyIndex>-1){
text=comm.replyList[this.curReplyIndex].content;
}
//复制到剪切版中
uni.setClipboardData({
data:text
});
this.btnsShow=false;
this.$refs.interactToast.show({message:'已复制',type:'success'});
}
}
}
</script>
<style lang="scss" scoped>
.view-all-com{
// width: 304upx;
display: inline-block;
height: 52upx;
line-height: 40upx;
background: #F6F6F6;
border-radius: 26upx;
box-sizing: border-box;
padding: 4upx 40upx 4upx 40upx;
font-size: 24upx;
color: #666666;
margin-left: 100upx;
margin-top: 20upx;
}
.comment{
padding-top: 20upx;
.comment-top{
display: flex;
// justify-content: space-between;
line-height: 50upx;
.comment-avatar{
height: 50upx;
width: 50upx;
border-radius: 10%;
border: 1px solid #f3f3f3;
}
.comment-time{
color: #696969;font-size: 0.9em;
}
}
.comment-body{
margin-left: 22upx;
padding: 0 0upx 0upx 60upx;
color: #373737;
.comment-content{
word-break:break-all;
padding: 0upx 10upx 10upx 0upx;
font-size: 28upx;
color: #666666;
}
.comment-btns{
display: flex;
justify-content: space-between;
padding-top: 10upx;
}
}
}
.comments{
margin-top: 10px;
background-color: #FFFFFF;
padding: 20upx 30upx;
.comments-top{
display: flex;
justify-content: space-between;
padding-bottom:20upx;
border-bottom: 1px solid #f4f4f4;
font-weight: 500;
font-size: 1.1em;
}
.comments-items{
padding-top: 10upx;
}
}
.share-btn{
display: flex;
justify-content: flex-end;
padding-top: 10upx;
line-height: 28upx;
.share-btn-icon{
img{
width: 28upx;
height: 28upx;
}
}
.share-btn-name{
font-size: 28upx;
margin-left: 8upx;
}
}
.big-button{
text-align: center;
line-height: 80upx;
border-top: 1px solid #ebebeb;
}
.txtbtn{
background-color: #e9e9e9;
border: 1px solid #e0e0e0;
padding: 3px 10px;
border-radius: 6px;
font-size: 0.8em;
}
</style>