| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164 |
- <template>
- <view class="vote-page">
- <view class="round-toggle">
- <view :class="['round-tab', round === 1 ? 'active' : '']" @click="switchRound(1)">第1轮 · 我学会了</view>
- <view :class="['round-tab', round === 2 ? 'active' : '']" @click="switchRound(2)">第2轮 · 最想抄走</view>
- </view>
- <view v-if="!voted" class="vote-section">
- <text class="vote-hint">{{ round === 1 ? '每人2票,不可投本组' : '每人1票,可投本组' }}</text>
- <view class="group-list">
- <view class="group-item" v-for="(g, idx) in groups" :key="idx"
- :class="{ selected: selectedGroups.includes(g.id), disabled: round === 1 && g.id === myGroupId }"
- @click="toggleGroup(g.id)">
- <text class="group-name">{{ g.name }}</text>
- <text class="group-check" v-if="selectedGroups.includes(g.id)">✅</text>
- <text class="group-disabled" v-if="round === 1 && g.id === myGroupId">(本组)</text>
- </view>
- </view>
- <button class="submit-btn" @click="handleVote" :loading="voting"
- :disabled="voting || selectedGroups.length === 0">提交投票</button>
- </view>
- <view v-else class="result-section">
- <text class="result-title">投票结果</text>
- <view class="bar-list">
- <view class="bar-item" v-for="(b, idx) in bars" :key="idx">
- <view class="bar-label">{{ b.groupName }}</view>
- <view class="bar-track">
- <view class="bar-fill" :style="{ width: barWidth(b.count) }"></view>
- </view>
- <view class="bar-count">{{ b.count }}票</view>
- </view>
- </view>
- <view class="voted-badge">您已在第{{ round }}轮投票</view>
- </view>
- </view>
- </template>
- <script>
- import { castVote, getVoteResult, getVotedStatus, getMyGroup, getClassGroups } from '@/utils/api.js'
- import { guardPage } from '@/utils/guard.js'
- export default {
- data() {
- return {
- round: 1,
- classId: '',
- myGroupId: '',
- groups: [],
- selectedGroups: [],
- voted: false,
- bars: [],
- voting: false
- }
- },
- onShow() {
- if (!guardPage()) return
- this.loadGroup()
- },
- methods: {
- loadGroup() {
- var self = this
- getMyGroup().then(function(resp) {
- if (resp.data) {
- self.myGroupId = resp.data.id
- self.classId = resp.data.classId
- return getClassGroups()
- }
- }).then(function(resp) {
- if (resp && resp.data) {
- self.groups = resp.data
- }
- self.checkVoted()
- self.loadResult()
- }).catch(function() {})
- },
- switchRound(r) {
- this.round = r
- this.selectedGroups = []
- this.checkVoted()
- this.loadResult()
- },
- checkVoted() {
- var self = this
- if (!self.classId) return
- getVotedStatus({ round: self.round, classId: self.classId }).then(function(resp) {
- self.voted = resp.data === true
- }).catch(function() {
- self.voted = false
- })
- },
- loadResult() {
- var self = this
- if (!self.classId) return
- getVoteResult({ round: self.round, classId: self.classId }).then(function(resp) {
- self.bars = (resp.data && resp.data.bars) || []
- }).catch(function() {})
- },
- toggleGroup(id) {
- if (this.round === 1 && id === this.myGroupId) return
- var idx = this.selectedGroups.indexOf(id)
- if (idx >= 0) {
- this.selectedGroups.splice(idx, 1)
- } else {
- var max = this.round === 1 ? 2 : 1
- if (this.selectedGroups.length >= max) {
- uni.showToast({ title: '第' + this.round + '轮最多' + max + '票', icon: 'none' })
- return
- }
- this.selectedGroups.push(id)
- }
- },
- handleVote() {
- if (this.selectedGroups.length === 0 || this.voting) return
- this.voting = true
- var self = this
- castVote({
- round: self.round,
- classId: self.classId,
- targetGroupIds: self.selectedGroups
- }).then(function() {
- uni.showToast({ title: '投票成功', icon: 'success' })
- self.voted = true
- self.loadResult()
- }).catch(function(err) {
- uni.showToast({ title: (err && err.message) || '投票失败', icon: 'none' })
- }).finally(function() {
- self.voting = false
- })
- },
- barWidth(count) {
- var max = 1
- this.bars.forEach(function(b) { if (b.count > max) max = b.count })
- return Math.round((count / max) * 100) + '%'
- }
- }
- }
- </script>
- <style scoped>
- .vote-page { min-height: 100vh; background: #F5F5F5; padding: 24rpx 32rpx; }
- .round-toggle { display: flex; background: #FFF; border-radius: 12rpx; overflow: hidden; margin-bottom: 24rpx; }
- .round-tab { flex: 1; height: 80rpx; line-height: 80rpx; text-align: center; font-size: 28rpx; color: #5A4F4B; background: #FFF; }
- .round-tab.active { color: #FFF; background: #FC7A57; font-weight: 600; }
- .vote-hint { display: block; font-size: 26rpx; color: #FC7A57; margin-bottom: 20rpx; text-align: center; }
- .group-list { background: #FFF; border-radius: 12rpx; overflow: hidden; margin-bottom: 24rpx; }
- .group-item { display: flex; align-items: center; justify-content: space-between; padding: 24rpx 28rpx; border-bottom: 1rpx solid #F1F5F9; }
- .group-item.selected { background: #FFF0E8; }
- .group-item.disabled { opacity: 0.4; }
- .group-name { font-size: 28rpx; color: #2A2326; }
- .group-check { font-size: 28rpx; }
- .group-disabled { font-size: 24rpx; color: #94877F; margin-left: 8rpx; }
- .submit-btn { width: 100%; height: 88rpx; line-height: 88rpx; background: #FC7A57; color: #FFF; font-size: 30rpx; font-weight: 600; border-radius: 44rpx; border: none; }
- .submit-btn:active { opacity: 0.85; }
- .result-section { background: #FFF; border-radius: 16rpx; padding: 32rpx; }
- .result-title { display: block; font-size: 32rpx; font-weight: 700; color: #2A2326; margin-bottom: 24rpx; }
- .bar-list { margin-bottom: 24rpx; }
- .bar-item { display: flex; align-items: center; margin-bottom: 16rpx; }
- .bar-label { width: 160rpx; font-size: 26rpx; color: #2A2326; text-align: right; margin-right: 16rpx; }
- .bar-track { flex: 1; height: 32rpx; background: #F1F5F9; border-radius: 16rpx; overflow: hidden; }
- .bar-fill { height: 100%; background: linear-gradient(90deg, #FC7A57, #FF9E5E); border-radius: 16rpx; transition: width 0.5s; }
- .bar-count { width: 80rpx; font-size: 24rpx; color: #5A4F4B; text-align: right; margin-left: 12rpx; }
- .voted-badge { text-align: center; font-size: 26rpx; color: #22C55E; background: #F0FDF4; padding: 16rpx; border-radius: 8rpx; }
- </style>
|