1
0
mirror of https://github.com/ialley-workshop-open/uni-halo.git synced 2026-06-12 21:29:31 +08:00

fix: 修复投票多选BUG

This commit is contained in:
小莫唐尼
2025-08-21 11:18:08 +08:00
parent 61d3b22fdb
commit 5606e8c59f
4 changed files with 117 additions and 118 deletions
+23 -1
View File
@@ -151,6 +151,10 @@
index: { index: {
type: Number, type: Number,
default: 0 default: 0
},
article: {
type: Object,
default: () => ({})
} }
}, },
data() { data() {
@@ -236,6 +240,12 @@
formatJsonStr(jsonStr) { formatJsonStr(jsonStr) {
return jsonStr ? JSON.parse(jsonStr) : {} return jsonStr ? JSON.parse(jsonStr) : {}
}, },
handleSubmitTip() {
uni.showToast({
icon: "none",
title: "请选择选项后继续"
})
},
handleSubmit() { handleSubmit() {
if (!this.vote.spec.canAnonymously) { if (!this.vote.spec.canAnonymously) {
uni.showModal({ uni.showModal({
@@ -247,7 +257,8 @@
confirmText: "复制地址", confirmText: "复制地址",
success: (res) => { success: (res) => {
if (res.confirm) { if (res.confirm) {
this.$utils.copyText(this.$baseApiUrl, "复制成功") const articleUrl = this.$baseApiUrl + (this.article?.status?.permalink ?? "")
this.$utils.copyText(articleUrl, "原文地址复制成功")
} }
} }
}) })
@@ -296,6 +307,17 @@
handleSelectCheckboxOption(option) { handleSelectCheckboxOption(option) {
if (this.vote.spec.disabled) return if (this.vote.spec.disabled) return
const checkedList = this.vote.spec.options.filter(x => x.checked && x.id != option.id)
if (this.vote.spec.type === 'multiple' && checkedList.length >= this.vote.spec.maxVotes) {
uni.showToast({
icon: "none",
title: `最多选择 ${this.vote.spec.maxVotes}`
})
return
}
this.vote.spec.options.map(item => { this.vote.spec.options.map(item => {
if (option.id == item.id) { if (option.id == item.id) {
item.checked = !item.checked item.checked = !item.checked
+2 -2
View File
@@ -173,7 +173,7 @@
padding: 24rpx; padding: 24rpx;
border-radius: 12rpx; border-radius: 12rpx;
background-color: #ffff; background-color: #ffff;
box-shadow: 0rpx 2rpx 24rpx rgba(0, 0, 0, 0.075); box-shadow: 0rpx 2rpx 12rpx rgba(0, 0, 0, 0.035);
overflow: hidden; overflow: hidden;
margin-bottom: 24rpx; margin-bottom: 24rpx;
// border: 1px solid #eee; // border: 1px solid #eee;
@@ -207,7 +207,7 @@
box-sizing: border-box; box-sizing: border-box;
padding-top: 6px; padding-top: 6px;
margin-top: 6px; margin-top: 6px;
border-top: 2rpx solid #eee; border-top: 2rpx solid #F7F7F7;
.left{ .left{
+39 -28
View File
@@ -106,24 +106,32 @@
</view> </view>
<!-- 投票 --> <!-- 投票 -->
<view v-if="!calcAuditModeEnabled && result._voteIds.length!==0" class="vote-wrap copyright-wrap bg-white mt-24 pa-24 round-4"> <view v-if="!calcAuditModeEnabled && result._voteIds.length!==0"
<PluginUnavailable v-if="!uniHaloPluginAvailable" :pluginId="uniHaloPluginId" class="vote-wrap copyright-wrap bg-white mt-24 pa-24 round-4">
:error-text="uniHaloPluginAvailableError" />
<template v-else> <view class="copyright-title text-weight-b flex items-center justify-between">
<view class="copyright-title text-weight-b flex items-center justify-between"> <text>相关投票</text>
<text>相关投票</text> <text class="vote-opra" @click="voteIsOpen=!voteIsOpen">
<text class="vote-opra" @click="voteIsOpen=!voteIsOpen"> {{ voteIsOpen?'收起':'展开' }}
{{ voteIsOpen?'收起':'展开' }} </text>
</text> </view>
</view> <view v-show="voteIsOpen" class="flex flex-col uh-gap-8 uh-mt-8">
<view v-show="voteIsOpen" class="flex flex-col uh-gap-8 uh-mt-8"> <PluginUnavailable v-if="!uniHaloPluginAvailable" :article="result" :pluginId="uniHaloPluginId"
<ArticleVote v-for="(voteId,voteIdIndex) in result._voteIds" :key="voteId" :voteId="voteId" :index="voteIdIndex"> :error-text="uniHaloPluginAvailableError" :useDecoration="false" :customStyle="{
width:'100%',borderRadius:'16rpx' }" />
<template v-else>
<ArticleVote v-for="(voteId,voteIdIndex) in result._voteIds" :key="voteId" :voteId="voteId"
:index="voteIdIndex">
</ArticleVote> </ArticleVote>
</view> <view v-show="!voteIsOpen" class="vote-tip" @click="voteIsOpen=!voteIsOpen">
<view v-show="!voteIsOpen" class="vote-tip" @click="voteIsOpen=!voteIsOpen"> 投票已收起点击展开 {{result._voteIds.length}} 个投票项
投票已收起点击展开 {{result._voteIds.length}} 个投票项 </view>
</view> </template>
</template> </view>
<view v-show="!uniHaloPluginAvailable && !voteIsOpen" class="vote-tip"
@click="voteIsOpen=!voteIsOpen">
提示区域已收起点击显示
</view>
</view> </view>
<!-- 版权声明 --> <!-- 版权声明 -->
@@ -325,11 +333,12 @@
import RestrictReadSkeleton from "@/components/restrict-read-skeleton/restrict-read-skeleton.vue"; import RestrictReadSkeleton from "@/components/restrict-read-skeleton/restrict-read-skeleton.vue";
import TmImages from "@/tm-vuetify/components/tm-images/tm-images.vue"; import TmImages from "@/tm-vuetify/components/tm-images/tm-images.vue";
import TmInput from "@/tm-vuetify/components/tm-input/tm-input.vue"; import TmInput from "@/tm-vuetify/components/tm-input/tm-input.vue";
import pluginAvailable from "@/common/mixins/pluginAvailable.js" import pluginAvailableMixin from "@/common/mixins/pluginAvailable.js"
import PluginUnavailable from '@/components/plugin-unavailable/plugin-unavailable.vue'
let videoAd = null; let videoAd = null;
export default { export default {
mixins:[pluginAvailable], mixins: [pluginAvailableMixin],
components: { components: {
TmInput, TmInput,
TmImages, TmImages,
@@ -347,7 +356,8 @@
rCanvas, rCanvas,
barrage, barrage,
commentModal, commentModal,
ArticleVote ArticleVote,
PluginUnavailable
}, },
data() { data() {
return { return {
@@ -1444,15 +1454,16 @@
.vote-opra { .vote-opra {
font-size: 24rpx; font-size: 24rpx;
font-weight: normal; font-weight: normal;
color:#999; color: #999;
} }
.vote-tip{
margin-top:12rpx; .vote-tip {
padding:50rpx 24rpx; margin-top: 12rpx;
background:#F1F5F9; padding: 50rpx 24rpx;
color:#666; background: #F1F5F9;
font-size:24rpx; color: #666;
border-radius:12rpx; font-size: 24rpx;
border-radius: 12rpx;
text-align: center; text-align: center;
} }
+51 -85
View File
@@ -11,11 +11,9 @@
<tm-empty icon="icon-shiliangzhinengduixiang-" label="未查询到数据"></tm-empty> <tm-empty icon="icon-shiliangzhinengduixiang-" label="未查询到数据"></tm-empty>
</view> </view>
<block v-else> <block v-else>
<view class="vote-card"> <view class="vote-card vote-info-card">
<view class="sub-title"> 投票信息 </view> <view class="sub-title"> 投票信息 </view>
<view class="vote-card-body flex flex-col" <view class="vote-card-body flex flex-col uh-mt-8">
style="margin-top:12rpx;font-size:28rpx;gap:12rpx 0;background:#F3F4F6;color:#2B2F33;padding:24rpx;border-radius:12rpx;">
<view class=""> <view class="">
投票类型<tm-tags v-if="vote.spec.type==='single'" color="light-blue" :shadow="0" size="xs" 投票类型<tm-tags v-if="vote.spec.type==='single'" color="light-blue" :shadow="0" size="xs"
model="fill">单选</tm-tags> model="fill">单选</tm-tags>
@@ -34,9 +32,6 @@
model="fill">匿名</tm-tags> model="fill">匿名</tm-tags>
<tm-tags v-else color="red" size="xs" :shadow="0" model="fill">不匿名</tm-tags> <tm-tags v-else color="red" size="xs" :shadow="0" model="fill">不匿名</tm-tags>
</view> </view>
<view v-if="vote.spec.remark" class="">
投票说明{{ vote.spec.remark||"暂无说明" }}
</view>
<view class=""> <view class="">
截止时间{{ {d: vote.spec.endDate, f: 'yyyy-MM-dd HH:mm'} | formatTime }} 截止时间{{ {d: vote.spec.endDate, f: 'yyyy-MM-dd HH:mm'} | formatTime }}
</view> </view>
@@ -49,29 +44,14 @@
<view class="sub-content"> <view class="sub-content">
{{ vote.spec.title }} {{ vote.spec.title }}
</view> </view>
<view v-if="vote.spec.remark" class="sub-remark">
{{ vote.spec.remark }}
</view>
</view> </view>
<view class="vote-card-body"> <view class="vote-card-body uh-mt-8">
<view class="sub-title"> 投票选项 <text v-if="vote.spec.type==='multiple'" <view class="sub-title"> 投票选项 <text v-if="vote.spec.type==='multiple'"
class="sub-title-count">最多选择 {{ vote.spec.maxVotes }} </text> </view> class="sub-title-count">最多选择 {{ vote.spec.maxVotes }} </text> </view>
<view v-if="vote.spec.type==='single'" class="single"> <view v-if="vote.spec.type==='single'" class="single">
<!-- <tm-groupradio @change="onOptionRadioChange">
<tm-radio v-for="(option,optionIndex) in vote.spec.options" :key="optionIndex" dense
:disabled="vote.spec.disabled" v-model="option.checked" :extendData="option">
<template v-slot:default="{checkData}">
<tm-button :shadow="0" :theme="checkData.checked?'light-blue':'grey-lighten-3'"
:plan="false" size="m" :height="72">
<view class="flex flex-between w-full">
<text class="text-align-left text-overflow">
{{ checkData.extendData.title }}
</text>
<text v-if="checkData.extendData.isVoted" class="flex-shrink ml-12">
{{checkData.extendData.percent }}%
</text>
</view>
</tm-button>
</template>
</tm-radio>
</tm-groupradio> -->
<view class="w-full flex flex-col uh-gap-8"> <view class="w-full flex flex-col uh-gap-8">
<tm-button v-for="(option,optionIndex) in vote.spec.options" :key="optionIndex" <tm-button v-for="(option,optionIndex) in vote.spec.options" :key="optionIndex"
:shadow="0" :theme="option.checked?'light-blue':'grey-lighten-3'" :plan="false" :shadow="0" :theme="option.checked?'light-blue':'grey-lighten-3'" :plan="false"
@@ -90,25 +70,6 @@
</view> </view>
<view v-else-if="vote.spec.type==='multiple'" class="multiple"> <view v-else-if="vote.spec.type==='multiple'" class="multiple">
<!-- <tm-groupcheckbox @change="onOptionCheckboxChange">
<tm-checkbox v-for="(option,optionIndex) in vote.spec.options" :key="optionIndex" dense
:disabled="vote.spec.disabled" v-model="option.checked" :extendData="option">
<template v-slot:default="{checkData}">
<tm-button :shadow="0" :theme="checkData.checked?'light-blue':'grey-lighten-3'"
:plan="false" size="m" :height="72">
<view class="flex flex-between w-full">
<text class="text-align-left text-overflow">
{{ checkData.extendData.title }}
</text>
<text v-if="checkData.extendData.isVoted" class="flex-shrink ml-12">
{{checkData.extendData.percent }}%
</text>
</view>
</tm-button>
</template>
</tm-checkbox>
</tm-groupcheckbox> -->
<view class="w-full flex flex-col uh-gap-8"> <view class="w-full flex flex-col uh-gap-8">
<tm-button v-for="(option,optionIndex) in vote.spec.options" :key="optionIndex" <tm-button v-for="(option,optionIndex) in vote.spec.options" :key="optionIndex"
:shadow="0" :theme="option.checked?'light-blue':'grey-lighten-3'" :plan="false" :shadow="0" :theme="option.checked?'light-blue':'grey-lighten-3'" :plan="false"
@@ -138,25 +99,6 @@
</view> </view>
</view> </view>
<view class="option-foot w-full flex flex-between"> <view class="option-foot w-full flex flex-between">
<!-- <tm-groupradio @change="onOptionPkChange" >
<tm-radio v-for="(option,optionIndex) in vote.spec.options" :key="optionIndex" dense
:disabled="vote.spec.disabled" v-model="option.checked"
:extendData="{optionIndex:optionIndex,...option}" >
<template v-slot:default="{checkData}">
<tm-button :shadow="0"
:theme="checkData.checked?'light-blue':'grey-lighten-3'" :plan="false"
size="m" :height="72">
<view class="flex flex-between w-full">
<text class="text-align-left text-overflow">
选项{{checkData.extendData.optionIndex+1}}{{ checkData.extendData.title }}
</text>
</view>
</tm-button>
</template>
</tm-radio>
</tm-groupradio> -->
<view class="w-full flex flex-between uh-gap-8"> <view class="w-full flex flex-between uh-gap-8">
<tm-button v-for="(option,optionIndex) in vote.spec.options" :key="optionIndex" <tm-button v-for="(option,optionIndex) in vote.spec.options" :key="optionIndex"
:shadow="0" :theme="option.checked?'light-blue':'grey-lighten-3'" :plan="false" :shadow="0" :theme="option.checked?'light-blue':'grey-lighten-3'" :plan="false"
@@ -169,7 +111,6 @@
</view> </view>
</tm-button> </tm-button>
</view> </view>
</view> </view>
</view> </view>
</view> </view>
@@ -181,6 +122,7 @@
<view class=""> <view class="">
<tm-tags color="grey-darken-4" size="s" model="text">{{ vote.stats.voteCount }} <tm-tags color="grey-darken-4" size="s" model="text">{{ vote.stats.voteCount }}
人已参与</tm-tags> 人已参与</tm-tags>
<tm-tags v-if="vote.spec.isVoted" color="blue" rounded size="s" model="text">已投票</tm-tags>
</view> </view>
</view> </view>
</view> </view>
@@ -191,6 +133,8 @@
:block="true" @click="handleSubmit()">不允许匿名投票</tm-button> :block="true" @click="handleSubmit()">不允许匿名投票</tm-button>
<tm-button v-else-if="fnCalcIsVoted()" theme="white" text :block="true" <tm-button v-else-if="fnCalcIsVoted()" theme="white" text :block="true"
class="w-full">您已参与投票</tm-button> class="w-full">您已参与投票</tm-button>
<tm-button v-else-if="submitForm.voteData.length===0" theme="white" text class="w-full"
:block="true" @click="handleSubmitTip()">提交投票请选择选项</tm-button>
<tm-button v-else theme="light-blue" class="w-full" :block="true" <tm-button v-else theme="light-blue" class="w-full" :block="true"
@click="handleSubmit()">提交投票</tm-button> @click="handleSubmit()">提交投票</tm-button>
</view> </view>
@@ -203,10 +147,6 @@
import tmSkeleton from '@/tm-vuetify/components/tm-skeleton/tm-skeleton.vue'; import tmSkeleton from '@/tm-vuetify/components/tm-skeleton/tm-skeleton.vue';
import tmEmpty from '@/tm-vuetify/components/tm-empty/tm-empty.vue'; import tmEmpty from '@/tm-vuetify/components/tm-empty/tm-empty.vue';
import tmButton from '@/tm-vuetify/components/tm-button/tm-button.vue'; import tmButton from '@/tm-vuetify/components/tm-button/tm-button.vue';
import tmGroupradio from '@/tm-vuetify/components/tm-groupradio/tm-groupradio.vue';
import tmRadio from '@/tm-vuetify/components/tm-radio/tm-radio.vue';
import tmGroupcheckbox from '@/tm-vuetify/components/tm-groupcheckbox/tm-groupcheckbox.vue';
import tmCheckbox from '@/tm-vuetify/components/tm-checkbox/tm-checkbox.vue';
import tmTags from '@/tm-vuetify/components/tm-tags/tm-tags.vue'; import tmTags from '@/tm-vuetify/components/tm-tags/tm-tags.vue';
import { import {
@@ -224,10 +164,6 @@
tmSkeleton, tmSkeleton,
tmEmpty, tmEmpty,
tmButton, tmButton,
tmGroupradio,
tmRadio,
tmGroupcheckbox,
tmCheckbox,
tmTags, tmTags,
}, },
data() { data() {
@@ -241,11 +177,6 @@
vote: null, vote: null,
submitForm: { submitForm: {
voteData: [] voteData: []
},
votedSelected: {
checkbox: [],
radio: [],
pk: []
} }
}; };
}, },
@@ -350,6 +281,12 @@
formatJsonStr(jsonStr) { formatJsonStr(jsonStr) {
return jsonStr ? JSON.parse(jsonStr) : {} return jsonStr ? JSON.parse(jsonStr) : {}
}, },
handleSubmitTip(){
uni.showToast({
icon: "none",
title: "请选择选项后继续"
})
},
handleSubmit() { handleSubmit() {
if (!this.vote.spec.canAnonymously) { if (!this.vote.spec.canAnonymously) {
uni.showModal({ uni.showModal({
@@ -372,9 +309,6 @@
title: "正在保存..." title: "正在保存..."
}) })
// 使用简单版
this.submitForm.voteData = this.vote.spec.options.filter(x => x.checked).map(item => item.id)
this.$httpApi.v2 this.$httpApi.v2
.submitVote(this.name, this.submitForm, this.vote.spec.canAnonymously) .submitVote(this.name, this.submitForm, this.vote.spec.canAnonymously)
.then(res => { .then(res => {
@@ -410,15 +344,30 @@
item.checked = false item.checked = false
} }
}) })
this.submitForm.voteData = this.vote.spec.options.filter(x => x.checked).map(item => item.id)
}, },
handleSelectCheckboxOption(option) { handleSelectCheckboxOption(option) {
if (this.vote.spec.disabled) return if (this.vote.spec.disabled) return
const checkedList = this.vote.spec.options.filter(x => x.checked && x.id != option.id)
if (this.vote.spec.type === 'multiple' && checkedList.length >= this.vote.spec.maxVotes) {
uni.showToast({
icon: "none",
title: `最多选择 ${this.vote.spec.maxVotes}`
})
return
}
this.vote.spec.options.map(item => { this.vote.spec.options.map(item => {
if (option.id == item.id) { if (option.id == item.id) {
item.checked = !item.checked item.checked = !item.checked
} }
}) })
this.submitForm.voteData = this.vote.spec.options.filter(x => x.checked).map(item => item.id)
} }
} }
}; };
@@ -469,6 +418,17 @@
margin-bottom: 24rpx; margin-bottom: 24rpx;
} }
.vote-info-card {
.vote-card-body {
font-size: 28rpx;
gap: 12rpx 0;
background: #F3F4F6;
color: #3F3F3F;
padding: 24rpx;
border-radius: 12rpx;
}
}
.vote-card-head { .vote-card-head {
margin-bottom: 12rpx; margin-bottom: 12rpx;
display: flex; display: flex;
@@ -620,20 +580,26 @@
} }
.sub-content { .sub-content {
margin-bottom: 12rpx;
padding: 12rpx 0;
font-weight: bold; font-weight: bold;
color: #2B2F33; color: #2B2F33;
padding: 12rpx 0; font-size: 30rpx;
font-size: 32rpx;
margin-bottom: 12rpx;
} }
.sub-remark {
margin-bottom: 36rpx;
padding-top: 12rpx;
color: #3F3F3F;
font-size: 28rpx;
}
.sub-title { .sub-title {
box-sizing: border-box; box-sizing: border-box;
position: relative; position: relative;
margin-bottom: 12rpx; margin-bottom: 12rpx;
padding-left: 24rpx; padding-left: 24rpx;
font-weight: bold; // font-weight: bold;
font-size: 30rpx; font-size: 30rpx;
&:before { &:before {