Files
PC-vote/components/DetailsArea.vue
DESKTOP-RQ919RC\Pc a584a2771b fix(DetailsArea): 修复举报功能并更新相关样式
修复举报功能,区分评论和主题举报类型。更新讨论图标和投币文本样式。移除不必要的背景色和注释代码。

refactor(api): 重构举报相关API接口
将评论举报和主题举报分离为独立接口,提高代码可维护性。

style: 清理多余空格和注释
统一代码格式,删除无用注释和空白行。
2025-11-12 19:10:49 +08:00

585 lines
17 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="floor-area flexacenter" :class="{ show: isLoaded }" @click="closeDiscussInputFields()">
<div class="floor-content flexacenter">
<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>
<div class="floor-left flexacenter">
<div class="item flexacenter" @click="handleLike">
<img class="icon pitch" v-if="islike == 1" src="@/assets/img/like-red-pitch.png" />
<img class="icon" v-else src="@/assets/img/like-icon.png" />
<div>{{ topicInfo["likes"] || "赞" }}</div>
</div>
<div class="item flexacenter" @click="handleCollect()">
<img class="icon" v-if="iscollection == 1" src="@/assets/img/collect-icon-colours.svg" />
<img class="icon" v-else src="@/assets/img/collect-icon.png" />
<div>{{ topicInfo["collections"] || "收藏" }}</div>
</div>
<div class="item flexacenter" style="cursor: auto">
<img class="icon" src="@/assets/img/discuss-black-icon.png" />
<div>{{ commentComments || "讨论" }}</div>
</div>
<div class="item flexacenter" @click="openBi()">
<img class="icon" src="@/assets/img/bi-black-icon.png" />
<div class="coinText" id="coinText">{{ topicInfo.coins || "投币" }}</div>
</div>
<ClientOnly>
<el-popover placement="bottom" width="628px" trigger="click" popper-style="padding: 0;border-radius: 10px;" v-model:visible="transmitBoxState">
<template #reference>
<div class="item flexacenter" @click="handleShare"><img class="icon" src="@/assets/img/transmit-icon.png" />转发</div>
</template>
<div class="transmit-box flexflex">
<img class="cross-icon" @click.stop="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["title"] }}</div>
<div class="transmit-url">{{ getFullUrl() }}</div>
</div>
<div class="transmit-web-btn flexcenter" @click="copyText(`${info['title']} + ${getFullUrl()}`)">复制链接</div>
</div>
<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" />
扫码转发该投票
</div>
</div>
</div>
</div>
</el-popover>
</ClientOnly>
</div>
<!-- <div class="floor-middle" ref="floormiddle" @mouseover="closeMouseOver" @mouseout="openAutoCarousel" :class="{ 'floor-middle-respond': respondShowState }">
<div v-if="!respondShowState" class="flexacenter comment-box">
<img v-if="userInfoWin?.avatar" class="avatar" :src="userInfoWin?.avatar" />
<el-input class="comment-input flex1" name="14752869" v-model="floorCommentInput" placeholder="说说你的想法或疑问…" @keydown.enter="floorCommentBtn('input')" maxlength="500" show-word-limit autocomplete="off" @focus="closeMouseOver()"></el-input>
<div class="comment-btn flexcenter" @click="floorCommentBtn('input')">
<img class="comment-btn-icon" src="@/assets/img/arrow-white.svg" />
</div>
</div>
<div class="flexacenter respond">
<div class="respond-title">给个回应</div>
<div class="respond-box flex1">
<div class="respond-item" v-for="item in randomBottomEmojis" :key="item" v-html="jointriposte(item)" @click="selectEomji(item)"></div>
</div>
<RespondAdd type="bottom" :respondShowState="respondShowState" @update:respondShowState="respondShowState = $event"></RespondAdd>
</div>
</div> -->
</div>
</div>
<Like v-if="isLikeGif"></Like>
<bi-card :coins="topicInfo.coins" :token="topicToken" pagetpye="vote"></bi-card>
</template>
<script setup>
import { ElMessage } from "element-plus";
let props = defineProps({
ripostecount: Object,
commentComments: Number,
});
let topicInfo = inject("topicInfo");
const respondShowState = ref(false);
let openAttest = inject("openAttest");
const realname = inject("realname");
let isNeedLogin = inject("isNeedLogin");
const goLogin = inject("goLogin");
const userInfoWin = inject("userInfoWin");
let info = inject("info");
let islike = inject("islike");
let iscollection = inject("iscollection");
let qrcode = inject("qrcode");
let token = inject("token");
let topicToken = inject("topicToken");
const topHeadRef = inject("topHeadRef");
const isLoaded = inject("isLoaded");
const floormiddle = ref(null);
// 获取完整 url
const getFullUrl = () => {
if (typeof window === "undefined") return;
return window.location.href;
};
// 复制
let copyText = (text) => {
if (navigator.clipboard) {
copyText = () => {
navigator.clipboard.writeText(text);
ElMessage.success("复制成功");
};
} else {
copyText = () => {
var tempInput = document.createElement("input");
tempInput.value = text;
document.body.appendChild(tempInput);
tempInput.select();
document.execCommand("copy");
document.body.removeChild(tempInput);
ElMessage.success("复制成功");
};
}
copyText();
};
let floorRightState = ref(false); // 右下角 的二维码显示状态
// 处理右下角 鼠标经过箭头 展示二维码
const handleFloorRight = (value) => {
floorRightState.value = value;
};
// 点击 收藏
const handleCollect = () => {
if (isNeedLogin.value) {
goLogin();
return;
}
topHeadRef.value.count = {};
operateCollectHttp({ token: topicToken.value }).then((res) => {
if (res.code != 200) {
ElMessage.error(res["message"]);
return;
}
let data = res.data;
topicInfo.value["collections"] = data["collections"];
iscollection.value = data["status"];
ElMessage.success(res["message"]);
});
};
const isBrowser = computed(() => {
return process.client; // 使用 process.client 判断是否在浏览器环境下
});
let isLikeGif = ref(false);
// 点赞
const handleLike = () => {
if (realname.value == 0 && userInfoWin.value.uin > 0) {
openAttest();
return;
}
if (isNeedLogin.value) {
goLogin();
return;
}
if (islike.value) {
ElMessage.error("不可取消点赞");
return;
}
operateLikeHttp({ token: topicToken.value }).then((res) => {
if (res.code != 200) {
ElMessage.error(res.message);
return;
}
let data = res.data;
const status = data["status"];
topicInfo.value["likes"] = data["likes"];
islike.value = status;
ElMessage.success(res.message);
if (status) {
isLikeGif.value = true;
setTimeout(() => (isLikeGif.value = false), 2000);
}
});
};
// 底部转发弹窗显示 状态
let transmitBoxState = ref(false);
const floorCommentInput = inject("floorCommentInput");
const floorCommentBtn = inject("floorCommentBtn");
const emit = defineEmits(["closeDiscussInputFields"]);
// // 点击底部调用关闭讨论输入框
const closeDiscussInputFields = () => emit("closeDiscussInputFields");
onMounted(() => {});
watch(isLoaded, (newValue, oldValue) => {
if (newValue === true) {
openAutoCarousel();
}
});
let floormiddleIndex = 0; // 0起
let floormiddleTimer = null;
// 开启自动轮播
const openAutoCarousel = () => {
return;
floormiddleTimer = setInterval(() => {
floormiddleIndex = +!floormiddleIndex;
floormiddle.value.scrollTo({
top: floormiddleIndex * 40,
behavior: "smooth",
});
}, 2000);
};
// 鼠标移入 关闭 自动滚动
const closeMouseOver = () => {
clearInterval(floormiddleTimer);
};
onBeforeUnmount(() => {
clearInterval(floormiddleTimer);
});
const randomBottomEmojis = inject("randomBottomEmojis");
const selectEomji = inject("selectEomji");
const jointriposte = inject("jointriposte");
const openBi = () => {
if (isNeedLogin.value) {
goLogin();
return;
}
BiComponent.initComponent();
};
</script>
<style scoped lang="less">
.floor-area {
position: fixed;
left: 0;
bottom: 0;
// bottom: 50%;
width: 100vw;
min-width: 1200px;
height: 70px;
z-index: 11;
background: -webkit-linear-gradient(270deg, rgba(255, 255, 255, 1) 0%, rgba(242, 242, 242, 1) 100%);
background: -moz-linear-gradient(180deg, rgba(255, 255, 255, 1) 0%, rgba(242, 242, 242, 1) 100%);
background: linear-gradient(180deg, rgba(255, 255, 255, 1) 0%, rgba(242, 242, 242, 1) 100%);
-moz-box-shadow: 0px -1px 2px rgba(0, 0, 0, 0.192156862745098);
-webkit-box-shadow: 0px -1px 2px rgba(0, 0, 0, 0.192156862745098);
box-shadow: 0px -1px 2px rgba(0, 0, 0, 0.192156862745098);
display: none;
&.show {
display: flex;
animation: animafloor 1s forwards;
animation-timing-function: cubic-bezier(0.98, -0.2, 0.55, 0.97);
/* 先快后慢的时间曲线 */
animation-fill-mode: both;
}
.floor-content {
width: 1200px;
height: 100%;
margin: 0 auto;
padding: 0 30px;
display: flex;
justify-content: space-between;
.floor-left {
margin-left: 30px;
// flex: 1;
justify-content: space-between;
.item {
cursor: pointer;
color: #333333;
font-size: 14px;
margin-right: 50px;
.icon {
width: 16px;
margin-right: 5px;
// animation: anima 1s forwards;
animation: liftAndReset 0.3s forwards;
}
@keyframes liftAndReset {
0% {
transform: scale(1);
}
50% {
transform: scale(1.2);
}
100% {
transform: scale(1);
}
}
// :nth-of-type(1) {
// animation-delay: 1s;
// }
// :nth-of-type(2) {
// animation-delay: 2s;
// }
&.operate-item {
position: relative;
display: flex;
justify-content: center;
}
}
}
.floor-right {
color: #7f7f7f;
font-size: 13px;
cursor: pointer;
.arrows-icon {
width: 12px;
height: 12px;
margin: 0 10px;
}
.QR-code-ball {
width: 40px;
height: 40px;
background-color: rgba(235, 235, 235, 1);
border-radius: 20px;
cursor: pointer;
}
}
.comment-box {
width: 471px;
height: 40px;
border-radius: 152px;
background-color: #fff;
border: 1px solid rgba(215, 215, 215, 1);
.avatar {
width: 28px;
height: 28px;
border-radius: 50%;
margin-left: 6px;
}
.comment-input {
height: 100%;
border: none;
outline: none;
padding: 0 12px;
font-size: 14px;
/deep/ .el-input__wrapper {
box-shadow: none;
padding: 0;
}
}
.comment-btn {
width: 40px;
height: 40px;
background-color: var(--main-color);
border-radius: 20px;
cursor: pointer;
.comment-btn-icon {
width: 14px;
height: 15px;
}
}
}
.respond {
padding-left: 18px;
width: 471px;
height: 40px;
background-color: rgba(255, 255, 255, 1);
border: 1px solid rgba(235, 235, 235, 1);
border-radius: 208px;
position: relative;
.respond-title {
font-family: "PingFangSC-Regular", "PingFang SC", sans-serif;
font-weight: 400;
font-size: 14px;
color: #555555;
line-height: 20px;
}
.respond-box {
display: flex;
justify-content: space-around;
.respond-item {
font-family: "emojifont";
font-size: 18px;
line-height: 40px;
cursor: pointer;
}
}
/deep/ .respond-add {
width: 40px;
height: 40px;
border-radius: 50%;
// background-color: var(--main-color);
.respond-add-icon {
width: 16px;
height: 16px;
}
&.angle::after {
top: -17px;
bottom: auto;
transform: translateX(-50%) rotate(225deg);
}
}
}
.floor-middle {
display: flex;
flex-direction: column;
height: 40px;
overflow: hidden;
&.floor-middle-respond {
overflow: visible;
// overflow: hidden;
}
}
}
}
.transmit-box {
width: 628px;
border-radius: 10px;
justify-content: space-between;
padding: 40px 35px 42px;
// z-index: 3;
cursor: auto;
.cross-icon {
width: 22px;
height: 22px;
position: absolute;
top: 6px;
right: 6px;
cursor: pointer;
padding: 6px;
}
.transmit-title {
font-weight: 650;
font-size: 16px;
color: #000000;
line-height: 24px;
margin-bottom: 24px;
}
.transmit-content {
border: 1px solid rgba(242, 242, 242, 1);
border-radius: 16px;
}
.transmit-web {
.transmit-content {
width: 300px;
font-size: 14px;
line-height: 24px;
padding: 14px 16px;
margin-bottom: 32px;
.transmit-headline {
color: #333333;
}
.transmit-url {
color: #aaaaaa;
word-wrap: break-word;
}
}
.transmit-web-btn {
width: 120px;
height: 38px;
background-color: rgba(114, 219, 134, 1);
border-radius: 8px;
font-size: 14px;
color: #fff;
cursor: pointer;
}
}
.transmit-mini {
.transmit-content {
flex-direction: column;
padding: 22px 44px;
.transmit-mini-img {
width: 90px;
height: 90px;
margin-bottom: 21px;
}
color: #555555;
font-size: 13px;
.give-sweep {
width: 12px;
height: 12px;
margin-right: 8px;
}
}
}
}
.examine-code {
width: 113px;
height: 113px;
}
@keyframes animafloor {
0% {
transform: translate3d(-100%, 0, 0);
}
90% {
left: 20px;
}
100% {
transform: translateZ(0);
}
}
</style>