refactor: 重构SubjectInfo组件

This commit is contained in:
hello8693 2024-08-05 18:07:27 +08:00
parent 012c1dc80e
commit 5ff25e3259

View File

@ -1,50 +1,104 @@
<template> <template>
<div class="exam-info"> <v-card v-if="exam" class="mx-auto pa-4 subject-info-card" max-width="600" elevation="12">
<h2>当前科目: {{ exam.name }}</h2> <v-card-text>
<h2>考试时间: {{ formatDateTime(exam.start) }} ~ {{ formatDateTime(exam.end) }}</h2> <div class="text-h5">
<h2>考试状态: {{ statusText }}</h2> 当前科目:<span class="text-h5 ml-2">{{ exam.name }}</span>
</div> </div>
<div class="text-h5">
考试时间: {{ formatDateTime(exam.start) }} ~ {{ formatDateTime(exam.end) }}
</div>
<div class="text-h5 mt-4">
考试状态: <span :class="statusColor">{{ statusText }}</span>
</div>
<div v-if="isWarning" class="text-h5 text--warning">考试即将结束</div>
</v-card-text>
</v-card>
<v-card v-else class="mx-auto pa-4 subject-info-card" max-width="600" elevation="12">
<v-card-title class="headline grey lighten-2"> 考试已结束 </v-card-title>
</v-card>
</template> </template>
<script setup> <script setup lang="ts">
import moment from 'moment'; import { ref, computed } from 'vue';
// Define props
const props = defineProps({ const props = defineProps({
exam: { exam: {
type: Object, type: Object as () => { name: string; start: string; end: string },
required: true default: null
} }
}); });
const formatDateTime = (isoString) => moment(isoString).format('HH:mm'); // Computed properties
const formatDateTime = (isoString: string) =>
new Date(isoString).toLocaleTimeString([], {
hour: '2-digit',
minute: '2-digit'
});
const now = ref(new Date());
const statusColor = computed(() => { const statusColor = computed(() => {
const now = moment(); if (!props.exam) return '';
const start = moment(props.exam.start);
const end = moment(props.exam.end);
if (now.isBefore(start)) return 'running'; const start = new Date(props.exam.start);
if (now.isBetween(start, end)) return 'success'; const end = new Date(props.exam.end);
if (now.isAfter(end)) return 'error';
if (now.value < start) return 'status-before';
if (now.value >= start && now.value < end) return 'status-middle';
if (now.value >= end) return 'status-after';
}); });
const statusText = computed(() => { const statusText = computed(() => {
const now = moment(); if (!props.exam) return '考试已结束';
const start = moment(props.exam.start);
const end = moment(props.exam.end);
if (now.isBefore(start)) return '未开始'; const start = new Date(props.exam.start);
if (now.isBetween(start, end)) return '进行中'; const end = new Date(props.exam.end);
if (now.isAfter(end)) return '已结束';
if (now.value < start) return '未开始';
if (now.value >= start && now.value < end) return '进行中';
if (now.value >= end) return '已结束';
}); });
const isWarning = computed(() => {
if (!props.exam) return false;
const end = new Date(props.exam.end);
const fifteenMinutesBeforeEnd = new Date(end.getTime() - 15 * 60 * 1000);
return now.value >= fifteenMinutesBeforeEnd && now.value < end;
});
// Update the current time every second
const updateNow = () => {
now.value = new Date();
};
setInterval(updateNow, 1000);
updateNow();
</script> </script>
<style scoped> <style scoped>
.text-h5 {
font-size: 2.5rem !important;
}
.exam-info-bar { .text--warning {
display: flex; color: #ffc107 !important; /* Vuetify's default warning color */
align-items: center; }
justify-content: space-between;
font-size: 1.4em; .status-before {
color: orange;
}
.status-middle {
color: green;
}
.status-after {
color: red;
}
.subject-info-card {
margin-top: 20px;
} }
</style> </style>