提交 a90e02e5 authored 作者: 王鹏飞's avatar 王鹏飞

新增投票活动页

上级 8827d0e8
import httpRequest from '@/utils/axios'
// 获取城市列表
export function getCityList() {
return httpRequest.get('/api/alumni/v1/vote/city')
}
// 是否投票
export function checkVote() {
return httpRequest.get('/api/alumni/v1/vote/hasvote')
}
// 获取投票状态
export function getVoteStatus() {
return httpRequest.get('/api/alumni/v1/vote/status')
}
// 获取投票列表
export function getVoteList(params) {
return httpRequest.get('/api/alumni/v1/vote/candidate/list', { params })
}
// 获取投票item
export function getVoteItem(id) {
return httpRequest.get(`/api/alumni/v1/vote/candidate/detail/${id}`)
}
// 提交投票
export function addVote(data) {
return httpRequest.post('/api/alumni/v1/vote/add', data)
}
.vote {
display: flex;
flex-direction: column;
height: 100vh;
background: url('../../assets/img/vote_bg.png') no-repeat;
background-size: cover;
overflow: hidden;
}
.vote-banner {
height: 1.4rem;
}
.vote-banner img {
width: 100%;
height: 100%;
object-fit: cover;
}
.vote-title {
margin: 0.15rem;
font-size: 0.18rem;
font-weight: 600;
text-align: center;
color: #222;
}
.vote-box {
flex: 1;
margin: 0 0.2rem;
padding: 0.2rem;
background-color: #fff;
overflow-y: auto;
box-shadow: 0px 2px 10px 0px rgba(0, 0, 0, 0.05);
border-radius: 0.08rem;
-webkit-overflow-scrolling: touch;
}
.vote-box p {
font-size: 0.14rem;
line-height: 0.22rem;
}
.vote-button {
margin: 0.2rem auto;
width: 1rem;
height: 0.35rem;
background: linear-gradient(315deg, rgba(225, 47, 116, 0.83) 0%, #c01540 100%);
border-radius: 0.04rem;
color: #fff;
font-size: 0.15rem;
line-height: 0.35rem;
text-align: center;
}
.vote-tips {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
font-size: 0.15rem;
font-weight: 400;
color: #222;
}
......@@ -16,7 +16,6 @@ Vue.use(VueMeta)
import '@/assets/css/base.css'
Vue.config.productionTip = false
import avatar from '@/assets/img/avatar.png'
Vue.filter('avatar', function(value) {
return value && value !== 'null' ? value : avatar
......
......@@ -195,7 +195,7 @@ const routes = [
// 三级认证首页
{
path: '/attestation',
name: 'printing',
name: 'attestation',
component: () => import('@/views/attestation/index.vue'),
meta: { requiredLogin: true }
},
......@@ -205,6 +205,36 @@ const routes = [
name: 'attteUpload',
component: () => import('@/views/attestation/upload.vue'),
meta: { requiredLogin: true }
},
{
path: '/vote/index',
name: 'voteIndex',
component: () => import('@/views/vote/Index.vue'),
meta: { requiredLogin: true }
},
{
path: '/vote/city',
name: 'voteCity',
component: () => import('@/views/vote/City.vue'),
meta: { requiredLogin: true }
},
{
path: '/vote/choose',
name: 'voteChoose',
component: () => import('@/views/vote/Choose.vue'),
meta: { requiredLogin: true }
},
{
path: '/vote/item/:id',
name: 'voteItem',
component: () => import('@/views/vote/Item.vue'),
meta: { requiredLogin: true }
},
{
path: '/vote/primary',
name: 'votePrimary',
component: () => import('@/views/vote/Primary.vue'),
meta: { requiredLogin: true }
}
]
......
import Vue from 'vue'
import Vuex from 'vuex'
import { getUser } from '@/api/account'
import { getVoteList } from '@/api/vote'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
groupList: [],
user: {}
user: {},
voteList: []
},
mutations: {
setGroupList(state, list) {
......@@ -15,6 +17,9 @@ export default new Vuex.Store({
},
setUser(state, user) {
state.user = user
},
setVoteList(state, list) {
state.voteList = list
}
},
actions: {
......@@ -39,6 +44,20 @@ export default new Vuex.Store({
return false
})
return isLogin
},
async getVoteList({ commit }, city) {
await getVoteList({ city }).then(response => {
response = response.map(item => {
item.limit = item.limit ? parseInt(item.limit) : 0
item.checkedCount = 0
item.candidate = item.candidate.map(user => {
user.checked = false
return user
})
return item
})
commit('setVoteList', response)
})
}
}
})
......@@ -5,7 +5,9 @@
<!-- banner -->
<div class="banner">
<van-swipe :autoplay="3000" indicator-color="white">
<van-swipe-item><img src="img/home_banner.png" /></van-swipe-item>
<van-swipe-item>
<router-link to="/vote/index"><img src="img/home_banner2.jpg" /></router-link>
</van-swipe-item>
<van-swipe-item><img src="img/home_banner.png" /></van-swipe-item>
</van-swipe>
</div>
......
<template>
<div class="vote">
<div class="vote-box" style="margin-top: 0.2rem">
<div class="vote-project" v-for="(item, index) in list" :key="index">
<div class="vote-project-hd">
<h2 class="vote-project-title">{{ item.project }}:</h2>
<p class="vote-project-text">
您可选择{{ item.limit }}名候选人,已选择{{ item.checkedCount }}/{{ item.limit }}
</p>
</div>
<div class="vote-project-bd">
<div class="vote-item" v-for="user in item.candidate" :key="user.id">
<div class="vote-item-pic" @click="handleClickItem(user)">
<img :src="user.photo" />
</div>
<div class="vote-item-content" @click="handleClickItem(user)">{{ `${user.num}号:${user.name}` }}</div>
<div class="vote-like vote-like__active" @click="toggleCheck(user, item)" v-if="user.checked">
<img src="../../assets/img/vote_liked.png" />已投
</div>
<div class="vote-like vote-like__disabled" v-else-if="item.checkedCount === item.limit">
<img src="../../assets/img/vote_like_disabled.png" />已满
</div>
<div class="vote-like vote-like__primary" @click="toggleCheck(user, item)" v-else>
<img src="../../assets/img/vote_like.png" />投票
</div>
</div>
</div>
</div>
</div>
<div class="vote-button" @click="handSubmit">确认投票</div>
</div>
</template>
<script>
import * as api from '@/api/vote'
export default {
metaInfo: { title: '投票' },
data() {
return {}
},
computed: {
city() {
return this.$route.query.city
},
list() {
return this.$store.state.voteList
}
},
methods: {
handleClickItem(item) {
this.$router.push({ name: 'voteItem', params: { id: item.id } })
},
toggleCheck(item, parent) {
parent.checkedCount = item.checked ? --parent.checkedCount : ++parent.checkedCount
item.checked = !item.checked
},
handSubmit() {
const ids = this.list.reduce((results, item) => {
item.candidate.forEach(user => {
user.checked && results.push(user.id)
})
return results
}, [])
if (!ids.length) {
this.$notify('请投票')
return
}
this.$router.push({ name: 'votePrimary' })
},
// 检测是否投票
checkVote() {
api.checkVote().then(response => {
response.flag && this.$router.replace({ name: 'voteIndex' })
})
}
},
beforeMount() {
this.checkVote()
!this.list.length && this.$store.dispatch('getVoteList', this.city)
}
}
</script>
<style scoped src="../../assets/css/vote.css"></style>
<style lang="scss" scoped>
.vote-project-hd {
padding: 0.1rem 0;
border-bottom: 1px solid #ccc;
}
.vote-project-title {
font-size: 0.2rem;
font-weight: 600;
color: #222;
}
.vote-project-text {
margin-top: 0.05rem;
font-size: 0.14rem;
color: #666;
}
.vote-item {
display: flex;
align-items: center;
padding: 0.1rem 0;
border-bottom: 1px solid #ccc;
}
.vote-item-pic {
width: 0.4rem;
height: 0.4rem;
border-radius: 50%;
overflow: hidden;
margin-right: 0.1rem;
img {
width: 100%;
height: 100%;
object-fit: cover;
}
}
.vote-item-content {
flex: 1;
font-size: 0.15rem;
font-weight: 600;
color: #222;
}
.vote-like {
display: flex;
align-items: center;
justify-content: center;
width: 0.73rem;
height: 0.24rem;
border-radius: 0.12rem;
font-size: 0.15rem;
font-weight: 600;
img {
margin-right: 0.05rem;
width: 0.16rem;
height: 0.15rem;
}
}
.vote-like__disabled {
color: #999;
background: #ccc;
}
.vote-like__active {
color: #fff;
background: #ccc;
}
.vote-like__primary {
color: #fff;
background: linear-gradient(315deg, rgba(225, 47, 116, 0.83) 0%, #c01540 100%);
}
</style>
\ No newline at end of file
<template>
<div class="vote">
<div class="vote-city">
<h1>请选择您所在的区域</h1>
<ul>
<li v-for="item in cityList" :key="item" @click="handleClick(item)">
{{ item }}
</li>
</ul>
</div>
</div>
</template>
<script>
import * as api from '@/api/vote'
export default {
metaInfo: { title: '投票' },
data() {
return {
cityList: []
}
},
methods: {
getCity() {
api.getCityList().then(response => {
this.cityList = response
})
},
handleClick(city) {
this.$store.dispatch('getVoteList', city)
this.$router.push({ name: 'voteChoose', query: { city } })
}
},
beforeMount() {
this.getCity()
}
}
</script>
<style scoped src="../../assets/css/vote.css"></style>
<style lang="scss" scoped>
.vote-city {
padding: 0 0.2rem;
h1 {
padding: 0.65rem 0;
font-size: 0.18rem;
text-align: center;
}
li {
margin-bottom: 0.4rem;
font-size: 0.2rem;
font-weight: 600;
line-height: 0.5rem;
text-align: center;
background: #fff;
box-shadow: 0px 1px 5px 0px rgba(0, 0, 0, 0.05);
border-radius: 0.1rem;
cursor: pointer;
&:hover,
&:active {
color: #fff;
background: linear-gradient(315deg, rgba(225, 47, 116, 0.83) 0%, #c01540 100%);
}
}
}
</style>
\ No newline at end of file
<template>
<div class="vote">
<!-- 投票完成 -->
<template v-if="status === 2">
<div class="vote-banner"><img src="../../assets/img/vote_banner.png" /></div>
<div class="vote-box">
<p>公示</p>
</div>
<div class="vote-button" @click="toHome">回到首页</div>
</template>
<!-- 已投票 -->
<template v-else-if="hasVote">
<div class="vote-banner"><img src="../../assets/img/vote_banner.png" /></div>
<h1 class="vote-tips">您已投票成功</h1>
<div class="vote-button" @click="toHome">回到首页</div>
</template>
<!-- 投票结束 -->
<template v-else-if="status === 0">
<div class="vote-banner"><img src="../../assets/img/vote_banner.png" /></div>
<h1 class="vote-tips">投票已截止,请等待公示</h1>
<div class="vote-button" @click="toHome">回到首页</div>
</template>
<!-- 投票中 -->
<template v-else>
<div class="vote-banner"><img src="../../assets/img/vote_banner.png" /></div>
<h1 class="vote-title">投票活动说明</h1>
<div class="vote-box">
<p>
投票活动说明投票活动说明投票活动说明投票活动说明投票活动说明投票活动说明投票活动说明投票活动说明投票活动说明投票活动说明投票活动说明
</p>
</div>
<div class="vote-button" @click="$router.push({ name: 'voteCity' })">我已知晓</div>
</template>
</div>
</template>
<script>
import * as api from '@/api/vote'
export default {
metaInfo: { title: '投票' },
data() {
return {
hasVote: false,
status: 1
}
},
methods: {
getVoteStatus() {
api.getVoteStatus().then(response => {
this.status = response.status
})
},
// 检测是否投票
checkVote() {
api.checkVote().then(response => {
this.hasVote = response.flag
})
},
toHome() {
this.$router.replace('/')
}
},
beforeMount() {
this.getVoteStatus()
this.checkVote()
}
}
</script>
<style scoped src="../../assets/css/vote.css"></style>
\ No newline at end of file
<template>
<div class="vote">
<div class="box">
<div class="user">
<img :src="detail.photo" />
{{ `${detail.num}号:${detail.name}` }}
</div>
</div>
<div class="box">
{{ detail.describe }}
</div>
</div>
</template>
<script>
import * as api from '@/api/vote'
export default {
metaInfo: { title: '投票' },
data() {
return {
detail: {}
}
},
computed: {
pid() {
return this.$route.params.id
}
},
methods: {
getVoteItem() {
api.getVoteItem(this.pid).then(response => {
this.detail = response
})
}
},
beforeMount() {
this.getVoteItem()
}
}
</script>
<style scoped src="../../assets/css/vote.css"></style>
<style lang="scss" scoped>
.vote {
padding: 0.2rem;
}
.box {
margin-bottom: 0.1rem;
padding: 0.2rem;
background-color: #fff;
box-shadow: 0px 1px 5px 0px rgba(0, 0, 0, 0.05);
border-radius: 0.04rem;
}
.user {
display: flex;
align-items: center;
justify-content: center;
font-size: 0.15rem;
font-weight: 600;
color: #222;
img {
width: 0.4rem;
height: 0.4rem;
border-radius: 50%;
overflow: hidden;
margin-right: 0.1rem;
object-fit: cover;
}
}
</style>
\ No newline at end of file
<template>
<div class="vote">
<h1 class="vote-title">您的投票名单</h1>
<div class="vote-box">
<div class="vote-project" v-for="(item, index) in list" :key="index">
<h2 class="vote-project-title">{{ item.project }}:</h2>
<p class="vote-project-text">
<template v-for="user in item.candidate">
<span v-if="user.checked" :key="user.id">{{ user.name }}</span>
</template>
</p>
</div>
</div>
<div class="vote-button" @click="handSubmit">确认投票</div>
<van-dialog v-model="show" title="您已投票成功" :showConfirmButton="false">
<img src="../../assets/img/vote_success.png" class="vote-success-icon" />
<div class="vote-button-success" @click="goHome">回到首页</div>
</van-dialog>
</div>
</template>
<script>
import * as api from '@/api/vote'
export default {
metaInfo: { title: '投票' },
data() {
return {
show: false
}
},
computed: {
city() {
return this.$route.query.city
},
list() {
return this.$store.state.voteList
}
},
methods: {
handSubmit() {
const ids = this.list.reduce((results, item) => {
item.candidate.forEach(user => {
user.checked && results.push(user.id)
})
return results
}, [])
this.handleRequest(ids)
},
handleRequest(ids) {
api.addVote(ids).then(response => {
if (response.success) {
this.show = true
}
})
},
goHome() {
this.$router.replace('/')
}
},
beforeMount() {
!this.list.length && this.$router.back()
}
}
</script>
<style scoped src="../../assets/css/vote.css"></style>
<style lang="scss" scoped>
.vote-project {
margin-bottom: 0.2rem;
}
.vote-project-title {
font-size: 0.2rem;
font-weight: 600;
color: #222;
}
.vote-project-text {
margin-top: 0.05rem;
font-size: 0.14rem;
color: #666;
}
.vote-success-icon {
display: block;
width: 158px;
margin: 30px auto;
}
.vote-button-success {
margin: 20px auto;
width: 225px;
height: 35px;
background: #c62245;
border-radius: 6px;
font-size: 15px;
font-weight: 600;
color: #fff;
line-height: 35px;
text-align: center;
cursor: pointer;
}
</style>
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论