|
|
@ -11,16 +11,28 @@ |
|
|
|
</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 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" |
|
|
@ -55,9 +67,10 @@ |
|
|
|
<script setup> |
|
|
|
import { ref, reactive, computed } from 'vue' |
|
|
|
import {apiGetVote,apiAddVoteRecord,apiGetVoteIndex} from '@/apis/vote.js' |
|
|
|
import { useVoteStore } from '@/stores/vote' |
|
|
|
import { ElMessage } from 'element-plus'; |
|
|
|
|
|
|
|
// 进度条是否显示 |
|
|
|
const isResultShown = ref(false) |
|
|
|
// 添加投票记录 |
|
|
|
const record = reactive({ |
|
|
|
userId: 0, |
|
|
|
articleId: 0, |
|
|
@ -65,24 +78,37 @@ const record = reactive({ |
|
|
|
OptionId: [], |
|
|
|
voteIndex: 1 |
|
|
|
}) |
|
|
|
const totalVotes = ref(100); // 初始投票数 |
|
|
|
|
|
|
|
// 获取文章及其投票活动 |
|
|
|
// 初始投票数 |
|
|
|
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) |
|
|
|
record.voteId = ActiveAndVote.voteId |
|
|
|
totalVotes.value += ActiveAndVote.participationNumber; |
|
|
|
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() |
|
|
|
await GetIndex() // 调用函数 |
|
|
|
} else { |
|
|
|
console.error('请求失败:', res.message) |
|
|
|
} |
|
|
@ -105,17 +131,31 @@ const GetIndex = async() => { |
|
|
|
|
|
|
|
// 选择按钮点击事件,将选项的id存到数组 |
|
|
|
const selectedOptions = ref([]);// 数组,用于存储多个选中的选项ID |
|
|
|
const selectOption = (optionId) => { |
|
|
|
const index = selectedOptions.value.indexOf(optionId); |
|
|
|
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 (index > -1) { |
|
|
|
if (idx > -1) { |
|
|
|
// 已存在则移除 |
|
|
|
selectedOptions.value.splice(index, 1); |
|
|
|
selectedOptions.value.splice(idx, 1); |
|
|
|
console.log(selectedOptions.value) |
|
|
|
// 移除 √ |
|
|
|
optionLists[index].optionContent = optionLists[index].optionContent.replace(/ √$/, ''); |
|
|
|
} else { |
|
|
|
// 不存在则添加 |
|
|
|
if (selectedOptions.value.length >= 10) { |
|
|
@ -123,6 +163,9 @@ const selectOption = (optionId) => { |
|
|
|
return; |
|
|
|
} |
|
|
|
selectedOptions.value.push(optionId); |
|
|
|
console.log(selectedOptions.value) |
|
|
|
// 添加 √ |
|
|
|
optionLists[index].optionContent += ' √'; |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
@ -137,6 +180,21 @@ const showConfirmModal = () => { |
|
|
|
// 关闭模态框 |
|
|
|
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 |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
@ -150,16 +208,16 @@ const submitVote = async() => { |
|
|
|
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() |
|
|
|
showModal.value = false // 关闭模态框 |
|
|
|
if(userVoteIndexNow.value == 1){ |
|
|
|
isResultShown.value = true; // 进度条显示 |
|
|
|
} |
|
|
|
await getVote() // 调用函数 |
|
|
|
} else { |
|
|
|
ElMessage.error('没有剩余投票次数或未选择任何选项') |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
</script> |
|
|
|
|
|
|
|
<style scoped> |
|
|
@ -201,31 +259,66 @@ const submitVote = async() => { |
|
|
|
text-align: center; |
|
|
|
} |
|
|
|
|
|
|
|
.team-buttons { |
|
|
|
display: flex; |
|
|
|
flex-direction: column; |
|
|
|
gap: 10px; |
|
|
|
margin-bottom: 20px; |
|
|
|
.progressContainer { |
|
|
|
width: 400px; |
|
|
|
margin: 0 auto 20px; /* 让每个进度条容器居中,并有底部间距 */ |
|
|
|
} |
|
|
|
|
|
|
|
.team-button { |
|
|
|
padding: 12px 15px; |
|
|
|
border: none; |
|
|
|
border-radius: 25px; |
|
|
|
background-color: rgb(36, 184, 233); /* 点击前背景为蓝色 */ |
|
|
|
font-size: 15px; |
|
|
|
width: 80%; |
|
|
|
margin: 0 auto; |
|
|
|
.centered-progress { |
|
|
|
cursor: pointer; |
|
|
|
transition: all 0.3s; |
|
|
|
text-align: center; /* 文字居中 */ |
|
|
|
color: white; /* 文字颜色为白色 */ |
|
|
|
font-size: 18px !important; /* 控制字体大小 */ |
|
|
|
} |
|
|
|
|
|
|
|
.team-button.active { |
|
|
|
background-color: #FFA500; /* 点击后背景为黄色 */ |
|
|
|
font-weight: bold; |
|
|
|
color: black; /* 点击后文字颜色为黑色 */ |
|
|
|
/* 修改 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 { |
|
|
|