mirror of
https://github.com/BTMuli/TeyvatGuide.git
synced 2025-12-13 09:28:14 +08:00
128 lines
2.9 KiB
Vue
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>
|