2025-01-20 19:08:21 +08:00
|
|
|
|
<template>
|
|
|
|
|
<div class="answer-discuss">
|
|
|
|
|
<div class="header flexacenter">
|
|
|
|
|
回答&讨论
|
2025-01-23 19:10:04 +08:00
|
|
|
|
<span class="num">{{ commentTotalCount || "" }}</span>
|
2025-01-20 19:08:21 +08:00
|
|
|
|
</div>
|
|
|
|
|
<div class="input-box">
|
|
|
|
|
<div class="top flexflex">
|
2025-01-23 19:10:04 +08:00
|
|
|
|
<img class="avatar" v-if="user.avatar" :src="user.avatar" />
|
|
|
|
|
<textarea class="input-textarea flex1" maxlength="500" v-model="inputTextarea" @input="autoResize" @paste="handleInputPaste" placeholder="说说你的看法…"></textarea>
|
2025-01-20 19:08:21 +08:00
|
|
|
|
</div>
|
|
|
|
|
<div class="picture-box" v-if="picture.url">
|
|
|
|
|
<div class="picture">
|
|
|
|
|
<img class="close" @click="closeFileUpload()" src="/img/close-icon.png" />
|
2025-01-21 19:06:13 +08:00
|
|
|
|
<img class="img" @click="handleAnswerText" :src="picture.base64 || picture.url" />
|
2025-01-20 19:08:21 +08:00
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="bottom flexacenter">
|
|
|
|
|
<div class="operate flexacenter">
|
|
|
|
|
<div class="item" :class="{ 'pitch': emojiState }">
|
|
|
|
|
<img class="icon" src="/img/smiling-face.png" @click="openEmoji()" alt="" />
|
|
|
|
|
<div class="emoji-box">
|
|
|
|
|
<div class="emoji-icon" v-for="item in emojiData" :key="item" @click="selectEmoji(item)">{{ item }}</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="item flexacenter">
|
|
|
|
|
<input class="file" type="file" @change="handleFileUpload($event)" accept=".png, .jpg, .jpeg" />
|
|
|
|
|
<img class="icon" src="/img/picture-icon.png" alt="" />
|
|
|
|
|
<span class="file-hint">最多可上传1张图片,支持在输入框中直接粘贴图片。</span>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="btn" @click="submitAnswerComments()">发送</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="comments-box">
|
|
|
|
|
<div class="comments-item" v-for="(item, index) in commentList" :key="index">
|
|
|
|
|
<div class="comments-header flexacenter">
|
|
|
|
|
<div class="comments-header-left flexacenter">
|
2025-01-23 19:10:04 +08:00
|
|
|
|
<img class="comments-avatar" @click="openUserInfo(index)" :src="item['avatar']" />
|
|
|
|
|
<div class="comments-username" @click="openUserInfo(index)">{{ item["nickname"] }}</div>
|
2025-01-20 19:08:21 +08:00
|
|
|
|
<div class="comments-time">{{ handleDate(item["timestamp"]) }}</div>
|
|
|
|
|
<div class="comments-identity" v-if="item['isauthor'] == 1">提问者</div>
|
|
|
|
|
<div class="avatar-box flexflex" v-if="item['avatarState']">
|
|
|
|
|
<a class="avatar-item flexcenter" target="_blank" @click.prevent="sendMessage(item['uin'])">
|
|
|
|
|
<img class="avatar-icon" src="@/img/send-messages-icon.png" />
|
|
|
|
|
发送信息
|
|
|
|
|
</a>
|
|
|
|
|
<a class="avatar-item flexcenter" target="_blank" @click.prevent="TAHomePage(item['uin'])">
|
|
|
|
|
<img class="avatar-icon" src="@/img/homepage-icon.png" />
|
|
|
|
|
TA的主页
|
|
|
|
|
</a>
|
2025-01-23 19:10:04 +08:00
|
|
|
|
<div class="avatar-mask" @click="closeUserInfo(index)"></div>
|
2025-01-20 19:08:21 +08:00
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="comments-header-right flexacenter">
|
|
|
|
|
<div class="menu-box flexacenter" @click="openMenuState(index)">
|
|
|
|
|
<img class="menu-icon" src="/img/menu-icon-gray.svg" />
|
|
|
|
|
<div class="report-box flexcenter">举报</div>
|
|
|
|
|
</div>
|
|
|
|
|
<img class="comment-icon" @click="openAnswerCommentsChild(index)" src="/img/comment-icon-gray.svg" />
|
|
|
|
|
<div class="flexacenter like-box" @click="operateAnswerCommentsLike(item.token, index)">
|
|
|
|
|
<img class="like-icon" v-if="item['islike'] == 0" src="/img/like-icon-gray.png" />
|
|
|
|
|
<img class="like-icon" v-else src="/img/like-icon-colours.png" />
|
|
|
|
|
<div class="like-quantity">{{ item["likenum"] || "" }}</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="comments-content">
|
|
|
|
|
<div class="comments-text">{{ item["content"] }}</div>
|
2025-01-21 19:06:13 +08:00
|
|
|
|
<img class="comments-img" @click="handleAnswerText" :src="item.image?.base64 || item.image?.url" v-if="item.image?.url" />
|
2025-01-20 19:08:21 +08:00
|
|
|
|
<div class="input-box" v-if="item['childState']">
|
|
|
|
|
<img class="cross" @click="closeAnswerCommentsChild(index)" src="/img/cross-icon.png" />
|
|
|
|
|
<div class="top flexflex">
|
2025-01-23 19:10:04 +08:00
|
|
|
|
<textarea class="input-textarea flex1" maxlength="500" placeholder="说说你的看法…" v-model="item['commentInput']" @input="autoResize" @paste="handleInputPaste($event, index)"></textarea>
|
2025-01-20 19:08:21 +08:00
|
|
|
|
</div>
|
|
|
|
|
<div class="picture-box" v-if="item.picture?.url">
|
|
|
|
|
<div class="picture">
|
|
|
|
|
<img class="close" @click="closeFileUpload(index)" src="/img/close-icon.png" />
|
2025-01-21 19:06:13 +08:00
|
|
|
|
<img class="img" @click="handleAnswerText" :src="item.picture.base64 || item.picture.url" />
|
2025-01-20 19:08:21 +08:00
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="bottom flexacenter">
|
|
|
|
|
<div class="operate flexacenter">
|
|
|
|
|
<div class="item" :class="{ 'pitch': item.emojiState }">
|
|
|
|
|
<img class="icon" src="/img/smiling-face.png" @click="openEmoji(index)" alt="" />
|
|
|
|
|
<div class="emoji-box">
|
|
|
|
|
<div class="emoji-icon" v-for="item in emojiData" :key="item" @click="selectEmoji(item, index)">{{ item }}</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="item flexacenter">
|
|
|
|
|
<input class="file" type="file" @change="handleFileUpload($event, index)" accept=".png, .jpg, .jpeg" />
|
|
|
|
|
<img class="icon" src="/img/picture-icon.png" alt="" />
|
|
|
|
|
<span class="file-hint">最多可上传1张图片,支持在输入框中直接粘贴图片。</span>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="btn" @click="submitAnswerComments(index)">发送</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="child-comments" v-if="item['child'].length != 0">
|
|
|
|
|
<div class="comments-item" v-for="(ite, i) in item['child']" :key="ite.id">
|
|
|
|
|
<div class="comments-header flexacenter">
|
|
|
|
|
<div class="comments-header-left flexacenter">
|
2025-01-23 19:10:04 +08:00
|
|
|
|
<img class="comments-avatar" @click="openUserInfo(index, i)" :src="ite['avatar']" />
|
|
|
|
|
<div class="comments-username" @click="openUserInfo(index, i)">{{ ite["nickname"] }}</div>
|
2025-01-20 19:08:21 +08:00
|
|
|
|
<div class="comments-time">{{ handleDate(ite["timestamp"]) }}</div>
|
2025-01-23 19:10:04 +08:00
|
|
|
|
<!-- <div class="comments-identity" v-if="ite['questioner'] == 1">提问者</div> -->
|
|
|
|
|
<!-- <div class="comments-identity" v-else-if="ite['isauthor'] == 1">回答者</div> -->
|
|
|
|
|
<div class="comments-identity" v-if="ite['isauthor'] == 1">提问者</div>
|
2025-01-20 19:08:21 +08:00
|
|
|
|
<div class="avatar-box flexflex" v-if="ite['avatarState']">
|
|
|
|
|
<a class="avatar-item flexcenter" target="_blank">
|
2025-02-06 12:20:22 +08:00
|
|
|
|
<img class="avatar-icon" src="@/img/send-messages-icon.png" @click.prevent="sendMessage(ite['uin'])" />
|
2025-01-20 19:08:21 +08:00
|
|
|
|
发送信息
|
|
|
|
|
</a>
|
2025-02-06 12:20:22 +08:00
|
|
|
|
<a class="avatar-item flexcenter" target="_blank" @click.prevent="TAHomePage(ite['uin'])">
|
2025-01-20 19:08:21 +08:00
|
|
|
|
<img class="avatar-icon" src="@/img/homepage-icon.png" />
|
|
|
|
|
TA的主页
|
|
|
|
|
</a>
|
2025-01-23 19:10:04 +08:00
|
|
|
|
<div class="avatar-mask" @click="closeUserInfo(index, i)"></div>
|
2025-01-20 19:08:21 +08:00
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="comments-header-right flexacenter">
|
|
|
|
|
<div class="menu-box flexacenter">
|
|
|
|
|
<img class="menu-icon" src="/img/menu-icon-gray.svg" />
|
|
|
|
|
<div class="report-box flexcenter">举报</div>
|
|
|
|
|
</div>
|
|
|
|
|
<img class="comment-icon" @click="openAnswerCommentsChild(index, i)" src="/img/comment-icon-gray.svg" />
|
|
|
|
|
<div class="flexacenter like-box" @click="operateAnswerCommentsLike(ite.token, index, i)">
|
|
|
|
|
<img class="like-icon" v-if="ite['islike'] == 0" src="/img/like-icon-gray.png" />
|
|
|
|
|
<img class="like-icon" v-else src="/img/like-icon-colours.png" />
|
|
|
|
|
<div class="like-quantity">{{ ite["likenum"] || "" }}</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="comments-content">
|
|
|
|
|
<div class="comments-text">
|
2025-01-21 19:06:13 +08:00
|
|
|
|
<!-- <div class="comments-reply" v-if="JSON.stringify(ite['reply']) != '[]'">@{{ ite["reply"]["nickname"] }}</div> -->
|
|
|
|
|
<div class="comments-reply" v-if="ite?.reply?.nickname">@{{ ite["reply"]["nickname"] }}</div>
|
2025-01-20 19:08:21 +08:00
|
|
|
|
{{ ite["content"] }}
|
|
|
|
|
</div>
|
2025-01-21 19:06:13 +08:00
|
|
|
|
<img class="comments-img" @click="handleAnswerText" :src="ite.image?.base64 || ite.image?.url" v-if="ite.image?.url" />
|
|
|
|
|
<div class="input-box" v-if="ite['childState']">
|
|
|
|
|
<img class="cross" @click="closeAnswerCommentsChild(index)" src="/img/cross-icon.png" />
|
|
|
|
|
<div class="top flexflex">
|
2025-01-23 19:10:04 +08:00
|
|
|
|
<textarea class="input-textarea flex1" maxlength="500" v-model="ite['commentInput']" :placeholder="'回复“' + ite['nickname'] + '”:'" @input="autoResize" @paste="handleInputPaste($event, index, i)"></textarea>
|
2025-01-21 19:06:13 +08:00
|
|
|
|
</div>
|
|
|
|
|
<div class="picture-box" v-if="ite.picture?.url">
|
|
|
|
|
<div class="picture">
|
|
|
|
|
<img class="close" @click="closeFileUpload(index, i)" src="/img/close-icon.png" />
|
|
|
|
|
<img class="img" @click="handleAnswerText" :src="ite.picture.base64 || ite.picture.url" />
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="bottom flexacenter">
|
|
|
|
|
<div class="operate flexacenter">
|
|
|
|
|
<div class="item" :class="{ 'pitch': ite.emojiState }">
|
|
|
|
|
<img class="icon" src="/img/smiling-face.png" @click="openEmoji(index, i)" alt="" />
|
|
|
|
|
<div class="emoji-box">
|
|
|
|
|
<div class="emoji-icon" v-for="item in emojiData" :key="item" @click="selectEmoji(item, index, i)">{{ item }}</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="item flexacenter">
|
|
|
|
|
<input class="file" type="file" @change="handleFileUpload($event, index, i)" accept=".png, .jpg, .jpeg" />
|
|
|
|
|
<img class="icon" src="/img/picture-icon.png" alt="" />
|
|
|
|
|
<span class="file-hint">最多可上传1张图片,支持在输入框中直接粘贴图片。</span>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="btn" @click="submitAnswerComments(index, i)">发送</div>
|
2025-01-20 19:08:21 +08:00
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
2025-01-21 19:06:13 +08:00
|
|
|
|
<div class="comments-also flexacenter" v-if="item['childnum'] > item['child'].length" @click="alsoCommentsData(index, i)">
|
|
|
|
|
<div class>还有{{ item["childnum"] - item.child.length }}条回复</div>
|
2025-01-20 19:08:21 +08:00
|
|
|
|
<img class="also-icon" src="/img/arrow-circular-gray.png" />
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
<script setup>
|
2025-02-06 12:20:22 +08:00
|
|
|
|
import { tr } from "element-plus/es/locale"
|
|
|
|
|
|
2025-01-20 19:08:21 +08:00
|
|
|
|
const props = defineProps({
|
|
|
|
|
token: String,
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
onMounted(() => {
|
2025-01-21 19:06:13 +08:00
|
|
|
|
// getComment()
|
2025-01-20 19:08:21 +08:00
|
|
|
|
})
|
|
|
|
|
|
2025-02-06 12:20:22 +08:00
|
|
|
|
const aaa = inject("TAHomePag")
|
|
|
|
|
console.log("aaa", aaa)
|
|
|
|
|
|
2025-01-20 19:08:21 +08:00
|
|
|
|
const $ajax = inject("$ajax")
|
|
|
|
|
const $ajaxGET = inject("$ajaxGET")
|
|
|
|
|
const detailsToken = inject("detailsToken")
|
|
|
|
|
const handleDate = inject("handleDate")
|
|
|
|
|
const isNeedLogin = inject("isNeedLogin")
|
|
|
|
|
const handleMsg = inject("handleMsg")
|
|
|
|
|
const uploadImg = inject("uploadImg")
|
2025-01-21 19:06:13 +08:00
|
|
|
|
const handleAnswerText = inject("handleAnswerText")
|
|
|
|
|
const emojiMaskState = inject("emojiMaskState")
|
2025-01-23 19:10:04 +08:00
|
|
|
|
const user = inject("user")
|
2025-02-06 12:20:22 +08:00
|
|
|
|
const detailLoading = inject("detailLoading")
|
|
|
|
|
|
|
|
|
|
// 点击ta的主页
|
|
|
|
|
const TAHomePage = uin => {
|
|
|
|
|
redirectToExternalWebsite(`https://bbs.gter.net/home.php?mod=space&uid=${uin}`)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 点击发送信息
|
|
|
|
|
const sendMessage = uin => {
|
|
|
|
|
if (uin && typeof messagePrivateItem == "function") {
|
|
|
|
|
messagePrivateItem({ uin: uin })
|
|
|
|
|
return
|
|
|
|
|
} else redirectToExternalWebsite(`https://bbs.gter.net/home.php?mod=space&showmsg=1&uid=${uin}`)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 跳转 url
|
|
|
|
|
const redirectToExternalWebsite = url => {
|
|
|
|
|
const link = document.createElement("a")
|
|
|
|
|
link.href = url
|
|
|
|
|
link.target = "_blank"
|
|
|
|
|
link.click()
|
|
|
|
|
}
|
2025-01-20 19:08:21 +08:00
|
|
|
|
|
|
|
|
|
const commentList = ref([])
|
|
|
|
|
let commentCount = ref(0)
|
|
|
|
|
let commentTotalCount = ref(0)
|
|
|
|
|
let commentPage = ref(1)
|
|
|
|
|
let isgetCommentSate = false // 请求评论状态
|
|
|
|
|
let alreadyCommentIdList = []
|
|
|
|
|
|
|
|
|
|
const getComment = () => {
|
|
|
|
|
if (commentPage.value == 0 || isgetCommentSate) return
|
|
|
|
|
isgetCommentSate = true
|
|
|
|
|
$ajax("/api/comment/lists", {
|
|
|
|
|
token: detailsToken.value,
|
|
|
|
|
page: commentPage.value,
|
2025-01-21 19:06:13 +08:00
|
|
|
|
limit: 1500,
|
2025-01-20 19:08:21 +08:00
|
|
|
|
})
|
|
|
|
|
.then(res => {
|
|
|
|
|
if (res.code != 200) return
|
|
|
|
|
let data = res.data
|
|
|
|
|
|
|
|
|
|
data.data.forEach((element, index) => {
|
|
|
|
|
element["isReplyBoxShow"] = 0
|
|
|
|
|
// element.timestamp = util.timeformat(element.timestamp, 2)
|
|
|
|
|
if (element.child.length > 0) {
|
|
|
|
|
element.child.forEach(el => {
|
|
|
|
|
// el.timestamp = util.timeformat(el.timestamp, 2)
|
|
|
|
|
el["isReplyBoxShow"] = 0
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
if (commentPage.value > 1) {
|
|
|
|
|
let alreadyCommentIdList = alreadyCommentIdList
|
|
|
|
|
for (let index = 0; index < data.data.length; index++) {
|
|
|
|
|
if (alreadyCommentIdList.includes(data.data[index].id)) {
|
|
|
|
|
data.data.splice(index, 1)
|
|
|
|
|
index--
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
commentList.value = commentList.value.concat(data.data)
|
2025-01-21 19:06:13 +08:00
|
|
|
|
// console.log("commentList", commentList.value)
|
2025-01-20 19:08:21 +08:00
|
|
|
|
|
|
|
|
|
commentCount.value = data.count
|
|
|
|
|
commentTotalCount.value = data.comments
|
|
|
|
|
commentPage.value = data.count > commentList.length ? commentPage.value + 1 : 0
|
|
|
|
|
|
|
|
|
|
// console.log("commentList", commentList)
|
|
|
|
|
// this.setData({
|
|
|
|
|
// commentList,
|
|
|
|
|
// commentCount: data.count,
|
|
|
|
|
// commentTotalCount: data.comments,
|
|
|
|
|
// commentPage: data.count > commentList.length ? this.data.commentPage + 1 : 0,
|
|
|
|
|
// })
|
|
|
|
|
})
|
|
|
|
|
.finally(() => {
|
|
|
|
|
isgetCommentSate = false
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-05 18:41:37 +08:00
|
|
|
|
let picture = ref({})
|
|
|
|
|
|
2025-01-21 19:06:13 +08:00
|
|
|
|
// 监听 detailsToken 的变化
|
|
|
|
|
watch(
|
|
|
|
|
detailsToken,
|
|
|
|
|
(newValue, oldValue) => {
|
|
|
|
|
if (newValue !== oldValue) {
|
|
|
|
|
commentPage.value = 1
|
|
|
|
|
commentList.value = []
|
2025-02-05 18:41:37 +08:00
|
|
|
|
picture.value = {}
|
2025-01-21 19:06:13 +08:00
|
|
|
|
getComment()
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
{ immediate: true }
|
|
|
|
|
)
|
|
|
|
|
|
2025-01-23 19:10:04 +08:00
|
|
|
|
const maxSize = 20 * 1024 * 1024 // 20MB
|
|
|
|
|
|
2025-01-20 19:08:21 +08:00
|
|
|
|
const handleFileUpload = (event, index, i) => {
|
|
|
|
|
closeEmoji()
|
|
|
|
|
const file = event.target.files[0] // 获取选择的文件
|
|
|
|
|
|
2025-01-23 19:10:04 +08:00
|
|
|
|
if (!file) return
|
2025-01-20 19:08:21 +08:00
|
|
|
|
|
2025-01-23 19:10:04 +08:00
|
|
|
|
if (file.size > maxSize) {
|
|
|
|
|
handleMsg("error", "文件大小不能超过 20MB")
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const reader = new FileReader()
|
|
|
|
|
reader.onload = e => {
|
|
|
|
|
const base64 = e.target.result
|
|
|
|
|
uploadImg(base64).then(res => {
|
|
|
|
|
const obj = {
|
|
|
|
|
base64,
|
|
|
|
|
...res,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (i != undefined) commentList.value[index].child[i]["picture"] = obj
|
|
|
|
|
else if (index != undefined) commentList.value[index]["picture"] = obj
|
|
|
|
|
else picture.value = obj
|
|
|
|
|
|
|
|
|
|
handleMsg("success", "上传成功")
|
|
|
|
|
})
|
2025-01-20 19:08:21 +08:00
|
|
|
|
}
|
2025-01-23 19:10:04 +08:00
|
|
|
|
reader.readAsDataURL(file)
|
2025-01-20 19:08:21 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 删除上传的图片
|
|
|
|
|
const closeFileUpload = (index, i) => {
|
|
|
|
|
if (i != undefined) commentList.value[index].child[i]["picture"] = {}
|
|
|
|
|
else if (index != undefined) commentList.value[index]["picture"] = {}
|
|
|
|
|
else picture.value = {}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
let emojiState = ref(false)
|
|
|
|
|
|
|
|
|
|
const emojiData = ["😀", "😁", "😆", "😅", "😂", "😉", "😍", "🥰", "😋", "😜", "🤪", "😎", "🤩", "🥳", "😔", "🙁", "😭", "😡", "😳", "🤗", "🤔", "🤭", "🤫", "😯", "😵", "🙄", "🥴", "🤢", "🤑", "🤠", "👌", "✌️", "🤟", "🤘", "🤙", "👍", "👎", "✊", "👏", "🤝", "🙏", "💪", "❤️", "💔", "🌹", "🥀", "🎉", "🎁", "🧧", "🌙", "⭐", "🌍", "💌", "📬", "🚗", "🚕", "🚲", "🛵", "🚀", "🚁", "⛵", "🚢", "🍎", "🍐", "🍊", "🍉", "🍓", "🍑", "🍔", "🍟", "🍕", "🥪", "🍜", "🍡", "🍨", "🍦", "🎂", "🍰", "🍭", "🍿", "🍩", "🧃", "🍹"]
|
|
|
|
|
|
|
|
|
|
// 打开 Emoji
|
|
|
|
|
const openEmoji = (index, i) => {
|
|
|
|
|
if (i != undefined) commentList.value[index].child[i]["emojiState"] = true
|
|
|
|
|
else if (index != undefined) commentList.value[index]["emojiState"] = true
|
2025-02-05 18:41:37 +08:00
|
|
|
|
else {
|
|
|
|
|
closeEmoji()
|
|
|
|
|
closeAnswerCommentsChild()
|
|
|
|
|
emojiState.value = true
|
|
|
|
|
}
|
2025-01-20 19:08:21 +08:00
|
|
|
|
|
|
|
|
|
emojiMaskState.value = true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 关闭 Emoji
|
|
|
|
|
const closeEmoji = (index, i) => {
|
|
|
|
|
commentList.value.forEach(ele => {
|
|
|
|
|
ele["emojiState"] = false
|
|
|
|
|
if (ele["child"] && ele["child"].length != 0) {
|
|
|
|
|
ele["child"].forEach(el => {
|
|
|
|
|
el["emojiState"] = false
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
emojiState.value = false
|
|
|
|
|
emojiMaskState.value = false
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-21 19:06:13 +08:00
|
|
|
|
defineExpose({
|
|
|
|
|
closeEmoji,
|
|
|
|
|
})
|
|
|
|
|
|
2025-01-20 19:08:21 +08:00
|
|
|
|
// 选择 Emoji
|
|
|
|
|
const selectEmoji = (key, index, i) => {
|
|
|
|
|
closeEmoji()
|
|
|
|
|
if (i != undefined) {
|
2025-01-23 19:10:04 +08:00
|
|
|
|
if (!commentList.value[index]["child"][i]["commentInput"]) commentList.value[index]["child"][i]["commentInput"] = ""
|
|
|
|
|
commentList.value[index]["child"][i]["commentInput"] += key
|
2025-01-20 19:08:21 +08:00
|
|
|
|
} else if (index != undefined) {
|
2025-01-23 19:10:04 +08:00
|
|
|
|
if (!commentList.value[index]["commentInput"]) commentList.value[index]["commentInput"] = ""
|
|
|
|
|
commentList.value[index]["commentInput"] += key
|
2025-01-20 19:08:21 +08:00
|
|
|
|
} else {
|
2025-01-23 19:10:04 +08:00
|
|
|
|
inputTextarea.value += key
|
2025-01-20 19:08:21 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-23 19:10:04 +08:00
|
|
|
|
// 自动输入框增高
|
|
|
|
|
const autoResize = e => {
|
|
|
|
|
e.target.style.height = "auto" // 重置高度
|
|
|
|
|
e.target.style.height = `${e.target.scrollHeight}px` // 设置为内容高度
|
2025-01-20 19:08:21 +08:00
|
|
|
|
}
|
|
|
|
|
|
2025-01-21 19:06:13 +08:00
|
|
|
|
const handleInputPaste = (event, index, ii) => {
|
2025-01-20 19:08:21 +08:00
|
|
|
|
const items = event.clipboardData.items // 获取粘贴的内容
|
2025-01-23 19:10:04 +08:00
|
|
|
|
|
2025-01-20 19:08:21 +08:00
|
|
|
|
for (let i = 0; i < items.length; i++) {
|
|
|
|
|
const item = items[i]
|
|
|
|
|
if (item.type.startsWith("image/")) {
|
|
|
|
|
event.preventDefault()
|
|
|
|
|
const file = item.getAsFile() // 获取文件
|
2025-01-23 19:10:04 +08:00
|
|
|
|
|
|
|
|
|
if (file.size > maxSize) {
|
|
|
|
|
handleMsg("error", "文件大小不能超过 20MB")
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-20 19:08:21 +08:00
|
|
|
|
const reader = new FileReader()
|
|
|
|
|
reader.onload = e => {
|
|
|
|
|
const base64 = e.target.result
|
2025-01-23 19:10:04 +08:00
|
|
|
|
|
2025-01-20 19:08:21 +08:00
|
|
|
|
uploadImg(base64).then(res => {
|
|
|
|
|
const obj = {
|
|
|
|
|
base64,
|
|
|
|
|
...res,
|
|
|
|
|
}
|
2025-01-23 19:10:04 +08:00
|
|
|
|
if (ii != undefined) commentList.value[index].child[ii]["picture"] = obj
|
2025-01-21 19:06:13 +08:00
|
|
|
|
else if (index != undefined) commentList.value[index]["picture"] = obj
|
2025-01-20 19:08:21 +08:00
|
|
|
|
else picture.value = obj
|
|
|
|
|
handleMsg("success", "上传成功")
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
reader.readAsDataURL(file)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-23 19:10:04 +08:00
|
|
|
|
let inputTextarea = ref("")
|
2025-01-20 19:08:21 +08:00
|
|
|
|
|
|
|
|
|
// 提交回答-评论
|
|
|
|
|
const submitAnswerComments = (index, i) => {
|
|
|
|
|
if (isNeedLogin.value) {
|
|
|
|
|
goLogin()
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let content = ""
|
|
|
|
|
let parentid = null
|
|
|
|
|
let token = detailsToken.value
|
2025-01-21 19:06:13 +08:00
|
|
|
|
let image = {}
|
2025-01-20 19:08:21 +08:00
|
|
|
|
|
|
|
|
|
if (i != null) {
|
2025-01-23 19:10:04 +08:00
|
|
|
|
content = commentList.value[index]["child"][i]["commentInput"]
|
2025-01-20 19:08:21 +08:00
|
|
|
|
parentid = commentList.value[index]["child"][i]["id"]
|
2025-01-21 19:06:13 +08:00
|
|
|
|
image = commentList.value[index]["child"][i]["picture"]
|
2025-01-20 19:08:21 +08:00
|
|
|
|
} else if (index != null) {
|
2025-01-23 19:10:04 +08:00
|
|
|
|
content = commentList.value[index]["commentInput"]
|
2025-01-20 19:08:21 +08:00
|
|
|
|
parentid = commentList.value[index]["id"]
|
2025-01-21 19:06:13 +08:00
|
|
|
|
image = commentList.value[index]["picture"]
|
2025-01-20 19:08:21 +08:00
|
|
|
|
} else {
|
2025-01-23 19:10:04 +08:00
|
|
|
|
content = inputTextarea.value
|
2025-01-20 19:08:21 +08:00
|
|
|
|
image = picture.value
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-06 12:20:22 +08:00
|
|
|
|
detailLoading.value = true
|
|
|
|
|
|
2025-01-20 19:08:21 +08:00
|
|
|
|
$ajax("/api/comment/submit", {
|
|
|
|
|
content,
|
|
|
|
|
token,
|
|
|
|
|
parentid,
|
2025-01-23 19:10:04 +08:00
|
|
|
|
image: image ? { aid: image.aid, url: image.url } : null,
|
2025-02-06 12:20:22 +08:00
|
|
|
|
})
|
|
|
|
|
.then(res => {
|
|
|
|
|
if (res.code != 200) return
|
|
|
|
|
let data = res.data
|
2025-01-20 19:08:21 +08:00
|
|
|
|
|
2025-02-06 12:20:22 +08:00
|
|
|
|
if (i != null) {
|
|
|
|
|
let targetData = {
|
|
|
|
|
id: data["commentid"],
|
|
|
|
|
content,
|
|
|
|
|
isauthor: 1,
|
|
|
|
|
islike: 0,
|
|
|
|
|
likenum: 0,
|
|
|
|
|
reply: {
|
|
|
|
|
nickname: commentList.value[index]["child"][i]["nickname"],
|
|
|
|
|
},
|
|
|
|
|
...data,
|
|
|
|
|
image,
|
|
|
|
|
}
|
2025-01-20 19:08:21 +08:00
|
|
|
|
|
2025-02-06 12:20:22 +08:00
|
|
|
|
commentList.value[index]["child"].push(targetData)
|
|
|
|
|
commentList.value[index]["childnum"]++
|
|
|
|
|
} else if (index != null) {
|
|
|
|
|
let targetData = {
|
|
|
|
|
id: data["commentid"],
|
|
|
|
|
content,
|
|
|
|
|
isauthor: 1,
|
|
|
|
|
islike: 0,
|
|
|
|
|
likenum: 0,
|
|
|
|
|
reply: [],
|
|
|
|
|
...data,
|
|
|
|
|
image,
|
|
|
|
|
}
|
|
|
|
|
commentList.value[index]["child"].unshift(targetData)
|
|
|
|
|
commentList.value[index]["childnum"]++
|
|
|
|
|
} else {
|
|
|
|
|
let targetData = {
|
|
|
|
|
id: data["commentid"],
|
|
|
|
|
content,
|
|
|
|
|
isauthor: 1,
|
|
|
|
|
islike: 0,
|
|
|
|
|
likenum: 0,
|
|
|
|
|
...data,
|
|
|
|
|
child: [],
|
|
|
|
|
image,
|
|
|
|
|
}
|
|
|
|
|
commentList.value.unshift(targetData)
|
|
|
|
|
// commentCount.value++
|
|
|
|
|
inputTextarea.value = ""
|
|
|
|
|
picture.value = {}
|
2025-01-20 19:08:21 +08:00
|
|
|
|
}
|
|
|
|
|
|
2025-02-06 12:20:22 +08:00
|
|
|
|
commentTotalCount.value = data.count || 0
|
2025-01-23 19:10:04 +08:00
|
|
|
|
|
2025-02-06 12:20:22 +08:00
|
|
|
|
// targetAnswerList[index]["commentnum"] = data["count"]
|
2025-01-20 19:08:21 +08:00
|
|
|
|
|
2025-02-06 12:20:22 +08:00
|
|
|
|
closeAnswerCommentsChild()
|
2025-01-20 19:08:21 +08:00
|
|
|
|
|
2025-02-06 12:20:22 +08:00
|
|
|
|
handleMsg("success", res["message"] || "操作成功")
|
|
|
|
|
})
|
|
|
|
|
.finally(() => {
|
|
|
|
|
detailLoading.value = false
|
|
|
|
|
})
|
2025-01-20 19:08:21 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 回答-评论 点赞
|
|
|
|
|
const operateAnswerCommentsLike = (token, index, i) => {
|
|
|
|
|
if (isNeedLogin.value) {
|
|
|
|
|
goLogin()
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$ajax("/api/comment/like", {
|
|
|
|
|
token,
|
|
|
|
|
}).then(res => {
|
|
|
|
|
if (res.code != 200) return
|
|
|
|
|
let data = res.data
|
|
|
|
|
|
|
|
|
|
if (i != undefined) {
|
|
|
|
|
commentList.value[index].child[i]["islike"] = data["status"]
|
|
|
|
|
commentList.value[index].child[i]["likenum"] = data["likenum"]
|
|
|
|
|
} else {
|
|
|
|
|
commentList.value[index]["islike"] = data["status"]
|
|
|
|
|
commentList.value[index]["likenum"] = data["likenum"]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
handleMsg("success", res["message"] || "操作成功")
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 打开 回答-评论 的子评论
|
|
|
|
|
const openAnswerCommentsChild = (index, i) => {
|
2025-01-21 19:06:13 +08:00
|
|
|
|
// console.log("isNeedLogin", isNeedLogin)
|
2025-01-20 19:08:21 +08:00
|
|
|
|
|
|
|
|
|
if (isNeedLogin.value) {
|
|
|
|
|
goLogin()
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
closeAnswerCommentsChild()
|
|
|
|
|
|
|
|
|
|
if (i == null) commentList.value[index]["childState"] = true
|
|
|
|
|
else commentList.value[index]["child"][i]["childState"] = true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 关闭 回答-评论 的子评论
|
|
|
|
|
const closeAnswerCommentsChild = () => {
|
|
|
|
|
commentList.value.forEach(ele => {
|
|
|
|
|
ele["childState"] = false
|
2025-02-06 12:20:22 +08:00
|
|
|
|
ele["commentInput"] = "" // 删除原本输入值
|
2025-01-20 19:08:21 +08:00
|
|
|
|
if (ele["child"] && ele["child"].length != 0) {
|
|
|
|
|
ele["child"].forEach(el => {
|
|
|
|
|
el["childState"] = false
|
2025-02-06 12:20:22 +08:00
|
|
|
|
el["commentInput"] = ""
|
2025-01-20 19:08:21 +08:00
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 获取剩下的子评论
|
2025-01-21 19:06:13 +08:00
|
|
|
|
const alsoCommentsData = (index, i) => {
|
|
|
|
|
// const targetAnswerList = [...answerList.value]
|
|
|
|
|
const parentid = commentList.value[index]["id"]
|
|
|
|
|
const token = detailsToken.value
|
2025-01-20 19:08:21 +08:00
|
|
|
|
|
|
|
|
|
$ajax("/api/comment/childrenList", {
|
|
|
|
|
token,
|
|
|
|
|
parentid,
|
2025-01-23 19:10:04 +08:00
|
|
|
|
limit: 2000,
|
2025-01-20 19:08:21 +08:00
|
|
|
|
page: 1,
|
2025-01-23 19:10:04 +08:00
|
|
|
|
childlimit: 3,
|
2025-01-20 19:08:21 +08:00
|
|
|
|
}).then(res => {
|
|
|
|
|
if (res.code != 200) return
|
|
|
|
|
let data = res.data
|
|
|
|
|
|
2025-01-21 19:06:13 +08:00
|
|
|
|
let merged = [...commentList.value[index]["child"], ...data.data.filter(item2 => !commentList.value[index]["child"].find(item1 => item1.id == item2.id))]
|
|
|
|
|
|
|
|
|
|
commentList.value[index]["child"] = merged
|
|
|
|
|
// answerList.value = targetAnswerList
|
2025-01-20 19:08:21 +08:00
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const handleMenuState = inject("handleMenuState")
|
|
|
|
|
|
|
|
|
|
const openMenuState = (index, i) => {
|
|
|
|
|
if (isNeedLogin.value) {
|
|
|
|
|
goLogin()
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
let reportToken = ""
|
|
|
|
|
if (i === undefined) reportToken = commentList.value[index]["token"]
|
|
|
|
|
else reportToken = commentList.value[index]["child"][i]["token"]
|
|
|
|
|
handleMenuState(reportToken)
|
|
|
|
|
}
|
2025-01-23 19:10:04 +08:00
|
|
|
|
|
|
|
|
|
const openUserInfo = (index, i) => {
|
|
|
|
|
if (i != undefined && commentList.value[index].child[i]["uin"] > 0) commentList.value[index].child[i]["avatarState"] = true
|
|
|
|
|
else if (index != undefined && commentList.value[index]["uin"] > 0) commentList.value[index]["avatarState"] = true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const closeUserInfo = (index, i) => {
|
|
|
|
|
if (i != undefined) commentList.value[index].child[i]["avatarState"] = false
|
|
|
|
|
else if (index != undefined) commentList.value[index]["avatarState"] = false
|
|
|
|
|
}
|
2025-01-20 19:08:21 +08:00
|
|
|
|
</script>
|
|
|
|
|
<style scoped></style>
|