PC-vote/components/MyPopup.vue
2024-01-12 19:12:30 +08:00

439 lines
14 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>
<el-dialog v-model="show" width="750px" align-center class="dialog-box">
<div class="box flexflex">
<img class="cross" src="@/assets/img/cross-icon.png" alt @click="closeDialog()" />
<div class="tab-list flexcenter">
<div class="tab-item flexcenter" :class="{ pitch: MyPopupState == item.type }" v-for="item in tabList" :key="item.type" @click="cutMy(item.type)">
{{ item.name }}
<div class="value">{{ count[item.type] }}</div>
</div>
</div>
<div class="empty-box flexcenter" v-loading="true" v-if="(MyPopupState == 'collect' && collectLoading) || (MyPopupState == 'mj' && publisloading)"></div>
<div class="empty-box flexcenter" v-else-if="showList.length == 0">
<Empty></Empty>
</div>
<el-scrollbar v-else height="479px">
<div class="content" @scroll="handleListScroll">
<div class="item flexflex" v-for="(item, index) in showList" :key="index" @click="goDetails(item['uniqid'] || item?.data?.uniqid)">
<div class="left flexflex">
<div class="name">{{ item.title }}</div>
<div class="message">{{ item.message }}</div>
<div class="data">
30人参与 <i>|</i> 投票已结束
<span><i>|</i> 我已投不懂围观学习</span>
</div>
</div>
<div class="operate-area flexacenter">
<img class="delete-icon" v-if="MyPopupState == 'collect'" @click.stop="cancelCollection(item['token'], index)" src="@/assets/img/delete-icon.svg" />
<div class="anonymous-box flexacenter" v-else @click.stop="openAnonymousState(index)">
<div class="text">{{ item["anonymous"] == 1 ? "匿名" : "公开" }}</div>
<img class="arrow-icon" src="@/assets/img/arrow-gray.svg" />
<div class="state-popup flexflex" v-if="item['anonymousState']" @click.stop="">
<div class="state-popup-item flexacenter flex1" :class="{ 'pitch': item['anonymous'] == 0 }" @click="handleAnonymousState(item['token'], index, 0)">
<div class>公开发表</div>
<img class="state-popup-icon" src="@/assets/img/tick-green.svg" />
</div>
<div class="state-popup-item flexacenter flex1" :class="{ 'pitch': item['anonymous'] == 1 }" @click="handleAnonymousState(item['token'], index, 1)">
<div class>匿名发表</div>
<img class="state-popup-icon" src="@/assets/img/tick-green.svg" />
</div>
</div>
</div>
</div>
</div>
</div>
</el-scrollbar>
</div>
</el-dialog>
<!-- </div> -->
</template>
<script setup>
let props = defineProps({
// MyPopupState: String, // collect mj
count: Object,
})
let show = ref(false)
const router = useRouter()
const route = useRoute()
let MyPopupState = ref("") // collect participation sponsor
onMounted(() => {
// if (MyPopupState.value == "collect") getCollect();
// else if (MyPopupState.value == "mj") getPublish();
})
const tabList = [
{ name: "我的收藏", type: "collect" },
{ name: "我参与的投票", type: "participation" },
{ name: "我发起的投票", type: "sponsor" },
]
// 展示的 列表数据
let showList = ref([])
let collectList = []
let collectPage = 1
let collectLoading = ref(false)
let collectCount = ref(0)
const getCollect = () => {
if (collectPage == 0 || collectLoading.value) return
collectLoading.value = true
MyUserCollectHttp({ page: collectPage })
.then(res => {
if (res.code != 200) return
let data = res.data
collectList = collectList.concat(data.data)
showList.value = collectList
if (collectList.length < data["count"]) collectPage++
else collectPage = 0
collectCount.value = data["count"]
// MyPopupState.value = "collect"
// show.value = true
})
.finally(() => (collectLoading.value = false))
}
let publishList = []
let publisPage = 1
let publisloading = ref(false)
const getPublish = () => {
return
if (publisPage == 0 && !publisloading.value) return
publisloading.value = true
MyUserPublishHttp({ limit: 4, page: publisPage })
.then(res => {
if (res.code != 200) return
let data = res.data
publishList = publishList.concat(data.data)
if (publishList.length < data["count"]) publisPage++
else publisPage = 0
showList.value = publishList
// MyPopupState.value = "mj"
// show.value = true
})
.finally(() => (publisloading.value = false))
}
// 切换 isEmpty 是否清空收藏数据, 因为不确定用户是否有新收藏
const cutMy = (key, isEmpty) => {
if (isEmpty) {
collectList = []
collectPage = 1
collectCount.value = 0
}
if (key == "collect" && collectList.length == 0) getCollect()
else if (key == "mj" && publishList.length == 0) getPublish()
if (key == "collect") showList.value = collectList
else if (key == "mj") showList.value = publishList
MyPopupState.value = key
if (MyPopupState.value) show.value = true
}
// 打开匿名弹窗
const openAnonymousState = index => {
publishList.forEach(element => {
element["anonymousState"] = false
})
publishList[index]["anonymousState"] = true
showList.value = [...publishList]
}
// 关闭全部匿名弹窗
const closeAllAnonymousState = () => {
publishList.forEach(element => {
element["anonymousState"] = false
})
showList.value = [...publishList]
}
// 修改匿名状态
const handleAnonymousState = (token, index, anonymous) => {
changeAnonymousHttp({ token, anonymous }).then(res => {
if (res.code != 200) return
publishList[index]["anonymous"] = anonymous
showList.value = [...publishList]
closeAllAnonymousState()
ElMessage.success(res.message)
})
}
// 详情页滚动事件
const handleListScroll = e => {
const el = e.target
// 判断滚动到底部
if (el.scrollHeight - el.scrollTop !== el.clientHeight) return
if (MyPopupState.value == "collect") getCollect()
if (MyPopupState.value == "mj") getPublish()
}
let clearAllData = inject("clearAllData") || null
let getDetails = inject("getDetails") || null
// 打开详情页
const goDetails = uniqid => {
return
let path = route["path"] || ""
if (path.indexOf("/details/") != -1) {
clearAllData()
nextTick(() => getDetails())
}
// router.replace(`/details/${uniqid}`)
goToURL(`/details/${uniqid}`, false)
show.value = false
MyPopupState.value = ""
}
//暴露state和play方法
defineExpose({
cutMy,
})
// 关闭弹窗
const closeDialog = () => {
show.value = false
}
// const emit = defineEmits(["cutMy"]);
// 处理取消收藏
const cancelCollection = (token, index) => {
MyUserDeleteCollectHttp({ token }).then(res => {
if (res.code != 200) {
ElMessage.error(res.message)
return
}
collectList.splice(index, 1)
collectCount.value--
showList.value = [...collectList]
})
}
</script>
<style lang="less" scoped>
.popup-mask {
width: 100vw;
height: 100vh;
background: rgba(0, 0, 0, 0.5);
position: fixed;
top: 0;
left: 0;
max-width: none;
max-height: none;
border: none;
outline: none;
z-index: 1;
}
.box {
width: 750px;
height: 606px;
background-color: rgba(255, 255, 255, 1);
border-radius: 10px;
-moz-box-shadow: 0px 0px 3px rgba(0, 0, 0, 0.117647058823529);
-webkit-box-shadow: 0px 0px 3px rgba(0, 0, 0, 0.117647058823529);
box-shadow: 0px 0px 3px rgba(0, 0, 0, 0.117647058823529);
flex-direction: column;
// padding: 30px 30px 46px;
padding: 30px 8px 46px;
position: relative;
.cross {
position: absolute;
top: 12px;
right: 12px;
width: 12px;
height: 12px;
cursor: pointer;
}
.tab-list {
font-size: 16px;
margin-bottom: 29px;
.tab-item {
color: #aaaaaa;
padding: 0 22px;
cursor: pointer;
position: relative;
&:not(:last-of-type)::after {
content: "";
width: 1px;
height: 16px;
background: #d7d7d7;
position: absolute;
right: 0;
}
.value {
margin-left: 10px;
}
&.pitch {
font-weight: 650;
color: #000000;
.value {
color: #555;
font-weight: 400;
}
}
}
}
.empty-box {
width: calc(100% - 44px);
height: 100%;
background-color: rgba(255, 255, 255, 1);
border: 1px solid rgba(235, 235, 235, 1);
border-radius: 6px;
margin: 0 22px;
}
.content {
width: 100%;
height: 100%;
// background: #000000;
overflow: auto;
// padding-right: 13px;
// padding-bottom: 35px;
padding: 22px 22px 35px;
.item {
// flex-direction: column;
border-bottom: 1px dotted #ebebeb;
padding-bottom: 20px;
cursor: pointer;
margin-left: 22px;
margin-bottom: 21px;
.left {
flex-direction: column;
flex: 1;
position: relative;
&::after {
content: "";
position: absolute;
top: 4px;
left: -22px;
width: 5px;
height: 12px;
background-color: rgba(49, 215, 46, 1);
border-radius: 25px;
}
.name {
// font-weight: 650;
color: #000000;
line-height: 20px;
font-size: 14px;
margin-bottom: 10px;
}
.message {
color: #7f7f7f;
line-height: 22px;
font-size: 13px;
margin-bottom: 6px;
}
.data {
color: #aaaaaa;
line-height: 22px;
font-size: 12px;
i {
margin: 0 5px;
font-style: normal;
}
}
}
.operate-area {
display: flex;
justify-content: flex-end;
.delete-icon {
width: 12px;
cursor: pointer;
}
.anonymous-box {
.text {
font-size: 13px;
color: #333333;
}
.arrow-icon {
width: 8px;
height: 5px;
margin-left: 6px;
}
position: relative;
.state-popup {
position: absolute;
top: 30px;
right: 0;
width: 140px;
height: 101px;
background-color: rgba(255, 255, 255, 1);
border-radius: 10px;
-moz-box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.203921568627451);
-webkit-box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.203921568627451);
box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.203921568627451);
flex-direction: column;
.state-popup-item {
justify-content: space-between;
color: #555;
font-size: 14px;
padding: 0 10px;
&:hover {
color: #000000;
}
&.pitch {
color: #72db86;
.state-popup-icon {
display: block;
}
}
&:not(:last-of-type) {
border-bottom: 1px dotted #e3e3e3;
}
.state-popup-icon {
width: 11px;
height: 8px;
display: none;
}
}
}
}
}
}
}
}
</style>
<style lang="less">
.dialog-box {
header {
display: none;
}
border-radius: 10px;
.el-dialog__body {
padding: 0;
}
}
</style>