Files
TeyvatGuide/src/components/viewPost/tp-vote.vue
2025-01-16 15:51:59 +08:00

128 lines
2.9 KiB
Vue

<template>
<div class="tp-vote-box">
<div class="tp-vote-info">
<span>{{ votes?.title }}</span>
<span>{{ votes?.count }}人已参与|{{ votes?.is_over ? "已截止" : "投票中" }}</span>
</div>
<div class="tp-vote-list">
<div v-for="(item, index) in votes?.data" :key="index" class="tp-vote-item">
<div class="tp-vote-item-title">
<span>{{ item.title }}</span>
<span>
<span>{{ item.count }}</span>
<span>{{ item.percent.toFixed(2) }}%</span>
</span>
</div>
<div class="tp-vote-progress">
<div class="tp-vote-val" :style="getWidth(item)" />
</div>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { onMounted, shallowRef } from "vue";
import ApiHubReq from "@/web/request/apiHubReq.js";
type TpVote = { insert: { vote: { id: string; uid: string } } };
type TpVoteProps = { data: TpVote };
type TpVoteData = { title: string; count: number; percent: number };
type TpVoteInfo = { title: string; count: number; is_over: boolean; data: Array<TpVoteData> };
const props = defineProps<TpVoteProps>();
const votes = shallowRef<TpVoteInfo>();
onMounted(async () => {
const vote = props.data.insert.vote;
const voteInfo = await ApiHubReq.vote.info(vote.id, vote.uid);
const voteResult = await ApiHubReq.vote.result(vote.id, vote.uid);
votes.value = {
title: voteInfo.title,
count: voteResult.user_cnt,
is_over: voteResult.is_over,
data: voteInfo.vote_option_indexes.map((item, index) => ({
title: item,
count: voteResult.option_stats[index] ?? 0,
percent: ((voteResult.option_stats[index] ?? 0) / voteResult.user_cnt) * 100,
})),
};
});
function getWidth(item: TpVoteData): string {
return `width: ${item.percent}%;`;
}
</script>
<style lang="css" scoped>
.tp-vote-box {
display: flex;
flex-direction: column;
padding: 10px;
border: 1px solid var(--common-shadow-1);
border-radius: 5px;
row-gap: 10px;
}
.tp-vote-info {
display: flex;
align-items: center;
justify-content: space-between;
}
.tp-vote-info :first-child {
font-size: 20px;
font-weight: bold;
}
.tp-vote-list {
display: grid;
gap: 10px 20px;
grid-template-columns: repeat(2, 1fr);
}
.tp-vote-item {
display: flex;
flex-direction: column;
gap: 5px;
}
.tp-vote-item-title {
display: flex;
align-items: center;
justify-content: space-between;
}
.tp-vote-item-title :first-child {
font-size: 16px;
font-weight: bold;
}
.tp-vote-item-title :last-child {
display: flex;
flex-direction: column;
gap: 5px;
}
.tp-vote-item-title :last-child :first-child {
font-size: 12px;
}
.tp-vote-item-title :last-child :last-child {
font-size: 10px;
}
.tp-vote-progress {
overflow: hidden;
width: 100%;
height: 10px;
border-radius: 5px;
background: var(--common-shadow-1);
}
.tp-vote-val {
height: 100%;
border-radius: 5px;
background: linear-gradient(to right, #6cf, #f09199);
}
</style>