mirror of
https://github.com/ialley-workshop-open/uni-halo.git
synced 2026-06-12 21:29:31 +08:00
feat: 新增投票功能
This commit is contained in:
@@ -0,0 +1,330 @@
|
|||||||
|
<template>
|
||||||
|
<view class="vote-card" @click="$emit('on-click',vote)">
|
||||||
|
<view class="vote-card-head flex">
|
||||||
|
<view class="left flex flex-center">
|
||||||
|
<view class="flex-shrink">
|
||||||
|
<tm-tags v-if="vote.spec.type==='single'" color="light-blue" :shadow="0" rounded size="s"
|
||||||
|
model="fill">单选</tm-tags>
|
||||||
|
<tm-tags v-else-if="vote.spec.type==='multiple'" color="light-blue" :shadow="0" rounded size="s"
|
||||||
|
model="fill">多选</tm-tags>
|
||||||
|
<tm-tags v-else-if="vote.spec.type==='pk'" color="light-blue" :shadow="0" rounded size="s"
|
||||||
|
model="fill">双选PK</tm-tags>
|
||||||
|
</view>
|
||||||
|
<view class="title text-overflow">
|
||||||
|
{{ vote.spec.title }}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-shrink right flex flex-end">
|
||||||
|
<tm-tags v-if="vote.spec.hasEnded" color="red" rounded :shadow="0" size="s" model="text">已结束</tm-tags>
|
||||||
|
<tm-tags v-else color="green" rounded size="s" :shadow="0" model="text">进行中</tm-tags>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="vote-card-body">
|
||||||
|
|
||||||
|
<view v-if="vote.spec.remark" class="remark text-overflow-2 text-size-s">
|
||||||
|
{{vote.spec.remark}}
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<template v-if="showOptions">
|
||||||
|
<!-- 单选 -->
|
||||||
|
<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" :block="true" class="w-full" size="m" :height="72">
|
||||||
|
<view class="flex flex-between w-full">
|
||||||
|
<text class="text-align-left text-overflow"> {{ checkData.extendData.title }}
|
||||||
|
</text>
|
||||||
|
<text class="flex-shrink"> {{checkData.extendData.percent }}% </text>
|
||||||
|
</view>
|
||||||
|
</tm-button>
|
||||||
|
</template>
|
||||||
|
</tm-radio>
|
||||||
|
</tm-groupradio>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 多选 -->
|
||||||
|
<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" :block="true" class="w-full" size="m" :height="72">
|
||||||
|
<view class="flex flex-between w-full">
|
||||||
|
<text class="text-align-left text-overflow"> {{ checkData.extendData.title }}
|
||||||
|
</text>
|
||||||
|
<text class="flex-shrink"> {{checkData.extendData.percent }}% </text>
|
||||||
|
</view>
|
||||||
|
</tm-button>
|
||||||
|
</template>
|
||||||
|
</tm-checkbox>
|
||||||
|
</tm-groupcheckbox>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- PK -->
|
||||||
|
<view v-else-if="vote.spec.type==='pk'" class="pk">
|
||||||
|
<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="option"
|
||||||
|
class="radio-item" :class="[optionIndex==0?'radio-left':'radio-right']"
|
||||||
|
:style="{width:option.percent + '%'}">
|
||||||
|
<template v-slot:default="{checkData}">
|
||||||
|
<view class="option-item"
|
||||||
|
:class="[optionIndex==0?'option-item-left':'option-item-right']">
|
||||||
|
{{checkData.extendData.percent }}%
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
</tm-radio>
|
||||||
|
</tm-groupradio>
|
||||||
|
<view class="option-foot w-full flex flex-between">
|
||||||
|
<view v-for="(option,optionIndex) in vote.spec.options" :key="optionIndex">
|
||||||
|
<view v-if="optionIndex==0" class="left flex-1 flex-shrink text-overflow">
|
||||||
|
{{option.title}}
|
||||||
|
</view>
|
||||||
|
<view v-else class="right flex-1 flex-shrink text-overflow text-align-right">
|
||||||
|
{{option.title}}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
</view>
|
||||||
|
<view class="vote-card-foot flex flex-between">
|
||||||
|
<view class="left flex">
|
||||||
|
<tm-tags color="grey-darken-2" rounded size="s"
|
||||||
|
model="text">{{ {d: vote.spec.endDate, f: 'yyyy-MM-dd HH:mm'} | formatTime }} 结束</tm-tags>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="right flex flex-end">
|
||||||
|
<tm-tags color="grey-darken-2" rounded size="s" model="text">{{ vote.stats.voteCount }} 人已参与</tm-tags>
|
||||||
|
<tm-tags v-if="vote.spec.isVoted" color="blue" rounded size="s" model="text">已投票</tm-tags>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
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 tmButton from '@/tm-vuetify/components/tm-button/tm-button.vue';
|
||||||
|
import tmTags from '@/tm-vuetify/components/tm-tags/tm-tags.vue';
|
||||||
|
export default {
|
||||||
|
name: "VoteCard",
|
||||||
|
options: {
|
||||||
|
virtualHost: true,
|
||||||
|
styleIsolation: 'shared'
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
tmGroupradio,
|
||||||
|
tmRadio,
|
||||||
|
tmGroupcheckbox,
|
||||||
|
tmCheckbox,
|
||||||
|
tmButton,
|
||||||
|
tmTags
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
vote: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({})
|
||||||
|
},
|
||||||
|
index: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
showOptions: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
onOptionRadioChange(e) {
|
||||||
|
console.log("onOptionRadioChange", e)
|
||||||
|
},
|
||||||
|
onOptionCheckboxChange(e) {
|
||||||
|
console.log("onOptionCheckboxChange", e)
|
||||||
|
},
|
||||||
|
onOptionPkChange(e) {
|
||||||
|
console.log("onOptionPkChange", e)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.w-full {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wp-50 {
|
||||||
|
width: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vote-card {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
box-sizing: border-box;
|
||||||
|
margin: 0 24rpx;
|
||||||
|
padding: 24rpx;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
background-color: #ffff;
|
||||||
|
box-shadow: 0rpx 2rpx 24rpx rgba(0, 0, 0, 0.075);
|
||||||
|
overflow: hidden;
|
||||||
|
margin-bottom: 24rpx;
|
||||||
|
// border: 1px solid #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vote-card-head {
|
||||||
|
margin-bottom: 12rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
.left {
|
||||||
|
.title {
|
||||||
|
font-size: 28rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.vote-card-body {
|
||||||
|
|
||||||
|
.remark {
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 12rpx 6rpx;
|
||||||
|
padding-top: 0;
|
||||||
|
color: rgba(0, 0, 0, 0.75);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.vote-card-foot {
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding-top: 6px;
|
||||||
|
margin-top: 6px;
|
||||||
|
border-top: 2rpx solid #eee;
|
||||||
|
|
||||||
|
.left{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.single {
|
||||||
|
::v-deep {
|
||||||
|
.tm-groupradio {
|
||||||
|
width: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 12rpx 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tm-checkbox {
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: block;
|
||||||
|
padding: 0 12rpx;
|
||||||
|
width: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tm-button-label {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.multiple {
|
||||||
|
::v-deep {
|
||||||
|
.tm-groupcheckbox {
|
||||||
|
width: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 12rpx 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tm-checkbox {
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: block;
|
||||||
|
padding: 0 12rpx;
|
||||||
|
width: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tm-button-label {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.pk {
|
||||||
|
box-sizing: border-box;
|
||||||
|
width: 100%;
|
||||||
|
padding: 0 12rpx;
|
||||||
|
|
||||||
|
::v-deep {
|
||||||
|
.tm-groupradio {
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tm-checkbox {
|
||||||
|
flex-grow: 1;
|
||||||
|
min-width: 30% !important;
|
||||||
|
max-width: 70% !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.radio-item {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.selected {
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.radio-left {}
|
||||||
|
|
||||||
|
.radio-right {}
|
||||||
|
|
||||||
|
.option-item {
|
||||||
|
width: 100%;
|
||||||
|
padding: 12rpx 24rpx;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.option-item-left {
|
||||||
|
background: linear-gradient(90deg, #3B82F6, #60A5FA);
|
||||||
|
color: white;
|
||||||
|
clip-path: polygon(0 0, calc(100% - 40rpx) 0, 100% 100%, 0 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.option-item-right {
|
||||||
|
background: linear-gradient(90deg, #F87171, #EF4444);
|
||||||
|
color: white;
|
||||||
|
clip-path: polygon(0 0, 100% 0, 100% 100%, 40rpx 100%);
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.option-foot {
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 6rpx;
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #666;
|
||||||
|
|
||||||
|
.left {
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding-right: 24rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.right {
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding-left: 24rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
+26
@@ -279,6 +279,32 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "votes/votes",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "投票列表",
|
||||||
|
"enablePullDownRefresh": true,
|
||||||
|
"app-plus": {
|
||||||
|
"pullToRefresh": {
|
||||||
|
"color": "#03a9f4",
|
||||||
|
"style": "circle"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "vote-detail/vote-detail",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "投票详情",
|
||||||
|
"enablePullDownRefresh": true,
|
||||||
|
"app-plus": {
|
||||||
|
"pullToRefresh": {
|
||||||
|
"color": "#03a9f4",
|
||||||
|
"style": "circle"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
+42
-3
@@ -1,18 +1,35 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="app-page"></view>
|
<view class="app-page flex flex-center">
|
||||||
|
<PluginUnavailable v-if="!uniHaloPluginAvailable" :pluginId="uniHaloPluginId"
|
||||||
|
:error-text="uniHaloPluginAvailableError" />
|
||||||
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import pluginAvailable from "@/common/mixins/pluginAvailable.js"
|
||||||
|
|
||||||
const homePagePath = '/pages/tabbar/home/home'
|
const homePagePath = '/pages/tabbar/home/home'
|
||||||
const startPagePath = '/pagesA/start/start'
|
const startPagePath = '/pagesA/start/start'
|
||||||
const articleDetailPath = '/pagesA/article-detail/article-detail';
|
const articleDetailPath = '/pagesA/article-detail/article-detail';
|
||||||
|
|
||||||
|
const _DEV_ = false
|
||||||
|
const _DEV_TO_TYPE_ = "page"
|
||||||
|
const _DEV_TO_PATH_ = "/pagesA/votes/votes"
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
mixins: [pluginAvailable],
|
||||||
computed: {
|
computed: {
|
||||||
configs() {
|
configs() {
|
||||||
return this.$tm.vx.getters().getConfigs;
|
return this.$tm.vx.getters().getConfigs;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onLoad: function (options) {
|
async onLoad(options) {
|
||||||
|
// 检查插件
|
||||||
|
this.setPluginId(this.NeedPluginIds.PluginUniHalo)
|
||||||
|
this.setPluginError("阿偶,检测到当前插件没有安装或者启用,无法启动 uni-halo 哦,请联系管理员")
|
||||||
|
if (!await this.checkPluginAvailable()) return
|
||||||
|
|
||||||
|
// 获取配置
|
||||||
uni.$tm.vx.actions('config/fetchConfigs').then(async (res) => {
|
uni.$tm.vx.actions('config/fetchConfigs').then(async (res) => {
|
||||||
if (options.scene) {
|
if (options.scene) {
|
||||||
if ('' !== options.scene) {
|
if ('' !== options.scene) {
|
||||||
@@ -35,7 +52,8 @@ export default {
|
|||||||
if (res.auditConfig.auditModeData.jsonUrl) {
|
if (res.auditConfig.auditModeData.jsonUrl) {
|
||||||
await uni.$tm.vx.actions('config/fetchMockJson')
|
await uni.$tm.vx.actions('config/fetchMockJson')
|
||||||
} else {
|
} else {
|
||||||
const mockJson = uni.$utils.checkJsonAndParse(res.auditConfig.auditModeData.jsonData)
|
const mockJson = uni.$utils.checkJsonAndParse(res.auditConfig.auditModeData
|
||||||
|
.jsonData)
|
||||||
if (mockJson.ok) {
|
if (mockJson.ok) {
|
||||||
uni.$tm.vx.commit('config/setMockJson', mockJson.jsonData)
|
uni.$tm.vx.commit('config/setMockJson', mockJson.jsonData)
|
||||||
}
|
}
|
||||||
@@ -52,6 +70,20 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
fnCheckShowStarted() {
|
fnCheckShowStarted() {
|
||||||
|
// 本地开发,快速跳转页面,发布请设置 _DEV_ = false
|
||||||
|
if (_DEV_) {
|
||||||
|
if (_DEV_TO_TYPE_ == 'tabbar') {
|
||||||
|
uni.switchTab({
|
||||||
|
url: _DEV_TO_PATH_
|
||||||
|
});
|
||||||
|
} else if (_DEV_TO_TYPE_ == 'page') {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: _DEV_TO_PATH_
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if (!this.configs.appConfig.startConfig.enabled) {
|
if (!this.configs.appConfig.startConfig.enabled) {
|
||||||
uni.switchTab({
|
uni.switchTab({
|
||||||
url: homePagePath
|
url: homePagePath
|
||||||
@@ -91,3 +123,10 @@ export default {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.app-page {
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -84,9 +84,18 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import {checkHasAdminLogin} from '@/utils/auth.js';
|
import {
|
||||||
|
checkHasAdminLogin
|
||||||
|
} from '@/utils/auth.js';
|
||||||
import CheckAppUpdate from '@/uni_modules/uni-upgrade-center-app/utils/check-update';
|
import CheckAppUpdate from '@/uni_modules/uni-upgrade-center-app/utils/check-update';
|
||||||
import {CheckWxUpdate} from '@/utils/update.js';
|
import {
|
||||||
|
CheckWxUpdate
|
||||||
|
} from '@/utils/update.js';
|
||||||
|
import {
|
||||||
|
NeedPluginIds,
|
||||||
|
NeedPlugins,
|
||||||
|
checkNeedPluginAvailable
|
||||||
|
} from "@/utils/plugin.js"
|
||||||
|
|
||||||
import tmGrouplist from '@/tm-vuetify/components/tm-grouplist/tm-grouplist.vue';
|
import tmGrouplist from '@/tm-vuetify/components/tm-grouplist/tm-grouplist.vue';
|
||||||
import tmListitem from '@/tm-vuetify/components/tm-listitem/tm-listitem.vue';
|
import tmListitem from '@/tm-vuetify/components/tm-listitem/tm-listitem.vue';
|
||||||
@@ -152,7 +161,8 @@ export default {
|
|||||||
},
|
},
|
||||||
copyrightConfig() {
|
copyrightConfig() {
|
||||||
return this.haloConfigs.basicConfig.copyrightConfig;
|
return this.haloConfigs.basicConfig.copyrightConfig;
|
||||||
}, calcAuditModeEnabled() {
|
},
|
||||||
|
calcAuditModeEnabled() {
|
||||||
return this.haloConfigs.auditConfig.auditModeEnabled
|
return this.haloConfigs.auditConfig.auditModeEnabled
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -173,14 +183,13 @@ export default {
|
|||||||
this.fnGetData();
|
this.fnGetData();
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
fnGetNavList() {
|
async fnGetNavList() {
|
||||||
const systemInfo = uni.getSystemInfoSync();
|
const systemInfo = uni.getSystemInfoSync();
|
||||||
let _isWx = false;
|
let _isWx = false;
|
||||||
// #ifdef MP-WEIXIN
|
// #ifdef MP-WEIXIN
|
||||||
_isWx = true;
|
_isWx = true;
|
||||||
// #endif
|
// #endif
|
||||||
this.navList = [
|
this.navList = [{
|
||||||
{
|
|
||||||
key: 'archives',
|
key: 'archives',
|
||||||
title: this.calcAuditModeEnabled ? '内容归档' : '文章归档',
|
title: this.calcAuditModeEnabled ? '内容归档' : '文章归档',
|
||||||
leftIcon: 'halocoloricon-classify',
|
leftIcon: 'halocoloricon-classify',
|
||||||
@@ -200,6 +209,16 @@ export default {
|
|||||||
isAdmin: false,
|
isAdmin: false,
|
||||||
type: 'page',
|
type: 'page',
|
||||||
show: this.haloConfigs.loveConfig.loveEnabled
|
show: this.haloConfigs.loveConfig.loveEnabled
|
||||||
|
}, {
|
||||||
|
key: 'vote',
|
||||||
|
title: '投票中心',
|
||||||
|
leftIcon: 'icon-box',
|
||||||
|
leftIconColor: 'red',
|
||||||
|
rightText: '查看当前的投票',
|
||||||
|
path: '/pagesA/votes/votes',
|
||||||
|
isAdmin: false,
|
||||||
|
type: 'page',
|
||||||
|
show: true
|
||||||
}, {
|
}, {
|
||||||
key: 'disclaimers',
|
key: 'disclaimers',
|
||||||
title: '友情链接',
|
title: '友情链接',
|
||||||
@@ -340,8 +359,7 @@ export default {
|
|||||||
url: '/pagesB/login/login'
|
url: '/pagesB/login/login'
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(err => {});
|
||||||
});
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -362,8 +380,7 @@ export default {
|
|||||||
this.navList.find(x => x.key == 'cache').rightText =
|
this.navList.find(x => x.key == 'cache').rightText =
|
||||||
uni.getStorageInfoSync().currentSize + 'KB';
|
uni.getStorageInfoSync().currentSize + 'KB';
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(err => {});
|
||||||
});
|
|
||||||
break;
|
break;
|
||||||
case 'update':
|
case 'update':
|
||||||
// #ifdef APP-PLUS
|
// #ifdef APP-PLUS
|
||||||
|
|||||||
+141
-19
@@ -23,18 +23,33 @@
|
|||||||
<block v-else>
|
<block v-else>
|
||||||
<view v-if="bannerConfig.enabled" class="bg-white pb-24">
|
<view v-if="bannerConfig.enabled" class="bg-white pb-24">
|
||||||
<view class="banner bg-white ml-24 mr-24 mt-12 round-3" v-if="bannerList.length !== 0">
|
<view class="banner bg-white ml-24 mr-24 mt-12 round-3" v-if="bannerList.length !== 0">
|
||||||
<e-swiper
|
<e-swiper :height="bannerConfig.height" :dotPosition="bannerConfig.dotPosition" :autoplay="true"
|
||||||
:height="bannerConfig.height"
|
:useDot="bannerConfig.showIndicator" :showTitle="bannerConfig.showTitle"
|
||||||
:dotPosition="bannerConfig.dotPosition"
|
:type="bannerConfig.type" :list="bannerList" @on-click="fnOnBannerClick" />
|
||||||
:autoplay="true"
|
|
||||||
:useDot="bannerConfig.showIndicator"
|
|
||||||
:showTitle="bannerConfig.showTitle"
|
|
||||||
:type="bannerConfig.type"
|
|
||||||
:list="bannerList"
|
|
||||||
@on-click="fnOnBannerClick"
|
|
||||||
/>
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
|
<!-- 金刚区 :v-if="navList.filter(x=>x.show).length>=4" -->
|
||||||
|
<view :v-if="navList.filter(x=>x.show).length>=4" class="nav-box">
|
||||||
|
<view class="nav-list flex">
|
||||||
|
<template v-for="(item,index) in navList" >
|
||||||
|
<view v-if="item.show" class="nav-item" :key="index" @click="fnClickNav(item)">
|
||||||
|
<!-- :class="[item.bgClass]" -->
|
||||||
|
<view class="nav-item-icon" :class="[item.bgClass]" :style="{
|
||||||
|
'--bgColor':item.bgColor,
|
||||||
|
// boxShadow: '0rpx 0rpx 6rpx ' + item.shadow,
|
||||||
|
// backgroundColor: item.bgColor
|
||||||
|
}">
|
||||||
|
<tm-icons :size="48" color="white" prefx="halocoloricon" :name="item.icon"></tm-icons>
|
||||||
|
</view>
|
||||||
|
<view class="nav-item-text">
|
||||||
|
{{item.title}}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
<!-- 精品分类 -->
|
<!-- 精品分类 -->
|
||||||
<block v-if="calcIsShowCategory">
|
<block v-if="calcIsShowCategory">
|
||||||
<view class="flex flex-between mt-16 mb-24 pl-24 pr-24">
|
<view class="flex flex-between mt-16 mb-24 pl-24 pr-24">
|
||||||
@@ -84,8 +99,8 @@
|
|||||||
</tm-translate>
|
</tm-translate>
|
||||||
</view>
|
</view>
|
||||||
<view class="load-text mt-12">{{ loadMoreText }}</view>
|
<view class="load-text mt-12">{{ loadMoreText }}</view>
|
||||||
<tm-flotbutton v-if="articleList.length > 10" :width="90" color="light-blue" @click="fnToTopPage" size="s"
|
<tm-flotbutton v-if="articleList.length > 10" :width="90" color="light-blue" @click="fnToTopPage"
|
||||||
icon="icon-angle-up"></tm-flotbutton>
|
size="s" icon="icon-angle-up"></tm-flotbutton>
|
||||||
</block>
|
</block>
|
||||||
</block>
|
</block>
|
||||||
|
|
||||||
@@ -103,6 +118,7 @@ import tmTranslate from '@/tm-vuetify/components/tm-translate/tm-translate.vue';
|
|||||||
import tmFlotbutton from '@/tm-vuetify/components/tm-flotbutton/tm-flotbutton.vue';
|
import tmFlotbutton from '@/tm-vuetify/components/tm-flotbutton/tm-flotbutton.vue';
|
||||||
import tmIcons from '@/tm-vuetify/components/tm-icons/tm-icons.vue';
|
import tmIcons from '@/tm-vuetify/components/tm-icons/tm-icons.vue';
|
||||||
import tmEmpty from '@/tm-vuetify/components/tm-empty/tm-empty.vue';
|
import tmEmpty from '@/tm-vuetify/components/tm-empty/tm-empty.vue';
|
||||||
|
import tmGrid from '@/tm-vuetify/components/tm-grid/tm-grid.vue';
|
||||||
|
|
||||||
import eSwiper from '@/components/e-swiper/e-swiper.vue';
|
import eSwiper from '@/components/e-swiper/e-swiper.vue';
|
||||||
import NotifyDialog from "@/components/notify-dialog/notify-dialog.vue";
|
import NotifyDialog from "@/components/notify-dialog/notify-dialog.vue";
|
||||||
@@ -116,6 +132,7 @@ export default {
|
|||||||
tmFlotbutton,
|
tmFlotbutton,
|
||||||
tmIcons,
|
tmIcons,
|
||||||
tmEmpty,
|
tmEmpty,
|
||||||
|
tmGrid,
|
||||||
eSwiper,
|
eSwiper,
|
||||||
NotifyDialog
|
NotifyDialog
|
||||||
},
|
},
|
||||||
@@ -138,7 +155,8 @@ export default {
|
|||||||
notify: {
|
notify: {
|
||||||
show: false,
|
show: false,
|
||||||
data: {}
|
data: {}
|
||||||
}
|
},
|
||||||
|
navList: []
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@@ -174,6 +192,16 @@ export default {
|
|||||||
return this.haloConfigs.pageConfig.homeConfig.bannerConfig
|
return this.haloConfigs.pageConfig.homeConfig.bannerConfig
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
watch: {
|
||||||
|
haloConfigs: {
|
||||||
|
handler(val) {
|
||||||
|
if (!val) return;
|
||||||
|
this.fnGetNavList();
|
||||||
|
},
|
||||||
|
deep: true,
|
||||||
|
immediate: true,
|
||||||
|
}
|
||||||
|
},
|
||||||
onLoad() {
|
onLoad() {
|
||||||
this.fnSetPageTitle();
|
this.fnSetPageTitle();
|
||||||
},
|
},
|
||||||
@@ -328,8 +356,7 @@ export default {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
fail: (err) => {
|
fail: (err) => {}
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
},
|
},
|
||||||
@@ -496,6 +523,70 @@ export default {
|
|||||||
uni.switchTab({
|
uni.switchTab({
|
||||||
url: '/pages/tabbar/about/about'
|
url: '/pages/tabbar/about/about'
|
||||||
})
|
})
|
||||||
|
},
|
||||||
|
fnClickNav(data) {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: data.path
|
||||||
|
});
|
||||||
|
},
|
||||||
|
fnGetNavList() {
|
||||||
|
this.navList = [{
|
||||||
|
key: 'archives',
|
||||||
|
title: this.calcAuditModeEnabled ? '内容归档' : '文章归档',
|
||||||
|
bgColor: "rgba(3, 169, 244, 0.95)",
|
||||||
|
shadow: "rgba(3, 169, 244, 0.4)",
|
||||||
|
bgClass: 'bg-gradient-blue-accent',
|
||||||
|
icon: 'icon-news',
|
||||||
|
iconColor: '',
|
||||||
|
path: '/pagesA/archives/archives',
|
||||||
|
type: 'page',
|
||||||
|
show: true
|
||||||
|
}, {
|
||||||
|
key: 'vote',
|
||||||
|
title: '投票中心',
|
||||||
|
bgColor: "rgba(0, 188, 212,0.95)",
|
||||||
|
shadow: "rgba(0, 188, 212, 0.4)",
|
||||||
|
bgClass: 'bg-gradient-blue-accent',
|
||||||
|
icon: 'icon-box',
|
||||||
|
iconColor: '',
|
||||||
|
path: '/pagesA/votes/votes',
|
||||||
|
type: 'page',
|
||||||
|
show: this.haloConfigs.loveConfig.loveEnabled
|
||||||
|
}, {
|
||||||
|
key: 'disclaimers',
|
||||||
|
title: '友情链接',
|
||||||
|
bgColor: "rgba(0, 150, 136, 0.95)",
|
||||||
|
shadow: "rgba(0, 150, 136, 0.4)",
|
||||||
|
bgClass: 'bg-gradient-blue-accent',
|
||||||
|
icon: 'icon-lianjie',
|
||||||
|
iconColor: '',
|
||||||
|
path: '/pagesA/friend-links/friend-links',
|
||||||
|
type: 'page',
|
||||||
|
show: true
|
||||||
|
}, {
|
||||||
|
key: 'love',
|
||||||
|
title: '恋爱日记',
|
||||||
|
bgColor: "rgba(255,76,103, 0.95)",
|
||||||
|
shadow: "rgba(255,76,103, 0.4)",
|
||||||
|
bgClass: 'bg-gradient-blue-accent',
|
||||||
|
icon: 'icon-like',
|
||||||
|
iconColor: '',
|
||||||
|
path: '/pagesA/love/love',
|
||||||
|
type: 'page',
|
||||||
|
show: this.haloConfigs.loveConfig.loveEnabled
|
||||||
|
}, {
|
||||||
|
key: 'contact-blogger',
|
||||||
|
title: '联系博主',
|
||||||
|
bgColor: "rgba(255, 152, 0, 0.95)",
|
||||||
|
shadow: "rgba(255, 152, 0, 0.4)",
|
||||||
|
bgClass: 'bg-gradient-blue-accent',
|
||||||
|
icon: 'icon-paper-plane',
|
||||||
|
iconColor: '',
|
||||||
|
rightText: '博主主常用常用联系方式',
|
||||||
|
path: '/pagesA/contact/contact',
|
||||||
|
type: 'page',
|
||||||
|
show: this.haloConfigs.authorConfig.social.enabled
|
||||||
|
}]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -533,11 +624,9 @@ export default {
|
|||||||
margin-right: 24rpx;
|
margin-right: 24rpx;
|
||||||
|
|
||||||
/* #endif */
|
/* #endif */
|
||||||
&_icon {
|
&_icon {}
|
||||||
}
|
|
||||||
|
|
||||||
&_text {
|
&_text {}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.show-more {
|
.show-more {
|
||||||
@@ -614,4 +703,37 @@ export default {
|
|||||||
width: 50%;
|
width: 50%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.nav-box {
|
||||||
|
padding: 24rpx 8rpx;
|
||||||
|
background-color: #ffff;
|
||||||
|
overflow: hidden;
|
||||||
|
margin-bottom: 24rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-list {
|
||||||
|
align-items: center;
|
||||||
|
// justify-content: space-between;
|
||||||
|
justify-content: space-around;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-item {
|
||||||
|
font-size: 26rpx;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 12rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-item-icon {
|
||||||
|
padding: 24rpx;
|
||||||
|
// border-radius: 24rpx 32rpx 24rpx 32rpx;
|
||||||
|
border-radius: 24rpx;
|
||||||
|
// border: 2rpx solid #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-item-text {
|
||||||
|
font-size: 24rpx;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -1,5 +1,9 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="app-page">
|
<view class="app-page">
|
||||||
|
<PluginUnavailable v-if="!uniHaloPluginAvailable" :pluginId="uniHaloPluginId"
|
||||||
|
:error-text="uniHaloPluginAvailableError" />
|
||||||
|
<template v-else>
|
||||||
|
|
||||||
<!-- 顶部切换 -->
|
<!-- 顶部切换 -->
|
||||||
<view class="e-fixed shadow-1">
|
<view class="e-fixed shadow-1">
|
||||||
<tm-search v-model="queryParams.keyword" :round="24" :shadow="0" color="light-blue"
|
<tm-search v-model="queryParams.keyword" :round="24" :shadow="0" color="light-blue"
|
||||||
@@ -23,7 +27,8 @@
|
|||||||
<view v-else class="content">
|
<view v-else class="content">
|
||||||
<view v-if="dataList.length == 0" class="content-empty flex flex-center">
|
<view v-if="dataList.length == 0" class="content-empty flex flex-center">
|
||||||
<!-- 空布局 -->
|
<!-- 空布局 -->
|
||||||
<tm-empty v-if="!queryParams.keyword" icon="icon-shiliangzhinengduixiang-" label="请输入关键词搜索"></tm-empty>
|
<tm-empty v-if="!queryParams.keyword" icon="icon-shiliangzhinengduixiang-"
|
||||||
|
label="请输入关键词搜索"></tm-empty>
|
||||||
<tm-empty v-else icon="icon-shiliangzhinengduixiang-"
|
<tm-empty v-else icon="icon-shiliangzhinengduixiang-"
|
||||||
:label="`未搜到 ${queryParams.keyword} 相关内容`"></tm-empty>
|
:label="`未搜到 ${queryParams.keyword} 相关内容`"></tm-empty>
|
||||||
</view>
|
</view>
|
||||||
@@ -42,7 +47,8 @@
|
|||||||
<mp-html class="evan-markdown" lazy-load :domain="markdownConfig.domain"
|
<mp-html class="evan-markdown" lazy-load :domain="markdownConfig.domain"
|
||||||
:loading-img="markdownConfig.loadingGif" :scroll-table="true" :selectable="true"
|
:loading-img="markdownConfig.loadingGif" :scroll-table="true" :selectable="true"
|
||||||
:tag-style="markdownConfig.tagStyle" :content="item.description || item.content"
|
:tag-style="markdownConfig.tagStyle" :content="item.description || item.content"
|
||||||
:markdown="true" :showLineNumber="true" :showLanguageName="true" :copyByLongPress="true" />
|
:markdown="true" :showLineNumber="true" :showLanguageName="true"
|
||||||
|
:copyByLongPress="true" />
|
||||||
<view class="mt-12 flex flex-center flex-between">
|
<view class="mt-12 flex flex-center flex-between">
|
||||||
<text style="font-size: 24rpx;color:#888">
|
<text style="font-size: 24rpx;color:#888">
|
||||||
最近更新时间:{{ {d: item.updateTimestamp, f: 'yyyy年MM月dd日 HH点mm分ss秒'} | formatTime }}
|
最近更新时间:{{ {d: item.updateTimestamp, f: 'yyyy年MM月dd日 HH点mm分ss秒'} | formatTime }}
|
||||||
@@ -53,10 +59,12 @@
|
|||||||
</view>
|
</view>
|
||||||
</tm-translate>
|
</tm-translate>
|
||||||
|
|
||||||
<tm-flotbutton @click="fnToTopPage" size="m" color="light-blue" icon="icon-angle-up"></tm-flotbutton>
|
<tm-flotbutton @click="fnToTopPage" size="m" color="light-blue"
|
||||||
|
icon="icon-angle-up"></tm-flotbutton>
|
||||||
|
|
||||||
</block>
|
</block>
|
||||||
</view>
|
</view>
|
||||||
|
</template>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -71,7 +79,10 @@
|
|||||||
|
|
||||||
import MarkdownConfig from '@/common/markdown/markdown.config.js';
|
import MarkdownConfig from '@/common/markdown/markdown.config.js';
|
||||||
import mpHtml from '@/components/mp-html/components/mp-html/mp-html.vue';
|
import mpHtml from '@/components/mp-html/components/mp-html/mp-html.vue';
|
||||||
|
|
||||||
|
import pluginAvailable from "@/common/mixins/pluginAvailable.js"
|
||||||
export default {
|
export default {
|
||||||
|
mixins: [pluginAvailable],
|
||||||
components: {
|
components: {
|
||||||
tmSkeleton,
|
tmSkeleton,
|
||||||
tmSearch,
|
tmSearch,
|
||||||
@@ -92,7 +103,7 @@
|
|||||||
},
|
},
|
||||||
queryParams: {
|
queryParams: {
|
||||||
keyword: "",
|
keyword: "",
|
||||||
limit: 5,
|
limit: 50,
|
||||||
highlightPreTag: "",
|
highlightPreTag: "",
|
||||||
highlightPostTag: ""
|
highlightPostTag: ""
|
||||||
},
|
},
|
||||||
@@ -111,17 +122,21 @@
|
|||||||
return this.haloConfigs.auditConfig.auditModeEnabled
|
return this.haloConfigs.auditConfig.auditModeEnabled
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
onLoad() {
|
async onLoad() {
|
||||||
this.fnSetPageTitle('内容搜索');
|
this.fnSetPageTitle('内容搜索');
|
||||||
},
|
// 检查插件
|
||||||
created() {
|
this.setPluginId(this.NeedPluginIds.PluginSearchWidget)
|
||||||
|
this.setPluginError("阿偶,检测到当前插件没有安装或者启用,无法使用瞬间功能哦,请联系管理员")
|
||||||
|
if (!await this.checkPluginAvailable()) return
|
||||||
if (!this.queryParams.keyword) {
|
if (!this.queryParams.keyword) {
|
||||||
this.loading = 'success'
|
this.loading = 'success'
|
||||||
} else {
|
} else {
|
||||||
this.fnGetData();
|
this.fnGetData();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
onPullDownRefresh() {
|
onPullDownRefresh() {
|
||||||
|
if (!this.uniHaloPluginAvailable) return;
|
||||||
this.fnResetSetAniWaitIndex();
|
this.fnResetSetAniWaitIndex();
|
||||||
this.fnGetData();
|
this.fnGetData();
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1,680 @@
|
|||||||
|
<template>
|
||||||
|
<view class="app-page">
|
||||||
|
<view v-if="loading != 'success'" class="loading-wrap">
|
||||||
|
<tm-skeleton model="listAvatr"></tm-skeleton>
|
||||||
|
<tm-skeleton model="listAvatr"></tm-skeleton>
|
||||||
|
<tm-skeleton model="listAvatr"></tm-skeleton>
|
||||||
|
<tm-skeleton model="listAvatr"></tm-skeleton>
|
||||||
|
</view>
|
||||||
|
<block v-else>
|
||||||
|
<view v-if="!detail" class="empty">
|
||||||
|
<tm-empty icon="icon-shiliangzhinengduixiang-" label="未查询到数据"></tm-empty>
|
||||||
|
</view>
|
||||||
|
<block v-else>
|
||||||
|
<view class="vote-card">
|
||||||
|
<view class="sub-title"> 投票信息 </view>
|
||||||
|
<view class="vote-card-body flex flex-col"
|
||||||
|
style="margin-top:12rpx;font-size:28rpx;gap:12rpx 0;background:#F3F4F6;color:#2B2F33;padding:24rpx;border-radius:12rpx;">
|
||||||
|
|
||||||
|
<view class="">
|
||||||
|
投票类型:<tm-tags v-if="vote.spec.type==='single'" color="light-blue" :shadow="0" size="xs"
|
||||||
|
model="fill">单选</tm-tags>
|
||||||
|
<tm-tags v-else-if="vote.spec.type==='multiple'" color="light-blue" :shadow="0" size="xs"
|
||||||
|
model="fill">多选</tm-tags>
|
||||||
|
<tm-tags v-else-if="vote.spec.type==='pk'" color="light-blue" :shadow="0" size="xs"
|
||||||
|
model="fill">双选PK</tm-tags>
|
||||||
|
</view>
|
||||||
|
<view class="">
|
||||||
|
投票状态:<tm-tags v-if="vote.spec.hasEnded" color="red" size="xs" :shadow="0"
|
||||||
|
model="fill">已结束</tm-tags>
|
||||||
|
<tm-tags v-else color="green" size="xs" :shadow="0" model="fill">进行中</tm-tags>
|
||||||
|
</view>
|
||||||
|
<view class="">
|
||||||
|
投票方式:<tm-tags v-if="vote.spec.canAnonymously" color="light-blue" size="xs" :shadow="0"
|
||||||
|
model="fill">匿名</tm-tags>
|
||||||
|
<tm-tags v-else color="red" size="xs" :shadow="0" model="fill">不匿名</tm-tags>
|
||||||
|
</view>
|
||||||
|
<view v-if="vote.spec.remark" class="">
|
||||||
|
投票说明:{{ vote.spec.remark||"暂无说明" }}
|
||||||
|
</view>
|
||||||
|
<view class="">
|
||||||
|
截止时间:{{ {d: vote.spec.endDate, f: 'yyyy-MM-dd HH:mm'} | formatTime }}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="vote-card">
|
||||||
|
<view class="vote-card-head flex flex-col items-start mb-12">
|
||||||
|
<view class="sub-title"> 投票内容 </view>
|
||||||
|
<view class="sub-content">
|
||||||
|
{{ vote.spec.title }}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="vote-card-body">
|
||||||
|
<view class="sub-title"> 投票选项 <text v-if="vote.spec.type==='multiple'"
|
||||||
|
class="sub-title-count">(最多选择 {{ vote.spec.maxVotes }} 项)</text> </view>
|
||||||
|
<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 gap-8">
|
||||||
|
<tm-button v-for="(option,optionIndex) in vote.spec.options" :key="optionIndex"
|
||||||
|
:shadow="0" :theme="option.checked?'light-blue':'grey-lighten-3'" :plan="false"
|
||||||
|
size="m" :height="72" :block="true" class="flex-1 w-full"
|
||||||
|
@click="handleSelectSingleOption(option)">
|
||||||
|
<view class="flex flex-between w-full">
|
||||||
|
<text class="text-align-left text-overflow">
|
||||||
|
{{option.title }}
|
||||||
|
</text>
|
||||||
|
<text v-if="vote.spec.isVoted" class="flex-shrink ml-12">
|
||||||
|
{{option.percent }}%
|
||||||
|
</text>
|
||||||
|
</view>
|
||||||
|
</tm-button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<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 gap-8">
|
||||||
|
<tm-button v-for="(option,optionIndex) in vote.spec.options" :key="optionIndex"
|
||||||
|
:shadow="0" :theme="option.checked?'light-blue':'grey-lighten-3'" :plan="false"
|
||||||
|
size="m" :height="72" :block="true" class="flex-1 full"
|
||||||
|
@click="handleSelectCheckboxOption(option)">
|
||||||
|
<view class="flex flex-between w-full">
|
||||||
|
<text class="text-align-left text-overflow">
|
||||||
|
{{option.title }}
|
||||||
|
</text>
|
||||||
|
<text v-if="vote.spec.isVoted" class="flex-shrink ml-12">
|
||||||
|
{{option.percent }}%
|
||||||
|
</text>
|
||||||
|
</view>
|
||||||
|
</tm-button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view v-else-if="vote.spec.type==='pk'" class="pk">
|
||||||
|
<view class="pk-container">
|
||||||
|
<view class="radio-item" v-for="(option,optionIndex) in vote.spec.options"
|
||||||
|
:key="optionIndex" :class="[optionIndex==0?'radio-left':'radio-right']"
|
||||||
|
:style="{width:option.percent + '%'}">
|
||||||
|
<view class="option-item"
|
||||||
|
:class="[optionIndex==0?'option-item-left':'option-item-right']">
|
||||||
|
{{option.percent }}%
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<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 gap-8">
|
||||||
|
<tm-button v-for="(option,optionIndex) in vote.spec.options" :key="optionIndex"
|
||||||
|
:shadow="0" :theme="option.checked?'light-blue':'grey-lighten-3'" :plan="false"
|
||||||
|
size="m" :height="72" :block="true" class="flex-1"
|
||||||
|
@click="handleSelectSingleOption(option)">
|
||||||
|
<view class="flex flex-between w-full">
|
||||||
|
<text class="text-align-left text-overflow">
|
||||||
|
选项{{ optionIndex+1}}:{{option.title }}
|
||||||
|
</text>
|
||||||
|
</view>
|
||||||
|
</tm-button>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="vote-card">
|
||||||
|
<view class="vote-card-body">
|
||||||
|
<view class="sub-title"> 投票统计 </view>
|
||||||
|
<view class="">
|
||||||
|
<tm-tags color="grey-darken-4" size="s" model="text">{{ vote.stats.voteCount }}
|
||||||
|
人已参与</tm-tags>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="vote-submit flex w-full flex-center" :style="{
|
||||||
|
paddingBottom:safeAreaBottom + 'rpx'
|
||||||
|
}">
|
||||||
|
<tm-button v-if="!vote.spec.canAnonymously" theme="red" :shadow="0" class="w-full" text
|
||||||
|
:block="true" @click="handleSubmit()">不允许匿名投票</tm-button>
|
||||||
|
<tm-button v-else-if="fnCalcIsVoted()" theme="white" text :block="true"
|
||||||
|
class="w-full">您已参与投票</tm-button>
|
||||||
|
<tm-button v-else theme="light-blue" class="w-full" :block="true"
|
||||||
|
@click="handleSubmit()">提交投票</tm-button>
|
||||||
|
|
||||||
|
</view>
|
||||||
|
</block>
|
||||||
|
</block>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import tmSkeleton from '@/tm-vuetify/components/tm-skeleton/tm-skeleton.vue';
|
||||||
|
import tmEmpty from '@/tm-vuetify/components/tm-empty/tm-empty.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 {
|
||||||
|
voteCacheUtil
|
||||||
|
} from '@/utils/vote.js'
|
||||||
|
|
||||||
|
const types = {
|
||||||
|
"pk": "双选PK",
|
||||||
|
"multiple": "多选",
|
||||||
|
"single": "单选"
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
tmSkeleton,
|
||||||
|
tmEmpty,
|
||||||
|
tmButton,
|
||||||
|
tmGroupradio,
|
||||||
|
tmRadio,
|
||||||
|
tmGroupcheckbox,
|
||||||
|
tmCheckbox,
|
||||||
|
tmTags,
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
safeAreaBottom: 24,
|
||||||
|
loading: 'loading',
|
||||||
|
pageTitle: '加载中...',
|
||||||
|
|
||||||
|
name: '',
|
||||||
|
detail: null,
|
||||||
|
vote: null,
|
||||||
|
submitForm: {
|
||||||
|
voteData: []
|
||||||
|
},
|
||||||
|
votedSelected: {
|
||||||
|
checkbox: [],
|
||||||
|
radio: [],
|
||||||
|
pk: []
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
onLoad(e) {
|
||||||
|
this.name = e.name;
|
||||||
|
this.fnGetData();
|
||||||
|
|
||||||
|
// #ifndef H5
|
||||||
|
const systemInfo = uni.getSystemInfoSync();
|
||||||
|
this.safeAreaBottom = systemInfo.safeAreaInsets.bottom + 12;
|
||||||
|
// #endif
|
||||||
|
},
|
||||||
|
onPullDownRefresh() {
|
||||||
|
this.fnGetData();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
fnGetData() {
|
||||||
|
// 设置状态为加载中
|
||||||
|
this.loading = 'loading';
|
||||||
|
this.pageTitle = "加载中..."
|
||||||
|
this.$httpApi.v2
|
||||||
|
.getVoteDetail(this.name)
|
||||||
|
.then(res => {
|
||||||
|
this.pageTitle = "投票详情" + `(${types[res.vote.spec.type]})`
|
||||||
|
|
||||||
|
const tempVoteRes = res;
|
||||||
|
|
||||||
|
tempVoteRes.vote.spec.isVoted = this.fnCalcIsVoted()
|
||||||
|
tempVoteRes.vote.spec.disabled = this.fnCalcIsVoted()
|
||||||
|
|
||||||
|
tempVoteRes.vote.spec.options.map((option, index) => {
|
||||||
|
option.value = option.id
|
||||||
|
option.label = option.title
|
||||||
|
option.isVoted = this.fnCalcIsVoted()
|
||||||
|
option.checked = this.fnCalcIsChecked(option)
|
||||||
|
|
||||||
|
if (tempVoteRes.vote.spec.type === 'single') {
|
||||||
|
option.percent = this.fnCalcPercent(option, tempVoteRes.vote.stats);
|
||||||
|
} else if (tempVoteRes.vote.spec.type === 'multiple') {
|
||||||
|
option.percent = this.fnCalcPercent(option, tempVoteRes.vote.stats);
|
||||||
|
} else if (tempVoteRes.vote.spec.type === 'pk') {
|
||||||
|
option.percent = this.fnCalcPercent(option, tempVoteRes.vote.stats);
|
||||||
|
}
|
||||||
|
|
||||||
|
option.dataStr = JSON.stringify(option)
|
||||||
|
|
||||||
|
return option
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
this.vote = tempVoteRes.vote
|
||||||
|
console.log("this.vote", this.vote)
|
||||||
|
this.detail = tempVoteRes;
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
this.loading = 'success';
|
||||||
|
}, 200);
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.error(err);
|
||||||
|
this.loading = 'error';
|
||||||
|
this.pageTitle = "加载失败,请重试..."
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
setTimeout(() => {
|
||||||
|
uni.hideLoading();
|
||||||
|
uni.stopPullDownRefresh();
|
||||||
|
this.fnSetPageTitle(this.pageTitle);
|
||||||
|
}, 200);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
fnCalcPercent(voteOption, stats) {
|
||||||
|
if (!this.fnCalcIsVoted()) return 0;
|
||||||
|
if (!stats?.voteDataList) return 0;
|
||||||
|
const option = stats.voteDataList.find(x => x.id == voteOption.id)
|
||||||
|
if (!option) return 0;
|
||||||
|
const percent = (option.voteCount / stats.voteCount) * 100
|
||||||
|
return Math.round(percent)
|
||||||
|
},
|
||||||
|
|
||||||
|
fnCalcIsVoted() {
|
||||||
|
return voteCacheUtil.has(this.name)
|
||||||
|
},
|
||||||
|
|
||||||
|
fnCalcIsChecked(option) {
|
||||||
|
const data = voteCacheUtil.get(this.name)
|
||||||
|
if (!data) return false;
|
||||||
|
const checked = data.selected.includes(option.id)
|
||||||
|
return checked
|
||||||
|
},
|
||||||
|
|
||||||
|
onOptionRadioChange(e) {
|
||||||
|
this.submitForm.voteData = e.map(item => this.vote.spec.options[item.index]?.id);
|
||||||
|
},
|
||||||
|
onOptionCheckboxChange(e) {
|
||||||
|
this.submitForm.voteData = e.map(item => this.vote.spec.options[item.index]?.id);
|
||||||
|
},
|
||||||
|
onOptionPkChange(e) {
|
||||||
|
this.submitForm.voteData = e.map(item => this.vote.spec.options[item.index]?.id);
|
||||||
|
},
|
||||||
|
formatJsonStr(jsonStr) {
|
||||||
|
return jsonStr ? JSON.parse(jsonStr) : {}
|
||||||
|
},
|
||||||
|
handleSubmit() {
|
||||||
|
if (!this.vote.spec.canAnonymously) {
|
||||||
|
uni.showModal({
|
||||||
|
icon: "none",
|
||||||
|
title: "提示",
|
||||||
|
content: "该投票不允许匿名,请到博主的 网站端 进行投票!",
|
||||||
|
cancelColor: "#666666",
|
||||||
|
cancelText: "关闭",
|
||||||
|
confirmText: "复制地址",
|
||||||
|
success: (res) => {
|
||||||
|
if (res.confirm) {
|
||||||
|
this.$utils.copyText(this.$baseApiUrl, "复制成功")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
uni.showLoading({
|
||||||
|
title: "正在保存..."
|
||||||
|
})
|
||||||
|
|
||||||
|
// 使用简单版
|
||||||
|
this.submitForm.voteData = this.vote.spec.options.filter(x => x.checked).map(item => item.id)
|
||||||
|
|
||||||
|
this.$httpApi.v2
|
||||||
|
.submitVote(this.name, this.submitForm, this.vote.spec.canAnonymously)
|
||||||
|
.then(res => {
|
||||||
|
uni.showToast({
|
||||||
|
icon: "none",
|
||||||
|
title: "提交成功"
|
||||||
|
})
|
||||||
|
|
||||||
|
voteCacheUtil.set(this.name, {
|
||||||
|
selected: [...this.submitForm.voteData],
|
||||||
|
data: this.vote
|
||||||
|
})
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
uni.startPullDownRefresh()
|
||||||
|
}, 1500);
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.error(err);
|
||||||
|
uni.showToast({
|
||||||
|
icon: "none",
|
||||||
|
title: "提交失败,请重试"
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
handleSelectSingleOption(option) {
|
||||||
|
if (this.vote.spec.disabled) return
|
||||||
|
this.vote.spec.options.map(item => {
|
||||||
|
if (option.id == item.id) {
|
||||||
|
item.checked = true
|
||||||
|
} else {
|
||||||
|
item.checked = false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
handleSelectCheckboxOption(option) {
|
||||||
|
if (this.vote.spec.disabled) return
|
||||||
|
this.vote.spec.options.map(item => {
|
||||||
|
if (option.id == item.id) {
|
||||||
|
item.checked = !item.checked
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.app-page {
|
||||||
|
box-sizing: border-box;
|
||||||
|
width: 100vw;
|
||||||
|
min-height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 24rpx 0;
|
||||||
|
padding-bottom: 160rpx;
|
||||||
|
background-color: #fafafd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading-wrap {
|
||||||
|
padding: 0 24rpx;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty {
|
||||||
|
height: 60vh;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.w-full {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wp-50 {
|
||||||
|
width: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vote-card {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
box-sizing: border-box;
|
||||||
|
margin: 0 24rpx;
|
||||||
|
padding: 24rpx;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
background-color: #ffff;
|
||||||
|
box-shadow: 0rpx 2rpx 24rpx rgba(0, 0, 0, 0.03);
|
||||||
|
overflow: hidden;
|
||||||
|
margin-bottom: 24rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vote-card-head {
|
||||||
|
margin-bottom: 12rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-satrt;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
.left {
|
||||||
|
.title {
|
||||||
|
font-size: 28rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.vote-card-body {
|
||||||
|
|
||||||
|
.remark {
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 12rpx 6rpx;
|
||||||
|
padding-top: 0;
|
||||||
|
color: rgba(0, 0, 0, 0.75);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.vote-card-foot {
|
||||||
|
box-sizing: border-box;
|
||||||
|
margin-top: 12px;
|
||||||
|
padding-top: 6px;
|
||||||
|
border-top: 2rpx solid #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.single {
|
||||||
|
::v-deep {
|
||||||
|
.tm-groupradio {
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 16rpx 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tm-checkbox {
|
||||||
|
box-sizing: border-box;
|
||||||
|
// display: block;
|
||||||
|
// width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tm-button-label {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.multiple {
|
||||||
|
::v-deep {
|
||||||
|
.tm-groupcheckbox {
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 16rpx 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tm-checkbox {
|
||||||
|
box-sizing: border-box;
|
||||||
|
// display: block;
|
||||||
|
// width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tm-button-label {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.pk {
|
||||||
|
box-sizing: border-box;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
::v-deep {
|
||||||
|
.pk-container {
|
||||||
|
box-sizing: border-box;
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.radio-item {
|
||||||
|
flex-grow: 1;
|
||||||
|
min-width: 30% !important;
|
||||||
|
max-width: 70% !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.radio-left {}
|
||||||
|
|
||||||
|
.radio-right {}
|
||||||
|
|
||||||
|
.option-item {
|
||||||
|
box-sizing: border-box;
|
||||||
|
width: 100%;
|
||||||
|
padding: 24rpx;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.option-item-left {
|
||||||
|
background: linear-gradient(90deg, #3B82F6, #60A5FA);
|
||||||
|
color: white;
|
||||||
|
clip-path: polygon(0 0, calc(100% - 40rpx) 0, 100% 100%, 0 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.option-item-right {
|
||||||
|
background: linear-gradient(90deg, #F87171, #EF4444);
|
||||||
|
color: white;
|
||||||
|
clip-path: polygon(0 0, 100% 0, 100% 100%, 40rpx 100%);
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.option-foot {
|
||||||
|
margin-top: 24rpx;
|
||||||
|
width: 100%;
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #666;
|
||||||
|
|
||||||
|
.tm-groupradio {
|
||||||
|
display: flex;
|
||||||
|
gap: 12rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tm-checkbox {
|
||||||
|
// width: 100%;
|
||||||
|
max-width: initial !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tm-button {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.left {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.right {
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
.flex-start.fulled {
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.sub-content {
|
||||||
|
font-weight: bold;
|
||||||
|
color: #2B2F33;
|
||||||
|
padding: 12rpx 0;
|
||||||
|
font-size: 32rpx;
|
||||||
|
margin-bottom: 12rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.sub-title {
|
||||||
|
box-sizing: border-box;
|
||||||
|
position: relative;
|
||||||
|
margin-bottom: 12rpx;
|
||||||
|
padding-left: 24rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 30rpx;
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
content: "";
|
||||||
|
width: 8rpx;
|
||||||
|
height: 28rpx;
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 6rpx;
|
||||||
|
background: #03A9F4;
|
||||||
|
border-radius: 6rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sub-title-count {
|
||||||
|
font-size: 24rpx;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.vote-submit {
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 24rpx 36rpx;
|
||||||
|
position: fixed;
|
||||||
|
left: 0;
|
||||||
|
width: 100vw;
|
||||||
|
bottom: 0;
|
||||||
|
background-color: rgba(255, 255, 255, 0.98);
|
||||||
|
box-shadow: 0rpx 2rpx 24rpx rgba(0, 0, 0, 0.03);
|
||||||
|
border-top: 2rpx solid #eee;
|
||||||
|
z-index: 99;
|
||||||
|
|
||||||
|
::v-deep {
|
||||||
|
.tm-button {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tm-button-btn {
|
||||||
|
margin: 0;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,395 @@
|
|||||||
|
<template>
|
||||||
|
<view class="app-page">
|
||||||
|
<PluginUnavailable v-if="!uniHaloPluginAvailable" :pluginId="uniHaloPluginId"
|
||||||
|
:error-text="uniHaloPluginAvailableError" />
|
||||||
|
<template v-else>
|
||||||
|
<!-- 顶部切换 -->
|
||||||
|
<view class="e-fixed">
|
||||||
|
<tm-search v-model="queryParams.keyword" :round="24" :shadow="0" color="light-blue"
|
||||||
|
insert-color="light-blue" :clear="true" @input="fnOnSearch" @confirm="fnOnSearch"></tm-search>
|
||||||
|
<tm-dropDownMenu :shadow="1" color="light-blue" active-color="light-blue"
|
||||||
|
:default-selected="filterOption.selected" :list="filterOption.list"
|
||||||
|
@confirm="fnOnFilterConfirm"></tm-dropDownMenu>
|
||||||
|
</view>
|
||||||
|
<!-- 占位区域 -->
|
||||||
|
<view style="width: 100vw;height: 210rpx;"></view>
|
||||||
|
<!-- 加载区域 -->
|
||||||
|
<view v-if="loading == 'loading'" class="loading-wrap pa-24">
|
||||||
|
<tm-skeleton model="listAvatr"></tm-skeleton>
|
||||||
|
<tm-skeleton model="listAvatr"></tm-skeleton>
|
||||||
|
<tm-skeleton model="listAvatr"></tm-skeleton>
|
||||||
|
<tm-skeleton model="listAvatr"></tm-skeleton>
|
||||||
|
</view>
|
||||||
|
<view v-else-if="loading == 'error'" class="content-empty flex flex-center">
|
||||||
|
<tm-empty icon="icon-wind-cry" label="加载异常"></tm-empty>
|
||||||
|
</view>
|
||||||
|
<!-- 内容区域 -->
|
||||||
|
<view v-else class="content">
|
||||||
|
<view v-if="dataList.length == 0" class="content-empty flex flex-center">
|
||||||
|
<tm-empty icon="icon-shiliangzhinengduixiang-" label="暂无数据"></tm-empty>
|
||||||
|
</view>
|
||||||
|
<block v-else>
|
||||||
|
<tm-translate v-for="(item, index) in dataList" :key="item.metadata.name" animation-name="fadeUp"
|
||||||
|
:wait="calcAniWait(index)">
|
||||||
|
<VoteCard :vote="item" :index="index" @on-click="fnToDetail"></VoteCard>
|
||||||
|
</tm-translate>
|
||||||
|
<view class="load-text">{{ loadMoreText }}</view>
|
||||||
|
<tm-flotbutton @click="fnToTopPage" size="m" color="light-blue"
|
||||||
|
icon="icon-angle-up"></tm-flotbutton>
|
||||||
|
|
||||||
|
</block>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import tmSkeleton from '@/tm-vuetify/components/tm-skeleton/tm-skeleton.vue';
|
||||||
|
import tmSearch from '@/tm-vuetify/components/tm-search/tm-search.vue';
|
||||||
|
import tmTranslate from '@/tm-vuetify/components/tm-translate/tm-translate.vue';
|
||||||
|
import tmTabs from '@/tm-vuetify/components/tm-tabs/tm-tabs.vue';
|
||||||
|
import tmFlotbutton from '@/tm-vuetify/components/tm-flotbutton/tm-flotbutton.vue';
|
||||||
|
import tmEmpty from '@/tm-vuetify/components/tm-empty/tm-empty.vue';
|
||||||
|
import tmTags from '@/tm-vuetify/components/tm-tags/tm-tags.vue';
|
||||||
|
import tmDropDownMenu from '@/tm-vuetify/components/tm-dropDownMenu/tm-dropDownMenu.vue';
|
||||||
|
|
||||||
|
import VoteCard from '@/components/vote-card/vote-card.vue'
|
||||||
|
|
||||||
|
import {
|
||||||
|
voteCacheUtil
|
||||||
|
} from '@/utils/vote.js'
|
||||||
|
import pluginAvailable from "@/common/mixins/pluginAvailable.js"
|
||||||
|
|
||||||
|
export default {
|
||||||
|
options: {
|
||||||
|
styleIsolation: 'shared'
|
||||||
|
},
|
||||||
|
mixins: [pluginAvailable],
|
||||||
|
components: {
|
||||||
|
tmSkeleton,
|
||||||
|
tmSearch,
|
||||||
|
tmTranslate,
|
||||||
|
tmTabs,
|
||||||
|
tmFlotbutton,
|
||||||
|
tmEmpty,
|
||||||
|
tmTags,
|
||||||
|
tmDropDownMenu,
|
||||||
|
VoteCard
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
loading: 'loading',
|
||||||
|
hasNext: false,
|
||||||
|
isLoadMore: false,
|
||||||
|
loadMoreText: '加载中...',
|
||||||
|
filterOption: {
|
||||||
|
selected: [],
|
||||||
|
list: [{
|
||||||
|
title: '类型',
|
||||||
|
children: [{
|
||||||
|
title: "",
|
||||||
|
model: "list",
|
||||||
|
name: "type",
|
||||||
|
children: [{
|
||||||
|
title: "全部",
|
||||||
|
id: undefined
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "单选",
|
||||||
|
id: 'single'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "多选",
|
||||||
|
id: 'multiple'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "双选PK",
|
||||||
|
id: 'pk'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
title: '状态',
|
||||||
|
children: [{
|
||||||
|
title: "",
|
||||||
|
model: "list",
|
||||||
|
name: "hasEnded",
|
||||||
|
children: [{
|
||||||
|
title: "全部",
|
||||||
|
id: undefined
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "进行中",
|
||||||
|
id: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "已结束",
|
||||||
|
id: true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
title: '排序',
|
||||||
|
children: [{
|
||||||
|
title: "",
|
||||||
|
model: "list",
|
||||||
|
name: "sort",
|
||||||
|
children: [{
|
||||||
|
title: "默认排序",
|
||||||
|
id: undefined
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "较近创建",
|
||||||
|
id: 'metadata.creationTimestamp,desc'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "较早创建",
|
||||||
|
id: 'metadata.creationTimestamp,asc'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
title: '是否已投',
|
||||||
|
children: [{
|
||||||
|
title: "",
|
||||||
|
model: "list",
|
||||||
|
name: "isVoted",
|
||||||
|
children: [{
|
||||||
|
title: "全部",
|
||||||
|
id: undefined
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "未投票",
|
||||||
|
id: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "已投票",
|
||||||
|
id: true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
filterIsVoted: undefined,
|
||||||
|
queryParams: {
|
||||||
|
keyword: "",
|
||||||
|
page: 1,
|
||||||
|
size: 10,
|
||||||
|
sort: undefined,
|
||||||
|
type: undefined,
|
||||||
|
hasEnded: undefined
|
||||||
|
},
|
||||||
|
dataList: []
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
haloConfigs() {
|
||||||
|
return this.$tm.vx.getters().getConfigs;
|
||||||
|
},
|
||||||
|
calcAuditModeEnabled() {
|
||||||
|
return this.haloConfigs.auditConfig.auditModeEnabled
|
||||||
|
},
|
||||||
|
},
|
||||||
|
async onLoad() {
|
||||||
|
this.fnSetPageTitle('投票列表');
|
||||||
|
// 检查插件
|
||||||
|
this.setPluginId(this.NeedPluginIds.PluginVote)
|
||||||
|
this.setPluginError("阿偶,检测到当前插件没有安装或者启用,无法使用投票功能哦,请联系管理员")
|
||||||
|
if (!await this.checkPluginAvailable()) return
|
||||||
|
this.fnGetData();
|
||||||
|
},
|
||||||
|
onPullDownRefresh() {
|
||||||
|
if (!this.uniHaloPluginAvailable) return;
|
||||||
|
this.fnResetSetAniWaitIndex();
|
||||||
|
this.isLoadMore = false;
|
||||||
|
this.queryParams.page = 0;
|
||||||
|
this.fnGetData();
|
||||||
|
},
|
||||||
|
onReachBottom(e) {
|
||||||
|
if (!this.uniHaloPluginAvailable) return;
|
||||||
|
if (this.calcAuditModeEnabled) {
|
||||||
|
uni.showToast({
|
||||||
|
icon: 'none',
|
||||||
|
title: '没有更多数据了'
|
||||||
|
});
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (this.hasNext) {
|
||||||
|
this.queryParams.page += 1;
|
||||||
|
this.isLoadMore = true;
|
||||||
|
this.fnGetData();
|
||||||
|
} else {
|
||||||
|
uni.showToast({
|
||||||
|
icon: 'none',
|
||||||
|
title: '没有更多数据了'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
fnOnSearch() {
|
||||||
|
this.fnResetSetAniWaitIndex();
|
||||||
|
this.fnToTopPage();
|
||||||
|
this.fnGetData();
|
||||||
|
},
|
||||||
|
fnGetData() {
|
||||||
|
if (this.calcAuditModeEnabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
uni.showLoading({
|
||||||
|
mask: true,
|
||||||
|
title: '加载中...'
|
||||||
|
});
|
||||||
|
// 设置状态为加载中
|
||||||
|
if (!this.isLoadMore) {
|
||||||
|
this.loading = 'loading';
|
||||||
|
}
|
||||||
|
this.loadMoreText = '加载中...';
|
||||||
|
this.$httpApi.v2
|
||||||
|
.getVoteList(this.queryParams)
|
||||||
|
.then(res => {
|
||||||
|
this.loading = 'success';
|
||||||
|
this.loadMoreText = res.hasNext ? '上拉加载更多' : '呜呜,没有更多数据啦~';
|
||||||
|
this.hasNext = res.hasNext;
|
||||||
|
|
||||||
|
const tempItems = res.items.map(item => {
|
||||||
|
item.spec.disabled = true
|
||||||
|
item.spec.isVoted = this.fnCalcIsVoted(item.metadata.name)
|
||||||
|
|
||||||
|
item.spec.options.map((option, index) => {
|
||||||
|
|
||||||
|
option.checked = this.fnCalcIsChecked(item.metadata.name, option)
|
||||||
|
option.value = option.id
|
||||||
|
option.label = option.title
|
||||||
|
|
||||||
|
// todo:计算当前的选择占比
|
||||||
|
if (item.spec.type === 'single') {
|
||||||
|
option.percent = this.fnCalcPercent(option, item.stats);
|
||||||
|
} else if (item.spec.type === 'multiple') {
|
||||||
|
option.percent = this.fnCalcPercent(option, item.stats);
|
||||||
|
} else if (item.spec.type === 'pk') {
|
||||||
|
option.percent = this.fnCalcPercent(option, item.stats);
|
||||||
|
}
|
||||||
|
|
||||||
|
return option
|
||||||
|
})
|
||||||
|
|
||||||
|
return item;
|
||||||
|
})
|
||||||
|
|
||||||
|
if (this.isLoadMore) {
|
||||||
|
this.dataList = this.dataList.concat(tempItems);
|
||||||
|
} else {
|
||||||
|
this.dataList = tempItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.dataList = this.dataList.sort((a, b) => {
|
||||||
|
return a.spec.isVoted - b.spec.isVoted
|
||||||
|
})
|
||||||
|
|
||||||
|
if (this.filterIsVoted != undefined) {
|
||||||
|
this.dataList = this.dataList.filter(x => x.spec.isVoted == this.filterIsVoted)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.error(err);
|
||||||
|
this.loading = 'error';
|
||||||
|
this.loadMoreText = '加载失败,请下拉刷新!';
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
setTimeout(() => {
|
||||||
|
uni.hideLoading();
|
||||||
|
uni.stopPullDownRefresh();
|
||||||
|
}, 100);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
fnCalcPercent(voteOption, stats) {
|
||||||
|
if (!stats?.voteDataList) return 0;
|
||||||
|
const option = stats.voteDataList.find(x => x.id == voteOption.id)
|
||||||
|
if (!option) return 0;
|
||||||
|
const percent = (option.voteCount / stats.voteCount) * 100
|
||||||
|
return Math.round(percent)
|
||||||
|
},
|
||||||
|
|
||||||
|
fnCalcIsVoted(name) {
|
||||||
|
return voteCacheUtil.has(name)
|
||||||
|
},
|
||||||
|
fnCalcIsChecked(name, option) {
|
||||||
|
const data = voteCacheUtil.get(name)
|
||||||
|
if (!data) return false;
|
||||||
|
const checked = data.selected.includes(option.id)
|
||||||
|
return checked
|
||||||
|
},
|
||||||
|
//跳转详情
|
||||||
|
fnToDetail(item) {
|
||||||
|
if (this.calcAuditModeEnabled) return;
|
||||||
|
uni.navigateTo({
|
||||||
|
url: '/pagesA/vote-detail/vote-detail?name=' + item.metadata.name,
|
||||||
|
animationType: 'slide-in-right'
|
||||||
|
});
|
||||||
|
},
|
||||||
|
fnOnFilterConfirm(e) {
|
||||||
|
// 类型
|
||||||
|
const type = e.find(x => x.name == 'type')
|
||||||
|
if (type.children.length == 0) {
|
||||||
|
this.queryParams.type = undefined
|
||||||
|
} else {
|
||||||
|
this.queryParams.type = type.children[0]?.id
|
||||||
|
}
|
||||||
|
|
||||||
|
// 状态
|
||||||
|
const hasEnded = e.find(x => x.name == 'hasEnded')
|
||||||
|
if (hasEnded.children.length == 0) {
|
||||||
|
this.queryParams.hasEnded = undefined
|
||||||
|
} else {
|
||||||
|
this.queryParams.hasEnded = hasEnded.children[0]?.id
|
||||||
|
}
|
||||||
|
|
||||||
|
// 排序
|
||||||
|
const sort = e.find(x => x.name == 'sort')
|
||||||
|
if (sort.children.length == 0) {
|
||||||
|
this.queryParams.sort = undefined
|
||||||
|
} else {
|
||||||
|
this.queryParams.sort = sort.children[0]?.id
|
||||||
|
}
|
||||||
|
|
||||||
|
// 是否已经投
|
||||||
|
const isVoted = e.find(x => x.name == 'isVoted')
|
||||||
|
if (isVoted.children.length == 0) {
|
||||||
|
this.filterIsVoted = undefined
|
||||||
|
} else {
|
||||||
|
this.filterIsVoted = isVoted.children[0]?.id
|
||||||
|
}
|
||||||
|
|
||||||
|
this.queryParams.page = 0;
|
||||||
|
this.isLoadMore = false;
|
||||||
|
this.fnResetSetAniWaitIndex();
|
||||||
|
this.fnToTopPage();
|
||||||
|
this.fnGetData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.app-page {
|
||||||
|
width: 100vw;
|
||||||
|
min-height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding-bottom: 24rpx;
|
||||||
|
background-color: #fafafd;
|
||||||
|
|
||||||
|
&.is-balck {
|
||||||
|
background-color: #212121;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
padding-top: 24rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-empty {
|
||||||
|
height: 60vh;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
<view @click="onclick" class=" tm-checkbox " :class="[dense?'':'pa-20',inline?'d-inline-block':'']">
|
<view @click="onclick" class=" tm-checkbox " :class="[dense?'':'pa-20',inline?'d-inline-block':'']">
|
||||||
<view class=" flex-start">
|
<view class=" flex-start">
|
||||||
|
|
||||||
<slot name="default" :checkData="{label:label,checked:changValue}" :on="onclick">
|
<slot name="default" :checkData="{label:label,checked:changValue,extendData}" :on="onclick">
|
||||||
<view :style="{width: sizes.wk,height: sizes.wk}" class="tm-checkbox-boey relative d-inline-block"
|
<view :style="{width: sizes.wk,height: sizes.wk}" class="tm-checkbox-boey relative d-inline-block"
|
||||||
:class="[black?'bk':'','flex-shrink mr-10',
|
:class="[black?'bk':'','flex-shrink mr-10',
|
||||||
changValue?'ani':'',
|
changValue?'ani':'',
|
||||||
@@ -51,6 +51,10 @@
|
|||||||
*/
|
*/
|
||||||
import tmIcons from "@/tm-vuetify/components/tm-icons/tm-icons.vue"
|
import tmIcons from "@/tm-vuetify/components/tm-icons/tm-icons.vue"
|
||||||
export default {
|
export default {
|
||||||
|
options: {
|
||||||
|
virtualHost: true,
|
||||||
|
styleIsolation: 'shared'
|
||||||
|
},
|
||||||
components:{tmIcons},
|
components:{tmIcons},
|
||||||
name: 'tm-checkbox',
|
name: 'tm-checkbox',
|
||||||
model: {
|
model: {
|
||||||
@@ -117,6 +121,10 @@
|
|||||||
fllowTheme:{
|
fllowTheme:{
|
||||||
type:Boolean|String,
|
type:Boolean|String,
|
||||||
default:true
|
default:true
|
||||||
|
},
|
||||||
|
extendData:{
|
||||||
|
type:Object,
|
||||||
|
default:()=>({})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
|
|||||||
@@ -17,6 +17,10 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export default {
|
export default {
|
||||||
|
options: {
|
||||||
|
virtualHost: true,
|
||||||
|
styleIsolation: 'shared'
|
||||||
|
},
|
||||||
name:'tm-groupcheckbox',
|
name:'tm-groupcheckbox',
|
||||||
props:{
|
props:{
|
||||||
// 最大选择数量
|
// 最大选择数量
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<view @click="onclick" class=" tm-checkbox " :class="[dense?'':'pa-20',inline?'d-inline-block ':'fulled']">
|
<view @click="onclick" class=" tm-checkbox " :class="[dense?'':'pa-20',inline?'d-inline-block ':'fulled']">
|
||||||
<view class="flex-start fulled">
|
<view class="flex-start fulled">
|
||||||
|
|
||||||
<slot name="default" :checkData="{label:label,checked:changValue}" :on="onclick">
|
<slot name="default" :checkData="{label:label,checked:changValue,extendData}" :on="onclick">
|
||||||
<view :style="{width: sizes.wk,height: sizes.wk}" class="tm-checkbox-boey relative d-inline-block"
|
<view :style="{width: sizes.wk,height: sizes.wk}" class="tm-checkbox-boey relative d-inline-block"
|
||||||
:class="[black?'bk':'','flex-shrink mr-10 ',
|
:class="[black?'bk':'','flex-shrink mr-10 ',
|
||||||
changValue?'ani':'',
|
changValue?'ani':'',
|
||||||
@@ -119,8 +119,11 @@
|
|||||||
fllowTheme:{
|
fllowTheme:{
|
||||||
type:Boolean|String,
|
type:Boolean|String,
|
||||||
default:true
|
default:true
|
||||||
}
|
},
|
||||||
|
extendData:{
|
||||||
|
type:Object,
|
||||||
|
default:()=>({})
|
||||||
|
},
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
const UnihaloVoteUid = "unihalo_vote_uid"
|
||||||
|
|
||||||
|
export const voteCacheUtil = {
|
||||||
|
getAll() {
|
||||||
|
const data = uni.getStorageSync(UnihaloVoteUid)
|
||||||
|
if (!data) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
return JSON.parse(data)
|
||||||
|
},
|
||||||
|
get(name) {
|
||||||
|
const data = this.getAll()
|
||||||
|
if (!data) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
return data[name]
|
||||||
|
},
|
||||||
|
has(name) {
|
||||||
|
const data = this.getAll()
|
||||||
|
if (!data) return false
|
||||||
|
return data[name] != undefined
|
||||||
|
},
|
||||||
|
set(name, value) {
|
||||||
|
let data = this.getAll()
|
||||||
|
if (!data) {
|
||||||
|
data = {
|
||||||
|
[name]: value
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
data[name] = value
|
||||||
|
}
|
||||||
|
uni.setStorageSync(UnihaloVoteUid, JSON.stringify(data))
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user