折叠面板使用时拿到后端数据渲染的处理(错误状态:数据循环渲染时,折叠面板展开时一起展开,收起一起收起。本文用于评论回复场景!)
<template>
<div class="discuss" v-loading="tableLoading">
<div class="discuss-body-wrap" ref="discussBody" v-if="dataList.length">
<section class="discuss-body" v-for="(v, i) in dataList" :key="i">
<div style="margin-bottom: 15px;">
<section class="discuss-content">
<div class="content-top">
<!-- 头像 -->
<div class="avatar">{{ v.sendUserName.slice(0, 1) }}</div>
<!-- 时间名字 -->
<div class="comment_detail">
<div class="content-header">
<div>
<span class="nickName">{{ v.sendUserName }}</span>
<span class="time">{{ v.createTime }}</span>
</div>
<div class="content-btn">
<el-tooltip content="回复" placement="top">
<i
v-if="v.sendUserId !=userId"
@click="replyComment(v)"
style="cursor:pointer; margin-right: 5px;"
class="el-icon-chat-dot-round">
</i>
</el-tooltip>
<el-tooltip content="删除" placement="top">
<i v-if="v.sendUserId ==userId" @click="delComment(v)" style="cursor: pointer; color: #f56c6c;" class="el-icon-delete"> </i>
</el-tooltip>
</div>
</div>
<span class="message">{{ v.messageInfo }}</span>
</div>
</div>
</section>
<!-- 子评论的折叠面板 -->
<el-collapse v-if="v.whetherReply > 0" v-model="comments[v.id].active" @change="active=>handleChange(v,active)" accordion>
<el-collapse-item :title="comments[v.id].active ? '收起回复' : '更多回复'" :name="v.id">
<section class="discuss-body" v-for="(v2) in comments[v.id].list" :key="v2.id+'-'+v.id">
<div style="margin-bottom: 15px;">
<section class="discuss-content">
<div class="content-top">
<!-- 头像 -->
<div class="avatar">{{ v2.sendUserName.slice(0, 1) }}</div>
<!-- 时间名字 -->
<div class="comment_detail">
<div class="content-header">
<div>
<span class="nickNamerole">
{{ v2.sendUserName }} <span class="nickName">回复</span> <span>{{ v2.replyUserName }}</span>
</span>
<span class="time">{{ v2.createTime }}</span>
</div>
<div class="content-btn">
<el-tooltip content="回复" placement="top">
<i
v-if="v2.sendUserId !=userId"
@click="replyComment(v2,v)"
style="cursor:pointer; margin-right: 5px;"
class="el-icon-chat-dot-round">
</i>
</el-tooltip>
<el-tooltip content="删除" placement="top">
<i
v-if="v2.sendUserId ==userId"
@click="delComment(v2,v)"
style="cursor: pointer; color: #f56c6c;"
class="el-icon-delete">
</i>
</el-tooltip>
</div>
</div>
<span class="message">{{ v2.messageInfo }}</span>
</div>
</div>
</section>
</div>
</section>
</el-collapse-item>
</el-collapse>
</div>
</section>
</div>
<div v-if="!dataList.length" class="discuss-body-wrap" ref="discussBody">
<el-empty description="暂无评论" />
</div>
<!-- 底部输入区域 -->
<section class="discuss-input">
<!-- 分页代码 -->
<div style="margin: 5px 0;">
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="requestStr.page"
:page-sizes="[10, 20, 30, 40]"
:page-size="requestStr.size"
layout="prev, pager, next,sizes"
:total="requestStr.total"
:pagerCount="pagerCount">
</el-pagination>
</div>
<!-- 回复消息时的显示 -->
<div class="title" v-if="infoData.sendUserName">
<!-- <span class="text" v-if="infoData.sendUserName.length > 8">
<span class="title-nickName">回复 : </span>
{{ infoData.sendUserName.length > 8 ? infoData.sendUserName.slice(0,8) + "..." : infoData.sendUserName}}
</span> -->
<span class="text">
<span class="title-nickName">回复 : </span>
{{ infoData.sendUserName }}
</span>
<span class="title-data">
<span class="title-info">内容 :</span>
{{ infoData.messageInfo.length > 9 ? infoData.messageInfo.slice(0,9) + "..." : infoData.messageInfo}}
</span>
</div>
<!-- 文本输入组件 -->
<InputText
:maxlength="maxnum"
:rows="row"
:placeholder="placeholder"
v-model="values"
:values="values"
:clearable="true"
:input-change="inputChangeMethod"
:focusMethod="focusMethod" />
<div class="foot-btn">
<el-button v-if="CancelBtn" @click="Cancel">取 消</el-button>
<el-button v-if="showBtn" type="primary" @click="onSubmit">发 送</el-button>
<el-button v-if="replyBtn" type="primary" @click="replyInfo">回 复</el-button>
</div>
</section>
</div>
</template>
<script >
import { ApiBugcreate, ApiqueryAllmodule, ApiTaskCreate, ApiTaskDelete, ApiTaskReply } from "@/api/fillingGroups/projectTaskApi.js";
export default {
data() {
return {
collapseTitle: "更多回复",
tableLoading: false,
pagerCount: 5,
userId: this.$store.state.user.user.id, //当前登录用户id
requestStr: {
page: 1,
size: 10,
total: 0
},
Expandcomment: [], //子评论
activeNames: "",
totalCount: null,
maxnum: 2500,
row: 1,
values: "",
placeholder: "请输入内容",
CancelBtn: false,
infoData: {},
replyBtn: false,
news: "",
Infotask: {},
dataList: [], //父评论
showBtn: false,
comments: {},
parentData: {}
};
},
props: {
itemGuid: {
type: String,
default: true
},
taskIntel: {
type: Object,
default: true
}
},
watch: {
itemGuid(newVal, oldVal) {
if (newVal) {
this.itemGuid = newVal;
}
},
taskIntel(newVal, oldVal) {
if (newVal) {
this.Infotask = newVal;
// this.$nextTick(() => {
// this.getDataList();
// });
}
}
},
mounted() {
// this.$nextTick(() => {
// this.getDataList();
// });
this.Infotask = this.taskIntel;
// console.log("🚀 ~ taskIntel ~ newVal:", this.taskIntel);
// console.log("🚀 ~ taskIntel ~ newVal:", this.itemGuid);
},
methods: {
// 问题: 获取评论列表
async getDataList(val) {
this.tableLoading = true;
let oParam = {
...(val !== undefined && { createBoolean: val }), //获取排序的参数
moduleType: "bug",
proId: this.Infotask.affiliatedProject,
moduleId: this.Infotask.id,
page: this.requestStr.page - 1,
size: this.requestStr.size
};
await ApiqueryAllmodule(oParam).then((res) => {
// console.log("🚀 ~ awaitApiqueryAllmodule ~ res:", res);
if (res.code == "200") {
this.tableLoading = false;
this.$set(this, "dataList", res.rows);
// this.dataList = res.rows;
this.dataList.forEach((v, i) => {
if (!this.comments[v.id]) {
this.$set(this.comments, v.id, {
active: "",
list: []
});
}
});
this.requestStr.total = res.totalCount; //获取总数
//this.totalCount = res.totalCount; //获取总数
this.$emit("update:total-count", this.requestStr.total); //获取总数传到父组件去
}
});
},
// 聚焦时的操作
focusMethod() {
//判断显示操作按钮
if (this.CancelBtn == false) {
this.showBtn = true;
}
if (this.showBtn == true) {
this.CancelBtn == true;
}
this.CancelBtn = true; //显示取消按钮
this.row = 4;
//计算滚动条高度
this.$nextTick(() => {
const el = this.$refs.discussBody;
// console.log(el.scrollHeight, el.clientHeight);
el.scrollTop = el.scrollHeight - el.clientHeight;
});
},
// 拿到输入框的值
inputChangeMethod() {
this.news = this.values;
},
//删除
delComment(val, parent) {
this.$confirm("此操作将永久删除该评论, 是否继续?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
.then(() => {
let oParam = {
id: val.id
};
// console.log(333, val, this.infoData);
ApiTaskDelete(oParam).then((res) => {
if (res.code == "200") {
this.$message.success("删除成功!");
// 判断子评论与父评论的调用刷新
if (val.replyId) {
this.handleChange(parent);
} else {
this.getDataList();
}
}
});
})
.catch(() => {
this.$message.info("已取消删除!");
});
},
//回复
replyComment(val, parentData) {
// console.log("🚀 ~ replyComment ~ val:", val);
// console.log("🚀 ~ replyComment ~ parentData:", parentData);
this.CancelBtn = true;
this.showBtn = false;
this.replyBtn = true;
this.row = 4;
this.infoData = val;
this.parentData = parentData;
//获取滚动条的高度
this.$nextTick(() => {
const el = this.$refs.discussBody;
el.scrollTop = el.scrollHeight - el.clientHeight;
});
},
// 回复消息请求
async replyInfo() {
let oParam = {
messageInfo: this.news,
replyId: this.infoData.id
};
await ApiTaskReply(oParam).then((res) => {
if (res.code == "200") {
this.news = "";
this.values = "";
this.row = 1;
this.replyBtn = false;
this.CancelBtn = false;
this.$message.success("评论成功!");
// console.log(222, this.infoData, this.parentData);
// 判断子评论与父评论的调用刷新
if (this.infoData.replyId) {
this.handleChange(this.parentData);
} else {
this.getDataList();
}
this.infoData = {};
}
});
},
//提交
async onSubmit() {
this.infoData = {};
this.CancelBtn = true;
this.replyBtn = false;
if (!this.news) {
this.$message.error("请输入内容");
return;
}
let oParam = {
messageInfo: this.news,
proId: this.Infotask.affiliatedProject,
moduleId: this.Infotask.id
};
await ApiBugcreate(oParam).then((res) => {
if (res.code == "200") {
this.getDataList();
this.news = "";
this.values = "";
this.showBtn = false;
this.CancelBtn = false;
this.row = 1;
}
});
},
// 取消
Cancel() {
this.infoData = {};
this.news = "";
this.values = "";
this.showBtn = false;
this.replyBtn = false;
this.CancelBtn = false;
this.row = 1;
},
//获取回复内容
async handleChange(val, active) {
if (active !== undefined) {
this.comments[val.id].active = active;
}
// 判断没有值时收起时不触发接口
if (active === "") {
return;
}
this.Expandcomment = [];
let oParam = {
moduleType: "bug",
proId: this.Infotask.affiliatedProject,
moduleId: this.Infotask.id,
replyId: val.id
};
// console.log(444, this.comments, val.id, this.comments[val.id]);
await ApiqueryAllmodule(oParam).then((res) => {
if (res.code == "200") {
this.comments[val.id].list = res.rows;
// this.$set(this, "Expandcomment", res.rows);
// this.Expandcomment = res.rows;
}
// console.log(res, "获取回复内容评论列表");
});
},
//分页
handleCurrentChange(val) {
this.requestStr.page = val;
this.getDataList();
},
//每页
handleSizeChange(val) {
this.requestStr.size = val;
this.getDataList();
}
},
components: {
InputText: () => import("@/views/components/taskDetails/input-text.vue") //文本输入组件
}
};
</script>
<style lang="scss" scoped>
::v-deep .el-collapse-item__content {
padding-bottom: 0;
}
::v-deep .el-pagination .el-select .el-input .el-input__inner {
padding-right: 21px;
border-radius: 3px;
}
// 更多回复的折叠面板颜色
::v-deep .el-collapse-item__wrap {
background-color: #f2f2f2;
border-radius: 8px;
margin-top: 3px;
}
// 更多回复的折叠面板内容颜色
::v-deep .el-collapse-item__header {
border-radius: 8px;
background-color: #f2f2f2;
color: #807b7b;
}
// 选择多少页的选择项
::v-deep .el-pagination .el-select .el-input {
width: 79px;
/* margin: 0 5px; */
}
//分页页码字
::v-deep .el-pager li {
min-width: 26px;
}
//分页右边箭头
::v-deep .el-pagination .btn-next {
padding-left: 0px;
}
//分页左边箭头
::v-deep .el-pagination .btn-prev {
padding-right: 0px;
}
::v-deep .el-collapse {
border: none;
// border-top: 1px solid #ebeef5;
// border-bottom: 1px solid #ebeef5;
}
.discuss {
width: 100%;
height: 100%;
overflow-y: hidden;
display: flex;
flex-direction: column;
// position: relative;
// height: calc(100% - 160px);
// overflow-y: auto;
.discuss-body-wrap {
flex: 1;
min-height: 0;
overflow-y: auto;
//border: 1px solid #1f2329;
// position: relative;
// overflow: auto;
// height: calc(100% - 160px);
}
// .discuss-content:hover {
// border-radius: 5px;
// background-color: #eaeced; /* 设置悬停时的背景颜色 */
// }
.discuss-content:hover .content-btn {
display: block !important;
}
::v-deep.el-divider--horizontal {
margin: 3px 0;
}
.discuss-content {
// width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
.content-top {
display: flex;
align-items: center;
.avatar {
width: 32px;
height: 32px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
color: #fff;
font-size: 12px;
background-color: #56abfb;
}
.comment_detail {
width: 305px;
color: #1f2329;
font-size: 14px;
margin-left: 10px;
.content-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 3px;
.nickNamerole {
margin-right: 6px;
color: #8f9a9e;
.nickName {
color: #1f2329;
font-size: 15px;
}
}
.time {
margin-left: 4px;
color: #8f9a9e;
font-size: 12px;
}
}
.message {
font-size: 13px;
letter-spacing: 2px;
color: #666666;
// word-break: break-all;
}
}
}
.content-btn {
width: 36px;
display: none;
}
}
.discuss-input {
width: 345px;
bottom: 50px;
box-sizing: border-box;
// position: absolute;
// height: 200px;
.title {
display: flex;
align-items: center;
justify-content: flex-start;
// overflow: hidden; /* 超出部分隐藏 */
// text-overflow: ellipsis; /* 显示省略号 */
// white-space: nowrap; /* 防止文本换行 */
padding: 0 3px;
margin-bottom: 0;
color: #8f9a9e;
width: 345px;
height: 30px;
line-height: 30px;
border-radius: 6px;
border: 1px solid #56abfb;
border-bottom: 0;
.text {
margin-right: 9px;
}
.title-nickName {
color: #1f2329;
font-size: 15px;
}
.title-data {
letter-spacing: 2px;
.title-info {
color: #1f2329;
font-size: 15px;
}
}
}
.foot-btn {
margin-top: 8px;
float: right;
}
}
}
</style>
效果图:
推荐阅读:
扫描二维码,在手机上阅读