Changes
This commit is contained in:
@@ -0,0 +1,872 @@
|
||||
<!--#
|
||||
layout("/layouts/platform_h5.html"){
|
||||
#-->
|
||||
|
||||
<div id="app" v-cloak class="vote-page">
|
||||
<van-nav-bar :title="pageTitle" left-arrow left-text="返回" @click-left="historyBack" placeholder fixed></van-nav-bar>
|
||||
|
||||
<div class="vote-header">
|
||||
<h1>{{activity.title}}</h1>
|
||||
<div class="vote-stat-box">
|
||||
<div class="vote-stat-item">
|
||||
<strong>{{voteStats.optionCount || optionList.length}}</strong>
|
||||
<span>参与选项</span>
|
||||
</div>
|
||||
<div class="vote-stat-item">
|
||||
<strong>{{voteStats.totalParticipants || 0}}</strong>
|
||||
<span>投票总人数</span>
|
||||
</div>
|
||||
<button class="vote-rank-btn" @click="rankShow = true">
|
||||
<i class="fa fa-bar-chart"></i>
|
||||
<span>排行榜</span>
|
||||
<van-icon name="arrow"></van-icon>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="vote-countdown" v-if="!isEnd">
|
||||
距离投票结束还有:
|
||||
<b>{{countdown.days}}</b> 天
|
||||
<b>{{countdown.hours}}</b> 时
|
||||
<b>{{countdown.minutes}}</b> 分
|
||||
<b>{{countdown.seconds}}</b> 秒
|
||||
</div>
|
||||
<div class="vote-countdown" v-else>投票已结束</div>
|
||||
|
||||
<div class="vote-search">
|
||||
<van-search
|
||||
v-model="keyword"
|
||||
placeholder="请输入选项编号/名称"
|
||||
clearable
|
||||
shape="square"
|
||||
background="transparent">
|
||||
</van-search>
|
||||
<button @click="noop">搜索</button>
|
||||
</div>
|
||||
|
||||
<div class="vote-subject" v-if="currentSubject">
|
||||
<div class="vote-subject-title">
|
||||
<span>*</span>
|
||||
{{currentSubject.title}}
|
||||
<em v-if="currentSubject.type === 'checkbox' && currentSubject.maxMulti">
|
||||
【请选择1-{{currentSubject.maxMulti}}项,已选择{{selectedOptionIds.length}}项】
|
||||
</em>
|
||||
<em v-else>【请选择{{currentSubject.type === 'radio' ? '1' : '至少1'}}项】</em>
|
||||
</div>
|
||||
|
||||
<div :class="getVoteOptionListClass(currentSubject)">
|
||||
<div
|
||||
v-for="(option, index) in filteredOptions"
|
||||
:key="option.id"
|
||||
:class="['vote-option-card', isOptionSelected(option.id) ? 'active' : '']"
|
||||
@click="toggleOption(option)">
|
||||
<div class="vote-option-img" v-if="option.imgUrl">
|
||||
<img :src="option.imgUrl" alt="">
|
||||
</div>
|
||||
<div class="vote-option-img vote-option-placeholder" v-else>
|
||||
<span>{{index + 1}}</span>
|
||||
</div>
|
||||
<div class="vote-option-info">
|
||||
<input
|
||||
class="vote-option-control"
|
||||
:type="currentSubject.type === 'radio' ? 'radio' : 'checkbox'"
|
||||
:checked="isOptionSelected(option.id)"
|
||||
:disabled="answerRecord.isFinish || isEnd"
|
||||
@click.stop.prevent="toggleOption(option)">
|
||||
<div class="vote-option-text">
|
||||
<strong>{{getOptionVotes(option.id)}}票({{getOptionPercent(option.id)}}%)</strong>
|
||||
<span>{{option.text}}</span>
|
||||
</div>
|
||||
<button
|
||||
class="vote-option-detail-btn"
|
||||
v-if="hasOptionDetail(option)"
|
||||
@click.stop="openOptionDetail(option)">
|
||||
详情
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<van-empty v-if="!currentSubject" description="暂无投票题目"></van-empty>
|
||||
|
||||
<div class="vote-bottom">
|
||||
<van-button
|
||||
type="primary"
|
||||
block
|
||||
color="#ff4d00"
|
||||
:disabled="answerRecord.isFinish || isEnd"
|
||||
@click="onSubmit">
|
||||
{{answerRecord.isFinish ? '已投票' : '投票'}}
|
||||
</van-button>
|
||||
</div>
|
||||
|
||||
<van-action-sheet v-model="rankShow" title="排行榜">
|
||||
<div class="vote-rank-list">
|
||||
<div v-for="(item, index) in voteStats.rankList || []" :key="item.optionId" class="vote-rank-item">
|
||||
<span class="vote-rank-index">{{index + 1}}</span>
|
||||
<div class="vote-rank-name">{{item.text}}</div>
|
||||
<div class="vote-rank-votes">{{item.votes}}票</div>
|
||||
</div>
|
||||
</div>
|
||||
</van-action-sheet>
|
||||
|
||||
<div class="vote-detail-page" v-if="detailVisible && detailOption">
|
||||
<div class="vote-detail-hero">
|
||||
<h2>{{activity.title}}</h2>
|
||||
<h3>》 {{detailOption.text}} 《</h3>
|
||||
<div class="vote-detail-stats">
|
||||
<span><i class="fa fa-th-large"></i> {{getOptionVotes(detailOption.id)}}票</span>
|
||||
<span><i class="fa fa-institution"></i> 第{{getOptionRank(detailOption.id)}}名</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="vote-countdown vote-detail-countdown" v-if="!isEnd">
|
||||
距离投票结束还有:
|
||||
<b>{{countdown.days}}</b> 天
|
||||
<b>{{countdown.hours}}</b> 时
|
||||
<b>{{countdown.minutes}}</b> 分
|
||||
<b>{{countdown.seconds}}</b> 秒
|
||||
</div>
|
||||
<div class="vote-countdown vote-detail-countdown" v-else>投票已结束</div>
|
||||
<div class="vote-detail-section">
|
||||
<h4>投票规则</h4>
|
||||
<p><i class="fa fa-play-circle"></i> 开始时间:{{activity.startTime || '-'}}</p>
|
||||
<p><i class="fa fa-stop-circle"></i> 结束时间:{{activity.endTime || '-'}}</p>
|
||||
<a v-if="detailOption.link" :href="detailOption.link" target="_blank">查看规则详情</a>
|
||||
</div>
|
||||
<div class="vote-detail-section">
|
||||
<h4>详情介绍</h4>
|
||||
<div class="vote-detail-content" v-if="detailOption.description" v-html="detailOption.description"></div>
|
||||
<div class="vote-detail-empty" v-else>暂无详情</div>
|
||||
</div>
|
||||
<div class="vote-detail-bottom">
|
||||
<button @click="closeOptionDetail">返回</button>
|
||||
<button
|
||||
class="primary"
|
||||
:disabled="answerRecord.isFinish || isEnd"
|
||||
@click="voteFromDetail">
|
||||
{{answerRecord.isFinish ? '已投票' : '投票'}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script nonce="${cspNonce!}">
|
||||
const vue = new Vue({
|
||||
el: "#app",
|
||||
data() {
|
||||
return {
|
||||
id: GetQueryString("id"),
|
||||
activity: {},
|
||||
subjects: [],
|
||||
answerRecordId: null,
|
||||
answerRecord: {},
|
||||
voteStats: {},
|
||||
keyword: "",
|
||||
selectedOptionIds: [],
|
||||
countdown: {
|
||||
days: 0,
|
||||
hours: 0,
|
||||
minutes: 0,
|
||||
seconds: 0
|
||||
},
|
||||
countdownTimer: null,
|
||||
rankShow: false,
|
||||
detailVisible: false,
|
||||
detailOption: null
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
currentSubject() {
|
||||
return this.subjects.length > 0 ? this.subjects[0] : null
|
||||
},
|
||||
optionList() {
|
||||
return this.currentSubject && this.currentSubject.options ? this.currentSubject.options : []
|
||||
},
|
||||
filteredOptions() {
|
||||
const keyword = (this.keyword || "").trim()
|
||||
if (!keyword) {
|
||||
return this.optionList
|
||||
}
|
||||
return this.optionList.filter((option, index) => {
|
||||
return String(index + 1).indexOf(keyword) > -1 || (option.text || "").indexOf(keyword) > -1
|
||||
})
|
||||
},
|
||||
pageTitle() {
|
||||
return this.getCategoryPageTitle(this.activity && this.activity.category, "投票")
|
||||
},
|
||||
isEnd() {
|
||||
if (!this.activity || !this.activity.endTime) {
|
||||
return false
|
||||
}
|
||||
return this.$moment().unix() > this.$moment(this.activity.endTime).unix()
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getCategoryPageTitle(category, defaultTitle) {
|
||||
const titleMap = {
|
||||
QUIZ: "在线答题",
|
||||
SURVEY: "问卷调查",
|
||||
VOTE: "投票"
|
||||
}
|
||||
return titleMap[category] || defaultTitle
|
||||
},
|
||||
noop() {
|
||||
},
|
||||
|
||||
getVoteOptionColumns(subject) {
|
||||
if (!subject || subject.optionLayout !== "HORIZONTAL") {
|
||||
return 1
|
||||
}
|
||||
return Number(subject.optionColumns) === 3 ? 3 : 2
|
||||
},
|
||||
|
||||
getVoteOptionListClass(subject) {
|
||||
return "vote-option-list vote-option-list-" + this.getVoteOptionColumns(subject)
|
||||
},
|
||||
|
||||
hasOptionDetail(option) {
|
||||
return !!(option && ((option.description && option.description.trim()) || option.link))
|
||||
},
|
||||
|
||||
openOptionDetail(option) {
|
||||
this.detailOption = option
|
||||
this.detailVisible = true
|
||||
},
|
||||
|
||||
closeOptionDetail() {
|
||||
this.detailVisible = false
|
||||
this.detailOption = null
|
||||
},
|
||||
|
||||
getOptionRank(optionId) {
|
||||
const list = this.voteStats.rankList || []
|
||||
const index = list.findIndex((item) => String(item.optionId) === String(optionId))
|
||||
return index > -1 ? index + 1 : "-"
|
||||
},
|
||||
|
||||
voteFromDetail() {
|
||||
if (!this.detailOption || this.answerRecord.isFinish || this.isEnd) {
|
||||
return
|
||||
}
|
||||
if (!this.isOptionSelected(this.detailOption.id)) {
|
||||
this.toggleOption(this.detailOption)
|
||||
}
|
||||
if (this.isOptionSelected(this.detailOption.id)) {
|
||||
this.onSubmit()
|
||||
}
|
||||
},
|
||||
|
||||
listSubjects() {
|
||||
this.$axios.post("/platform/h5/qsv/vote/subjects", {activityId: this.id}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.activity = res.data.activity || {}
|
||||
this.subjects = res.data.subjects || []
|
||||
this.answerRecordId = res.data.answerRecordId
|
||||
this.answerRecord = res.data.answerRecord || {}
|
||||
this.voteStats = res.data.voteStats || {}
|
||||
this.initAnswer()
|
||||
this.startCountdown()
|
||||
} else {
|
||||
this.$dialog.alert({
|
||||
title: "提示",
|
||||
message: res.msg
|
||||
}).then(() => {
|
||||
pjaxReplace("/platform/h5/qsv")
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
initAnswer() {
|
||||
if (!this.currentSubject || !this.answerRecord || !this.answerRecord.extJson) {
|
||||
this.selectedOptionIds = []
|
||||
return
|
||||
}
|
||||
const answer = this.answerRecord.extJson[this.currentSubject.id]
|
||||
this.selectedOptionIds = answer && answer.optionIds ? answer.optionIds.map(String) : []
|
||||
},
|
||||
|
||||
startCountdown() {
|
||||
if (this.countdownTimer) {
|
||||
clearInterval(this.countdownTimer)
|
||||
}
|
||||
this.updateCountdown()
|
||||
this.countdownTimer = setInterval(() => {
|
||||
this.updateCountdown()
|
||||
}, 1000)
|
||||
},
|
||||
|
||||
updateCountdown() {
|
||||
if (!this.activity || !this.activity.endTime) {
|
||||
return
|
||||
}
|
||||
const diff = Math.max(0, this.$moment(this.activity.endTime).unix() - this.$moment().unix())
|
||||
this.countdown.days = Math.floor(diff / 86400)
|
||||
this.countdown.hours = Math.floor((diff % 86400) / 3600)
|
||||
this.countdown.minutes = Math.floor((diff % 3600) / 60)
|
||||
this.countdown.seconds = diff % 60
|
||||
},
|
||||
|
||||
toggleOption(option) {
|
||||
if (this.answerRecord.isFinish || this.isEnd) {
|
||||
return
|
||||
}
|
||||
const optionId = String(option.id)
|
||||
const index = this.selectedOptionIds.indexOf(optionId)
|
||||
if (this.currentSubject.type === "radio") {
|
||||
this.selectedOptionIds = index > -1 ? [] : [optionId]
|
||||
return
|
||||
}
|
||||
if (index > -1) {
|
||||
this.selectedOptionIds.splice(index, 1)
|
||||
return
|
||||
}
|
||||
if (this.currentSubject.maxMulti && this.selectedOptionIds.length >= this.currentSubject.maxMulti) {
|
||||
this.$toast("最多选择" + this.currentSubject.maxMulti + "项")
|
||||
return
|
||||
}
|
||||
this.selectedOptionIds.push(optionId)
|
||||
},
|
||||
|
||||
isOptionSelected(optionId) {
|
||||
return this.selectedOptionIds.indexOf(String(optionId)) > -1
|
||||
},
|
||||
|
||||
getOptionStats(optionId) {
|
||||
return this.voteStats.optionStats && this.voteStats.optionStats[optionId]
|
||||
? this.voteStats.optionStats[optionId]
|
||||
: {votes: 0, percent: 0}
|
||||
},
|
||||
|
||||
getOptionVotes(optionId) {
|
||||
return this.getOptionStats(optionId).votes || 0
|
||||
},
|
||||
|
||||
getOptionPercent(optionId) {
|
||||
const percent = this.getOptionStats(optionId).percent || 0
|
||||
return Number(percent).toFixed(2)
|
||||
},
|
||||
|
||||
previewOptionImg(img) {
|
||||
vant.ImagePreview([img])
|
||||
},
|
||||
|
||||
onSubmit() {
|
||||
if (!this.currentSubject) {
|
||||
return
|
||||
}
|
||||
if (this.isEnd) {
|
||||
this.$toast("投票已结束")
|
||||
return
|
||||
}
|
||||
if (this.selectedOptionIds.length === 0) {
|
||||
this.$toast.fail("请选择投票选项")
|
||||
return
|
||||
}
|
||||
this.$axios.post("/platform/h5/qsv/vote/submitAnswer", {
|
||||
answer: JSON.stringify({
|
||||
activityId: this.id,
|
||||
answerRecordId: this.answerRecordId,
|
||||
subjects: [
|
||||
{
|
||||
id: this.currentSubject.id,
|
||||
userSelectOptionIds: this.selectedOptionIds
|
||||
}
|
||||
]
|
||||
})
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$toast.success(res.msg)
|
||||
this.listSubjects()
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
historyBack() {
|
||||
pjaxReplace("/platform/h5/qsv")
|
||||
}
|
||||
},
|
||||
created() {
|
||||
if (this.id) {
|
||||
this.listSubjects()
|
||||
}
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (this.countdownTimer) {
|
||||
clearInterval(this.countdownTimer)
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.vote-page {
|
||||
min-height: 100vh;
|
||||
background: #fff1e9;
|
||||
padding-bottom: calc(20px + env(safe-area-inset-bottom));
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.vote-header {
|
||||
padding: 36px 20px 28px;
|
||||
background: radial-gradient(circle at right top, #fff 0, #fff7f2 38%, #fffdfb 100%);
|
||||
}
|
||||
|
||||
.vote-header h1 {
|
||||
margin: 0 0 34px;
|
||||
color: #ff4d00;
|
||||
font-size: 22px;
|
||||
text-align: center;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.vote-stat-box {
|
||||
height: 106px;
|
||||
border: 1px solid #ff6a2b;
|
||||
border-radius: 8px;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr 1fr;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
background: rgba(255, 255, 255, .62);
|
||||
}
|
||||
|
||||
.vote-stat-box:before,
|
||||
.vote-stat-box:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: -1px;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
background: #fff7f2;
|
||||
}
|
||||
|
||||
.vote-stat-box:before {
|
||||
left: -1px;
|
||||
border-right: 1px solid #ff6a2b;
|
||||
border-bottom: 1px solid #ff6a2b;
|
||||
border-radius: 0 0 8px 0;
|
||||
}
|
||||
|
||||
.vote-stat-box:after {
|
||||
right: -1px;
|
||||
border-left: 1px solid #ff6a2b;
|
||||
border-bottom: 1px solid #ff6a2b;
|
||||
border-radius: 0 0 0 8px;
|
||||
}
|
||||
|
||||
.vote-stat-item {
|
||||
text-align: center;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.vote-stat-item strong {
|
||||
display: block;
|
||||
margin-bottom: 8px;
|
||||
color: #ff4d00;
|
||||
font-size: 24px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.vote-stat-item span {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.vote-rank-btn {
|
||||
justify-self: center;
|
||||
min-width: 82px;
|
||||
height: 30px;
|
||||
border: 1px solid #ff6a2b;
|
||||
border-radius: 4px;
|
||||
background: #fff;
|
||||
color: #ff4d00;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 4px;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.vote-rank-btn .fa {
|
||||
margin-right: 8px;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.vote-countdown {
|
||||
padding: 12px 16px;
|
||||
color: #ff4d00;
|
||||
font-size: 13px;
|
||||
background: #fff7f2;
|
||||
}
|
||||
|
||||
.vote-countdown b {
|
||||
display: inline-block;
|
||||
min-width: 22px;
|
||||
height: 20px;
|
||||
margin: 0 2px;
|
||||
border-radius: 2px;
|
||||
background: #ff5a1f;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
line-height: 20px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.vote-search {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: 8px 4px 0;
|
||||
background: #fff;
|
||||
border: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.vote-search .van-search {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.vote-search button {
|
||||
width: 58px;
|
||||
height: 44px;
|
||||
border: 0;
|
||||
border-left: 1px solid #f0f0f0;
|
||||
background: #fff;
|
||||
color: #ff4d00;
|
||||
}
|
||||
|
||||
.vote-subject {
|
||||
padding: 14px 15px 18px;
|
||||
}
|
||||
|
||||
.vote-subject-title {
|
||||
margin-bottom: 12px;
|
||||
color: #333;
|
||||
font-size: 16px;
|
||||
line-height: 1.55;
|
||||
}
|
||||
|
||||
.vote-subject-title span {
|
||||
color: #e61f1f;
|
||||
}
|
||||
|
||||
.vote-subject-title em {
|
||||
color: #666;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
.vote-option-list {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.vote-option-list-2,
|
||||
.vote-option-list-3 {
|
||||
display: grid;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.vote-option-list-2 {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.vote-option-list-3 {
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.vote-option-card {
|
||||
margin-bottom: 14px;
|
||||
background: #fff;
|
||||
border: 1px solid transparent;
|
||||
box-sizing: border-box;
|
||||
transition: border-color .2s, background-color .2s;
|
||||
}
|
||||
|
||||
.vote-option-list-2 .vote-option-card,
|
||||
.vote-option-list-3 .vote-option-card {
|
||||
min-width: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.vote-option-card.active {
|
||||
border-color: #ff4d00;
|
||||
background: #fff8f4;
|
||||
}
|
||||
|
||||
.vote-option-img {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 172px;
|
||||
border-radius: 6px;
|
||||
overflow: hidden;
|
||||
background: #f4f4f4;
|
||||
}
|
||||
|
||||
.vote-option-list-2 .vote-option-img {
|
||||
height: 126px;
|
||||
}
|
||||
|
||||
.vote-option-list-3 .vote-option-img {
|
||||
height: 92px;
|
||||
}
|
||||
|
||||
.vote-option-img img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: inherit;
|
||||
object-fit: cover;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.vote-option-img .van-icon {
|
||||
position: absolute;
|
||||
right: 8px;
|
||||
top: 8px;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
border-radius: 50%;
|
||||
background: rgba(255, 255, 255, .78);
|
||||
color: #5a8ee8;
|
||||
text-align: center;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.vote-option-placeholder {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #ff7b3c;
|
||||
font-size: 42px;
|
||||
font-weight: 700;
|
||||
background: linear-gradient(135deg, #fff7f2, #ffe4d7);
|
||||
}
|
||||
|
||||
.vote-option-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 10px 12px;
|
||||
min-height: 50px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.vote-option-control {
|
||||
flex-shrink: 0;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
margin: 0;
|
||||
accent-color: #ff4d00;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.vote-option-control:disabled {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.vote-option-text {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.vote-option-text strong {
|
||||
display: block;
|
||||
margin-bottom: 5px;
|
||||
color: #ff4d00;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.vote-option-text span {
|
||||
display: block;
|
||||
color: #333;
|
||||
font-size: 15px;
|
||||
line-height: 20px;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.vote-option-detail-btn {
|
||||
flex-shrink: 0;
|
||||
align-self: center;
|
||||
margin: 0;
|
||||
padding: 4px 0 4px 8px;
|
||||
border: 0;
|
||||
background: transparent;
|
||||
color: #ff4d00;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.vote-bottom {
|
||||
position: relative;
|
||||
width: auto;
|
||||
margin: 0 15px;
|
||||
padding: 14px 19px calc(14px + env(safe-area-inset-bottom));
|
||||
background: #fff1e9;
|
||||
z-index: 1;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.vote-rank-list {
|
||||
padding: 12px;
|
||||
background: #f8f8f8;
|
||||
}
|
||||
|
||||
.vote-rank-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 12px;
|
||||
margin-bottom: 8px;
|
||||
border-radius: 8px;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.vote-rank-index {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border-radius: 50%;
|
||||
background: #ff5a1f;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
.vote-rank-name {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.vote-rank-votes {
|
||||
color: #ff4d00;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.vote-detail-page {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: 1000;
|
||||
overflow-y: auto;
|
||||
padding-bottom: calc(88px + env(safe-area-inset-bottom));
|
||||
background: #f5f8fb;
|
||||
box-sizing: border-box;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
.vote-detail-hero {
|
||||
padding: 30px 18px 28px;
|
||||
min-height: 150px;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
background: linear-gradient(135deg, #ff4d00 0%, #ff6a1f 48%, #f24a00 100%);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.vote-detail-hero h2 {
|
||||
margin: 0 0 24px;
|
||||
font-size: 21px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.vote-detail-hero h3 {
|
||||
margin: 0 0 28px;
|
||||
font-size: 20px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.vote-detail-stats {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
font-size: 15px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.vote-detail-countdown {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.vote-detail-section {
|
||||
margin: 10px 0;
|
||||
padding: 16px;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.vote-detail-section h4 {
|
||||
margin: 0 0 14px;
|
||||
color: #222;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.vote-detail-section p {
|
||||
margin: 10px 0;
|
||||
color: #333;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.vote-detail-section i {
|
||||
margin-right: 8px;
|
||||
color: #ff4d00;
|
||||
}
|
||||
|
||||
.vote-detail-section a {
|
||||
color: #ff4d00;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.vote-detail-content {
|
||||
color: #333;
|
||||
font-size: 14px;
|
||||
line-height: 1.7;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.vote-detail-content img {
|
||||
max-width: 100%;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.vote-detail-empty {
|
||||
color: #999;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.vote-detail-bottom {
|
||||
position: fixed;
|
||||
left: 50%;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
max-width: 750px;
|
||||
transform: translateX(-50%);
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
min-height: calc(54px + env(safe-area-inset-bottom));
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
border-top: 1px solid #eee;
|
||||
background: #fff;
|
||||
z-index: 1001;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.vote-detail-bottom button {
|
||||
border: 0;
|
||||
background: #fff;
|
||||
color: #ff4d00;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.vote-detail-bottom button.primary {
|
||||
background: #ff4d00;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.vote-detail-bottom button:disabled {
|
||||
background: #f3f3f3;
|
||||
color: #bbb;
|
||||
}
|
||||
</style>
|
||||
|
||||
<!--#
|
||||
}
|
||||
#-->
|
||||
Reference in New Issue
Block a user