|
|
<template> <div class="articleandvote-section"> <!-- 文章组件 --> <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 v-for="(option,index) in optionLists" :key="option.id" class="progressContainer"> <el-progress v-if="!isResultShown" class="centered-progress" :percentage="100" :stroke-width="40" :format="() => option.optionContent" :text-inside="true" :class="{ active: selectedOptions.includes(option.id) }" @click="selectOption(option.id,index)" > </el-progress> <div v-if="isResultShown" class="progressWrapper"> <el-progress class="left-progress" :percentage="getPercentage(option.count + 25)" :stroke-width="40" :format="() => option.optionContent" :text-inside="true" /> <span class="count-right">{{ option.count + 25 }}</span> </div> </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 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> </template>
<script setup> import { ref, reactive, computed } from 'vue' import {apiGetVote,apiAddVoteRecord,apiGetVoteIndex} from '@/apis/vote.js' import { ElMessage } from 'element-plus'; // 进度条是否显示
const isResultShown = ref(false) // 添加投票记录
const record = reactive({ userId: 0, articleId: 0, voteId: 0, OptionId: [], voteIndex: 1 }) // 初始投票数
const totalVotes = ref(0); const selectNum = ref(0); // 文章与投票活动信息
const ActiveAndVote = reactive({ voteId: 0, optionList:[], participationNumber:0 }); // 投票选项信息
const optionLists = reactive([{ id:0, optionContent:"", count: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) // 赋值
optionLists.splice(0) // 清空旧数据
optionLists.push(...ActiveAndVote.optionList) // 批量添加新数据
record.voteId = ActiveAndVote.voteId // 赋值
selectNum.value = ActiveAndVote.optionList.length totalVotes.value = selectNum.value * 25 totalVotes.value += ActiveAndVote.participationNumber; // 赋值
console.log('投票数据加载成功:', ActiveAndVote) await GetIndex() // 调用函数
} else { console.error('请求失败:', res.message) } } catch (err) { console.error('网络错误:', err) } } getVote()
// 获取当前用户今天参与本活动的次数
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) }
// 选择按钮点击事件,将选项的id存到数组
const selectedOptions = ref([]);// 数组,用于存储多个选中的选项ID
const selectOption = (optionId,index) => { const idx = selectedOptions.value.indexOf(optionId); // 单选逻辑:只允许选一个
if (ActiveAndVote.multiOption == 0) { // 先清除之前所有已选中项的 √
selectedOptions.value.forEach(id => { const prevIndex = optionLists.findIndex(opt => opt.id === id); if (prevIndex > -1) { optionLists[prevIndex].optionContent = optionLists[prevIndex].optionContent.replace(/ √$/, ''); } }); // 将选项id加到存储数组
selectedOptions.value = [optionId]; console.log(selectedOptions.value) // 给新选中的项添加 √
optionLists[index].optionContent += ' √'; return; } // 多选逻辑:最多选十个
if (idx > -1) { // 已存在则移除
selectedOptions.value.splice(idx, 1); console.log(selectedOptions.value) // 移除 √
optionLists[index].optionContent = optionLists[index].optionContent.replace(/ √$/, ''); } else { // 不存在则添加
if (selectedOptions.value.length >= 10) { alert('最多只能选择 10 个选项'); return; } selectedOptions.value.push(optionId); console.log(selectedOptions.value) // 添加 √
optionLists[index].optionContent += ' √'; } };
// 提示框
// 控制模态框显示
const showModal = ref(false) // 显示确认模态框
const showConfirmModal = () => { showModal.value = true; }; // 关闭模态框
const closeModal = () => { showModal.value = false; isResultShown.value = true; // 进度条显示
};
// 进度条
const totalcounts = computed(() => { const baseCount = ActiveAndVote.optionList.reduce((sum, option) => sum + option.count, 0); //基础票数
const extra = selectNum.value * 25; // 假数据
return baseCount + extra; });
const getPercentage = (count) => { if (totalVotes.value === 0) return 0; const percentage = Math.min(100, Number(((count / totalcounts.value) * 100).toFixed(2))); return percentage };
// 提交投票
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('添加成功') selectedOptions.value = []; // 清空已选选项
showModal.value = false // 关闭模态框
if(userVoteIndexNow.value == 1){ isResultShown.value = true; // 进度条显示
} await getVote() // 调用函数
} else { ElMessage.error('没有剩余投票次数或未选择任何选项') } }; </script>
<style scoped> .articleandvote-section { width: 40%; /* 占屏幕的 */ max-width: 800px; /* 最大宽度限制 */ margin-left: 18%; /* 距离左边屏幕四分之一 */ background-color: #fff; border: 1px solid #eee; border-radius: 8px; padding: 20px; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05); }
/* 文章区域样式 */ .article-section { margin-bottom: 20px; }
.article-title { font-size: 20px; font-weight: bold; margin-bottom: 10px; color: #333; }
.article-content { font-size: 14px; color: #555; line-height: 1.5; }
/* 投票区域样式 */ .voting-title { font-size: 30px; font-weight: bold; margin-bottom: 15px; color: #333; text-align: center; }
.progressContainer { width: 400px; margin: 0 auto 20px; /* 让每个进度条容器居中,并有底部间距 */ }
.centered-progress { cursor: pointer; font-size: 18px !important; /* 控制字体大小 */ }
/* 修改 Element Plus 进度条内层样式 */ .centered-progress :deep(.el-progress-bar__inner) { display: flex !important; align-items: center !important; justify-content: center !important; font-size: 18px !important; color: #000 !important; }
.centered-progress :deep(.el-progress-bar__innerText) { margin: 0 !important; width: 100% !important; text-align: center !important; font-size: 18px !important; color: #000 !important; }
/* 点击激活后的颜色 */ .centered-progress.active :deep(.el-progress-bar__inner) { background-color: #FF9900 !important; }
/* 包含进度条的相对定位容器 */ .progressWrapper { width: 400px; /* 同进度条宽度 */ position: relative; }
/* count 数字,绝对定位到右端,中间垂直对齐 */ .count-right { position: absolute; right: 0; top: 50%; transform: translateY(-50%); margin-right: 10px; /* 根据需要微调,让数字在灰条内稍留空隙 */ font-weight: normal; z-index: 1; }
/* 左对齐文本状态 */ .left-progress :deep(.el-progress-bar__inner) { display: flex !important; align-items: center !important; justify-content: flex-start !important; padding-left: 8px !important; } .left-progress :deep(.el-progress-bar__innerText) { font-size: 15px !important; color: #000 !important; margin: 0 !important; }
.confirm-button { background-color: #FF0000; /* 确认按钮背景为红色 */ color: white; border: none; padding: 10px 30px; border-radius: 25px; cursor: pointer; font-size: 15px; width: 25%; /* 确认按钮宽度为选择按钮的四分之一 */ margin: 0 auto; /* 确认按钮居中 */ display: block; transition: background-color 0.3s; 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 { font-size: 13px; color: #888; line-height: 1.6; }
.homily-link { color: #4267B2; text-decoration: none; font-size: 13px; } </style>
|