330 lines
7.4 KiB
Vue
330 lines
7.4 KiB
Vue
<template>
|
||
<div class="comment-content">
|
||
<div class="comment-title">
|
||
Comment
|
||
<span class="little-text">({{commentList.length}} comments)</span>
|
||
</div>
|
||
<!--写评论-->
|
||
<div class="write-comment-box card">
|
||
<div class="flex-between-center" style="margin-bottom: 30px">
|
||
<div class="flex-1">
|
||
<h2 class="content-title">Would you recommend Skywork?</h2>
|
||
<div class="rate-box flex-between-center">
|
||
<div class="flex items-center">
|
||
<Rate v-model="rate" />
|
||
<span style="margin-left: 30px; display: block">Full score: 5 points</span>
|
||
</div>
|
||
<div class="flex items-center" style="gap: 16px" v-if="alarmText">
|
||
<img src="/logo/icon_alarm.png" alt="" style="width: 16px; height: 16px;" />
|
||
<p style="color: #CD0E4AFF">{{ alarmText }}</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="comment-avatar flex-center">
|
||
<img src="/logo/logo-rect.png" alt="" />
|
||
</div>
|
||
</div>
|
||
<!--评论输入框-->
|
||
<el-input
|
||
type="textarea"
|
||
placeholder="Please express your opinions"
|
||
v-model="commentText"
|
||
:maxlength="1000"
|
||
>
|
||
</el-input>
|
||
<div class="information-container flex-between-center">
|
||
<el-input v-model="nickName" placeholder="NickName" :maxlength="50" />
|
||
<el-input v-model="email" placeholder="Email" :maxlength="50" />
|
||
</div>
|
||
<div class="submit-button flex-center" @click="submitComment">
|
||
<span>Submit</span>
|
||
<img src="/ToolDetail/icon_arrow.png" alt="" />
|
||
</div>
|
||
</div>
|
||
<!--评论列表-->
|
||
<div class="comment-list card">
|
||
<div class="list-header flex-between-center">
|
||
<h2 class="content-title">All comments <span class="little-text">({{commentList.length}} comments)</span></h2>
|
||
<div class="more pointer" v-if="!checkMore" @click="checkMore = true">
|
||
View more<i class="el-icon-arrow-right"></i>
|
||
</div>
|
||
</div>
|
||
<div class="comment-list-wrap">
|
||
<CommentItem v-for="(it, index) in filterList" :key="index" :item="it" />
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<script>
|
||
import CommentItem from "@/pages/ToolDetail/components/CommentItem.vue";
|
||
import Rate from "@/components/Rate.vue";
|
||
|
||
export default {
|
||
components: {
|
||
CommentItem,
|
||
Rate,
|
||
},
|
||
props: {
|
||
commentType: {
|
||
type: String,
|
||
default: 'tool',
|
||
},
|
||
id: {
|
||
type: Number,
|
||
default: 0,
|
||
},
|
||
},
|
||
data() {
|
||
return {
|
||
commentText: '',
|
||
nickName: '',
|
||
email: '',
|
||
rate: 0,
|
||
commentList: [],
|
||
checkMore: false,
|
||
alarmText: '',
|
||
}
|
||
},
|
||
methods: {
|
||
// 获取评论列表
|
||
async getCommentListData() {
|
||
if (this.id) {
|
||
const params = this.commentType === 'tool' ? {toolId: this.id} : {articleId: this.id};
|
||
const {data: res} = await this.$api.comment.getToolCommentList(params);
|
||
const {code, data} = res;
|
||
if (code === 0 && data.list && data.list instanceof Array) {
|
||
this.commentList = [...data.list];
|
||
// 向父组件传递评论数量
|
||
this.$emit('update:commentCount', this.commentList.length);
|
||
} else {
|
||
// 即使没有数据也更新评论数量为0
|
||
this.$emit('update:commentCount', 0);
|
||
}
|
||
}
|
||
},
|
||
// 验证昵称
|
||
validateNickname() {
|
||
if (!this.nickName) {
|
||
this.alarmText = 'Please enter your nickname';
|
||
return false;
|
||
} else if (this.nickName.length >= 50) {
|
||
this.alarmText = 'Nickname should not exceed 50 characters';
|
||
return false;
|
||
}
|
||
return true;
|
||
},
|
||
|
||
// 验证邮箱
|
||
validateEmail() {
|
||
if (!this.email) {
|
||
this.alarmText = 'Please enter your email';
|
||
return false;
|
||
}
|
||
|
||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||
if (!emailRegex.test(this.email)) {
|
||
this.alarmText = 'Please fill in the correct email address';
|
||
return false;
|
||
}
|
||
|
||
if (this.email.length >= 50) {
|
||
this.alarmText = 'Email should not exceed 50 characters';
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
},
|
||
|
||
// 验证评论内容词数
|
||
validateComment() {
|
||
if (!this.commentText) {
|
||
this.alarmText = 'Please enter your comment';
|
||
return false;
|
||
}
|
||
|
||
const wordCount = this.commentText.length;
|
||
if (wordCount > 1000) {
|
||
this.alarmText = 'Comment should not exceed 1000 words';
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
},
|
||
// 提交评论
|
||
async submitComment() {
|
||
if (!this.id) {
|
||
return false;
|
||
}
|
||
// 清除之前的警告信息
|
||
this.alarmText = '';
|
||
|
||
// 验证各项输入
|
||
const isCommentValid = this.validateComment();
|
||
const isNicknameValid = this.validateNickname();
|
||
const isEmailValid = this.validateEmail();
|
||
|
||
if (!isCommentValid || !isNicknameValid || !isEmailValid) {
|
||
return;
|
||
}
|
||
|
||
const params = {
|
||
content: this.commentText,
|
||
username: this.nickName,
|
||
email: this.email,
|
||
rating: this.rate,
|
||
};
|
||
|
||
this.commentType === 'tool' ? params.toolId = this.id : params.articleId = this.id;
|
||
const {data: res} = await this.$api.comment.addToolComment(params);
|
||
const {code} = res;
|
||
if (code === 0) {
|
||
this.$message.success('Comment submitted successfully');
|
||
this.rate = null;
|
||
this.commentText = '';
|
||
this.nickName = '';
|
||
this.email = '';
|
||
await this.getCommentListData();
|
||
} else {
|
||
this.$message.error('Comment submission failed');
|
||
}
|
||
}
|
||
},
|
||
watch: {
|
||
id: {
|
||
handler(newVal) {
|
||
if (newVal) {
|
||
this.getCommentListData();
|
||
}
|
||
},
|
||
immediate: true
|
||
}
|
||
},
|
||
computed: {
|
||
filterList() {
|
||
if (!this.checkMore) {
|
||
return this.commentList.slice(0, 5);
|
||
} else {
|
||
return this.commentList;
|
||
}
|
||
}
|
||
},
|
||
}
|
||
</script>
|
||
|
||
<style scoped lang="scss">
|
||
.card {
|
||
background-color: #fff;
|
||
border-radius: 12px;
|
||
padding: 30px;
|
||
box-shadow: 0 10px 30px 0 #0000000d;
|
||
}
|
||
.comment-content {
|
||
padding-top: 50px;
|
||
.comment-title {
|
||
font-size: 30px;
|
||
font-weight: 600;
|
||
margin-bottom: 30px;
|
||
font-family: 'Poppins-SemiBold', serif;
|
||
color: #1E293B;
|
||
display: flex;
|
||
align-items: center;
|
||
&::before {
|
||
content: '';
|
||
display: inline-block;
|
||
width: 6px;
|
||
height: 26px;
|
||
background: $header-backgroungd;
|
||
margin-right: 8px;
|
||
border-radius: 0 6px 6px 0;
|
||
}
|
||
}
|
||
.write-comment-box {
|
||
.rate-box {
|
||
margin-top: 14px;
|
||
font-family: 'Poppins-Regular', serif;
|
||
color: #E2E8F0;
|
||
}
|
||
::v-deep .el-textarea {
|
||
.el-textarea__inner {
|
||
border-color: #E2E8F0 !important;
|
||
padding: 30px !important;
|
||
height: 320px !important;
|
||
}
|
||
}
|
||
.information-container {
|
||
margin-top: 20px;
|
||
gap: 20px;
|
||
::v-deep .el-input {
|
||
.el-input__inner {
|
||
border-color: #E2E8F0 !important;
|
||
}
|
||
}
|
||
}
|
||
.submit-button {
|
||
padding: 8px 38px;
|
||
background: $header-backgroungd;
|
||
border-radius: 12px;
|
||
gap: 4px;
|
||
margin-top: 30px;
|
||
color: #fff;
|
||
font-size: 18px;
|
||
font-family: 'Poppins-Medium', serif;
|
||
width: fit-content;
|
||
margin-left: auto;
|
||
cursor: pointer;
|
||
img {
|
||
width: 24px;
|
||
height: 24px;
|
||
}
|
||
&:active {
|
||
opacity: 0.8;
|
||
}
|
||
}
|
||
.comment-avatar {
|
||
width: 50px;
|
||
height: 50px;
|
||
border-radius: 50%;
|
||
border: 1px solid #E2E8F0;
|
||
margin-left: 24px;
|
||
img {
|
||
width: 24px;
|
||
height: 24px;
|
||
}
|
||
}
|
||
}
|
||
.comment-list {
|
||
margin-top: 20px;
|
||
.list-header {
|
||
margin-top: 30px;
|
||
margin-bottom: 20px;
|
||
}
|
||
.comment-list-wrap {
|
||
padding-right: 36px;
|
||
}
|
||
}
|
||
}
|
||
.little-text {
|
||
font-size: 14px;
|
||
font-family: 'Poppins-Regular', serif;
|
||
color: #64748B;
|
||
vertical-align: middle;
|
||
margin-left: 8px;
|
||
}
|
||
.content-title {
|
||
font-size: 24px;
|
||
font-weight: 600;
|
||
font-family: 'Poppins-SemiBold', serif;
|
||
color: #1E293B;
|
||
line-height: 24px;
|
||
margin: 0;
|
||
}
|
||
.more {
|
||
display: block;
|
||
text-align: right;
|
||
color: $grey-color;
|
||
font-size: $mid-font-size;
|
||
font-family: 'Poppins-Regular', serif;
|
||
}
|
||
</style>
|