restyle: layout not login
This commit is contained in:
@@ -1,17 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
<v-app :class="{ 'large-text-mode': isLargeText, 'high-contrast-mode': isHighContrast }">
|
<v-app :class="{ 'large-text-mode': isLargeText }">
|
||||||
<!-- 頂部導航欄 -->
|
<!-- 頂部導航欄 -->
|
||||||
<v-app-bar class="px-2 elevation-1" color="primary" flat>
|
<v-app-bar class="px-2 elevation-1" color="primary" flat>
|
||||||
<template #prepend>
|
<template #prepend>
|
||||||
<v-app-bar-nav-icon variant="text" @click="drawer = !drawer" />
|
<v-app-bar-nav-icon variant="text" @click="drawer = !drawer" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<v-app-bar-title class="font-weight-bold flex-grow-1">
|
<v-app-bar-title class="font-weight-bold flex-grow-1"> 運動玩轉健康力 </v-app-bar-title>
|
||||||
<div class="d-flex align-center">
|
|
||||||
<v-icon class="mr-2 text-accent" icon="mdi-heart-pulse" />
|
|
||||||
<span class="text-subtitle-1 text-sm-h6 font-weight-bold">運動玩轉健康力</span>
|
|
||||||
</div>
|
|
||||||
</v-app-bar-title>
|
|
||||||
|
|
||||||
<template #append>
|
<template #append>
|
||||||
<div class="d-flex align-center">
|
<div class="d-flex align-center">
|
||||||
@@ -38,18 +33,6 @@
|
|||||||
store.userProfile.name.substring(1)
|
store.userProfile.name.substring(1)
|
||||||
}}</span>
|
}}</span>
|
||||||
</v-avatar>
|
</v-avatar>
|
||||||
|
|
||||||
<v-btn
|
|
||||||
v-else
|
|
||||||
class="font-weight-bold"
|
|
||||||
color="accent"
|
|
||||||
prepend-icon="mdi-login"
|
|
||||||
size="small"
|
|
||||||
to="/login"
|
|
||||||
variant="flat"
|
|
||||||
>
|
|
||||||
登入
|
|
||||||
</v-btn>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</v-app-bar>
|
</v-app-bar>
|
||||||
@@ -65,7 +48,9 @@
|
|||||||
</v-avatar>
|
</v-avatar>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<v-list-item-title class="font-weight-bold">{{ store.userProfile.name }} 先生</v-list-item-title>
|
<v-list-item-title class="font-weight-bold">
|
||||||
|
{{ store.userProfile.name }} 先生
|
||||||
|
</v-list-item-title>
|
||||||
|
|
||||||
<v-list-item-subtitle class="text-white-50">{{
|
<v-list-item-subtitle class="text-white-50">{{
|
||||||
store.userProfile.phone
|
store.userProfile.phone
|
||||||
@@ -79,16 +64,11 @@
|
|||||||
</v-avatar>
|
</v-avatar>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<v-list-item-title class="font-weight-bold">運動玩轉健康力</v-list-item-title>
|
|
||||||
|
|
||||||
<v-list-item-subtitle class="text-white-50">未登入訪客</v-list-item-subtitle>
|
<v-list-item-subtitle class="text-white-50">未登入訪客</v-list-item-subtitle>
|
||||||
</v-list-item>
|
</v-list-item>
|
||||||
|
|
||||||
<v-divider />
|
<v-divider />
|
||||||
|
|
||||||
<!-- 高齡與無障礙設定區 -->
|
|
||||||
<v-list-subheader class="font-weight-bold text-primary">高齡友善設定</v-list-subheader>
|
|
||||||
|
|
||||||
<v-list-item>
|
<v-list-item>
|
||||||
<template #prepend>
|
<template #prepend>
|
||||||
<v-icon color="primary" icon="mdi-format-size" />
|
<v-icon color="primary" icon="mdi-format-size" />
|
||||||
@@ -101,23 +81,12 @@
|
|||||||
</template>
|
</template>
|
||||||
</v-list-item>
|
</v-list-item>
|
||||||
|
|
||||||
<v-list-item>
|
|
||||||
<template #prepend>
|
|
||||||
<v-icon color="primary" icon="mdi-contrast-box" />
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<v-list-item-title>高對比模式</v-list-item-title>
|
|
||||||
|
|
||||||
<template #append>
|
|
||||||
<v-switch v-model="isHighContrast" color="secondary" density="compact" hide-details />
|
|
||||||
</template>
|
|
||||||
</v-list-item>
|
|
||||||
|
|
||||||
<v-divider class="my-2" />
|
<v-divider class="my-2" />
|
||||||
|
|
||||||
<!-- 主要功能連結 -->
|
<!-- 主要功能連結 -->
|
||||||
<v-list density="compact" nav>
|
<v-list density="comfortable" nav>
|
||||||
<v-list-item
|
<v-list-item
|
||||||
|
class="py-2"
|
||||||
color="primary"
|
color="primary"
|
||||||
exact
|
exact
|
||||||
prepend-icon="mdi-view-dashboard"
|
prepend-icon="mdi-view-dashboard"
|
||||||
@@ -185,7 +154,7 @@
|
|||||||
<v-btn
|
<v-btn
|
||||||
v-else
|
v-else
|
||||||
block
|
block
|
||||||
color="primary"
|
color="secondary"
|
||||||
prepend-icon="mdi-login"
|
prepend-icon="mdi-login"
|
||||||
to="/login"
|
to="/login"
|
||||||
variant="flat"
|
variant="flat"
|
||||||
@@ -205,31 +174,25 @@
|
|||||||
</v-main>
|
</v-main>
|
||||||
|
|
||||||
<!-- 底部導航欄 (Mobile First 核心) -->
|
<!-- 底部導航欄 (Mobile First 核心) -->
|
||||||
<v-bottom-navigation
|
<v-bottom-navigation v-model="activeTab" color="primary" tag="div" grow>
|
||||||
v-model="activeTab"
|
|
||||||
class="elevation-8 border-top"
|
|
||||||
color="primary"
|
|
||||||
grow
|
|
||||||
style="position: fixed; bottom: 0; left: 0; right: 0; z-index: 1000"
|
|
||||||
>
|
|
||||||
<v-btn to="/" value="home">
|
<v-btn to="/" value="home">
|
||||||
<v-icon>mdi-view-dashboard</v-icon>
|
<v-icon color="secondary">mdi-view-dashboard</v-icon>
|
||||||
<span>主控台</span>
|
<span class="bottom-nav-text">主控台</span>
|
||||||
</v-btn>
|
</v-btn>
|
||||||
|
|
||||||
<v-btn to="/self-assessment" value="self-assessment">
|
<v-btn to="/self-assessment" value="self-assessment">
|
||||||
<v-icon>mdi-clipboard-text-search</v-icon>
|
<v-icon color="secondary">mdi-clipboard-text-search</v-icon>
|
||||||
<span>線上自評</span>
|
<span class="bottom-nav-text">線上自評</span>
|
||||||
</v-btn>
|
</v-btn>
|
||||||
|
|
||||||
<v-btn v-if="store.isLoggedIn" to="/appointment" value="appointment">
|
<v-btn v-if="store.isLoggedIn" to="/appointment" value="appointment">
|
||||||
<v-icon>mdi-calendar-check</v-icon>
|
<v-icon color="secondary">mdi-calendar-check</v-icon>
|
||||||
<span>活動預約</span>
|
<span class="bottom-nav-text">活動預約</span>
|
||||||
</v-btn>
|
</v-btn>
|
||||||
|
|
||||||
<v-btn v-if="store.isLoggedIn" to="/checkin" value="checkin">
|
<v-btn v-if="store.isLoggedIn" to="/checkin" value="checkin">
|
||||||
<v-icon>mdi-qrcode-scan</v-icon>
|
<v-icon color="secondary">mdi-qrcode-scan</v-icon>
|
||||||
<span>現場量測</span>
|
<span class="bottom-nav-text">現場量測</span>
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</v-bottom-navigation>
|
</v-bottom-navigation>
|
||||||
|
|
||||||
@@ -263,7 +226,9 @@
|
|||||||
color="primary"
|
color="primary"
|
||||||
variant="flat"
|
variant="flat"
|
||||||
@click="showPrivacy = false"
|
@click="showPrivacy = false"
|
||||||
>確認關閉</v-btn>
|
>
|
||||||
|
確認關閉
|
||||||
|
</v-btn>
|
||||||
</v-card-actions>
|
</v-card-actions>
|
||||||
</v-card>
|
</v-card>
|
||||||
</v-dialog>
|
</v-dialog>
|
||||||
@@ -301,7 +266,9 @@
|
|||||||
color="primary"
|
color="primary"
|
||||||
variant="flat"
|
variant="flat"
|
||||||
@click="showEmergency = false"
|
@click="showEmergency = false"
|
||||||
>儲存並關閉</v-btn>
|
>
|
||||||
|
儲存並關閉
|
||||||
|
</v-btn>
|
||||||
</v-card-actions>
|
</v-card-actions>
|
||||||
</v-card>
|
</v-card>
|
||||||
</v-dialog>
|
</v-dialog>
|
||||||
@@ -324,26 +291,21 @@
|
|||||||
|
|
||||||
// 無障礙狀態 (可持久化儲存於 localStorage)
|
// 無障礙狀態 (可持久化儲存於 localStorage)
|
||||||
const isLargeText = ref(localStorage.getItem('mode-large-text') === 'true')
|
const isLargeText = ref(localStorage.getItem('mode-large-text') === 'true')
|
||||||
const isHighContrast = ref(localStorage.getItem('mode-high-contrast') === 'true')
|
|
||||||
|
|
||||||
watch(isLargeText, newVal => {
|
watch(isLargeText, (newVal) => {
|
||||||
localStorage.setItem('mode-large-text', String(newVal))
|
localStorage.setItem('mode-large-text', String(newVal))
|
||||||
})
|
})
|
||||||
|
|
||||||
watch(isHighContrast, newVal => {
|
|
||||||
localStorage.setItem('mode-high-contrast', String(newVal))
|
|
||||||
})
|
|
||||||
|
|
||||||
// 同步底部導航狀態與當前路由
|
// 同步底部導航狀態與當前路由
|
||||||
watch(
|
watch(
|
||||||
() => route.path,
|
() => route.path,
|
||||||
path => {
|
(path) => {
|
||||||
if (path === '/') activeTab.value = 'home'
|
if (path === '/') activeTab.value = 'home'
|
||||||
else if (path.startsWith('/self-assessment')) activeTab.value = 'self-assessment'
|
else if (path.startsWith('/self-assessment')) activeTab.value = 'self-assessment'
|
||||||
else if (path.startsWith('/appointment')) activeTab.value = 'appointment'
|
else if (path.startsWith('/appointment')) activeTab.value = 'appointment'
|
||||||
else if (path.startsWith('/checkin')) activeTab.value = 'checkin'
|
else if (path.startsWith('/checkin')) activeTab.value = 'checkin'
|
||||||
},
|
},
|
||||||
{ immediate: true },
|
{ immediate: true }
|
||||||
)
|
)
|
||||||
|
|
||||||
function handleLogout() {
|
function handleLogout() {
|
||||||
@@ -369,6 +331,7 @@
|
|||||||
.v-card-title,
|
.v-card-title,
|
||||||
.text-subtitle-1 {
|
.text-subtitle-1 {
|
||||||
font-size: 1.25rem !important;
|
font-size: 1.25rem !important;
|
||||||
|
line-height: unset !important;
|
||||||
}
|
}
|
||||||
.v-card-text,
|
.v-card-text,
|
||||||
.text-body-1,
|
.text-body-1,
|
||||||
@@ -382,35 +345,9 @@
|
|||||||
.text-h6 {
|
.text-h6 {
|
||||||
font-size: 1.5rem !important;
|
font-size: 1.5rem !important;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// 高對比模式
|
.bottom-nav-text {
|
||||||
.high-contrast-mode {
|
font-size: 1rem;
|
||||||
--v-theme-background: #000000 !important;
|
|
||||||
--v-theme-surface: #121212 !important;
|
|
||||||
--v-theme-primary: #ffeb3b !important; // 明亮黃色作為主色
|
|
||||||
--v-theme-accent: #00e676 !important;
|
|
||||||
--v-theme-secondary: #ff9100 !important;
|
|
||||||
|
|
||||||
// 文字高對比
|
|
||||||
.text-primary,
|
|
||||||
.v-list-item-title,
|
|
||||||
.v-btn,
|
|
||||||
.v-card-title,
|
|
||||||
.v-app-bar-title,
|
|
||||||
span,
|
|
||||||
p,
|
|
||||||
div {
|
|
||||||
color: #ffffff !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.v-app-bar {
|
|
||||||
border-bottom: 2px solid #ffeb3b !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.v-bottom-navigation {
|
|
||||||
border-top: 2px solid #ffeb3b !important;
|
|
||||||
background-color: #121212 !important;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
<template>
|
<template>
|
||||||
<v-app class="bg-gradient">
|
<v-app class="bg-background">
|
||||||
<v-container>
|
<v-container>
|
||||||
<v-row justify="center" no-gutters>
|
<v-row justify="center" no-gutters>
|
||||||
<v-col class="text-center" cols="12" sm="6">
|
<v-col class="text-center" cols="12" sm="6">
|
||||||
<!-- Logo 與品牌名稱 -->
|
<!-- Logo 與品牌名稱 -->
|
||||||
<v-card class="bg-transparent" variant="flat">
|
<v-card class="bg-transparent" variant="flat">
|
||||||
<v-avatar class="" color="primary" size="80">
|
<v-avatar class="logo-spin-on-load" color="primary" size="80">
|
||||||
<v-icon color="accent" icon="mdi-heart-pulse" size="48" />
|
<v-icon color="red-accent-1" icon="mdi-heart-pulse" size="48" />
|
||||||
</v-avatar>
|
</v-avatar>
|
||||||
|
|
||||||
<v-card-title>運動玩轉健康力</v-card-title>
|
<v-card-title class="text-primary font-weight-bold">運動玩轉健康力</v-card-title>
|
||||||
<v-card-subtitle>Taipei Masters Hub</v-card-subtitle>
|
<v-card-subtitle class="text-primary">Taipei Masters Hub</v-card-subtitle>
|
||||||
</v-card>
|
</v-card>
|
||||||
|
|
||||||
<!-- 登入卡片 -->
|
<!-- 登入卡片 -->
|
||||||
@@ -47,8 +47,8 @@
|
|||||||
|
|
||||||
<v-btn
|
<v-btn
|
||||||
block
|
block
|
||||||
class="rounded-lg font-weight-bold elevation-2 mb-4 text-button"
|
class="glow-sweep-button rounded-lg font-weight-bold elevation-2 mb-4"
|
||||||
color="primary"
|
color="secondary"
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
size="large"
|
size="large"
|
||||||
type="submit"
|
type="submit"
|
||||||
@@ -89,7 +89,7 @@
|
|||||||
</v-card>
|
</v-card>
|
||||||
|
|
||||||
<!-- 版權 -->
|
<!-- 版權 -->
|
||||||
<div class="mt-8 text-caption text-grey-darken-1">
|
<div class="mt-8 text-body-small text-grey-darken-1">
|
||||||
<p>© 2026 SKYTEK</p>
|
<p>© 2026 SKYTEK</p>
|
||||||
</div>
|
</div>
|
||||||
</v-col>
|
</v-col>
|
||||||
@@ -121,7 +121,7 @@ function handleLogin() {
|
|||||||
}, 1000)
|
}, 1000)
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleLineLogin() {
|
function _handleLineLogin () {
|
||||||
lineLoading.value = true
|
lineLoading.value = true
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
store.login('0912-345-678') // LINE 模擬登入預設手機
|
store.login('0912-345-678') // LINE 模擬登入預設手機
|
||||||
@@ -132,7 +132,53 @@ function handleLineLogin() {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.bg-gradient {
|
.logo-spin-on-load {
|
||||||
background: linear-gradient(135deg, #f0f9f6 0%, #dcefea 100%) !important;
|
animation: logo-spin 0.9s ease-out both;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glow-sweep-button {
|
||||||
|
overflow: hidden;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glow-sweep-button::after {
|
||||||
|
position: absolute;
|
||||||
|
top: -50%;
|
||||||
|
left: -70%;
|
||||||
|
width: 45%;
|
||||||
|
height: 200%;
|
||||||
|
background: linear-gradient(
|
||||||
|
120deg,
|
||||||
|
transparent 0%,
|
||||||
|
rgba(255, 255, 255, 0.15) 35%,
|
||||||
|
rgba(255, 255, 255, 0.75) 50%,
|
||||||
|
rgba(255, 255, 255, 0.15) 65%,
|
||||||
|
transparent 100%
|
||||||
|
);
|
||||||
|
content: "";
|
||||||
|
transform: rotate(18deg);
|
||||||
|
animation: glow-sweep 2.4s ease-in-out infinite;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes glow-sweep {
|
||||||
|
0% {
|
||||||
|
left: -70%;
|
||||||
|
}
|
||||||
|
|
||||||
|
45%,
|
||||||
|
100% {
|
||||||
|
left: 125%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes logo-spin {
|
||||||
|
from {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user