PC-mj/pages/details/[id].vue

2212 lines
93 KiB
Vue
Raw Permalink Normal View History

2023-12-18 11:12:07 +08:00
<template>
<Head>
<Title>{{ `${seo["title"] || "面经"} - 寄托天下出国留学网` }}</Title>
<Meta name="keyword" :content="seo['keyword']" />
<Meta name="description" :content="seo['description']" />
</Head>
2024-01-03 15:28:16 +08:00
<!-- <div @click="router.push(`/index.html`)">1111</div> -->
<!-- <PageHeade></PageHeade> -->
<div>
2024-01-03 19:11:30 +08:00
<TopHead ref="topHeadRef"></TopHead>
2024-01-03 15:28:16 +08:00
<div class="content flexflex">
2024-01-03 18:31:15 +08:00
<div class="left" :style="{ height: contentRightHeight + 'px' }">
2024-01-10 19:04:17 +08:00
<div class="school-box flexcenter" :style="{ 'pointer-events': info['school']?.['url'] ? 'auto' : 'none' }">
2024-01-03 15:28:16 +08:00
<a class="school-box-icon" :href="info['school']?.['url']" target="_blank"><img class="school-icon" v-if="info['school']?.['image']" :src="info['school']?.['image']" /></a>
<a class="school-name" :href="info['school']?.['url']" target="_blank">{{ info["school"]?.["name"] }}</a>
<a class="school-en-name" :href="info['school']?.['url']" target="_blank">{{ info["school"]?.["enname"] }}</a>
</div>
2023-12-18 11:12:07 +08:00
2024-01-03 15:28:16 +08:00
<div class="mj-total flexacenter">
该校共有
<div class="value">{{ relatedcount }}</div>
个面经
</div>
2024-01-03 17:08:29 +08:00
<div class="mj-list" @scroll="handleListScroll">
2024-01-05 18:20:39 +08:00
<template v-for="(item, index) in relatedlist" :key="index">
<a v-if="item['type']" class="mj-item flexflex recommend" :href="item?.url" target="_blank">
<div class="mj-header flexacenter">
2024-01-10 15:31:42 +08:00
<div class="label flexacenter">
<div class="label-text flexcenter"></div>
2024-01-10 16:56:47 +08:00
<div class="label-title">{{ labelObj[item["type"] || "offer"] }}</div>
2024-01-10 15:31:42 +08:00
</div>
2024-01-05 18:20:39 +08:00
<h1>{{ item["title"] }}</h1>
</div>
2023-12-29 18:37:38 +08:00
2024-01-05 18:20:39 +08:00
<div class="info-list flexflex" v-if="item['type'] == 'offer'">
<div class="info-item flexacenter">
<div class="info-name">专业</div>
<div class="info-value flex1 ellipsis">{{ item["professional"] }}</div>
</div>
<div class="info-item flexacenter">
<div class="info-name">学位</div>
<div class="info-value flex1 ellipsis">{{ item["degree"] }}</div>
</div>
<div class="info-item flexacenter">
<div class="info-name">结果</div>
<div class="info-value flex1 ellipsis">{{ item["apply_results"] }}</div>
</div>
2023-12-29 18:37:38 +08:00
</div>
2024-01-05 18:20:39 +08:00
<div class="thread-text ellipsis flexflex" v-if="item['type'] == 'thread' || item['type'] == 'ask'">
<div class="ask-label" v-if="item['type'] == 'ask'">回答</div>
<div class="flex1 ellipsis">{{ item["message"] }}</div>
2024-01-03 15:28:16 +08:00
</div>
2024-01-05 18:20:39 +08:00
<div class="vote-list" v-if="item['type'] == 'vote'">
<div class="vote-item" v-for="(ite, i) in item['option'].slice(0, 2)" :key="i">{{ numberToEnclosed(i) }} &nbsp; {{ ite }}</div>
<div class="vote-item">{{ numberToEnclosed(3) }} &nbsp; </div>
2024-01-03 15:28:16 +08:00
</div>
2024-01-05 18:20:39 +08:00
</a>
<a v-else class="mj-item flexflex" :class="{ pitch: pitchIndex == index }" @click.stop.prevent="handleItem(item['uniqid'])" :href="`./details/${item['uniqid']}`">
<div class="mj-header flexacenter">
<img class="mj-avatar" :src="item['avatar']" />
<div class="user-name">{{ item["username"] || "匿名用户" }}</div>
<div class="time">{{ handleDate(item["releasetime"]) }}发布</div>
</div>
<div class="info-list flexflex">
<div class="info-item flexacenter" v-if="item['profession']">
<div class="info-name">专业</div>
<div class="info-value flex1 ellipsis">{{ item["profession"] }}</div>
</div>
<div class="info-item flexacenter" v-if="item['project']">
<div class="info-name">项目</div>
<div class="info-value flex1 ellipsis">{{ item["project"] }}</div>
</div>
<div class="info-item flexacenter" v-if="item['interviewtime']">
2024-01-09 15:11:03 +08:00
<div class="info-name">面试</div>
2024-01-05 18:20:39 +08:00
<div class="info-value flex1 ellipsis">{{ item["interviewtime"] }}</div>
</div>
</div>
</a>
</template>
2023-12-18 11:12:07 +08:00
</div>
</div>
2024-01-03 17:08:29 +08:00
<!-- <div class="right flex1" @scroll="handleCommentsScroll" v-loading="detailsLoading"> -->
2024-01-03 18:31:15 +08:00
<div class="right flex1" ref="contentRightRef" v-loading="detailsLoading">
2024-01-03 15:28:16 +08:00
<!-- <div class="right-loading"></div> -->
<div class="header">
2024-01-03 17:08:29 +08:00
<div class="titletitle">{{ info["subject"] }}</div>
2024-01-03 15:28:16 +08:00
<div class="mj-header flexacenter">
<div class="mj-header-left flexacenter">
<el-popover placement="bottom-start" :width="140" trigger="click" popper-class="avatar-box-popper" :show-arrow="false">
<template #reference>
<img class="mj-avatar" :src="info['avatar']" />
</template>
<div class="avatar-box flexflex" v-if="info['uin']">
<!-- <div class="avatar-box flexflex"> -->
<a class="avatar-item flexcenter" target="_blank" @click.prevent="sendMessage(info['uin'])">
<img class="avatar-icon" src="@/assets/img/send-messages-icon.png" />
发送信息
</a>
<a class="avatar-item flexcenter" target="_blank" @click.prevent="TAHomePage(info['uin'])">
<img class="avatar-icon" src="@/assets/img/homepage-icon.png" />
TA的主页
</a>
</div>
</el-popover>
<div class="user-name">{{ info["nickname"] || "匿名用户" }}</div>
<div class="time">{{ handleDate(info["releasetime"]) }}发布</div>
2025-02-18 19:06:04 +08:00
<div class="hide flexacenter" @click="openHide" v-if="permissions.includes('mj.hide')">
<img class="icon" src="@/assets/img/set-icon.png" />
隐藏
</div>
2023-12-18 11:12:07 +08:00
</div>
2024-01-05 18:20:39 +08:00
<a class="mj-header-right flexacenter" target="_blank" :href="info['threadurl']">
<img class="original-icon" src="@/assets/img/original-icon.png" />
论坛原帖
<!-- <img class="eye-icon" src="@/assets/img/eye-icon.svg" /> -->
<!-- {{ info["views"] }} -->
</a>
2023-12-18 11:12:07 +08:00
</div>
</div>
2024-01-03 15:28:16 +08:00
<div class="details-box">
2024-01-09 16:12:49 +08:00
<div class="details-item">
<div class="details-top">面试过程及内容</div>
<div class="details-list">
<div class="details-list-item flexacenter">
<div class="details-value describe" :class="{ 'unlock-unlock': !isdisplay }" v-if="info['message']">
2024-09-25 18:12:53 +08:00
<div class="text" v-html="info['message']"></div>
2025-03-21 16:02:51 +08:00
<div class="unlock-mask flexflex" style="width: 693px">
2025-02-10 19:03:44 +08:00
<div class="unlock-text-box flexcenter" @click="handleLike">
<div class="unlock-text">作者设置了浏览限制</div>
<div class="unlock-text flexacenter">
2025-02-10 19:03:44 +08:00
<div class="emphasis" @click="loginJudgment()">评论/点赞</div>
后即可查看完整内容
</div>
<template v-if="respondListState">
<div class="respond-list-mask" @click.stop="cutRespondState(false)"></div>
<div class="respond-list-box" @click.stop="">
<div class="respond-list-title">选择你的回应</div>
<div class="respond-list">
<template v-for="item in riposteoptions" :key="item">
<div class="respond-item" v-for="(item, key) in item.data" :key="key" v-html="jointriposte(key)" @click.stop="selectEomjiPop(key, true)"></div>
</template>
</div>
</div>
</template>
2024-01-09 16:12:49 +08:00
</div>
</div>
</div>
</div>
</div>
</div>
2024-01-03 15:28:16 +08:00
<div class="details-item">
<div class="details-top">申请信息</div>
<div class="details-list">
<div class="details-list-item flexacenter" v-if="info['school']">
<div class="details-name">学校</div>
2025-02-17 19:01:09 +08:00
<a class="details-value flex1" target="_blank" :href="info['school']?.['url']">{{ info["school"]?.name }}</a>
2024-01-03 15:28:16 +08:00
</div>
<div class="details-list-item flexacenter" v-if="info['profession']">
<div class="details-name">专业</div>
2025-02-17 19:01:09 +08:00
<div class="details-value flex1">{{ info["profession"] }}</div>
2024-01-03 15:28:16 +08:00
</div>
<div class="details-list-item flexacenter" v-if="info['project']">
<div class="details-name">项目</div>
2025-02-17 19:01:09 +08:00
<div class="details-value flex1">{{ info["project"] }}</div>
2024-01-03 15:28:16 +08:00
</div>
2023-12-18 11:12:07 +08:00
</div>
</div>
2024-01-03 15:28:16 +08:00
<div class="details-item">
<div class="details-top">面试时间</div>
<div class="details-list">
<div class="details-list-item flexacenter">
<div class="details-name">日期</div>
<div class="details-value date" v-if="info['interviewtime']">{{ timestampToDate(info["interviewtime"]) }}</div>
</div>
</div>
</div>
2023-12-18 11:12:07 +08:00
</div>
2024-07-19 15:03:52 +08:00
<!-- 回应 -->
2025-02-10 19:03:44 +08:00
<div class="respond-area" v-if="false">
<div class="respond-title flexacenter" ref="respondtitle">
2024-07-19 15:03:52 +08:00
回应
<div class="value">{{ ripostecount.total || 0 }}</div>
2024-07-24 16:17:06 +08:00
<div v-if="ripostecount.user > 0" class="respond-list-btn" @click="openPopList">
<span class="respond-list-btn-amount">{{ ripostecount.user }}</span
>人回应
<img class="respond-list-btn-icon" src="@/assets/img/arrowsRight.svg" />
</div>
2024-07-19 15:03:52 +08:00
</div>
<div v-if="ripostelist.length == 0" class="respond-no-box flexacenter">
<div class="respond-no flex1">
<div v-for="item in randomEmojis" :key="item" class="code" v-html="jointriposte(item)" @click="selectEomji(item)"></div>
</div>
<RespondAdd></RespondAdd>
</div>
<div v-else class="respond-box">
2025-03-21 16:02:51 +08:00
<div v-for="(item, index) in ripostelist" :key="item" class="respond-item flexacenter" :class="{ pitch: item.selected }" @click="selectListEomji(index)">
2024-07-19 15:03:52 +08:00
<div class="code flexacenter" v-html="jointriposte(item.item)"></div>
{{ item.num }}
</div>
<div v-if="ripostelist.length < 3" class="respond-select flexflex">
<div class="respond-select-box flex1 flexflex">
2024-07-24 16:17:06 +08:00
<template v-for="(item, index) in randomEmojis" :key="item">
<div v-if="index < 5" class="respond-select-item" v-html="jointriposte(item)" @click="selectEomji(item)"></div>
</template>
2024-07-19 15:03:52 +08:00
</div>
<RespondAdd></RespondAdd>
</div>
<RespondAdd v-else></RespondAdd>
</div>
</div>
2025-02-14 18:55:06 +08:00
<div v-if="emojiMaskState" class="emoji-box-mask" @click="closeEmoji()"></div>
2025-02-10 19:03:44 +08:00
2024-01-03 15:28:16 +08:00
<!-- 讨论 -->
2024-01-04 17:12:58 +08:00
<div class="comment-box" ref="commentBoxRef">
2025-02-17 19:01:09 +08:00
<!-- 编辑评论 -->
<div v-if="editCommentState" class="edit-comment flexcenter">
<div class="box">
<div class="text">编辑评论</div>
<div class="input-box">
<div class="top flexflex">
<textarea ref="editInputRef" class="input-textarea flex1" maxlength="500" v-model="editInput" @focus="judgeLogin" @input="autoResize" @paste="handleInputPaste" placeholder="说说你的想法或疑问…"></textarea>
</div>
<div class="picture-box" v-if="editPicture.url">
<div class="picture">
<img class="close" @click="closeEditFileUpload()" src="@/assets/img/close-icon.png" />
<img class="img" @click="handleAnswerText" :src="editPicture.base64 || editPicture.url" />
</div>
</div>
<div class="bottom flexacenter">
<div class="operate flexacenter">
2025-03-21 16:02:51 +08:00
<div class="item" :class="{ pitch: editEmojiState }">
2025-02-17 19:01:09 +08:00
<img class="icon" src="@/assets/img/smiling-face.png" @click="openEditEmoji()" alt="" />
2025-02-20 17:16:29 +08:00
<div v-if="editEmojiState" class="emoji-edit-box-mask" @click="closeEditEmoji()"></div>
2025-02-17 19:01:09 +08:00
<div class="emoji-box">
<div class="emoji-icon" v-for="item in emojiData" :key="item" @click="selectEditEmoji(item)">{{ item }}</div>
</div>
</div>
2025-02-20 17:16:29 +08:00
<div class="item flexacenter" @click="handleEditFile()">
2025-02-17 19:01:09 +08:00
<input class="file" type="file" @change="handleFileUpload($event)" accept=".png, .jpg, .jpeg" />
2025-03-21 16:02:51 +08:00
<img class="icon" style="border-radius: 0" src="@/assets/img/picture-icon.png" alt="" />
2025-02-17 19:01:09 +08:00
<span class="file-hint">最多可上传1张图片支持在输入框中直接粘贴图片</span>
</div>
</div>
</div>
</div>
<div class="btn-list flexacenter">
<div class="btn" @click="closeEdit()">取消</div>
<div class="btn send" @click="postEditComment()">发送</div>
</div>
</div>
</div>
2024-01-03 15:28:16 +08:00
<div class="comment-title flexacenter">
讨论
<div class="value">{{ commentComments || "" }}</div>
</div>
2025-02-10 19:03:44 +08:00
<!-- <div class="post-comment flexacenter" ref="postInputRef" :class="{ 'post-comment-focus': postCommentFocusState }" @click="loginJudgment()">
2024-01-30 19:08:34 +08:00
<div class="post-comment-input">
<el-input class="post-input flex1" type="textarea" :autosize="postCommentFocusState" :maxlength="500" show-word-limit placeholder="说说你的想法或疑问…" v-model="commentInputTop" @blur="postCommentFocusBlur" @focus="postCommentFocusState = true"></el-input>
</div>
2024-01-31 15:29:31 +08:00
<div class="post-ok flexcenter" @click="submitAnswerComments(commentInputTop)">发送</div>
2025-02-10 19:03:44 +08:00
</div> -->
<div class="input-box">
<div class="top flexflex">
<img class="avatar" v-if="user.avatar" :src="user.avatar" />
2025-02-14 18:55:06 +08:00
<textarea class="input-textarea flex1" maxlength="500" v-model="commentInputTop" @focus="judgeLogin" @input="autoResize" @paste="handleInputPaste" placeholder="说说你的想法或疑问…"></textarea>
2025-02-10 19:03:44 +08:00
</div>
<div class="picture-box" v-if="picture.url">
<div class="picture">
<img class="close" @click="closeFileUpload()" src="@/assets/img/close-icon.png" />
<img class="img" @click="handleAnswerText" :src="picture.base64 || picture.url" />
</div>
</div>
<div class="bottom flexacenter">
<div class="operate flexacenter">
2025-03-21 16:02:51 +08:00
<div class="item" :class="{ pitch: emojiState }">
2025-02-10 19:03:44 +08:00
<img class="icon" src="@/assets/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>
2025-02-14 18:55:06 +08:00
<div class="item flexacenter" @click="judgeLogin()">
2025-02-10 19:03:44 +08:00
<input class="file" type="file" @change="handleFileUpload($event)" accept=".png, .jpg, .jpeg" />
2025-03-21 16:02:51 +08:00
<img class="icon" style="border-radius: 0" src="@/assets/img/picture-icon.png" alt="" />
2025-02-10 19:03:44 +08:00
<span class="file-hint">最多可上传1张图片支持在输入框中直接粘贴图片</span>
</div>
</div>
<div class="btn" @click="submitAnswerComments(commentInputTop)">发送</div>
</div>
2023-12-25 18:39:49 +08:00
</div>
2023-12-29 18:37:38 +08:00
2024-01-03 15:28:16 +08:00
<template v-if="isEmptyState">
<div class="empty-box">
<Empty hint="说说你的观点吧"></Empty>
</div>
</template>
<template v-else>
<div class="comment-list">
<div class="comment-item flexflex" v-for="(item, index) in commentList" :key="item.id">
2024-01-04 17:12:58 +08:00
<el-popover placement="bottom-start" :width="140" trigger="click" popper-class="avatar-box-popper" :show-arrow="false" v-model:visible="item['popoverState']">
2024-01-03 15:28:16 +08:00
<template #reference>
<img class="comment-avatar" :src="item['avatar']" />
</template>
<div class="avatar-box flexflex" v-if="item['uin']">
<a class="avatar-item flexcenter" target="_blank" @click.prevent="sendMessage(item['uin'])">
<img class="avatar-icon" src="@/assets/img/send-messages-icon.png" />
发送信息
</a>
<a class="avatar-item flexcenter" target="_blank" @click.prevent="TAHomePage(item['uin'])">
<img class="avatar-icon" src="@/assets/img/homepage-icon.png" />
TA的主页
</a>
2023-12-18 11:12:07 +08:00
</div>
2024-01-03 15:28:16 +08:00
</el-popover>
<div class="comment-content flex1">
<div class="comment-header flexacenter">
<div class="comment-header-left flexacenter">
2024-01-04 17:12:58 +08:00
<div class="comments-username" @click="openAvatarPopover(index)">{{ item["nickname"] }}</div>
2024-01-03 15:28:16 +08:00
<div class="comments-time">{{ handleDate(item["timestamp"]) }}</div>
<div class="comments-identity" v-if="item['isauthor']">作者</div>
2025-03-21 16:02:51 +08:00
<img class="comments-title" v-if="item['groupimage']" :src="item.groupimage" :alt="item.grouptitle" style="height: 17px" />
2023-12-25 18:39:49 +08:00
</div>
2024-01-03 15:28:16 +08:00
<div class="comment-header-right flexacenter">
<div class="menu-box flexacenter">
<img class="menu-icon" src="@/assets/img/menu-icon-gray.svg" />
2025-02-14 18:55:06 +08:00
<!-- <div class="report-box flexcenter" @click="report(item['token'])">举报</div> -->
<div class="operate-box">
<div class="item flexcenter" @click="report(item['token'])">举报</div>
2025-02-17 19:01:09 +08:00
<div class="item flexcenter" v-if="permissions.includes('comment.edit')" @click="openEdit(item['token'], index)">编辑</div>
2025-02-14 18:55:06 +08:00
<div class="item flexcenter" v-if="permissions.includes('comment.delete')" @click="commentDelete(item['token'], index)">删除</div>
</div>
2024-01-03 15:28:16 +08:00
</div>
2024-01-30 19:08:34 +08:00
<img class="comment-icon" title="回复" @click="!item['childState'] ? openAnswerCommentsChild(index) : closeAnswerCommentsChild()" src="@/assets/img/comment-icon-gray.svg" />
2024-01-03 15:28:16 +08:00
<div class="flexacenter like-box" @click="commentLike(index)">
<img class="like-icon" v-if="item['islike'] == 1" src="@/assets/img/like-icon-colours.png" />
<img class="like-icon" v-else src="@/assets/img/like-icon-gray.png" />
<div class="like-quantity">{{ item["likenum"] || 0 }}</div>
</div>
2023-12-25 18:39:49 +08:00
</div>
2023-12-18 11:12:07 +08:00
</div>
2025-02-18 19:06:04 +08:00
<div class="comment-text" v-if="item['content']" @click="!item['childState'] ? openAnswerCommentsChild(index) : closeAnswerCommentsChild()" v-html="item['content']"></div>
2025-02-10 19:03:44 +08:00
<img class="comments-img" @click="handleAnswerText" :src="item.image?.base64 || item.image?.url" v-if="item.image?.url" />
<!-- <div class="comments-input-masking" @click="closeAnswerCommentsChild()" v-if="item['childState']"></div> -->
<!-- <div class="comments-input-box" :class="{ 'comments-input-box-show': item['childState'] }"> -->
<div class="input-box" v-if="item['childState']">
<img class="cross" @click="closeAnswerCommentsChild()" src="@/assets/img/cross-icon.png" />
<div class="top flexflex">
2025-02-14 18:55:06 +08:00
<img class="avatar" v-if="user.avatar" :src="user.avatar" />
<textarea class="input-textarea flex1" maxlength="500" placeholder="说说你的想法或疑问…" v-model="item['commentInput']" @focus="judgeLogin" @input="autoResize" @paste="handleInputPaste($event, index)"></textarea>
2025-02-10 19:03:44 +08:00
</div>
<div class="picture-box" v-if="item.picture?.url">
<div class="picture">
<img class="close" @click="closeFileUpload(index)" src="@/assets/img/close-icon.png" />
<img class="img" @click="handleAnswerText" :src="item.picture?.base64 || item.picture.url" />
</div>
</div>
<div class="bottom flexacenter">
<div class="operate flexacenter">
2025-03-21 16:02:51 +08:00
<div class="item" :class="{ pitch: item.emojiState }">
2025-02-10 19:03:44 +08:00
<img class="icon" src="@/assets/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>
2025-02-14 18:55:06 +08:00
<div class="item flexacenter" @click="judgeLogin()">
2025-02-10 19:03:44 +08:00
<input class="file" type="file" @change="handleFileUpload($event, index)" accept=".png, .jpg, .jpeg" />
2025-03-21 16:02:51 +08:00
<img class="icon" style="border-radius: 0" src="@/assets/img/picture-icon.png" alt="" />
2025-02-10 19:03:44 +08:00
<span class="file-hint">最多可上传1张图片支持在输入框中直接粘贴图片</span>
</div>
</div>
<div class="btn" @click="submitAnswerComments(item['commentInput'], index)">发送</div>
</div>
</div>
<!-- <div class="comments-input-box" :class="{ 'comments-input-box-show': item['childState'] }">
2024-01-31 15:29:31 +08:00
<div class="comments-input">
2024-01-30 19:08:34 +08:00
<el-input type="textarea" v-model="commentInput" placeholder="回复" :maxlength="500" show-word-limit></el-input>
<div class="operate-bottom flexacenter">
<div class="comments-btn comments-btn-cancel flexcenter" @click="closeAnswerCommentsChild()">取消</div>
<div class="comments-btn flexcenter" @click="submitAnswerComments(commentInput, index)">发送</div>
</div>
2024-01-03 15:28:16 +08:00
</div>
2025-02-10 19:03:44 +08:00
</div> -->
2024-01-03 15:28:16 +08:00
<!-- 子评论 -->
<div class="child-comments" v-if="item['child'].length > 0">
<div class="comment-item flexflex" v-for="(ite, i) in item['child']" :key="ite.id">
<!-- <img class="comment-avatar" :src="ite['avatar']" /> -->
2024-01-04 17:12:58 +08:00
<el-popover placement="bottom-start" :width="140" trigger="click" popper-class="avatar-box-popper" :show-arrow="false" v-model:visible="ite['popoverState']">
2024-01-03 15:28:16 +08:00
<template #reference>
<img class="comment-avatar" :src="ite['avatar']" />
</template>
2024-01-04 17:12:58 +08:00
<div class="avatar-box flexflex" v-if="ite['uin']">
<a class="avatar-item flexcenter" target="_blank" @click.prevent="sendMessage(ite['uin'])">
2024-01-03 15:28:16 +08:00
<img class="avatar-icon" src="@/assets/img/send-messages-icon.png" />
发送信息
</a>
<a class="avatar-item flexcenter" target="_blank" @click.prevent="TAHomePage(ite['uin'])">
<img class="avatar-icon" src="@/assets/img/homepage-icon.png" />
TA的主页
</a>
2023-12-18 11:12:07 +08:00
</div>
2024-01-03 15:28:16 +08:00
</el-popover>
<div class="comment-content flex1">
<div class="comment-header flexacenter">
<div class="comment-header-left flexacenter">
2024-01-04 17:12:58 +08:00
<div class="comments-username" @click="openAvatarPopover(index, i)">{{ ite["nickname"] }}</div>
2024-01-03 15:28:16 +08:00
<div class="comments-time">{{ handleDate(ite["timestamp"]) }}</div>
2024-01-09 18:49:37 +08:00
2024-01-03 15:28:16 +08:00
<div class="comments-identity" v-if="ite['isauthor']">作者</div>
2025-03-21 16:02:51 +08:00
<img class="comments-title" v-if="ite['groupimage']" :src="ite.groupimage" :alt="ite.grouptitle" style="height: 17px" />
2023-12-25 18:39:49 +08:00
</div>
2024-01-03 15:28:16 +08:00
<div class="comment-header-right flexacenter">
<div class="menu-box flexacenter">
<img class="menu-icon" src="@/assets/img/menu-icon-gray.svg" />
2025-02-14 18:55:06 +08:00
<div class="operate-box">
<div class="item flexcenter" @click="report(ite['token'])">举报</div>
2025-02-17 19:01:09 +08:00
<div class="item flexcenter" v-if="permissions.includes('comment.edit')" @click="openEdit(ite['token'], index, i)">编辑</div>
2025-02-14 18:55:06 +08:00
<div class="item flexcenter" v-if="permissions.includes('comment.delete')" @click="commentDelete(ite['token'], index, i)">删除</div>
</div>
<!-- <div class="report-box flexcenter" @click="report(ite['token'])">举报</div> -->
2024-01-03 15:28:16 +08:00
</div>
2024-01-30 19:08:34 +08:00
<img class="comment-icon" title="回复" @click="!ite['childState'] ? openAnswerCommentsChild(index, i) : closeAnswerCommentsChild()" src="@/assets/img/comment-icon-gray.svg" />
2024-01-03 15:28:16 +08:00
<div class="flexacenter like-box" @click="commentLike(index, i)">
<img class="like-icon" v-if="ite['islike'] == 1" src="@/assets/img/like-icon-colours.png" />
<img class="like-icon" v-else src="@/assets/img/like-icon-gray.png" />
<div class="like-quantity">{{ ite["likenum"] || 0 }}</div>
</div>
2023-12-25 18:39:49 +08:00
</div>
2023-12-18 11:12:07 +08:00
</div>
2025-02-18 19:06:04 +08:00
<div class="comment-text" v-if="ite['content']" @click="!ite['childState'] ? openAnswerCommentsChild(index, i) : closeAnswerCommentsChild()">
2024-01-03 15:28:16 +08:00
<div class="comments-reply" v-if="ite?.reply?.nickname">@{{ ite?.reply?.nickname }}</div>
{{ ite["content"] }}
</div>
2025-02-10 19:03:44 +08:00
<img class="comments-img" @click="handleAnswerText" :src="ite.image?.base64 || ite.image?.url" v-if="ite.image?.url" />
2024-01-31 15:29:31 +08:00
<!-- <div class="comments-input-box flexacenter" v-if="ite['childState']">
2024-01-03 15:28:16 +08:00
<div class="comments-input flexflex">
<textarea class="flex1" placeholder="回复" v-model="commentInput"></textarea>
<div class="comments-btn flexcenter" @click="submitAnswerComments(index, i)">发送</div>
</div>
2024-01-31 15:29:31 +08:00
</div> -->
2025-02-10 19:03:44 +08:00
<!-- <div class="comments-input-masking" @click="closeAnswerCommentsChild()" v-if="ite['childState']"></div> -->
<!-- <div class="comments-input-box" :class="{ 'comments-input-box-show': ite['childState'] }">
2024-01-31 15:29:31 +08:00
<div class="comments-input">
<el-input type="textarea" v-model="commentInput" placeholder="回复" :maxlength="500" show-word-limit></el-input>
<div class="operate-bottom flexacenter">
<div class="comments-btn comments-btn-cancel flexcenter" @click="closeAnswerCommentsChild()">取消</div>
<div class="comments-btn flexcenter" @click="submitAnswerComments(commentInput, index, i)">发送</div>
</div>
</div>
2025-02-10 19:03:44 +08:00
</div> -->
<div class="input-box" v-if="ite['childState']">
<img class="cross" @click="closeAnswerCommentsChild()" src="@/assets/img/cross-icon.png" />
<div class="top flexflex">
2025-02-14 18:55:06 +08:00
<textarea class="input-textarea flex1" maxlength="500" @focus="judgeLogin" :placeholder="'回复“' + (ite['nickname'] || '匿名用户') + '”:'" v-model="ite['commentInput']" @input="autoResize" @paste="handleInputPaste($event, index)"></textarea>
2025-02-10 19:03:44 +08:00
</div>
<div class="picture-box" v-if="ite.picture?.url">
<div class="picture">
<img class="close" @click="closeFileUpload(index, i)" src="@/assets/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">
2025-03-21 16:02:51 +08:00
<div class="item" :class="{ pitch: ite.emojiState }">
2025-02-10 19:03:44 +08:00
<img class="icon" src="@/assets/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>
2025-02-14 18:55:06 +08:00
<div class="item flexacenter" @click="judgeLogin()">
2025-02-10 19:03:44 +08:00
<input class="file" type="file" @change="handleFileUpload($event, index, i)" accept=".png, .jpg, .jpeg" />
2025-03-21 16:02:51 +08:00
<img class="icon" style="border-radius: 0" src="@/assets/img/picture-icon.png" alt="" />
2025-02-10 19:03:44 +08:00
<span class="file-hint">最多可上传1张图片支持在输入框中直接粘贴图片</span>
</div>
</div>
<div class="btn" @click="submitAnswerComments(ite['commentInput'], index, i)">发送</div>
</div>
2023-12-25 18:39:49 +08:00
</div>
2023-12-18 11:12:07 +08:00
</div>
</div>
</div>
2024-01-03 15:28:16 +08:00
<!-- 还有几个 -->
<div class="comments-also flexacenter" v-if="item['childnum'] > item['child'].length" @click="alsoCommentsData(index)">
<div class="">还有{{ item["childnum"] - item["child"].length }}条回复</div>
<img class="also-icon" src="@/assets/img/arrow-circular-gray.png" />
</div>
2023-12-25 18:39:49 +08:00
</div>
2023-12-18 11:12:07 +08:00
</div>
</div>
2024-01-03 15:28:16 +08:00
<div class="comment-end" v-if="commentPage == 0 && commentList.length != 0">· End ·</div>
</template>
</div>
2023-12-18 11:12:07 +08:00
</div>
2024-01-31 15:29:31 +08:00
<div class="floor-area flexacenter" @click="closeAnswerCommentsChild()">
2024-01-03 15:28:16 +08:00
<div class="floor-content flexacenter">
2024-01-09 18:49:37 +08:00
<div class="floor-right flexacenter" @mouseenter="handleFloorRight(true)" @mouseleave="handleFloorRight(false)">
手机查看该面经
<img class="arrows-icon" src="@/assets/img/arrows-icon.png" />
<el-popover placement="bottom" width="160px" trigger="hover" v-model:visible="floorRightState" popper-style="padding: 24px;border-radius: 18px;">
<template #reference>
<div class="QR-code-ball flexcenter">
<img class="" src="@/assets/img/QR-code-icon.svg" />
</div>
</template>
<img class="examine-code" :src="qrcode" />
</el-popover>
</div>
2025-02-18 19:06:04 +08:00
<!-- <div class="floor-centre flexflex flexacenter" @click="openHide" v-if="permissions.includes('mj.hide')">
2025-02-13 19:05:25 +08:00
<img class="icon" src="@/assets/img/set-icon.png" />
隐藏
2025-02-18 19:06:04 +08:00
</div> -->
2025-02-13 19:05:25 +08:00
2024-01-03 15:28:16 +08:00
<div class="floor-left flexacenter">
2025-03-21 16:02:51 +08:00
<div class="item flexacenter" v-if="isBrowser" style="cursor: auto">
2024-01-09 18:49:37 +08:00
<img class="icon h8" src="@/assets/img/eye-icon-black.svg" />
2024-01-05 18:20:39 +08:00
{{ info["views"] }}
</div>
2025-02-10 19:03:44 +08:00
<div class="item flexacenter" @click="handleLike" v-if="true">
2024-07-22 11:38:51 +08:00
<img class="icon h16" v-if="islike == 1" src="@/assets/img/like-icon-colours.png" />
<img class="icon h16" v-else src="@/assets/img/like-icon.png" />
{{ info["likenum"] || "" }}
</div>
<div class="item flexacenter" v-else>
2024-07-19 15:03:52 +08:00
<img class="icon h16" src="@/assets/img/riposte-icon.png" />
{{ ripostecount.total || 0 }}
2024-01-03 15:28:16 +08:00
</div>
2024-01-09 18:49:37 +08:00
<div class="item flexacenter" @click="handleScrollComments()"><img class="icon h15" src="@/assets/img/comment-icon.png" />{{ commentComments }}</div>
2024-01-08 16:18:40 +08:00
<ClientOnly>
<div class="item flexacenter" @click="handleCollect()">
2024-01-09 18:49:37 +08:00
<img class="icon h16" v-if="iscollection == 1" src="@/assets/img/collect-icon-colours.svg" />
<img class="icon h16" v-else src="@/assets/img/collect-icon.png" />
2024-01-08 16:18:40 +08:00
{{ info["favnum"] || "收藏" }}
</div>
</ClientOnly>
2024-01-04 14:54:37 +08:00
<ClientOnly>
<el-popover placement="bottom" width="628px" trigger="click" popper-style="padding: 0;border-radius: 10px;" v-model:visible="transmitBoxState">
<template #reference>
2024-01-09 18:49:37 +08:00
<div class="item flexacenter" @click="handleShare"><img class="icon h15" src="@/assets/img/transmit-icon.png" />转发</div>
2024-01-04 14:54:37 +08:00
</template>
2024-01-03 15:28:16 +08:00
2024-01-04 14:54:37 +08:00
<div class="transmit-box flexflex">
<img class="cross-icon" @click="transmitBoxState = false" src="@/assets/img/cross-icon.png" />
<div class="transmit-left transmit-web">
<div class="transmit-title">转发网页版</div>
<div class="transmit-content">
<div class="transmit-headline">{{ info["subject"] }}</div>
<div class="transmit-url">{{ getFullUrl() }}</div>
</div>
<div class="transmit-web-btn flexcenter" @click="copyText(`${info['subject']} + ${getFullUrl()}`)">复制链接</div>
2024-01-03 15:28:16 +08:00
</div>
2024-01-04 14:54:37 +08:00
<div class="transmit-right transmit-mini">
<div class="transmit-title">转发小程序版</div>
<div class="transmit-content flexcenter">
<img class="transmit-mini-img" :src="qrcode" />
<div class="flexcenter">
<img class="give-sweep" src="@/assets/img/give-sweep.png" />
2025-02-18 19:06:04 +08:00
扫码转发该面经
2024-01-04 14:54:37 +08:00
</div>
2024-01-03 15:28:16 +08:00
</div>
2023-12-18 11:12:07 +08:00
</div>
</div>
2024-01-04 14:54:37 +08:00
</el-popover>
</ClientOnly>
2024-01-03 15:28:16 +08:00
</div>
2023-12-18 11:12:07 +08:00
2025-02-10 19:03:44 +08:00
<!-- <div class="floor-middle flexacenter coin-box">
2024-01-10 16:56:47 +08:00
<div class="coin-content flexacenter flex1" @click="openCoinRankList" :style="{ cursor: info.coins != 0 ? 'pointer' : '' }">
2024-01-05 18:20:39 +08:00
<img class="coin-icon" src="@/assets/img/coin-icon.png" />
<div class="coin-text flex1 flexacenter">
已获
<div class="coin-value">{{ info.coins }}</div>
个寄托币
</div>
</div>
<div class="coin-btn flexcenter" @click="openCoinOperation()">给TA投币</div>
2025-02-10 19:03:44 +08:00
</div> -->
2023-12-18 11:12:07 +08:00
</div>
</div>
</div>
2024-01-03 15:28:16 +08:00
<Report v-if="reportAlertShow" :reportToken="reportToken"></Report>
2023-12-18 11:12:07 +08:00
</div>
2024-01-05 18:20:39 +08:00
<!-- 投币操作 弹窗 -->
<div class="pop-masking flexcenter" v-if="isInsertCoinsOperationShow">
2025-03-21 16:02:51 +08:00
<div class="slit-pop-box" v-if="coinMybalance > 0" style="border-radius: 11px">
<div class="slit-left" style="width: 50px">
<img class="slit-left-icon" src="//app.gter.net/image/gter/offer/imgdetails/u620.png" style="margin-top: -8px" />
2024-01-05 18:20:39 +08:00
</div>
<div class="slit-box">
2025-03-21 16:02:51 +08:00
<div class="slit-head" style="flex: 1; flex-direction: column; align-items: flex-start">
<div class="slit-head-title flexflex" style="width: 100%; justify-content: space-between">
2024-01-05 18:20:39 +08:00
<span>投币</span>
<div class="in-all">
你共有 <span>{{ coinMybalance }}</span> 寄托币
</div>
<!-- <a target="_blank" :href="coinConfig.strategy.url" style="font-weight: 100; font-size: 13px; text-decoration: underline;">{{ coinConfig.strategy.button }}</a> -->
</div>
</div>
<div class="coin-quantity flexacenter">
<div class="coin-quantity-item" :class="{ 'coin-pitch': coinAmount == item }" v-for="(item, index) in coinConfig.list" :key="index" @click="coinSelectAmountDispose(item)">
{{ item }} <span>{{ coinConfig.unit }}</span>
</div>
</div>
<el-input class="slit-input" v-model="coinAmount" placeholder="自定义投币金额" show-word-limit="false"> </el-input>
<div class="message-box">
<div class="message-hint">顺便说点什么</div>
2025-03-21 16:02:51 +08:00
<el-input class="slit-input" style="font-size: 15px" v-model="coinMessage" placeholder="请输入" maxlength="500" show-word-limit> </el-input>
2024-01-05 18:20:39 +08:00
</div>
<div class="operation">
<div class="operation-item flexcenter" @click="isInsertCoinsOperationShow = !isInsertCoinsOperationShow">取消</div>
<div class="operation-item flexcenter greenBj" @click="postCoinSbmit()">确定</div>
</div>
</div>
</div>
<div class="no-jituobi-pop-box" v-else>
<img class="no-jituobi-close" @click="isInsertCoinsOperationShow = !isInsertCoinsOperationShow" src="@/assets/img/cross-icon.png" />
<div class="no-jituobi-head flexacenter">
2025-03-21 16:02:51 +08:00
<img class="bi-icon" src="//app.gter.net/image/gter/offer/imgdetails/u620.png" style="margin-right: 12px" />
<span style="margin-top: 10px">
2024-01-05 18:20:39 +08:00
{{ coinConfig?.strategy?.tips }}
</span>
</div>
<a :href="coinConfig?.strategy?.url" target="_blank">
<div class="strategy-btn greenBj flexcenter">{{ coinConfig?.strategy?.button }}<img class="strategy-icon" src="@/assets/img/strategy-icon.svg" /></div>
</a>
</div>
</div>
<!-- 投币 排行榜 -->
<RankingBox v-if="coinrankingState" :coinrankingList="coinrankingList"></RankingBox>
2024-07-24 16:17:06 +08:00
<div class="respond-pop-mask" v-if="respondPopListState">
<div class="respond-pop">
<div class="respond-pop-no" v-if="JSON.stringify(respondDetail) == '{}'">
<img class="respond-title-icon" @click="closePopList()" src="@/assets/img/cross-grey.png" />
<img src="@/assets/img/no-discussion.png" class="respond-pop-no-icon" />
<div class="respond-pop-no-text">- 暂无数据 -</div>
</div>
<template v-else>
<div class="respond-pop-title">
<span class="respond-pop-amount">{{ ripostecount.user }}</span
>人回应
<img class="respond-title-icon" @click="closePopList()" src="@/assets/img/cross-grey.png" />
</div>
<div class="respond-list">
<div class="respond-item" v-for="(item, index) in respondDetail" :key="index">
2025-03-21 16:02:51 +08:00
<div class="respond-code" :class="{ pitch: item.selected }" v-html="jointriposte(item.item)" @click="selectEomjiListPop(item.item)"></div>
2024-07-24 16:17:06 +08:00
<div class="respond-content flex1">
<div class="respond-total">{{ item.user.length }} 人作此回应</div>
<div class="user-item" v-for="(item, index) in item.user" :key="index" @click="TAHomePage(item['uin'])">
<img class="user-avatar" :src="item.avatar" />
{{ item.nickname || item.username }}
</div>
</div>
</div>
</div>
</template>
</div>
</div>
2025-02-10 19:03:44 +08:00
<!-- 大图 -->
<div class="detail-image-mask flexcenter" v-if="dialogSrc" @click="dialogSrc = ''">
<div class="detail-image flexcenter">
<img class="detail-img" :src="dialogSrc" />
</div>
</div>
2025-02-18 19:06:04 +08:00
<el-dialog v-model="dialogVisible" title="提示" width="500">
<span>确定隐藏该面经吗</span>
<template #footer>
<div class="dialog-footer">
<el-button @click="dialogVisible = false"> </el-button>
<el-button type="primary" @click="handleHide"> </el-button>
</div>
</template>
</el-dialog>
2023-12-18 11:12:07 +08:00
</template>
<script setup>
2025-03-21 16:02:51 +08:00
import { ElMessage } from "element-plus";
const route = useRoute();
let uniqid = route.params.id;
let user = inject("userInfo");
let isNeedLogin = inject("isNeedLogin");
const goLogin = inject("goLogin");
2024-01-03 15:28:16 +08:00
2025-03-21 16:02:51 +08:00
useHead({ script: [{ src: "https://app.gter.net/bottom?tpl=header&menukey=mj" }, { src: "https://app.gter.net/bottom?tpl=footer,popupnotification", body: true }] });
2024-01-03 17:08:29 +08:00
2025-03-21 16:02:51 +08:00
let contentRightRef = ref(null);
let contentRightHeight = ref(null);
2023-12-18 11:12:07 +08:00
onMounted(() => {
2025-03-21 16:02:51 +08:00
window.addEventListener("scroll", handleScroll);
getDetails();
2024-01-03 17:08:29 +08:00
// openObserverBottom()
// 在元素挂载后执行回调函数
nextTick(() => {
// 创建 ResizeObserver 实例
2025-03-21 16:02:51 +08:00
const observer = new ResizeObserver((entries) => {
2024-01-03 17:08:29 +08:00
for (const entry of entries) {
// 元素的高度变化
2025-03-21 16:02:51 +08:00
contentRightHeight.value = entry.contentRect.height;
2024-01-03 17:08:29 +08:00
}
2025-03-21 16:02:51 +08:00
});
2024-01-03 17:08:29 +08:00
// 监听元素的变化
2025-03-21 16:02:51 +08:00
observer.observe(contentRightRef.value);
});
2023-12-18 11:12:07 +08:00
2025-03-21 16:02:51 +08:00
clearBottom();
});
2024-01-02 19:03:39 +08:00
2025-03-21 16:02:51 +08:00
let floorAreaState = ref(false); // 底部操作显示状态
2024-01-02 19:03:39 +08:00
2024-01-04 14:11:30 +08:00
watch(
() => route.path,
(newValue, oldValue) => {
// 在这里处理route.path的变化
if (typeof window !== "undefined" && route.path) {
2025-03-21 16:02:51 +08:00
if (window._hmt) window._hmt.push(["_trackPageview", route.fullPath]);
2024-01-04 14:11:30 +08:00
if (window._czc) {
2025-03-21 16:02:51 +08:00
let location = window.location;
let contentUrl = location.pathname + location.hash;
let refererUrl = "/";
window._czc.push(["_trackPageview", contentUrl, refererUrl]);
window._czc.push(["_setAutoPageview", false]);
2024-01-04 14:11:30 +08:00
}
}
}
2025-03-21 16:02:51 +08:00
);
2024-01-04 14:11:30 +08:00
2024-01-02 19:03:39 +08:00
// 开启一个监听最底部是否在可视窗口内
const openObserverBottom = () => {
// 获取目标元素的引用
2025-03-21 16:02:51 +08:00
const target = document.querySelector("section.index-footer");
2024-01-02 19:03:39 +08:00
if (!target) {
2025-03-21 16:02:51 +08:00
openObserverBottom();
return;
2024-01-02 19:03:39 +08:00
}
// 创建一个 Intersection Observer 实例
const observer = new IntersectionObserver(
(entries, observer) => {
2025-03-21 16:02:51 +08:00
entries.forEach((entry) => {
if (entry.isIntersecting) floorAreaState.value = false;
else floorAreaState.value = true;
});
2024-01-02 19:03:39 +08:00
},
{
root: null,
threshold: 0.5,
}
2025-03-21 16:02:51 +08:00
);
2024-01-02 19:03:39 +08:00
// 开始观察目标元素
2025-03-21 16:02:51 +08:00
observer.observe(target);
};
2023-12-25 18:39:49 +08:00
2024-01-03 18:31:15 +08:00
// 清除底部的次数
2025-03-21 16:02:51 +08:00
let clearBottomCount = 0;
2024-01-03 18:31:15 +08:00
// 清除 底部
const clearBottom = () => {
2025-03-21 16:02:51 +08:00
const indexFooter = document.querySelector("section.index-footer");
2024-01-03 18:31:15 +08:00
if (!indexFooter) {
2025-03-21 16:02:51 +08:00
clearBottomCount++;
setTimeout(() => clearBottom(), 200);
return;
2024-01-03 18:31:15 +08:00
}
2025-03-21 16:02:51 +08:00
if (clearBottomCount == 5) return;
2024-01-03 18:31:15 +08:00
2025-03-21 16:02:51 +08:00
indexFooter.style.display = "none";
};
2024-01-03 18:31:15 +08:00
2023-12-25 18:39:49 +08:00
// 清空全部数据
const clearAllData = () => {
2025-03-21 16:02:51 +08:00
uniqid = route.params.id;
info.value = {};
qrcode.value = "";
iscollection.value = 0;
isdisplay.value = true;
islike.value = 0;
ismyself.value = 0;
relatedlist.value = [];
relatedcount.value = 0;
pitchIndex.value = null;
2023-12-25 18:39:49 +08:00
2025-03-21 16:02:51 +08:00
seo.value = {};
commentCount.value = 0;
commentPage.value = 1;
commentList.value = [];
commentLoading = false;
token = "";
};
let floorRightState = ref(false); // 右下角 的二维码显示状态
2023-12-18 11:12:07 +08:00
2024-01-08 18:58:46 +08:00
// 处理右下角 鼠标经过箭头 展示二维码
2025-03-21 16:02:51 +08:00
const handleFloorRight = (value) => {
floorRightState.value = value;
};
2023-12-18 11:12:07 +08:00
// 转发弹窗 的 显示状态
2025-03-21 16:02:51 +08:00
let transmitBoxState = ref(false);
2023-12-18 11:12:07 +08:00
2025-03-21 16:02:51 +08:00
let info = ref({});
let qrcode = ref(""); // 分享二维码
let iscollection = ref(0); // 是否收藏
let isdisplay = ref(true); // 是否隐藏
let islike = ref(0); // 是否点赞
let ismyself = ref(0); // 是否是作者
let detailsLoading = ref(false); // 详情加载中
2023-12-18 11:12:07 +08:00
2023-12-18 19:09:29 +08:00
const getDetails = () => {
2025-03-21 16:02:51 +08:00
if (detailsLoading.value) return;
detailsLoading.value = true;
2023-12-29 18:37:38 +08:00
2025-03-21 16:02:51 +08:00
detailsHttp({ uniqid }).then((res) => {
2023-12-29 18:37:38 +08:00
if (res.code != 200) {
2025-03-21 16:02:51 +08:00
ElMessage.error(res.message);
setTimeout(() => goToURL("/index.html", false), 1000);
return;
2023-12-29 18:37:38 +08:00
}
2025-03-21 16:02:51 +08:00
let data = res.data;
token = data["token"];
info.value = data["info"];
seo.value = data.seo;
iscollection.value = data.iscollection || 0;
isdisplay.value = data.isdisplay;
islike.value = data.islike;
ismyself.value = data.ismyself;
qrcode.value = data["share"]["qrcode"];
if (relatedlist.value.length == 0) getRelatedlistHttp();
else CalculateSelectedList();
if (JSON.stringify(coinConfig.value) == "{}") getCoinInfo();
detailsLoading.value = false;
getCommentListHttp();
getRiposte();
});
};
2023-12-18 19:09:29 +08:00
// 计算选中的列表
const CalculateSelectedList = () => {
2025-03-21 16:02:51 +08:00
let targetRelatedlist = [...relatedlist.value];
2023-12-18 19:09:29 +08:00
targetRelatedlist.forEach((element, index) => {
2025-03-21 16:02:51 +08:00
if (element["uniqid"] == uniqid) pitchIndex.value = index;
});
2023-12-18 19:09:29 +08:00
if (pitchIndex.value == null) {
targetRelatedlist.unshift({
avatar: info.value["avatar"],
interviewtime: timestampToDate(info.value["interviewtime"]),
profession: info.value["profession"],
project: info.value["project"],
releasetime: info.value["releasetime"],
subject: info.value["subject"],
uniqid: uniqid,
username: info.value["nickname"],
2025-03-21 16:02:51 +08:00
});
relatedlist.value = targetRelatedlist;
pitchIndex.value = 0;
2023-12-18 19:09:29 +08:00
}
2025-03-21 16:02:51 +08:00
};
2023-12-18 11:12:07 +08:00
// 左侧列表数据
2025-03-21 16:02:51 +08:00
let relatedlist = ref([]);
let relatedcount = ref(0);
let relatedpage = ref(1);
let relatedloading = false;
2023-12-18 11:12:07 +08:00
2025-03-21 16:02:51 +08:00
let pitchIndex = ref(null); // 列表选中 index
2023-12-18 19:09:29 +08:00
2023-12-18 11:12:07 +08:00
const getRelatedlistHttp = () => {
2025-03-21 16:02:51 +08:00
if (relatedloading || relatedpage.value == 0 || !token) return;
2024-01-03 11:42:49 +08:00
2025-03-21 16:02:51 +08:00
relatedloading = true;
2024-01-03 11:42:49 +08:00
relatedlistHttp({ token, page: relatedpage.value })
2025-03-21 16:02:51 +08:00
.then((res) => {
if (res.code != 200) return;
2023-12-18 11:12:07 +08:00
2025-03-21 16:02:51 +08:00
let data = res.data;
2023-12-18 11:12:07 +08:00
2025-03-21 16:02:51 +08:00
relatedlist.value = relatedlist.value.concat(data.data);
relatedcount.value = data.count;
2024-01-02 19:03:39 +08:00
2025-03-21 16:02:51 +08:00
if (relatedlist.value.length >= data["count"]) relatedpage.value = 0;
else relatedpage.value++;
2023-12-18 19:09:29 +08:00
2025-03-21 16:02:51 +08:00
CalculateSelectedList();
2024-01-03 11:42:49 +08:00
})
.finally(() => {
2025-03-21 16:02:51 +08:00
relatedloading = false;
});
};
let seo = ref({});
let commentCount = ref(0);
let commentComments = ref(0); // 所有的评论数
let commentPage = ref(1);
let commentList = ref([]);
let commentLoading = false;
let token = "";
let isEmptyState = ref(false); // 评论是否为空
2023-12-25 18:39:49 +08:00
2023-12-18 11:12:07 +08:00
// 获取详情评论数据
const getCommentListHttp = () => {
2025-03-21 16:02:51 +08:00
if (commentPage.value == 0 || commentLoading || detailsLoading.value) return;
commentLoading = true;
2023-12-29 18:37:38 +08:00
2025-03-21 16:02:51 +08:00
if (commentPage.value != 1) getRelatedlistHttp();
2024-01-03 17:08:29 +08:00
2023-12-18 11:12:07 +08:00
detailsCommentListHttp({
2023-12-29 18:37:38 +08:00
page: commentPage.value,
childlimit: 1,
limit: 10,
2023-12-18 11:12:07 +08:00
token,
})
2025-03-21 16:02:51 +08:00
.then((res) => {
if (res.code != 200) return;
2023-12-18 11:12:07 +08:00
2025-03-21 16:02:51 +08:00
let data = res.data;
commentCount.value = data["count"];
if (data["count"] == 0) isEmptyState.value = true;
else isEmptyState.value = false;
2023-12-25 18:39:49 +08:00
2025-03-21 16:02:51 +08:00
commentList.value = commentList.value.concat(data["data"]);
2023-12-18 11:12:07 +08:00
2025-03-21 16:02:51 +08:00
commentComments.value = data["comments"];
2023-12-29 18:37:38 +08:00
2025-03-21 16:02:51 +08:00
if (commentList.value.length == data["count"]) commentPage.value = 0;
else commentPage.value++;
2024-01-10 16:56:47 +08:00
// https://bbs.gter.net/static/image/smiley/lxh/rose.gif
2023-12-18 11:12:07 +08:00
})
2025-03-21 16:02:51 +08:00
.finally(() => (commentLoading = false));
};
2023-12-18 11:12:07 +08:00
// 获取剩下的子评论
const alsoCommentsData = (index, ind) => {
2025-03-21 16:02:51 +08:00
let targetCommentItem = { ...commentList.value[index] };
2024-01-15 17:55:41 +08:00
// const token = targetCommentItem["token"]
2025-03-21 16:02:51 +08:00
const parentid = targetCommentItem["id"];
let page = targetCommentItem["childPage"] ?? 1;
2023-12-18 11:12:07 +08:00
detailsChildCommentListHttp({
childlimit: 1,
limit: 10,
page,
parentid,
token,
2025-03-21 16:02:51 +08:00
}).then((res) => {
if (res.code != 200) return;
let data = res.data;
let childData = targetCommentItem.child.concat(data.data);
2024-01-02 19:03:39 +08:00
2024-01-09 18:49:37 +08:00
// 检查当前对象在数组中的第一个索引是否与当前索引相等
2024-01-02 19:03:39 +08:00
const filteredData = childData.filter((obj, index, self) => {
2025-03-21 16:02:51 +08:00
return self.findIndex((item) => item.id == obj.id) == index;
});
2024-01-02 19:03:39 +08:00
2025-03-21 16:02:51 +08:00
targetCommentItem.child = filteredData;
targetCommentItem["childnum"] = data.count;
2023-12-18 11:12:07 +08:00
2025-03-21 16:02:51 +08:00
if (targetCommentItem.child.length == data["count"]) page = 0;
else page++;
2023-12-25 18:39:49 +08:00
2025-03-21 16:02:51 +08:00
targetCommentItem["childPage"] = page;
2023-12-18 11:12:07 +08:00
2025-03-21 16:02:51 +08:00
commentList.value[index] = targetCommentItem;
});
};
2023-12-29 18:37:38 +08:00
// 全部的启动到底部
2025-03-21 16:02:51 +08:00
const handleCommentsScroll = (e) => {
const el = e.target;
if (el.scrollHeight - el.scrollTop >= el.clientHeight + 40) return;
getCommentListHttp();
};
2023-12-18 11:12:07 +08:00
2023-12-29 18:37:38 +08:00
// 评论点赞
const commentLike = (index, i) => {
2024-01-09 15:53:19 +08:00
if (isNeedLogin.value) {
2025-03-21 16:02:51 +08:00
goLogin();
return;
2024-01-09 15:53:19 +08:00
}
2025-03-21 16:02:51 +08:00
const targetCommentList = [...commentList.value];
2023-12-29 18:37:38 +08:00
2025-03-21 16:02:51 +08:00
let token = "";
if (i != null) token = targetCommentList[index]["child"][i].token;
else token = targetCommentList[index].token;
2023-12-18 11:12:07 +08:00
2025-03-21 16:02:51 +08:00
detailsLikeCommentHttp({ token }).then((res) => {
if (res.code != 200) return;
let data = res.data;
2023-12-18 11:12:07 +08:00
2023-12-29 18:37:38 +08:00
if (i != null) {
2025-03-21 16:02:51 +08:00
targetCommentList[index]["child"][i].islike = data["status"];
targetCommentList[index]["child"][i].likenum = data["likenum"];
2023-12-29 18:37:38 +08:00
} else {
2025-03-21 16:02:51 +08:00
targetCommentList[index].islike = data["status"];
targetCommentList[index].likenum = data["likenum"];
2023-12-29 18:37:38 +08:00
}
2025-03-21 16:02:51 +08:00
ElMessage.success(res.message);
});
};
2023-12-18 11:12:07 +08:00
2025-03-21 16:02:51 +08:00
let scrollTopValue = ref(0);
2024-01-02 19:03:39 +08:00
2023-12-18 11:12:07 +08:00
// 监听滚动到底部
const handleScroll = () => {
2024-01-03 17:08:29 +08:00
// return
2025-03-21 16:02:51 +08:00
const scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
2023-12-18 11:12:07 +08:00
2025-03-21 16:02:51 +08:00
scrollTopValue.value = scrollTop;
2024-01-02 19:03:39 +08:00
2024-01-03 17:08:29 +08:00
// return
2024-01-02 19:03:39 +08:00
2025-03-21 16:02:51 +08:00
const scrollHeight = document.documentElement.scrollHeight;
const clientHeight = document.documentElement.clientHeight;
2023-12-18 11:12:07 +08:00
// 列表下 滑动到底部 获取新数据
2024-01-04 14:54:37 +08:00
if (scrollTop + clientHeight >= scrollHeight - 40) {
2025-03-21 16:02:51 +08:00
getCommentListHttp();
2024-01-04 14:54:37 +08:00
// 整个页面滚动到底部时 判断左边是否有滚动条 没有则需要加载左边数据的下一页
2025-03-21 16:02:51 +08:00
const mjList = document.querySelector(".content .left .mj-list");
if (!(mjList.scrollHeight > mjList.clientHeight || mjList.scrollWidth > mjList.clientWidth)) getRelatedlistHttp();
2024-01-04 14:54:37 +08:00
}
2025-03-21 16:02:51 +08:00
};
2023-12-18 11:12:07 +08:00
// 打开 回答-评论 的子评论
const openAnswerCommentsChild = (index, i) => {
2024-01-09 15:53:19 +08:00
if (isNeedLogin.value) {
2025-03-21 16:02:51 +08:00
goLogin();
return;
2024-01-09 15:53:19 +08:00
}
2025-03-21 16:02:51 +08:00
closeAnswerCommentsChild();
if (i == null) commentList.value[index]["childState"] = true;
else commentList.value[index]["child"][i]["childState"] = true;
};
2023-12-18 11:12:07 +08:00
// 关闭 回答-评论 的子评论
const closeAnswerCommentsChild = () => {
2025-03-21 16:02:51 +08:00
commentInput.value = "";
commentList.value.forEach((ele) => {
ele["childState"] = false;
ele["commentInput"] = ""; // 删除原本输入值
2025-02-10 19:03:44 +08:00
if (ele["child"] && ele["child"].length != 0) {
2025-03-21 16:02:51 +08:00
ele["child"].forEach((el) => {
el["childState"] = false;
el["commentInput"] = "";
});
2025-02-10 19:03:44 +08:00
}
2025-03-21 16:02:51 +08:00
});
};
2023-12-18 11:12:07 +08:00
// 讨论的输入框
2025-03-21 16:02:51 +08:00
let commentInputTop = ref("");
let commentInput = ref("");
2023-12-18 11:12:07 +08:00
// 提交回答-评论
2024-01-31 15:29:31 +08:00
const submitAnswerComments = (content, index, i) => {
2024-01-03 15:28:16 +08:00
if (isNeedLogin.value) {
2025-03-21 16:02:51 +08:00
goLogin();
return;
2024-01-03 15:28:16 +08:00
}
2025-03-21 16:02:51 +08:00
const targetCommentList = [...commentList.value];
2024-01-31 15:29:31 +08:00
// let content = ""
2025-03-21 16:02:51 +08:00
let parentid = null;
2023-12-18 11:12:07 +08:00
2024-01-31 15:29:31 +08:00
// if (index == null) content = commentInputTop.value
// else content = commentInput.value
2023-12-18 11:12:07 +08:00
2025-03-21 16:02:51 +08:00
let image = {};
2025-02-10 19:03:44 +08:00
if (i != null) {
2025-03-21 16:02:51 +08:00
parentid = targetCommentList[index]["child"][i]["id"];
image = commentList.value[index]["child"][i]["picture"] || {};
2025-02-10 19:03:44 +08:00
} else if (index != null) {
2025-03-21 16:02:51 +08:00
parentid = targetCommentList[index]["id"];
image = commentList.value[index]["picture"] || {};
} else image = picture.value;
2023-12-18 11:12:07 +08:00
detailsSubmitommentListHttp({
content,
2023-12-29 18:37:38 +08:00
token,
parentid,
2025-02-10 19:03:44 +08:00
image: image ? { aid: image.aid, url: image.url } : null,
2025-03-21 16:02:51 +08:00
}).then((res) => {
2024-01-03 15:28:16 +08:00
if (res.code != 200) {
2025-03-21 16:02:51 +08:00
ElMessage.error(res.message);
return;
2024-01-03 15:28:16 +08:00
}
2025-03-21 16:02:51 +08:00
let data = res.data;
2023-12-18 11:12:07 +08:00
2025-03-21 16:02:51 +08:00
isdisplay.value = true;
2023-12-29 18:37:38 +08:00
2023-12-18 11:12:07 +08:00
if (i != null) {
let targetData = {
id: data["commentid"],
content,
isauthor: 1,
islike: 0,
likenum: 0,
reply: {
2023-12-25 18:39:49 +08:00
nickname: targetCommentList[index]["child"][i]["nickname"],
2023-12-18 11:12:07 +08:00
},
...data,
2025-02-10 19:03:44 +08:00
image,
2025-03-21 16:02:51 +08:00
};
2023-12-18 11:12:07 +08:00
2025-03-21 16:02:51 +08:00
targetCommentList[index]["child"].unshift(targetData);
targetCommentList[index]["childnum"]++;
2023-12-18 11:12:07 +08:00
} else {
let targetData = {
id: data["commentid"],
content,
isauthor: 1,
islike: 0,
likenum: 0,
...data,
child: [],
2025-02-10 19:03:44 +08:00
image,
2025-03-21 16:02:51 +08:00
};
2023-12-29 18:37:38 +08:00
if (index != null) {
2025-03-21 16:02:51 +08:00
targetCommentList[index]["child"].unshift(targetData);
targetCommentList[index]["childnum"]++;
2023-12-29 18:37:38 +08:00
} else {
2025-03-21 16:02:51 +08:00
targetCommentList.unshift(targetData);
commentCount.value++;
2023-12-29 18:37:38 +08:00
}
2023-12-18 11:12:07 +08:00
}
2025-03-21 16:02:51 +08:00
commentComments.value++;
commentList.value = targetCommentList;
2023-12-29 18:37:38 +08:00
// 请求 输入框的数据
2025-03-21 16:02:51 +08:00
commentInputTop.value = "";
commentInput.value = "";
isEmptyState.value = false; // 取消有可能的 没有评论
2023-12-29 18:37:38 +08:00
2025-03-21 16:02:51 +08:00
closeAnswerCommentsChild();
2023-12-29 18:37:38 +08:00
2025-03-21 16:02:51 +08:00
picture.value = {};
2025-02-10 19:03:44 +08:00
2023-12-25 18:39:49 +08:00
ElMessage({
message: res.message,
type: "success",
2025-03-21 16:02:51 +08:00
});
2024-07-19 15:03:52 +08:00
2025-03-21 16:02:51 +08:00
if (!isdisplay.value) isdisplay.value = true;
});
};
2023-12-18 11:12:07 +08:00
// 处理时间戳数据
2025-03-21 16:02:51 +08:00
const timestampToDate = (timestamp) => {
const date = new Date(timestamp * 1000); // 如果你的时间戳是秒级的需要乘以1000
const year = date.getFullYear();
const month = (date.getMonth() + 1).toString().padStart(2, "0"); // getMonth() 返回的月份是从0开始计数的
const day = date.getDate().toString().padStart(2, "0");
2023-12-18 11:12:07 +08:00
2025-03-21 16:02:51 +08:00
return `${year}-${month}-${day}`;
};
2023-12-18 11:12:07 +08:00
2025-03-21 16:02:51 +08:00
onUnmounted(() => window.removeEventListener("scroll", handleScroll));
2023-12-18 11:12:07 +08:00
// 获取完整 url
const getFullUrl = () => {
2025-03-21 16:02:51 +08:00
if (typeof window === "undefined") return;
return window.location.href;
};
2023-12-18 11:12:07 +08:00
// 复制
2025-03-21 16:02:51 +08:00
let copyText = (text) => {
2023-12-18 11:12:07 +08:00
if (navigator.clipboard) {
copyText = () => {
2025-03-21 16:02:51 +08:00
navigator.clipboard.writeText(text);
2023-12-18 11:12:07 +08:00
ElMessage({
message: "复制成功",
type: "success",
2025-03-21 16:02:51 +08:00
});
};
2023-12-18 11:12:07 +08:00
} else {
copyText = () => {
2025-03-21 16:02:51 +08:00
var tempInput = document.createElement("input");
tempInput.value = text;
document.body.appendChild(tempInput);
tempInput.select();
document.execCommand("copy");
document.body.removeChild(tempInput);
2023-12-18 11:12:07 +08:00
ElMessage({
message: "复制成功",
type: "success",
2025-03-21 16:02:51 +08:00
});
};
2023-12-18 11:12:07 +08:00
}
2025-03-21 16:02:51 +08:00
copyText();
};
2023-12-18 11:12:07 +08:00
// 点击点赞
const handleLike = () => {
2023-12-29 18:37:38 +08:00
if (islike.value) {
2025-03-21 16:02:51 +08:00
ElMessage.error("不可取消点赞");
return;
2023-12-29 18:37:38 +08:00
}
2024-01-03 15:28:16 +08:00
if (isNeedLogin.value) {
2025-03-21 16:02:51 +08:00
goLogin();
return;
2024-01-03 15:28:16 +08:00
}
2025-03-21 16:02:51 +08:00
operateLikeHttp({ token }).then((res) => {
if (res.code != 200) return;
let data = res.data;
info.value["likenum"] = data["count"];
islike.value = data["status"];
2023-12-18 19:09:29 +08:00
2025-03-21 16:02:51 +08:00
isdisplay.value = true;
ElMessage.success(res.message);
});
};
let topHeadRef = ref(null);
2024-01-03 19:11:30 +08:00
2023-12-18 19:09:29 +08:00
// 点击 收藏
const handleCollect = () => {
2024-01-03 15:28:16 +08:00
if (isNeedLogin.value) {
2025-03-21 16:02:51 +08:00
goLogin();
return;
2024-01-03 15:28:16 +08:00
}
2025-03-21 16:02:51 +08:00
topHeadRef.value.count = {};
2024-01-03 19:11:30 +08:00
2025-03-21 16:02:51 +08:00
operateCollectHttp({ token }).then((res) => {
2024-01-03 15:28:16 +08:00
if (res.code != 200) {
2025-03-21 16:02:51 +08:00
ElMessage.error(res["message"]);
return;
2024-01-03 15:28:16 +08:00
}
2025-03-21 16:02:51 +08:00
let data = res.data;
2023-12-18 19:09:29 +08:00
2025-03-21 16:02:51 +08:00
info.value["favnum"] = data["count"];
iscollection.value = data["status"];
2023-12-25 18:39:49 +08:00
2025-03-21 16:02:51 +08:00
ElMessage.success(res["message"]);
});
};
2023-12-18 19:09:29 +08:00
2025-03-21 16:02:51 +08:00
const router = useRouter();
2023-12-25 18:39:49 +08:00
2023-12-18 19:09:29 +08:00
// 处理点击列表
2025-03-21 16:02:51 +08:00
const handleItem = (uni) => {
// if (uni == route?.params?.id) return
// router.push(`/details/${uni}`)
// console.log(uniqid, uni);
2025-03-21 16:02:51 +08:00
if (uniqid == uni) return;
2025-03-21 16:02:51 +08:00
uniqid = uni;
2023-12-29 18:37:38 +08:00
// info.value = {}
2025-03-21 16:02:51 +08:00
info.value["message"] = "";
info.value["subject"] = "";
info.value["profession"] = "";
qrcode.value = "";
iscollection.value = 0;
isdisplay.value = true;
islike.value = 0;
ismyself.value = 0;
commentCount.value = 0;
commentPage.value = 1;
commentList.value = [];
commentLoading = false;
token = "";
2023-12-25 18:39:49 +08:00
// clearAllData()
2025-03-21 16:02:51 +08:00
nextTick(() => getDetails());
2023-12-29 18:37:38 +08:00
2025-03-21 16:02:51 +08:00
replaceState(uni);
2024-01-03 17:08:29 +08:00
window.scrollTo({
top: 0,
behavior: "smooth",
2025-03-21 16:02:51 +08:00
});
};
2023-12-25 18:39:49 +08:00
// 修改 url
2025-03-21 16:02:51 +08:00
const replaceState = (uni) => {
if (typeof window === "undefined") return;
2025-03-28 16:20:20 +08:00
const location = JSON.parse(JSON.stringify(window.location));
2023-12-25 18:39:49 +08:00
// 替换当前URL但不刷新页面
2025-03-21 16:02:51 +08:00
window.history.pushState({}, "", `${window.location.origin}/details/${uni}`);
2025-03-28 16:20:20 +08:00
console.log("uni",uni,"location",location);
if (location.pathname.indexOf(uni) == -1) XSTAT.trackNewPage();
2025-03-21 16:02:51 +08:00
};
2023-12-29 18:37:38 +08:00
2025-03-21 16:02:51 +08:00
let reportAlertShow = ref(false);
let reportToken = ref("");
2023-12-29 18:37:38 +08:00
// 点击打开举报
2025-03-21 16:02:51 +08:00
const report = (token) => {
2024-01-03 15:28:16 +08:00
if (isNeedLogin.value) {
2025-03-21 16:02:51 +08:00
goLogin();
return;
2024-01-03 15:28:16 +08:00
}
2025-03-21 16:02:51 +08:00
reportToken.value = token;
reportAlertShow.value = true;
};
2023-12-29 18:37:38 +08:00
2025-03-21 16:02:51 +08:00
provide("reportAlertShow", reportAlertShow);
provide("clearAllData", clearAllData);
provide("getDetails", getDetails);
2023-12-29 18:37:38 +08:00
// seo的
if (process.server) {
try {
2025-03-21 16:02:51 +08:00
await detailsHttp({ uniqid }).then((res) => {
2023-12-29 18:37:38 +08:00
if (res.code != 200) {
2025-03-21 16:02:51 +08:00
ElMessage.error(res.message);
return;
2023-12-29 18:37:38 +08:00
}
2025-03-21 16:02:51 +08:00
let data = res.data;
token = data["token"];
info.value = data["info"];
seo.value = data.seo;
iscollection.value = data.iscollection;
isdisplay.value = data.isdisplay;
islike.value = data.islike;
ismyself.value = data.ismyself;
qrcode.value = data["share"]["qrcode"];
if (relatedlist.value.length == 0) getRelatedlistHttp();
else CalculateSelectedList();
detailsLoading.value = false;
getCommentListHttp();
});
await relatedlistHttp({ token, page: 1 }).then((res) => {
if (res.code != 200) return;
let data = res.data;
relatedlist.value = data.data;
relatedcount.value = data.count;
CalculateSelectedList();
});
2023-12-29 18:37:38 +08:00
} catch (error) {}
}
const isBrowser = computed(() => {
2025-03-21 16:02:51 +08:00
return process.client; // 使用 process.client 判断是否在浏览器环境下
});
2023-12-29 18:37:38 +08:00
// 点击发送信息
2025-03-21 16:02:51 +08:00
const sendMessage = (uin) => {
2024-05-23 17:26:53 +08:00
if (uin && typeof messagePrivateItem == "function") {
2025-03-21 16:02:51 +08:00
messagePrivateItem({ uin: uin });
return;
} else redirectToExternalWebsite(`https://bbs.gter.net/home.php?mod=space&showmsg=1&uid=${uin}`);
2024-05-23 17:26:53 +08:00
// redirectToExternalWebsite(`https://bbs.gter.net/home.php?mod=space&showmsg=1&uid=${uin}`)
2025-03-21 16:02:51 +08:00
};
2023-12-29 18:37:38 +08:00
// 点击ta的主页
2025-03-21 16:02:51 +08:00
const TAHomePage = (uin) => {
redirectToExternalWebsite(`https://bbs.gter.net/home.php?mod=space&uid=${uin}`);
};
2023-12-29 18:37:38 +08:00
// 跳转 url
2025-03-21 16:02:51 +08:00
const redirectToExternalWebsite = (url) => {
const link = document.createElement("a");
link.href = url;
link.target = "_blank";
link.click();
};
2024-01-02 19:03:39 +08:00
// 全部的启动到底部
2025-03-21 16:02:51 +08:00
const handleListScroll = (e) => {
const el = e.target;
if (el.scrollHeight - el.scrollTop >= el.clientHeight + 40) return;
getRelatedlistHttp();
};
2024-01-04 17:12:58 +08:00
2025-03-21 16:02:51 +08:00
const commentBoxRef = ref(null);
2024-01-04 17:12:58 +08:00
// 点进滚动到评论
const handleScrollComments = () => {
2025-03-21 16:02:51 +08:00
const element = commentBoxRef.value;
if (!element) return;
2024-01-04 17:12:58 +08:00
window.scrollTo({
top: element.offsetTop - 85 || 0,
behavior: "smooth",
2025-03-21 16:02:51 +08:00
});
return;
2024-01-04 17:12:58 +08:00
2025-03-21 16:02:51 +08:00
const rect = element.getBoundingClientRect();
2024-01-04 17:12:58 +08:00
2025-03-21 16:02:51 +08:00
let elementTop = 0;
elementTop = rect.top - window.innerHeight / 2;
2024-01-04 17:12:58 +08:00
if (rect.top > window.innerHeight) {
2025-03-21 16:02:51 +08:00
elementTop = rect.top - window.innerHeight / 2;
2024-01-04 17:12:58 +08:00
window.scrollTo({
top: elementTop || 0,
behavior: "smooth",
2025-03-21 16:02:51 +08:00
});
2024-01-04 17:12:58 +08:00
} else {
2025-03-21 16:02:51 +08:00
elementTop = window.innerHeight / 2 + rect.top / 2;
2024-01-04 17:12:58 +08:00
window.scrollTo({
top: elementTop || 0,
behavior: "smooth",
2025-03-21 16:02:51 +08:00
});
2024-01-04 17:12:58 +08:00
}
// window.scrollTo({
// top: elementTop,
// behavior: "smooth",
// })
2025-03-21 16:02:51 +08:00
};
2024-01-04 17:12:58 +08:00
// 打开评论的 信息框
const openAvatarPopover = (index, i) => {
2025-03-21 16:02:51 +08:00
if (i != null) commentList.value[index]["child"][i]["popoverState"] = true;
else commentList.value[index]["popoverState"] = true;
};
let isInsertCoinsOperationShow = ref(false); // 投票弹窗
let coinMybalance = ref({}); // 我的寄托币数量
let coinConfig = ref({}); // 投币的配置
let coinConnum = ref(0); // 寄托币数量
let coinRanklist = ref({}); // 投币排行榜
let coinAmount = ref(null); // 投币选择的金额
let coinCustomAmount = ref(null); // 投币自定义的金额
let defaultcoinnum = ref(0); // 投币金额默认寄托币数
let coinMessage = ref(""); // 投币时的说点什么
let postCoinSbmitState = false; // 投币中
2024-01-05 18:20:39 +08:00
// 获取寄托币
const getCoinInfo = () => {
2025-03-21 16:02:51 +08:00
coinHttp({ token }).then((res) => {
if (res.code != 200) return;
let data = res.data;
coinConfig.value = data.config;
coinMybalance.value = data.mybalance;
coinRanklist.value = data.ranklist;
defaultcoinnum.value = data.defaultcoinnum;
});
};
2024-01-05 18:20:39 +08:00
// 打开寄托币弹窗
const openCoinOperation = () => {
2024-01-09 15:53:19 +08:00
if (isNeedLogin.value) {
2025-03-21 16:02:51 +08:00
goLogin();
return;
2024-01-09 15:53:19 +08:00
}
2025-03-21 16:02:51 +08:00
isInsertCoinsOperationShow.value = true;
};
2024-01-05 18:20:39 +08:00
// 处理投币的选择选项
2025-03-21 16:02:51 +08:00
const coinSelectAmountDispose = (amount) => {
coinAmount.value = amount;
};
2024-01-05 18:20:39 +08:00
// 提交寄托币
const postCoinSbmit = () => {
2025-03-21 16:02:51 +08:00
if (postCoinSbmitState) return;
postCoinSbmitState = true;
2024-01-05 18:20:39 +08:00
coinsubmitHttp({
token,
coinnum: coinAmount.value,
message: coinMessage.value,
})
2025-03-21 16:02:51 +08:00
.then((res) => {
2024-01-05 18:20:39 +08:00
if (res.code != 200) {
2025-03-21 16:02:51 +08:00
ElMessage.error(res.message);
return;
2024-01-05 18:20:39 +08:00
}
2025-03-21 16:02:51 +08:00
let data = res.data;
2024-01-05 18:20:39 +08:00
2025-03-21 16:02:51 +08:00
info.value.coins = info.value.coins + data["coinnum"];
coinMybalance.value = coinMybalance.value - data["coinnum"];
2024-01-05 18:20:39 +08:00
2025-03-21 16:02:51 +08:00
coinAmount.value = null;
isInsertCoinsOperationShow.value = false;
ElMessage.success(res.message);
2024-01-05 18:20:39 +08:00
if (data.comment) {
2025-03-21 16:02:51 +08:00
const userInfoWin = window.userInfoWin || {};
commentComments.value = data.comment.count;
2024-01-05 18:20:39 +08:00
let newComment = {
avatar: userInfoWin["avatar"],
child: [],
childnum: 0,
content: coinMessage.value,
id: parseInt(data.comment.commentid),
...data.comment,
islike: 0,
likenum: 0,
nickname: userInfoWin["nickname"] || "匿名用户",
parentid: 0,
reply: [],
timestamp: generateTime(),
2025-03-21 16:02:51 +08:00
};
commentList.value.unshift(newComment);
2024-01-05 18:20:39 +08:00
}
2025-03-21 16:02:51 +08:00
coinMessage.value = "";
2024-01-05 18:20:39 +08:00
2025-03-21 16:02:51 +08:00
coinrankingList.value = [];
2024-01-05 18:20:39 +08:00
})
2025-03-21 16:02:51 +08:00
.finally(() => (postCoinSbmitState = false));
};
2024-01-05 18:20:39 +08:00
2025-03-21 16:02:51 +08:00
let coinrankingList = ref([]); // 投币排行榜数据
let coinrankingState = ref(false); // 投币排行榜 弹窗状态
let coinrankingLoading = false; // 投币排行榜加载中
2024-01-05 18:20:39 +08:00
const getCoinranking = () => {
2025-03-21 16:02:51 +08:00
if (coinrankingLoading) return;
coinrankingLoading = true;
2024-01-05 18:20:39 +08:00
coinrankingHttp({ token })
2025-03-21 16:02:51 +08:00
.then((res) => {
if (res.code != 200) return;
const data = res.data;
coinrankingList.value = data;
coinrankingState.value = true;
2024-01-05 18:20:39 +08:00
})
2025-03-21 16:02:51 +08:00
.finally(() => (coinrankingLoading = false));
};
2024-01-05 18:20:39 +08:00
// 打开寄托币排行榜
const openCoinRankList = () => {
2025-03-21 16:02:51 +08:00
if (info.value.coins == 0) return;
2024-01-05 18:20:39 +08:00
2025-03-21 16:02:51 +08:00
if (coinrankingList.value.length == 0) getCoinranking();
else coinrankingState.value = true;
};
2024-01-05 18:20:39 +08:00
// 生成时间
const generateTime = () => {
2025-03-21 16:02:51 +08:00
let date = new Date();
let Y = date.getFullYear() + "-";
let M = (date.getMonth() + 1 < 10 ? "0" + (date.getMonth() + 1) : date.getMonth() + 1) + "-";
let D = (date.getDate() < 10 ? "0" + date.getDate() : date.getDate()) + " ";
let h = (date.getHours() < 10 ? "0" + date.getHours() : date.getHours()) + ":";
let m = date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes();
return "" + Y + M + D + h + m;
};
provide("coinrankingState", coinrankingState);
provide("openCoinOperation", openCoinOperation);
2024-01-05 18:20:39 +08:00
// 处理点击转发统计
2025-03-21 16:02:51 +08:00
const handleShare = () => shareHttp({ token });
2024-01-09 15:53:19 +08:00
// 登录判断
const loginJudgment = () => {
2025-03-21 16:02:51 +08:00
if (isNeedLogin.value) goLogin();
};
2024-01-09 18:49:37 +08:00
// 取消了同页面的收藏
const unbookmarkSamePage = () => {
2025-03-21 16:02:51 +08:00
iscollection.value = 0;
info.value.favnum--;
};
2024-01-09 18:49:37 +08:00
2025-03-21 16:02:51 +08:00
provide("unbookmarkSamePage", unbookmarkSamePage);
2024-01-10 15:31:42 +08:00
let labelObj = {
offer: "Offer",
vote: "投票",
mj: "面经",
thread: "帖子",
ask: "回答",
2025-03-21 16:02:51 +08:00
};
2024-01-30 19:08:34 +08:00
2025-03-21 16:02:51 +08:00
let postCommentFocusState = ref(false);
2024-01-30 19:08:34 +08:00
2025-03-21 16:02:51 +08:00
const postInputRef = ref(null);
2024-01-30 19:08:34 +08:00
const postCommentFocusBlur = () => {
2025-03-21 16:02:51 +08:00
const refref = postInputRef.value;
2024-01-30 19:08:34 +08:00
setTimeout(() => {
2025-03-21 16:02:51 +08:00
postCommentFocusState.value = false;
2024-01-30 19:08:34 +08:00
nextTick(() => {
2025-03-21 16:02:51 +08:00
let targetDom = refref.querySelector(".el-textarea__inner");
targetDom.style.height = "41px";
});
}, 200);
};
2024-07-19 15:03:52 +08:00
2025-03-21 16:02:51 +08:00
let ripostelist = ref([]);
let ripostecount = ref({});
let riposteoptions = ref({});
2024-07-19 15:03:52 +08:00
2025-03-21 16:02:51 +08:00
provide("riposteoptions", riposteoptions);
2024-07-19 15:03:52 +08:00
const getRiposte = () => {
2025-03-21 16:02:51 +08:00
getRiposteHttp({ token }).then((res) => {
if (res.code != 200) return;
let data = res.data;
ripostecount.value = data.count || {};
ripostelist.value = data.list || [];
riposteoptions.value = data.options || [];
if (ripostelist.value.length <= 3) randomEmoji();
});
};
2024-07-19 15:03:52 +08:00
2025-03-21 16:02:51 +08:00
let randomEmojis = ref([]); // 随机 五个 emoji
provide("randomEmojis", randomEmojis);
2024-07-19 15:03:52 +08:00
// 随机 7 个Emoji
const randomEmoji = () => {
2025-03-21 16:02:51 +08:00
let emojiList = ripostelist.value;
2024-07-19 15:03:52 +08:00
// 需要排除的 Emoji
2025-03-21 16:02:51 +08:00
let exclude = [];
emojiList.forEach((element) => {
exclude.push(element.item);
});
2024-07-19 15:03:52 +08:00
2025-03-21 16:02:51 +08:00
let selectedList = []; // 待选择 Emoji To be selected
2024-07-19 15:03:52 +08:00
// 默认是有点赞的
for (const key in riposteoptions.value[0].data) {
2025-03-21 16:02:51 +08:00
if (key != "c150") selectedList.push(key);
2024-07-19 15:03:52 +08:00
}
2025-03-21 16:02:51 +08:00
const random = [];
if (!exclude.includes("c150")) random.push("c150"); // 添加第一个点赞 emoji
selectedList = selectedList.filter((itemB) => !exclude.includes(itemB));
2024-07-19 15:03:52 +08:00
// 生成随机索引,确保不重复
2025-03-21 16:02:51 +08:00
let indexes = [];
2024-07-19 15:03:52 +08:00
while (indexes.length < 7) {
2025-03-21 16:02:51 +08:00
let randomIndex = Math.floor(Math.random() * selectedList.length);
2024-07-19 15:03:52 +08:00
if (indexes.indexOf(randomIndex) === -1) {
2025-03-21 16:02:51 +08:00
indexes.push(randomIndex);
random.push(selectedList[randomIndex]);
2024-07-19 15:03:52 +08:00
}
}
2025-03-21 16:02:51 +08:00
randomEmojis.value = random;
};
2024-07-19 15:03:52 +08:00
// 拼接 回应需要的 字符
2025-03-21 16:02:51 +08:00
const jointriposte = (item) => {
return `&#x${item};`;
};
2024-07-19 15:03:52 +08:00
2025-03-21 16:02:51 +08:00
provide("jointriposte", jointriposte);
2024-07-19 15:03:52 +08:00
2025-03-21 16:02:51 +08:00
let riposteHttpState = false; // 回应加载中
2024-07-19 15:03:52 +08:00
// 选择 emoji
2025-03-21 16:02:51 +08:00
const selectEomji = (item) => {
2024-07-19 15:03:52 +08:00
if (isNeedLogin.value) {
2025-03-21 16:02:51 +08:00
goLogin();
return;
2024-07-19 15:03:52 +08:00
}
2025-03-21 16:02:51 +08:00
if (riposteHttpState) return;
riposteHttpState = true;
2024-07-19 15:03:52 +08:00
riposteSubmitHttp({ token, item })
2025-03-21 16:02:51 +08:00
.then((res) => {
2024-07-19 15:03:52 +08:00
if (res.code != 200) {
2025-03-21 16:02:51 +08:00
ElMessage.error(res.message);
return;
2024-07-19 15:03:52 +08:00
}
2025-03-21 16:02:51 +08:00
let data = res.data;
handleEmojiData(data);
2024-07-19 15:03:52 +08:00
})
.finally(() => {
2025-03-21 16:02:51 +08:00
riposteHttpState = false;
});
};
2024-07-19 15:03:52 +08:00
2025-03-21 16:02:51 +08:00
provide("selectEomji", selectEomji);
2024-07-19 15:03:52 +08:00
// 选中 在 Emoji 弹窗中 选择
2024-08-12 11:11:03 +08:00
const selectEomjiPop = (key, isroll) => {
2024-07-19 15:03:52 +08:00
if (isNeedLogin.value) {
2025-03-21 16:02:51 +08:00
goLogin();
return;
2024-07-19 15:03:52 +08:00
}
2025-03-21 16:02:51 +08:00
let emojiList = ripostelist.value;
2024-07-19 15:03:52 +08:00
// 判断 是否已经 有了
2025-03-21 16:02:51 +08:00
const index = emojiList.findIndex((item) => item.item == key);
if (index != -1 && emojiList[index].selected) return;
if (riposteHttpState) return;
riposteHttpState = true;
2024-07-25 14:13:42 +08:00
riposteSubmitHttp({ token, item: key })
2025-03-21 16:02:51 +08:00
.then((res) => {
2024-07-25 14:13:42 +08:00
if (res.code != 200) {
2025-03-21 16:02:51 +08:00
ElMessage.error(res.message);
return;
2024-07-25 14:13:42 +08:00
}
if (isroll) {
2025-03-21 16:02:51 +08:00
rollRiposte();
}
2025-03-21 16:02:51 +08:00
let data = res.data;
respondListState.value = false;
handleEmojiData(data);
2024-07-25 14:13:42 +08:00
})
.finally(() => {
2025-03-21 16:02:51 +08:00
riposteHttpState = false;
});
};
2024-07-19 15:03:52 +08:00
2025-03-21 16:02:51 +08:00
provide("selectEomjiPop", selectEomjiPop);
2024-07-19 15:03:52 +08:00
// 专门处理 展示列表的 数据结构
2025-03-21 16:02:51 +08:00
const handleEmojiData = (data) => {
let emojiList = ripostelist.value;
let isnew = true;
2024-07-19 15:03:52 +08:00
emojiList.forEach((element, index) => {
if (element.item == data.item) {
2025-03-21 16:02:51 +08:00
isnew = false;
if (element.selected) element.num--;
else element.num++;
element.selected = !element.selected;
2024-07-19 15:03:52 +08:00
}
2025-03-21 16:02:51 +08:00
});
2024-07-19 15:03:52 +08:00
// 代表是新数据
if (isnew) {
emojiList.push({
item: data.item,
num: 1,
selected: true,
2025-03-21 16:02:51 +08:00
});
2024-07-19 15:03:52 +08:00
}
2025-03-21 16:02:51 +08:00
let newArray = [];
emojiList.forEach((item) => {
if (item.num > 0) newArray.push(item);
});
2024-07-19 15:03:52 +08:00
2025-03-21 16:02:51 +08:00
if (newArray.length < 3) randomEmoji();
2024-07-19 15:03:52 +08:00
2025-03-21 16:02:51 +08:00
ripostecount.value = data.count;
ripostelist.value = newArray;
2024-07-19 15:03:52 +08:00
2025-03-21 16:02:51 +08:00
if (!isdisplay.value) isdisplay.value = true;
};
2024-07-19 15:03:52 +08:00
// 选择回应
2025-03-21 16:02:51 +08:00
const selectListEomji = (index) => {
2024-07-19 15:03:52 +08:00
if (isNeedLogin.value) {
2025-03-21 16:02:51 +08:00
goLogin();
return;
2024-07-19 15:03:52 +08:00
}
2025-03-21 16:02:51 +08:00
let emojiList = ripostelist.value;
let target = emojiList[index];
if (riposteHttpState) return;
riposteHttpState = true;
2024-07-19 15:03:52 +08:00
riposteSubmitHttp({ token, item: target.item })
2025-03-21 16:02:51 +08:00
.then((res) => {
2024-07-19 15:03:52 +08:00
if (res.code != 200) {
2025-03-21 16:02:51 +08:00
ElMessage.error(res.message);
return;
2024-07-19 15:03:52 +08:00
}
2025-03-21 16:02:51 +08:00
let data = res.data;
handleEmojiData(data);
2024-07-19 15:03:52 +08:00
})
.finally(() => {
2025-03-21 16:02:51 +08:00
riposteHttpState = false;
});
};
2024-07-24 16:17:06 +08:00
2025-03-21 16:02:51 +08:00
let respondPopListState = ref(false); // 回应列表弹窗状态
let respondDetail = ref({}); // 已回应列表
2024-07-24 16:17:06 +08:00
// 打开回应弹窗列表
const openPopList = () => {
2025-03-21 16:02:51 +08:00
respondPopListState.value = true;
getRespondDetail();
};
2024-07-24 16:17:06 +08:00
// 关闭回应弹窗列表
const closePopList = () => {
2025-03-21 16:02:51 +08:00
respondPopListState.value = false;
};
2024-07-24 16:17:06 +08:00
// 回应详情
const getRespondDetail = () => {
2025-03-21 16:02:51 +08:00
riposteDetailHttp({ token }).then((res) => {
if (res.code != 200) return;
respondDetail.value = res.data;
});
};
2024-07-24 16:17:06 +08:00
// 点击回应列表的
2025-03-21 16:02:51 +08:00
const selectEomjiListPop = (key) => {
2024-07-24 16:17:06 +08:00
// let respondDetail = respondDetail.value
2025-03-21 16:02:51 +08:00
let target = respondDetail.value[key];
2024-07-24 16:17:06 +08:00
2025-03-21 16:02:51 +08:00
riposteSubmitHttp({ token, item: target.item }).then((res) => {
2024-07-24 16:17:06 +08:00
if (res.code != 200) {
2025-03-21 16:02:51 +08:00
ElMessage.error(res.message);
return;
2024-07-24 16:17:06 +08:00
}
2025-03-21 16:02:51 +08:00
let data = res.data;
2024-07-24 16:17:06 +08:00
2025-03-21 16:02:51 +08:00
handleEmojiData(data);
2024-07-24 16:17:06 +08:00
if (target.selected) {
2025-03-21 16:02:51 +08:00
target.user = target.user.filter((item) => item.uin != data.uin);
2024-07-24 16:17:06 +08:00
} else {
2025-03-21 16:02:51 +08:00
target.user.push(data);
2024-07-24 16:17:06 +08:00
}
2025-03-21 16:02:51 +08:00
let emojiList = ripostelist.value;
2024-07-24 16:17:06 +08:00
if (target.user.length == 0) {
2025-03-21 16:02:51 +08:00
emojiList = emojiList.filter((item) => item.item != key);
delete respondDetail.value[key];
2024-07-24 16:17:06 +08:00
} else {
2025-03-21 16:02:51 +08:00
target.selected = !target.selected;
respondDetail.value[key] = target;
2024-07-24 16:17:06 +08:00
}
2025-03-21 16:02:51 +08:00
ripostelist.value = emojiList;
});
};
2025-03-21 16:02:51 +08:00
let respondListState = ref(false);
// 切换限制回应的弹窗
2025-03-21 16:02:51 +08:00
const cutRespondState = (value) => {
respondListState.value = value;
};
2025-03-21 16:02:51 +08:00
const respondtitle = ref(null);
const rollRiposte = () => {
2025-03-21 16:02:51 +08:00
const respondBox = respondtitle.value;
// 获取元素的位置信息
2025-03-21 16:02:51 +08:00
const rect = respondBox.getBoundingClientRect();
// 计算节点距离浏览器视口顶部的距离
2025-03-21 16:02:51 +08:00
const distanceToViewportTop = rect.top + window.scrollY - 60;
window.scrollTo({
top: distanceToViewportTop,
behavior: "smooth",
2025-03-21 16:02:51 +08:00
});
};
2023-12-18 11:12:07 +08:00
2025-03-21 16:02:51 +08:00
let picture = ref({});
2023-12-18 11:12:07 +08:00
2025-03-21 16:02:51 +08:00
let emojiState = ref(false);
let emojiMaskState = ref(false);
2023-12-18 11:12:07 +08:00
2025-03-21 16:02:51 +08:00
const emojiData = ["😀", "😁", "😆", "😅", "😂", "😉", "😍", "🥰", "😋", "😜", "🤪", "😎", "🤩", "🥳", "😔", "🙁", "😭", "😡", "😳", "🤗", "🤔", "🤭", "🤫", "😯", "😵", "🙄", "🥴", "🤢", "🤑", "🤠", "👌", "✌️", "🤟", "🤘", "🤙", "👍", "👎", "✊", "👏", "🤝", "🙏", "💪", "❤️", "💔", "🌹", "🥀", "🎉", "🎁", "🧧", "🌙", "⭐", "🌍", "💌", "📬", "🚗", "🚕", "🚲", "🛵", "🚀", "🚁", "⛵", "🚢", "🍎", "🍐", "🍊", "🍉", "🍓", "🍑", "🍔", "🍟", "🍕", "🥪", "🍜", "🍡", "🍨", "🍦", "🎂", "🍰", "🍭", "🍿", "🍩", "🧃", "🍹"];
2023-12-18 11:12:07 +08:00
2025-02-10 19:03:44 +08:00
// 打开 Emoji
const openEmoji = (index, i) => {
2025-02-14 18:55:06 +08:00
if (isNeedLogin.value) {
2025-03-21 16:02:51 +08:00
goLogin();
return;
2025-02-14 18:55:06 +08:00
}
2025-03-21 16:02:51 +08:00
if (i != undefined) commentList.value[index].child[i]["emojiState"] = true;
else if (index != undefined) commentList.value[index]["emojiState"] = true;
2025-02-10 19:03:44 +08:00
else {
2025-03-21 16:02:51 +08:00
closeEmoji();
closeAnswerCommentsChild();
emojiState.value = true;
2023-12-18 11:12:07 +08:00
}
2025-03-21 16:02:51 +08:00
emojiMaskState.value = true;
};
2024-07-19 15:03:52 +08:00
2025-02-10 19:03:44 +08:00
// 关闭 Emoji
const closeEmoji = (index, i) => {
2025-03-21 16:02:51 +08:00
commentList.value.forEach((ele) => {
ele["emojiState"] = false;
2025-02-10 19:03:44 +08:00
if (ele["child"] && ele["child"].length != 0) {
2025-03-21 16:02:51 +08:00
ele["child"].forEach((el) => {
el["emojiState"] = false;
});
2024-07-19 15:03:52 +08:00
}
2025-03-21 16:02:51 +08:00
});
2024-07-19 15:03:52 +08:00
2025-03-21 16:02:51 +08:00
emojiState.value = false;
emojiMaskState.value = false;
editEmojiState.value = false;
};
2023-12-18 11:12:07 +08:00
2025-02-10 19:03:44 +08:00
// 选择 Emoji
const selectEmoji = (key, index, i) => {
2025-03-21 16:02:51 +08:00
closeEmoji();
2025-02-10 19:03:44 +08:00
if (i != undefined) {
2025-03-21 16:02:51 +08:00
if (!commentList.value[index]["child"][i]["commentInput"]) commentList.value[index]["child"][i]["commentInput"] = "";
commentList.value[index]["child"][i]["commentInput"] += key;
2025-02-10 19:03:44 +08:00
} else if (index != undefined) {
2025-03-21 16:02:51 +08:00
if (!commentList.value[index]["commentInput"]) commentList.value[index]["commentInput"] = "";
commentList.value[index]["commentInput"] += key;
2025-02-10 19:03:44 +08:00
} else {
2025-03-21 16:02:51 +08:00
commentInputTop.value += key;
2023-12-18 11:12:07 +08:00
}
2025-03-21 16:02:51 +08:00
};
2023-12-18 11:12:07 +08:00
2025-02-10 19:03:44 +08:00
// 自动输入框增高
2025-03-21 16:02:51 +08:00
const autoResize = (e) => {
e.target.style.height = "auto"; // 重置高度
e.target.style.height = `${e.target.scrollHeight}px`; // 设置为内容高度
};
2023-12-18 11:12:07 +08:00
2025-03-21 16:02:51 +08:00
const maxSize = 20 * 1024 * 1024; // 20MB
2023-12-18 11:12:07 +08:00
2025-02-10 19:03:44 +08:00
const handleInputPaste = (event, index, ii) => {
2025-03-21 16:02:51 +08:00
const items = event.clipboardData.items; // 获取粘贴的内容
2024-01-05 18:20:39 +08:00
2025-02-10 19:03:44 +08:00
for (let i = 0; i < items.length; i++) {
2025-03-21 16:02:51 +08:00
const item = items[i];
2025-02-10 19:03:44 +08:00
if (item.type.startsWith("image/")) {
2025-03-21 16:02:51 +08:00
event.preventDefault();
const file = item.getAsFile(); // 获取文件
2024-01-05 18:20:39 +08:00
2025-02-10 19:03:44 +08:00
if (file.size > maxSize) {
ElMessage({
message: "文件大小不能超过 20MB",
type: "error",
2025-03-21 16:02:51 +08:00
});
return;
2024-01-05 18:20:39 +08:00
}
2025-03-21 16:02:51 +08:00
const reader = new FileReader();
reader.onload = (e) => {
const base64 = e.target.result;
2023-12-18 11:12:07 +08:00
2025-03-21 16:02:51 +08:00
uploadImg(base64).then((res) => {
2025-02-10 19:03:44 +08:00
const obj = {
base64,
...res,
2025-03-21 16:02:51 +08:00
};
if (editCommentState.value) editPicture.value = obj;
2025-02-17 19:01:09 +08:00
else {
2025-03-21 16:02:51 +08:00
if (ii != undefined) commentList.value[index].child[ii]["picture"] = obj;
else if (index != undefined) commentList.value[index]["picture"] = obj;
else picture.value = obj;
2025-02-17 19:01:09 +08:00
}
2025-03-21 16:02:51 +08:00
ElMessage.success("上传成功");
});
};
reader.readAsDataURL(file);
2023-12-18 11:12:07 +08:00
}
}
2025-03-21 16:02:51 +08:00
};
2023-12-18 11:12:07 +08:00
2025-02-10 19:03:44 +08:00
const handleFileUpload = (event, index, i) => {
2025-03-21 16:02:51 +08:00
closeEmoji();
const file = event.target.files[0]; // 获取选择的文件
2023-12-18 11:12:07 +08:00
2025-03-21 16:02:51 +08:00
if (!file) return;
2023-12-18 11:12:07 +08:00
2025-02-10 19:03:44 +08:00
if (file.size > maxSize) {
ElMessage({
message: "文件大小不能超过 20MB",
type: "error",
2025-03-21 16:02:51 +08:00
});
return;
2023-12-18 11:12:07 +08:00
}
2025-03-21 16:02:51 +08:00
const reader = new FileReader();
reader.onload = (e) => {
const base64 = e.target.result;
uploadImg(base64).then((res) => {
2025-02-10 19:03:44 +08:00
const obj = {
base64,
...res,
2025-03-21 16:02:51 +08:00
};
2023-12-18 11:12:07 +08:00
2025-03-21 16:02:51 +08:00
if (editCommentState.value) editPicture.value = obj;
2025-02-17 19:01:09 +08:00
else {
2025-03-21 16:02:51 +08:00
if (i != undefined) commentList.value[index].child[i]["picture"] = obj;
else if (index != undefined) commentList.value[index]["picture"] = obj;
else picture.value = obj;
2025-02-17 19:01:09 +08:00
}
2023-12-18 11:12:07 +08:00
2025-02-10 19:03:44 +08:00
ElMessage({
message: "上传成功",
type: "success",
2025-03-21 16:02:51 +08:00
});
});
};
reader.readAsDataURL(file);
};
2023-12-18 11:12:07 +08:00
2025-02-10 19:03:44 +08:00
// 删除上传的图片
const closeFileUpload = (index, i) => {
2025-03-21 16:02:51 +08:00
if (i != undefined) commentList.value[index].child[i]["picture"] = {};
else if (index != undefined) commentList.value[index]["picture"] = {};
else picture.value = {};
};
2024-01-05 18:20:39 +08:00
2025-02-10 19:03:44 +08:00
// 上传图片 获取图片url
2025-03-21 16:02:51 +08:00
const uploadImg = (base64) => {
2025-02-10 19:03:44 +08:00
return new Promise((resolve, reject) => {
// detailLoading.value = true
commonUploadHttp({
data: base64,
})
2025-03-21 16:02:51 +08:00
.then((res) => {
2025-02-20 17:16:29 +08:00
if (res.code != 200) {
ElMessage({
message: res.message || "上传失败",
type: "error",
2025-03-21 16:02:51 +08:00
});
return;
2025-02-20 17:16:29 +08:00
}
2025-03-21 16:02:51 +08:00
let data = res.data;
resolve(data);
2025-02-20 17:16:29 +08:00
})
2025-03-21 16:02:51 +08:00
.catch((err) => {
console.log("err", err);
});
2025-02-10 19:03:44 +08:00
// .finally(() => (detailLoading.value = false))
2025-03-21 16:02:51 +08:00
});
};
2024-01-05 18:20:39 +08:00
2025-03-21 16:02:51 +08:00
let dialogSrc = ref(""); // 大图的src
2024-01-05 18:20:39 +08:00
2025-02-10 19:03:44 +08:00
// 处理点击答案图片 展开大图
2025-03-21 16:02:51 +08:00
const handleAnswerText = (e) => {
2025-02-10 19:03:44 +08:00
if (e.target.tagName === "IMG") {
2025-03-21 16:02:51 +08:00
var src = e.target.getAttribute("src");
dialogSrc.value = src;
window.addEventListener("keydown", handleKeydown);
2024-01-05 18:20:39 +08:00
}
2025-03-21 16:02:51 +08:00
};
2024-07-24 16:17:06 +08:00
2025-02-10 19:03:44 +08:00
// 大图的监听 esc 键盘按钮
2025-03-21 16:02:51 +08:00
const handleKeydown = (event) => {
if (event.key !== "Escape") return;
dialogSrc.value = "";
window.removeEventListener("keydown", handleKeydown); // 取消监听
};
2025-02-13 19:05:25 +08:00
2025-03-21 16:02:51 +08:00
let permissions = ref([]);
2025-02-14 18:55:06 +08:00
onMounted(() => {
setTimeout(() => {
2025-03-21 16:02:51 +08:00
permissions.value = window["permissions"] || [];
2025-03-11 13:57:38 +08:00
// permissions.value = ["mj.hide", "comment.edit", "comment.delete"]
2025-03-21 16:02:51 +08:00
}, 1000);
});
2025-02-13 19:05:25 +08:00
2025-03-21 16:02:51 +08:00
let dialogVisible = ref(false);
2025-02-18 19:06:04 +08:00
2025-03-21 16:02:51 +08:00
const openHide = () => (dialogVisible.value = true);
2025-02-18 19:06:04 +08:00
2025-02-13 19:05:25 +08:00
// 点击隐藏
const handleHide = () => {
2025-03-21 16:02:51 +08:00
mjHideHttp({ token }).then((res) => {
dialogVisible.value = false;
ElMessage.success(res.message || "隐藏成功");
router.replace("/index.html");
});
};
2025-02-13 19:05:25 +08:00
2025-02-14 18:55:06 +08:00
// 点击删除
const commentDelete = (token, index, i) => {
commentDeleteHttp({
token,
2025-03-21 16:02:51 +08:00
}).then((res) => {
2025-02-14 18:55:06 +08:00
if (res.code != 200) {
2025-03-21 16:02:51 +08:00
ElMessage.error(res.message);
return;
2025-02-14 18:55:06 +08:00
}
2025-02-13 19:05:25 +08:00
2025-02-14 18:55:06 +08:00
if (i >= 0) {
2025-03-21 16:02:51 +08:00
commentList.value[index].child.splice(i, 1);
commentList.value[index].childnum -= 1;
console.log("childnum", commentList.value[index]);
2025-02-14 18:55:06 +08:00
} else {
2025-03-21 16:02:51 +08:00
commentComments.value -= commentList.value[index].childnum;
commentList.value.splice(index, 1);
2025-02-14 18:55:06 +08:00
}
2025-02-13 19:05:25 +08:00
2025-03-21 16:02:51 +08:00
commentComments.value -= 1;
});
};
2025-02-14 18:55:06 +08:00
const judgeLogin = () => {
2025-03-21 16:02:51 +08:00
if (isNeedLogin.value) goLogin();
};
2025-02-17 19:01:09 +08:00
2025-03-21 16:02:51 +08:00
let editCommentState = ref(false);
let editToken = "";
let editPicture = ref({});
let editInput = ref("");
let editEmojiState = ref(false);
const editInputRef = ref(null);
2025-02-17 19:01:09 +08:00
const openEdit = (token, index, i) => {
2025-03-21 16:02:51 +08:00
const list = JSON.parse(JSON.stringify(commentList.value));
let target = {};
if (i != null) target = list[index]["child"][i];
else target = list[index];
console.log(token, index, i, target);
editToken = target.token || "";
editInput.value = target.content || "";
editPicture.value = target.image || {};
2025-02-17 19:01:09 +08:00
2025-03-21 16:02:51 +08:00
editCommentState.value = true;
2025-02-17 19:01:09 +08:00
nextTick(() => {
2025-03-21 16:02:51 +08:00
editInputRef.value.style.height = `${editInputRef.value.scrollHeight}px`;
});
};
2025-02-17 19:01:09 +08:00
const closeEdit = () => {
2025-03-21 16:02:51 +08:00
editPicture.value = {};
editToken = "";
editInput.value = "";
editCommentState.value = false;
};
2025-02-17 19:01:09 +08:00
// 打开 Emoji
const openEditEmoji = (index, i) => {
if (isNeedLogin.value) {
2025-03-21 16:02:51 +08:00
goLogin();
return;
2025-02-17 19:01:09 +08:00
}
2025-03-21 16:02:51 +08:00
editEmojiState.value = true;
};
2025-02-17 19:01:09 +08:00
2025-03-21 16:02:51 +08:00
const selectEditEmoji = (key) => {
closeEmoji();
editInput.value += key;
};
2025-02-17 19:01:09 +08:00
const postEditComment = () => {
if (isNeedLogin.value) {
2025-03-21 16:02:51 +08:00
goLogin();
return;
2025-02-17 19:01:09 +08:00
}
2025-03-21 16:02:51 +08:00
const image = editPicture.value;
2025-02-17 19:01:09 +08:00
commentsEditSubmit({
content: editInput.value,
token: editToken,
image: image ? { aid: image.aid, url: image.url } : null,
2025-03-21 16:02:51 +08:00
}).then((res) => {
2025-02-17 19:01:09 +08:00
if (res.code != 200) {
2025-03-21 16:02:51 +08:00
ElMessage.error(res.message);
return;
2025-02-17 19:01:09 +08:00
}
2025-03-21 16:02:51 +08:00
commentList.value.forEach((element) => {
2025-02-17 19:01:09 +08:00
if (element.token == editToken) {
2025-03-21 16:02:51 +08:00
element["content"] = editInput.value;
element["image"] = image;
2025-02-17 19:01:09 +08:00
}
element.child &&
2025-03-21 16:02:51 +08:00
element.child.forEach((ele) => {
2025-02-17 19:01:09 +08:00
if (ele.token == editToken) {
2025-03-21 16:02:51 +08:00
ele["content"] = editInput.value;
ele["image"] = image;
2025-02-17 19:01:09 +08:00
}
2025-03-21 16:02:51 +08:00
});
});
2025-02-17 19:01:09 +08:00
2025-03-21 16:02:51 +08:00
editPicture.value = {};
editToken = "";
editCommentState.value = false;
editEmojiState.value = false;
ElMessage.success(res.message);
});
};
2025-02-17 19:01:09 +08:00
2025-03-21 16:02:51 +08:00
const closeEditEmoji = () => (editEmojiState.value = false);
2025-02-20 17:16:29 +08:00
const handleEditFile = () => {
2025-03-21 16:02:51 +08:00
editEmojiState.value = false;
judgeLogin();
};
2025-02-20 17:16:29 +08:00
2025-03-21 16:02:51 +08:00
const closeEditFileUpload = () => (editPicture.value = {});
2025-02-10 19:03:44 +08:00
</script>
2025-02-10 19:03:44 +08:00
<style lang="less" scoped>
@import url(@/assets/css/details.css);
</style>
2025-02-10 19:03:44 +08:00
<style lang="less">
@import url(@/assets/css/detailsPop.css);
2023-12-18 11:12:07 +08:00
</style>