feat: add SingleRecordMnt component for student record maintenance with search, add, edit, view, and delete functionalities

This commit is contained in:
skytek_xinliang
2026-03-26 11:24:37 +08:00
parent 507afcc99c
commit 069141794e
116 changed files with 15247 additions and 107 deletions
+110
View File
@@ -0,0 +1,110 @@
<template>
<v-container class="fill-height">
<v-row align="center" justify="center" no-gutters>
<v-col cols="12" md="8" sm="10">
<v-card border class="pa-6" variant="flat">
<v-card-title class="d-flex align-center ga-3">
<v-icon :color="color" size="36">{{ icon }}</v-icon>
<div class="text-h5">{{ title }}</div>
<div class="text-caption text-medium-emphasis">{{ codeLabel }}</div>
<v-spacer />
<img alt="robot" class="robot-icon" height="32" src="@/assets/robot-svgrepo-com.svg" width="32" />
</v-card-title>
<v-card-text v-if="description" class="text-body-1 mt-4">
<p class="py-3">
{{ description }}
</p>
<v-alert v-if="backendMessage" class="mt-6" :color="color" density="compact" type="warning" variant="tonal">
{{ backendMessage }}
</v-alert>
</v-card-text>
<v-card-actions class="mt-6">
<v-btn v-if="showBack" variant="text" @click="router.back()">返回上一頁</v-btn>
<v-spacer />
<v-btn v-if="showHome" color="primary" :to="{ name: 'home' }" variant="flat">回到首頁</v-btn>
<v-btn v-if="showLogin" class="ml-2" color="primary" :to="{ name: 'login' }" variant="outlined">
前往登入
</v-btn>
</v-card-actions>
</v-card>
</v-col>
</v-row>
</v-container>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { useRoute, useRouter } from 'vue-router'
type Props = {
code: string | number
title: string
description?: string
icon?: string
color?: string
showHome?: boolean
showLogin?: boolean
showBack?: boolean
}
const props = withDefaults(defineProps<Props>(), {
description: undefined,
icon: 'mdi-alert-circle-outline',
color: 'warning',
showHome: true,
showLogin: true,
showBack: true
})
const route = useRoute()
const router = useRouter()
const codeLabel = computed(() => {
const code = props.code
return typeof code === 'number' ? `HTTP ${code}` : String(code)
})
const backendMessage = computed(() => {
const raw = route.query.message
if (typeof raw !== 'string') return ''
return raw.trim()
})
</script>
<style scoped>
@keyframes breathe {
0%, 100% {
transform: scale(1);
opacity: 1;
}
50% {
transform: scale(1.05);
opacity: 0.8;
}
}
@keyframes blink {
0%, 45%, 55%, 100% {
opacity: 1;
}
50% {
opacity: 0.3;
}
}
.robot-icon {
animation: breathe 3s ease-in-out infinite;
}
.robot-icon path:nth-child(2),
.robot-icon path:nth-child(3) {
animation: blink 4s ease-in-out infinite;
}
.robot-icon path:nth-child(3) {
animation-delay: 0.1s;
}
</style>