|
@ -1,126 +1,165 @@ |
|
|
<template> |
|
|
<template> |
|
|
<div class="articleandvote-section"> |
|
|
<div class="articleandvote-section"> |
|
|
<div :data="ActiveAndVote"> |
|
|
|
|
|
<!-- 文章组件 --> |
|
|
|
|
|
<div class="article-section"> |
|
|
|
|
|
<div> |
|
|
|
|
|
<h2 class="article-title">{{ ActiveAndVote.articleTitle }}</h2> |
|
|
|
|
|
<!-- <h2 class="article-title">“小柒战队” VS “MIke战队”, “公司达人动态”风格争霸赛</h2> --> |
|
|
|
|
|
<div class="article-content"> |
|
|
|
|
|
<!-- <p>{{ ActiveAndVote.articleContent }}</p> --> |
|
|
|
|
|
<p>正源谐音的“小柒战队” VS 暗藏谐音“MIke战队”, 赶快在视频下方留言选择自己的战队、争夺10金豆吧!</p> |
|
|
|
|
|
</div> |
|
|
|
|
|
</div> |
|
|
|
|
|
</div> |
|
|
|
|
|
<!-- 投票组件 --> |
|
|
|
|
|
<!-- <div class="voting-title">{{ ActiveAndVote.voteTitle }}</div> --> |
|
|
|
|
|
<div class="voting-title"> 你pick“小柒战队”还是“MIke战队”? </div> |
|
|
|
|
|
|
|
|
|
|
|
<!--<div class="team-buttons"> |
|
|
|
|
|
<button |
|
|
|
|
|
v-for="option in ActiveAndVote.optionList" |
|
|
|
|
|
:key="option.id" |
|
|
|
|
|
class="team-button" |
|
|
|
|
|
:class="{ active: selectedOption === option.id }" |
|
|
|
|
|
@click="selectOption(option.id)"> |
|
|
|
|
|
{{ option.optionContent }} |
|
|
|
|
|
</button> |
|
|
|
|
|
</div> --> |
|
|
|
|
|
<div class="team-buttons"> |
|
|
|
|
|
<button |
|
|
|
|
|
class="team-button" |
|
|
|
|
|
:class="{ active: selectedTeam === 'xiaoqi' }" |
|
|
|
|
|
@click="selectTeam('xiaoqi')"> |
|
|
|
|
|
小柒战队 |
|
|
|
|
|
</button> |
|
|
|
|
|
|
|
|
|
|
|
<button |
|
|
|
|
|
class="team-button" |
|
|
|
|
|
:class="{ active: selectedTeam === 'mike' }" |
|
|
|
|
|
@click="selectTeam('mike')"> |
|
|
|
|
|
MIke战队 |
|
|
|
|
|
</button> |
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
|
|
<button |
|
|
|
|
|
class="confirm-button" |
|
|
|
|
|
:disabled="!selectedTeam" |
|
|
|
|
|
@click="confirmVote"> |
|
|
|
|
|
确认投票 |
|
|
|
|
|
</button> |
|
|
|
|
|
|
|
|
|
|
|
<div class="voting-info"> |
|
|
|
|
|
<div style="display: flex; align-items: center;"> |
|
|
|
|
|
<p style="margin-right: 350px;">当前共有{{ totalVotes }}人参与</p> |
|
|
|
|
|
<a href="#" class="homily-link">Homily Link</a><a> 创建</a> |
|
|
|
|
|
<!-- <a href="#" class="homily-link">{{ ActiveAndVote.username }}</a><a> 创建</a> --> |
|
|
|
|
|
</div> |
|
|
|
|
|
<p>此投票于{{ formattedDate }}结束</p> |
|
|
|
|
|
|
|
|
<!-- 文章组件 --> |
|
|
|
|
|
<div class="article-section"> |
|
|
|
|
|
<div> |
|
|
|
|
|
<h2 class="article-title"> {{ ActiveAndVote.articleTitle }} </h2> |
|
|
|
|
|
<div class="article-content"> |
|
|
|
|
|
<p>{{ ActiveAndVote.articleContent }}</p> |
|
|
|
|
|
</div> |
|
|
|
|
|
</div> |
|
|
|
|
|
</div> |
|
|
|
|
|
<!-- 投票组件 --> |
|
|
|
|
|
<div class="voting-title">{{ ActiveAndVote.voteTitle }}</div> |
|
|
|
|
|
<div class="team-buttons"> |
|
|
|
|
|
<button |
|
|
|
|
|
v-for="option in ActiveAndVote.optionList" |
|
|
|
|
|
:key="option.id" |
|
|
|
|
|
:value="option.id" |
|
|
|
|
|
class="team-button" |
|
|
|
|
|
:class="{ active: selectedOptions.includes(option.id) }" |
|
|
|
|
|
@click="selectOption(option.id)"> |
|
|
|
|
|
{{ option.optionContent }} |
|
|
|
|
|
</button> |
|
|
|
|
|
</div> |
|
|
|
|
|
<button |
|
|
|
|
|
class="confirm-button" |
|
|
|
|
|
:class="{ 'disabled-style': ActiveAndVote.votePollStatus === 2 }" |
|
|
|
|
|
:disabled="ActiveAndVote.votePollStatus === 2 || selectedOptions.length === 0" |
|
|
|
|
|
@click="showConfirmModal"> |
|
|
|
|
|
确认投票 |
|
|
|
|
|
</button> |
|
|
|
|
|
|
|
|
|
|
|
<!-- 提示框 --> |
|
|
|
|
|
<div v-if="showModal" class="modal-overlay"> |
|
|
|
|
|
<div class="modal-content"> |
|
|
|
|
|
<p>今日投票次数剩余:{{ userVoteIndexNow }} 是否继续投票?</p> |
|
|
|
|
|
<div class="modal-buttons"> |
|
|
|
|
|
<button class="modal-button yes" @click="submitVote">是</button> |
|
|
|
|
|
<button class="modal-button no" @click="closeModal">否</button> |
|
|
|
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
|
|
<!-- 底部组件 --> |
|
|
|
|
|
<div class="voting-info"> |
|
|
|
|
|
<div style="display: flex; align-items: center;"> |
|
|
|
|
|
<p style="margin-right: 350px;">当前共有{{ totalVotes }}人参与</p> |
|
|
|
|
|
<a href="#" class="homily-link">{{ ActiveAndVote.username }}</a><a> 创建</a> |
|
|
|
|
|
</div> |
|
|
|
|
|
<p>此投票于{{ ActiveAndVote.deadlineTime }}结束</p> |
|
|
|
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
</template> |
|
|
</template> |
|
|
|
|
|
|
|
|
<script setup> |
|
|
<script setup> |
|
|
import { onMounted, ref } from 'vue' |
|
|
|
|
|
|
|
|
import { ref, reactive, computed } from 'vue' |
|
|
import {apiGetVote,apiAddVoteRecord,apiGetVoteIndex} from '@/apis/vote.js' |
|
|
import {apiGetVote,apiAddVoteRecord,apiGetVoteIndex} from '@/apis/vote.js' |
|
|
import { useVoteStore } from '@/stores/vote' |
|
|
import { useVoteStore } from '@/stores/vote' |
|
|
|
|
|
import { ElMessage } from 'element-plus'; |
|
|
|
|
|
|
|
|
// 获取文章及其投票活动 |
|
|
|
|
|
const ActiveAndVote = ref({}) |
|
|
|
|
|
const getVote = async (articleId) => { |
|
|
|
|
|
const res = await apiGetVote(articleId) |
|
|
|
|
|
ActiveAndVote.value = res.data |
|
|
|
|
|
} |
|
|
|
|
|
onMounted(async ()=>{ |
|
|
|
|
|
const res = await useVoteStore().getVote(9) |
|
|
|
|
|
console.log(res) |
|
|
|
|
|
|
|
|
const record = reactive({ |
|
|
|
|
|
userId: 0, |
|
|
|
|
|
articleId: 0, |
|
|
|
|
|
voteId: 0, |
|
|
|
|
|
OptionId: [], |
|
|
|
|
|
voteIndex: 1 |
|
|
}) |
|
|
}) |
|
|
// 获取当前用户今天参与本活动的次数 |
|
|
|
|
|
const userVoteIndexNow = ref(0) |
|
|
|
|
|
const voteId = ActiveAndVote.voteId |
|
|
|
|
|
const GetIndex = async(userId,voteId) => { |
|
|
|
|
|
const res = await apiGetVoteIndex(userId,voteId) |
|
|
|
|
|
userVoteIndexNow.value = res.data |
|
|
|
|
|
} |
|
|
|
|
|
GetIndex() |
|
|
|
|
|
|
|
|
|
|
|
// 按钮禁用 |
|
|
|
|
|
const selectedTeam = ref(null); |
|
|
|
|
|
const selectTeam = (team) => { |
|
|
|
|
|
selectedTeam.value = team; |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
const totalVotes = ref(100); // 初始投票数 |
|
|
|
|
|
|
|
|
|
|
|
// 获取文章及其投票活动 |
|
|
|
|
|
const ActiveAndVote = reactive({ |
|
|
|
|
|
voteId: 0, |
|
|
|
|
|
optionList:[], |
|
|
|
|
|
participationNumber:0 |
|
|
|
|
|
}); |
|
|
|
|
|
record.articleId = 12 // 模拟数据,此处为文章id |
|
|
|
|
|
const getVote = async () => { |
|
|
|
|
|
try { |
|
|
|
|
|
const res = await apiGetVote(record.articleId) |
|
|
|
|
|
if (res.data.code === 0) { |
|
|
|
|
|
Object.assign(ActiveAndVote, res.data.data) |
|
|
|
|
|
record.voteId = ActiveAndVote.voteId |
|
|
|
|
|
totalVotes.value += ActiveAndVote.participationNumber; |
|
|
|
|
|
console.log('投票数据加载成功:', ActiveAndVote) |
|
|
|
|
|
await GetIndex() |
|
|
|
|
|
} else { |
|
|
|
|
|
console.error('请求失败:', res.message) |
|
|
|
|
|
} |
|
|
|
|
|
} catch (err) { |
|
|
|
|
|
console.error('网络错误:', err) |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
getVote() |
|
|
|
|
|
|
|
|
// 获取总投票数(包含假数据) |
|
|
|
|
|
const totalVotes = ref(100); // 初始投票数 |
|
|
|
|
|
// totalVotes.value = totalVotes.value + ActiveAndVote.participationNumber |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 获取当前用户今天参与本活动的次数 |
|
|
|
|
|
const userVoteIndexNow = ref(3) // 用户今日本活动剩余投票数 |
|
|
|
|
|
record.userId = 1 // 模拟数据,此处为用户id |
|
|
|
|
|
const GetIndex = async() => { |
|
|
|
|
|
const res = await apiGetVoteIndex(record.userId,record.voteId) |
|
|
|
|
|
userVoteIndexNow.value = res.data.data.voteIndex |
|
|
|
|
|
console.log('用户今日本活动剩余投票数:', userVoteIndexNow.value) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const confirmVote = () => { |
|
|
|
|
|
if (selectedTeam.value) { |
|
|
|
|
|
totalVotes.value += 1; |
|
|
|
|
|
emit('vote-count-changed', totalVotes.value); |
|
|
|
|
|
selectedTeam.value = null; |
|
|
|
|
|
// 这里可以添加投票成功的动画效果 |
|
|
|
|
|
alert('投票成功!'); |
|
|
|
|
|
|
|
|
// 选择按钮点击事件,将选项的id存到数组 |
|
|
|
|
|
const selectedOptions = ref([]);// 数组,用于存储多个选中的选项ID |
|
|
|
|
|
const selectOption = (optionId) => { |
|
|
|
|
|
const index = selectedOptions.value.indexOf(optionId); |
|
|
|
|
|
// 单选逻辑:只允许选一个 |
|
|
|
|
|
if (ActiveAndVote.multiOption == 0) { |
|
|
|
|
|
selectedOptions.value = [optionId]; |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
// 多选逻辑:最多选十个 |
|
|
|
|
|
if (index > -1) { |
|
|
|
|
|
// 已存在则移除 |
|
|
|
|
|
selectedOptions.value.splice(index, 1); |
|
|
|
|
|
} else { |
|
|
|
|
|
// 不存在则添加 |
|
|
|
|
|
if (selectedOptions.value.length >= 10) { |
|
|
|
|
|
alert('最多只能选择 10 个选项'); |
|
|
|
|
|
return; |
|
|
} |
|
|
} |
|
|
|
|
|
selectedOptions.value.push(optionId); |
|
|
|
|
|
} |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
// 时间格式修改 |
|
|
|
|
|
const deadlineTime = "2025-06-21 15:20:41"; |
|
|
|
|
|
// 分割日期和时间部分 |
|
|
|
|
|
const [datePart, timePart] = deadlineTime.split(" "); |
|
|
|
|
|
// 分割年、月、日 |
|
|
|
|
|
const [year, month, day] = datePart.split("-"); |
|
|
|
|
|
// 构造新的日期格式 |
|
|
|
|
|
const formattedDate = `${year}年${month}月${day}日 ${timePart}`; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 提示框 |
|
|
|
|
|
// 控制模态框显示 |
|
|
|
|
|
const showModal = ref(false) |
|
|
|
|
|
// 显示确认模态框 |
|
|
|
|
|
const showConfirmModal = () => { |
|
|
|
|
|
showModal.value = true; |
|
|
|
|
|
}; |
|
|
|
|
|
// 关闭模态框 |
|
|
|
|
|
const closeModal = () => { |
|
|
|
|
|
showModal.value = false; |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 提交投票 |
|
|
|
|
|
const submitVote = async() => { |
|
|
|
|
|
console.log('剩余投票次数',userVoteIndexNow.value,'选择个数',selectedOptions.value.length) |
|
|
|
|
|
if (userVoteIndexNow.value > 0 && selectedOptions.value.length > 0) { |
|
|
|
|
|
record.OptionId = computed(() => selectedOptions.value); |
|
|
|
|
|
record.voteIndex = 4 - userVoteIndexNow.value |
|
|
|
|
|
// 这里可以发送请求提交投票 |
|
|
|
|
|
console.log('添加投票信息',record.userId,record.articleId,record.voteId,record.OptionId,record.voteIndex) |
|
|
|
|
|
await apiAddVoteRecord(record) |
|
|
|
|
|
ElMessage.success('添加成功') |
|
|
|
|
|
userVoteIndexNow.value -= 1; // 减少剩余投票次数 |
|
|
|
|
|
totalVotes.value += 1; // 总投票人数增加 |
|
|
|
|
|
selectedOptions.value = []; // 清空已选选项 |
|
|
|
|
|
closeModal(); // 关闭模态框 |
|
|
|
|
|
await getVote() |
|
|
|
|
|
} else { |
|
|
|
|
|
ElMessage.error('没有剩余投票次数或未选择任何选项') |
|
|
|
|
|
} |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
selectedTeam, |
|
|
|
|
|
selectTeam, |
|
|
|
|
|
confirmVote |
|
|
|
|
|
</script> |
|
|
</script> |
|
|
|
|
|
|
|
|
<style scoped> |
|
|
<style scoped> |
|
@ -173,7 +212,7 @@ const formattedDate = `${year}年${month}月${day}日 ${timePart}`; |
|
|
padding: 12px 15px; |
|
|
padding: 12px 15px; |
|
|
border: none; |
|
|
border: none; |
|
|
border-radius: 25px; |
|
|
border-radius: 25px; |
|
|
background-color: #4169E1; /* 点击前背景为蓝色 */ |
|
|
|
|
|
|
|
|
background-color: rgb(36, 184, 233); /* 点击前背景为蓝色 */ |
|
|
font-size: 15px; |
|
|
font-size: 15px; |
|
|
width: 80%; |
|
|
width: 80%; |
|
|
margin: 0 auto; |
|
|
margin: 0 auto; |
|
@ -184,7 +223,7 @@ const formattedDate = `${year}年${month}月${day}日 ${timePart}`; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
.team-button.active { |
|
|
.team-button.active { |
|
|
background-color: #FFD700; /* 点击后背景为黄色 */ |
|
|
|
|
|
|
|
|
background-color: #FFA500; /* 点击后背景为黄色 */ |
|
|
font-weight: bold; |
|
|
font-weight: bold; |
|
|
color: black; /* 点击后文字颜色为黑色 */ |
|
|
color: black; /* 点击后文字颜色为黑色 */ |
|
|
} |
|
|
} |
|
@ -204,6 +243,75 @@ const formattedDate = `${year}年${month}月${day}日 ${timePart}`; |
|
|
text-align: center; /* 文字居中 */ |
|
|
text-align: center; /* 文字居中 */ |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.confirm-button:hover { |
|
|
|
|
|
background-color: #CC0000; |
|
|
|
|
|
transform: translateY(-2px); /* 微微上移 */ |
|
|
|
|
|
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.confirm-button.disabled-style { |
|
|
|
|
|
background-color: gray; /* 灰色背景 */ |
|
|
|
|
|
color: #ccc; /* 灰色文字 */ |
|
|
|
|
|
cursor: not-allowed; /* 鼠标变成禁止符号 */ |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* 提示框样式 */ |
|
|
|
|
|
/* 提示框背景遮罩 */ |
|
|
|
|
|
.modal-overlay { |
|
|
|
|
|
position: fixed; |
|
|
|
|
|
top: 0; |
|
|
|
|
|
left: 0; |
|
|
|
|
|
width: 100%; |
|
|
|
|
|
height: 100%; |
|
|
|
|
|
background-color: rgba(0, 0, 0, 0.5); |
|
|
|
|
|
display: flex; |
|
|
|
|
|
justify-content: center; |
|
|
|
|
|
align-items: center; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* 提示框主体 */ |
|
|
|
|
|
.modal-content { |
|
|
|
|
|
background-color: #87CEEB; /* 更明显的浅蓝色背景 */ |
|
|
|
|
|
padding: 30px 40px; /* 增加内边距 */ |
|
|
|
|
|
border-radius: 12px; /* 边角更圆润一些 */ |
|
|
|
|
|
width: 350px; |
|
|
|
|
|
min-height: 180px; |
|
|
|
|
|
text-align: center; |
|
|
|
|
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2); /* 添加阴影效果 */ |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* 提示文字 */ |
|
|
|
|
|
.modal-content p { |
|
|
|
|
|
font-size: 25px; /* 文字更大 */ |
|
|
|
|
|
color: #333; |
|
|
|
|
|
margin-bottom: 20px; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.modal-buttons { |
|
|
|
|
|
display: flex; |
|
|
|
|
|
justify-content: space-around; |
|
|
|
|
|
margin-top: 10px; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.modal-button { |
|
|
|
|
|
padding: 10px 20px; |
|
|
|
|
|
border: none; |
|
|
|
|
|
border-radius: 25px; |
|
|
|
|
|
font-size: 14px; |
|
|
|
|
|
cursor: pointer; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.modal-button.yes { |
|
|
|
|
|
background-color: orange; |
|
|
|
|
|
color: white; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.modal-button.no { |
|
|
|
|
|
background-color: lightgray; |
|
|
|
|
|
color: black; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* 底部样式 */ |
|
|
.voting-info { |
|
|
.voting-info { |
|
|
font-size: 13px; |
|
|
font-size: 13px; |
|
|
color: #888; |
|
|
color: #888; |
|
|