mirror of
https://hub.gitmirror.com/https://github.com/ExamAware/ExamShowboard-Legacy.git
synced 2025-04-29 18:26:33 +00:00
refactor: 重构SubjectInfo组件
This commit is contained in:
parent
012c1dc80e
commit
5ff25e3259
@ -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>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user