feat(Details): 新增投票详情页管理功能和评论优化

- 添加投票详情页的管理功能,包括隐藏、推荐、精华和删除操作
- 优化评论组件,支持多图上传和显示
- 新增投币功能组件
- 更新API接口调用方式,适配新后端接口
- 完善用户权限管理逻辑
- 修复样式问题和交互体验
This commit is contained in:
DESKTOP-RQ919RC\Pc
2025-11-11 19:05:46 +08:00
parent ad6d186301
commit 68000d7e43
14 changed files with 839 additions and 226 deletions

View File

@@ -1,4 +1,5 @@
<template>
<Head>
<Title>{{ `${seo["title"] || "投票"} - 寄托天下出国留学网` }}</Title>
<Meta name="keyword" :content="seo['keyword']" />
@@ -7,13 +8,39 @@
<TopHead ref="topHeadRef"></TopHead>
<div class="content flexflex" :style="{ '--main-color': colourValue[uniqidIndex]['main'], '--bg-color': colourValue[uniqidIndex]['bg'], '--bc-color': colourValue[uniqidIndex]['bc'] }">
<div class="header flexflex">
<div class="label flexflex" v-if="sectionn?.length || tags?.length || info.recommend == 1 || info.best == 1">
<img class="item icon" v-if="info.recommend == 1" src="@/assets/img/recommend-icon.png" />
<img class="item icon" v-if="info.best == 1" src="@/assets/img/essence-icon.png" />
<a class="item blue" v-for="(item, index) in sectionn" :key="item" :href="'/section/' + item.uniqid" target="_blank">{{ item.name }}</a>
<a class="item" v-for="(item, index) in tags" :key="item" :href="'/tag/' + item" target="_blank">{{ item }}</a>
<div class="label flexflex" v-if="sectionn?.length || tags?.length || topicInfo.recommend == 1 || topicInfo.best == 1">
<img class="item icon" v-if="topicInfo.recommend == 1" src="@/assets/img/recommend-icon.png" />
<img class="item icon" v-if="topicInfo.best == 1" src="@/assets/img/essence-icon.png" />
<a class="item blue" v-for="(item, index) in sectionn" :key="item" :href="`https://f.gter.net/section/${item.uniqid}`" target="_blank">{{ item.name }}</a>
<a class="item" v-for="(item, index) in tags" :key="item" :href="`https://f.gter.net/tag/${item}?type=vote`" target="_blank">{{ item }}</a>
</div>
<div class="flexacenter" style="position: relative;">
<div class="flex1">{{ info.title }}</div>
<div class="view flexacenter">
<img class="icon" src="@/assets/img/eye-icon.svg" />
<div class="text">{{ topicInfo.views }}</div>
</div>
<div class="btn flexcenter" @click.stop="cutShow">
<img class="icon" src="@/assets/img/dot-dot-dot-gray.png" />
</div>
<div v-if="show">
<div class="mask" @click.stop="cutShow"></div>
<div class="operate">
<div class="item" @click.stop="report">举报</div>
<template v-if="ismanager">
<div class="item" @click.stop="hide">{{ topicInfo.hidden == 0 ? "隐藏" : "显示" }}</div>
<div class="item" @click.stop="recommend">{{ topicInfo.recommend == 1 ? "取消" : "" }}推荐</div>
<div class="item" @click.stop="essence">{{ topicInfo.best == 1 ? "取消" : "" }}精华</div>
</template>
<template v-if="ismyself">
<div class="item" @click.stop="deleteItem">删除</div>
</template>
</div>
</div>
</div>
<span>{{ info.title }}</span>
</div>
<div class="left">
<div class="info flexacenter">
@@ -96,8 +123,7 @@
回应
<div class="respond-amount">{{ ripostecount.total || 0 }}</div>
<div v-if="ripostecount.user > 0" class="respond-list-btn" @click="openPopList">
<span class="respond-list-btn-amount">{{ ripostecount.user }}</span
>人回应
<span class="respond-list-btn-amount">{{ ripostecount.user }}</span>人回应
<img class="respond-list-btn-icon" src="@/assets/img/arrowsRight.svg" />
</div>
</div>
@@ -125,7 +151,7 @@
</div>
</template>
<DetailsComments ref="commentsRef" :token="token" @update:commentComments="commentComments = $event"></DetailsComments>
<DetailsComments ref="commentsRef" :token="topicToken" @update:commentComments="commentComments = $event"></DetailsComments>
</div>
<DetailsArea @closeDiscussInputFields="closeDiscussInputFields" :ripostecount="ripostecount" :commentComments="commentComments"></DetailsArea>
</div>
@@ -147,8 +173,7 @@
</div>
<template v-else>
<div class="respond-pop-title">
<span class="respond-pop-amount">{{ ripostecount.user }}</span
>人回应
<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">
@@ -166,6 +191,9 @@
</template>
</div>
</div>
<Report v-if="reportAlertShow" :reportToken="reportToken"></Report>
</template>
<script setup>
@@ -414,9 +442,9 @@ const getDetails = async () => {
info.value = data["info"];
isvote.value = data["isvote"];
iscollection.value = data["iscollection"];
islike.value = data["islike"];
ismyself.value = data["ismyself"];
// iscollection.value = data["iscollection"];
// islike.value = data["islike"];
// ismyself.value = data["ismyself"];
option.value = data["option"];
qrcode.value = data.share?.qrcode;
token.value = data["token"];
@@ -429,9 +457,77 @@ const getDetails = async () => {
});
getRiposte();
const topic = data.topic
console.log("topic", topic);
getTopicDetail(topic.uniqid);
});
};
let topicToken = ref("");
let topicInfo = ref({});
let sectionn = ref([]);
let tags = ref([]);
provide("topicInfo", topicInfo);
provide("topicToken", topicToken);
const getTopicDetail = (uniqid) => {
topicDetailHttp({ uniqid }).then((res) => {
if (res.code != 200) {
ElMessage.error(res.message);
return;
}
let data = res.data;
topicToken.value = data.token;
console.log("topicDetail", data);
const targetInfo = data.info;
if (!targetInfo.hidden) targetInfo.hidden = 0;
const sectionNameSet = new Set(targetInfo.sectionn.map((item) => item.name));
if (targetInfo.tags) {
const newTag = targetInfo?.tags.filter((tagName) => !sectionNameSet.has(tagName));
tags.value = newTag;
}
sectionn.value = targetInfo.sectionn;
topicInfo.value = targetInfo;
// ismyself.value = data.ismyself;
if (data.islogin) getTopicOperation();
});
}
const getTopicOperation = () => {
topicgetOperationHttp({
token: topicToken.value,
actions: ["like", "collection"],
})
.then((res) => {
console.log("res", res);
const data = res.data;
const like = data.like;
const collection = data.collection;
islike.value = like.status;
iscollection.value = collection.status;
})
.catch((err) => {
console.log("err", err);
});
};
provide("getDetails", getDetails);
// 点击发送信息
@@ -447,10 +543,10 @@ const TAHomePage = (uin) => {
};
// 跳转 url
const redirectToExternalWebsite = (url) => {
const redirectToExternalWebsite = (url, target = "_blank") => {
const link = document.createElement("a");
link.href = url;
link.target = "_blank";
link.target = target;
link.click();
};
@@ -688,6 +784,68 @@ const selectEomjiListPop = (key) => {
});
};
let show = ref(false);
let ismanager = inject("ismanager");
const cutShow = () => {
show.value = !show.value; // 修改为切换显示状态
};
let reportAlertShow = ref(false);
let reportToken = ref("");
provide("reportAlertShow", reportAlertShow);
// 点击打开举报
const report = (token) => {
if (isNeedLogin.value) {
goLogin();
return;
}
cutShow()
reportToken.value = topicToken.value;
reportAlertShow.value = true;
};
// 隐藏
const hide = () => {
const target = topicInfo.value;
managerHide(topicToken.value, target.hidden, "vote").then((value) => {
target.hidden = value;
topicInfo.value = target;
cutShow();
});
};
// 推荐
const recommend = () => {
const target = topicInfo.value;
managerRecommend(topicToken.value, target.recommend).then((value) => {
target.recommend = value;
topicInfo.value = target;
cutShow();
});
};
// 精华
const essence = () => {
const target = topicInfo.value;
managerEssence(topicToken.value, target.best).then((value) => {
target.best = value;
topicInfo.value = target;
cutShow();
});
};
const deleteItem = () => {
managerDelete(token)
.then(() => redirectToExternalWebsite("/", "_self"))
.finally(() => cutShow());
};
const { $cache } = useNuxtApp();
try {
@@ -716,7 +874,7 @@ try {
});
}
}
} catch (error) {}
} catch (error) { }
</script>
<style scoped lang="less">
@@ -727,11 +885,13 @@ try {
.default-popup {
.el-dialog__header {
padding: 0;
.el-dialog__headerbtn {
width: 36px;
height: 36px;
}
}
.el-dialog__body {
padding: 0;
}