Merge pull request #9 from MKStoler4096/dev

v1.1.2
This commit is contained in:
MKStoler 2024-10-10 21:01:27 +08:00 committed by GitHub
commit c519e2c47b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 121 additions and 25 deletions

View File

@ -5,10 +5,20 @@
<link rel="icon" href="/favicon.ico" /> <link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>DSZ Exam Showboard</title> <title>DSZ Exam Showboard</title>
<style>
/* 隐藏滚动条 */
body {
overflow: hidden;
}
/* 适用于所有滚动容器 */
.no-scrollbar {
overflow: hidden;
}
</style>
</head> </head>
<body> <body>
<div id="app"></div> <div id="app" class="no-scrollbar"></div>
<script type="module" src="/src/main.ts"></script> <script type="module" src="/src/main.ts"></script>
</body> </body>
</html> </html>

View File

@ -4,39 +4,43 @@
<v-row justify="center"> <v-row justify="center">
<v-col cols="12"> <v-col cols="12">
<v-data-table <v-data-table
:items="sortedExams" :items="groupedExams"
:headers="headers" :headers="headers"
item-key="name" item-key="name"
hide-default-footer hide-default-footer
dense dense
class="text-h5" class="text-h5"
> >
<template #header.name> <template #item="{ item }">
<span class="text-h5">科目</span> <template v-if="item.isDate">
<tr>
<td colspan="4" class="text-h5">{{ item.date }}</td>
</tr>
</template> </template>
<template #header.start> <template v-else>
<span class="text-h5">开始</span> <tr>
</template> <td class="text-h5">{{ item.name }}</td>
<template #header.end> <td class="text-h5">{{ formatTime(item.start) }}</td>
<span class="text-h5">结束</span> <td class="text-h5">{{ formatTime(item.end) }}</td>
</template> <td>
<template #header.status>
<span class="text-h5">状态</span>
</template>
<template #item.name="{ item }">
<div class="text-h5">{{ item.name }}</div>
</template>
<template #item.start="{ item }">
<div class="text-h5">{{ formatTime(item.start) }}</div>
</template>
<template #item.end="{ item }">
<div class="text-h5">{{ formatTime(item.end) }}</div>
</template>
<template #item.status="{ item }">
<v-chip :color="getStatusColor(item)" dark class="exam-status-chip"> <v-chip :color="getStatusColor(item)" dark class="exam-status-chip">
{{ getStatusText(item) }} {{ getStatusText(item) }}
</v-chip> </v-chip>
</td>
</tr>
</template>
</template>
<template #header.name>
<span class="text-h5 font-weight-bold">科目</span>
</template>
<template #header.start>
<span class="text-h5 font-weight-bold">开始</span>
</template>
<template #header.end>
<span class="text-h5 font-weight-bold">结束</span>
</template>
<template #header.status>
<span class="text-h5 font-weight-bold">状态</span>
</template> </template>
</v-data-table> </v-data-table>
</v-col> </v-col>
@ -64,6 +68,27 @@ const sortedExams = computed(() => {
return state.exams.sort((a, b) => new Date(a.start).getTime() - new Date(b.start).getTime()); return state.exams.sort((a, b) => new Date(a.start).getTime() - new Date(b.start).getTime());
}); });
const groupedExams = computed(() => {
const grouped = [];
let currentDate = '';
sortedExams.value.forEach((exam) => {
const examDate = new Date(exam.start).toLocaleDateString('zh-CN', {
month: 'numeric',
day: 'numeric'
});
if (examDate !== currentDate) {
currentDate = examDate;
grouped.push({ isDate: true, date: `${currentDate}` });
}
grouped.push({ ...exam, isDate: false });
});
return grouped;
});
const headers = [ const headers = [
{ text: '科目', value: 'name' }, { text: '科目', value: 'name' },
{ text: '开始', value: 'start', sortable: false }, { text: '开始', value: 'start', sortable: false },
@ -121,6 +146,10 @@ onMounted(() => {
font-size: 1.8rem !important; font-size: 1.8rem !important;
} }
.font-weight-bold {
font-weight: bold;
}
.exam-status-chip { .exam-status-chip {
font-size: 1.5rem !important; font-size: 1.5rem !important;
} }

View File

@ -12,6 +12,7 @@
</div> </div>
<div v-if="isWarning" class="text-h5 text--warning">考试即将结束</div> <div v-if="isWarning" class="text-h5 text--warning">考试即将结束</div>
<div v-if="showRemainingTime" class="text-h5 text--info">剩余时间: {{ remainingTime }}</div> <div v-if="showRemainingTime" class="text-h5 text--info">剩余时间: {{ remainingTime }}</div>
<div v-if="showCountdown" class="text-h5 text--info">倒计时: {{ countdown }}</div>
</v-card-text> </v-card-text>
</v-card> </v-card>
@ -75,9 +76,17 @@ const showRemainingTime = computed(() => {
const start = new Date(props.exam.start); const start = new Date(props.exam.start);
const end = new Date(props.exam.end); const end = new Date(props.exam.end);
return now.value >= start && now.value < end;
});
const showCountdown = computed(() => {
if (!props.exam) return false;
const start = new Date(props.exam.start);
const fifteenMinutesBeforeStart = new Date(start.getTime() - 15 * 60 * 1000); const fifteenMinutesBeforeStart = new Date(start.getTime() - 15 * 60 * 1000);
return now.value >= fifteenMinutesBeforeStart && now.value < end; return now.value >= fifteenMinutesBeforeStart && now.value < start;
}); });
const remainingTime = computed(() => { const remainingTime = computed(() => {
@ -91,6 +100,17 @@ const remainingTime = computed(() => {
return `${minutes}${seconds}`; return `${minutes}${seconds}`;
}); });
const countdown = computed(() => {
if (!props.exam) return '';
const start = new Date(props.exam.start);
const timeDiff = start.getTime() - now.value.getTime();
const minutes = Math.floor(timeDiff / (1000 * 60));
const seconds = Math.floor((timeDiff % (1000 * 60)) / 1000);
return `${minutes}${seconds}`;
});
// Update the current time every second // Update the current time every second
const updateNow = () => { const updateNow = () => {
now.value = new Date(); now.value = new Date();

View File

@ -1,7 +1,7 @@
<template> <template>
<v-app> <v-app>
<AppTopBar /> <AppTopBar />
<v-main> <v-main class="no-scrollbar">
<router-view /> <router-view />
</v-main> </v-main>
</v-app> </v-app>
@ -10,3 +10,9 @@
<script lang="ts" setup> <script lang="ts" setup>
// //
</script> </script>
<style scoped>
.no-scrollbar {
overflow: hidden;
}
</style>

View File

@ -25,4 +25,16 @@ app.use(VueShowdownPlugin, {
registerPlugins(app); registerPlugins(app);
// 添加全局样式来隐藏滚动条
const style = document.createElement('style');
style.innerHTML = `
body {
overflow: hidden;
}
.no-scrollbar {
overflow: hidden;
}
`;
document.head.appendChild(style);
app.mount('#app'); app.mount('#app');

View File

@ -9,7 +9,7 @@
欢迎来到考试展板应用程序这是一个用于展示考试信息的工具帮助考生更好地了解考试安排和状态 欢迎来到考试展板应用程序这是一个用于展示考试信息的工具帮助考生更好地了解考试安排和状态
</p> </p>
<p>本应用程序旨在为考生提供便捷的考试信息查看体验</p> <p>本应用程序旨在为考生提供便捷的考试信息查看体验</p>
<p>版本号 1.1.0-Malkuth</p> <p>版本号 1.1.1-Malkuth</p>
<p>开发者Hello8963 & Mkstoler4096</p> <p>开发者Hello8963 & Mkstoler4096</p>
<v-btn <v-btn
href="https://github.com/MKStoler4096/dsz-exam-showboard-next" href="https://github.com/MKStoler4096/dsz-exam-showboard-next"

View File

@ -1,7 +1,7 @@
/** /**
* plugins/vuetify.js * plugins/vuetify.js
* *
* Framework documentation: https://vuetifyjs.com` * Framework documentation: https://vuetifyjs.com
*/ */
// Styles // Styles
@ -13,6 +13,25 @@ import { createVuetify } from 'vuetify';
import { md3 } from 'vuetify/blueprints'; import { md3 } from 'vuetify/blueprints';
// 添加全局样式来隐藏滚动条
const style = document.createElement('style');
style.innerHTML = `
body {
overflow: hidden;
}
.no-scrollbar {
overflow: hidden;
}
* {
scrollbar-width: none; /* Firefox */
-ms-overflow-style: none; /* Internet Explorer 10+ */
}
*::-webkit-scrollbar {
display: none; /* Safari and Chrome */
}
`;
document.head.appendChild(style);
// https://vuetifyjs.com/en/introduction/why-vuetify/#feature-guides // https://vuetifyjs.com/en/introduction/why-vuetify/#feature-guides
export default createVuetify({ export default createVuetify({
theme: { theme: {