feat(Details): 新增投票详情页管理功能和评论优化
- 添加投票详情页的管理功能,包括隐藏、推荐、精华和删除操作 - 优化评论组件,支持多图上传和显示 - 新增投币功能组件 - 更新API接口调用方式,适配新后端接口 - 完善用户权限管理逻辑 - 修复样式问题和交互体验
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user