feat: NavBart RWD 製作
This commit is contained in:
parent
d1b51dcc9d
commit
458cfc7eb0
@ -13,7 +13,7 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>諾亞克 U-ARK 戰情中心</title>
|
<title>諾亞克 U-ARK 戰情中心</title>
|
||||||
</head>
|
</head>
|
||||||
<body class="w-screen bg-brand-gray-light">
|
<body class="w-screen bg-brand-gray-light font-noto text-brand-black">
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
<script type="module" src="/src/main.js"></script>
|
<script type="module" src="/src/main.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
6
jsconfig.json
Normal file
6
jsconfig.json
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"checkJs": false
|
||||||
|
},
|
||||||
|
"include": ["src/**/*.js", "src/**/*.vue", "src/types/**/*.d.ts"]
|
||||||
|
}
|
7
package-lock.json
generated
7
package-lock.json
generated
@ -10,6 +10,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^1.11.0",
|
"axios": "^1.11.0",
|
||||||
"echarts": "^6.0.0",
|
"echarts": "^6.0.0",
|
||||||
|
"leaflet": "^1.9.4",
|
||||||
"pinia": "^3.0.3",
|
"pinia": "^3.0.3",
|
||||||
"three": "^0.179.1",
|
"three": "^0.179.1",
|
||||||
"vue": "^3.5.18",
|
"vue": "^3.5.18",
|
||||||
@ -2077,6 +2078,12 @@
|
|||||||
"jiti": "bin/jiti.js"
|
"jiti": "bin/jiti.js"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/leaflet": {
|
||||||
|
"version": "1.9.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.4.tgz",
|
||||||
|
"integrity": "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA==",
|
||||||
|
"license": "BSD-2-Clause"
|
||||||
|
},
|
||||||
"node_modules/lilconfig": {
|
"node_modules/lilconfig": {
|
||||||
"version": "3.1.3",
|
"version": "3.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz",
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^1.11.0",
|
"axios": "^1.11.0",
|
||||||
"echarts": "^6.0.0",
|
"echarts": "^6.0.0",
|
||||||
|
"leaflet": "^1.9.4",
|
||||||
"pinia": "^3.0.3",
|
"pinia": "^3.0.3",
|
||||||
"three": "^0.179.1",
|
"three": "^0.179.1",
|
||||||
"vue": "^3.5.18",
|
"vue": "^3.5.18",
|
||||||
|
Before Width: | Height: | Size: 541 KiB After Width: | Height: | Size: 541 KiB |
BIN
public/img/leaflet/marker-icon-2x.png
Normal file
BIN
public/img/leaflet/marker-icon-2x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.4 KiB |
BIN
public/img/leaflet/marker-icon.png
Normal file
BIN
public/img/leaflet/marker-icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
BIN
public/img/leaflet/marker-shadow.png
Normal file
BIN
public/img/leaflet/marker-shadow.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 618 B |
@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<section id="app" class="flex flex-col min-h-screen ">
|
<section id="app" class="flex flex-col min-h-screen ">
|
||||||
<NavBar class="fixed" />
|
<NavBar class="fixed" />
|
||||||
<main class="w-full p-4 overflow-x-hidden pt-[72px] pb-4">
|
<main class="w-full p-4 overflow-x-hidden pb-4">
|
||||||
<RouterView />
|
<RouterView />
|
||||||
</main>
|
</main>
|
||||||
</section>
|
</section>
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<section id="app" class="flex flex-col min-h-screen">
|
<section id="app" class="flex flex-col min-h-screen">
|
||||||
<NavBar class="fixed" />
|
<NavBar class="fixed" />
|
||||||
|
|
||||||
<main class="w-full p-4 mt-[72px]">
|
<main class="w-full p-4">
|
||||||
<section class="grid grid-cols-7 gap-4 overflow-hidden">
|
<section class="grid grid-cols-7 gap-4 overflow-hidden">
|
||||||
<!-- 左側:地圖 -->
|
<!-- 左側:地圖 -->
|
||||||
<section class="col-span-3 bg-white/50 rounded-md shadow p-3 h-full overflow-hidden">
|
<section class="col-span-3 bg-white/50 rounded-md shadow p-3 h-full overflow-hidden">
|
||||||
|
@ -1,46 +1,48 @@
|
|||||||
<template>
|
<template>
|
||||||
<nav
|
<nav
|
||||||
class="w-full h-[64px] bg-white bg-opacity-50 shadow-md flex justify-between items-center px-8"
|
class="sticky top-0 w-full h-14 md:h-16 bg-white/70 bg-opacity-80 shadow-md flex justify-between items-center px-4 sm:px-6 lg:px-8 z-[1000]"
|
||||||
>
|
>
|
||||||
<!-- 左側 logo、選單區 -->
|
<!-- 左側:Logo + 機構切換 -->
|
||||||
<div class="flex justify-start items-center gap-12">
|
<div
|
||||||
<RouterLink to="/" class="h-[45px]">
|
class="flex items-center gap-4 sm:gap-8 shrink-0 w-[240px] md:w-[300px] lg:w-[340px]"
|
||||||
<img src="/img/logo.png" alt="Logo" class="w-full h-full" />
|
>
|
||||||
|
<RouterLink to="/" class="h-9 md:h-11">
|
||||||
|
<img src="/img/logo.png" alt="Logo" class="h-full w-auto" />
|
||||||
</RouterLink>
|
</RouterLink>
|
||||||
|
|
||||||
<div class="relative">
|
<div class="relative">
|
||||||
|
<!-- 手機到桌機都顯示機構名稱,維持桌機尺寸 -->
|
||||||
<div
|
<div
|
||||||
ref="triggerRef"
|
ref="triggerRef"
|
||||||
class="btn text-white bg-brand-green hover:opacity-90 shadow-md border-none rounded-full px-8 tracking-widest"
|
class="btn bg-brand-green text-white hover:opacity-90 shadow-md border-none rounded-full px-6 lg:px-8 h-10 gap-2"
|
||||||
role="button"
|
role="button"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
aria-haspopup="true"
|
aria-haspopup="true"
|
||||||
:aria-expanded="isOpen ? 'true' : 'false'"
|
:aria-expanded="isOpen"
|
||||||
@click="toggle"
|
@click="toggle"
|
||||||
@keydown.enter.prevent="toggle"
|
@keydown.enter.prevent="toggle"
|
||||||
@keydown.space.prevent="toggle"
|
@keydown.space.prevent="toggle"
|
||||||
>
|
>
|
||||||
{{ displayLabel }}
|
<!-- 直接顯示,不再隱藏 -->
|
||||||
<span>
|
<span>{{ displayLabel }}</span>
|
||||||
<svg
|
<!-- caret icon -->
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
<svg
|
||||||
width="16"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
height="16"
|
class="w-4 h-4"
|
||||||
viewBox="0 0 512 512"
|
viewBox="0 0 512 512"
|
||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
d="m98 190.06l139.78 163.12a24 24 0 0 0 36.44 0L414 190.06c13.34-15.57 2.28-39.62-18.22-39.62h-279.6c-20.5 0-31.56 24.05-18.18 39.62"
|
d="m98 190.06l139.78 163.12a24 24 0 0 0 36.44 0L414 190.06c13.34-15.57 2.28-39.62-18.22-39.62h-279.6c-20.5 0-31.56 24.05-18.18 39.62"
|
||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Modal:定位在按鈕右下方 -->
|
<!-- Dropdown(小螢幕靠左;桌機可改靠右) -->
|
||||||
<div
|
<div
|
||||||
v-show="isOpen"
|
v-show="isOpen"
|
||||||
ref="panelRef"
|
ref="panelRef"
|
||||||
class="absolute top-16 left-0 z-50 w-64 rounded-md border border-gray-100 bg-white shadow-lg p-2"
|
class="absolute top-12 left-0 md:top-12 md:left-0 lg:left-0 z-50 w-56 md:w-64 rounded-md border border-gray-100 bg-white shadow-lg p-2"
|
||||||
@click.stop
|
@click.stop
|
||||||
>
|
>
|
||||||
<ul class="max-h-48 overflow-y-auto text-brand-black">
|
<ul class="max-h-48 overflow-y-auto text-brand-black">
|
||||||
@ -58,22 +60,20 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 中間 導覽按鈕區 -->
|
<!-- 中間:導覽(手機隱藏;平板以上顯示;桌機放大間距) -->
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="min-w-[300px] text-brand-black bg-white shadow-md rounded-full grid grid-cols-3 items-center"
|
class="hidden md:grid min-w-[300px] grid-cols-3 items-center bg-white shadow-md rounded-full md:px-0 lg:min-w-[420px]"
|
||||||
>
|
>
|
||||||
<RouterLink to="/" v-slot="{ href, navigate, isExactActive }">
|
<RouterLink to="/" v-slot="{ href, navigate, isExactActive }">
|
||||||
<a
|
<a
|
||||||
:href="href"
|
:href="href"
|
||||||
@click="navigate"
|
@click="navigate"
|
||||||
:class="[
|
:class="[
|
||||||
'px-5 py-2 rounded-full flex justify-center items-center transition-colors',
|
'px-4 lg:px-6 py-2 rounded-full flex justify-center items-center transition-colors',
|
||||||
isExactActive ? 'bg-brand-green-light' : 'hover:bg-gray-100',
|
isExactActive ? 'bg-brand-green-light' : 'hover:bg-gray-100',
|
||||||
]"
|
]"
|
||||||
|
>首頁</a
|
||||||
>
|
>
|
||||||
首頁
|
|
||||||
</a>
|
|
||||||
</RouterLink>
|
</RouterLink>
|
||||||
|
|
||||||
<RouterLink to="/operation" v-slot="{ href, navigate, isActive }">
|
<RouterLink to="/operation" v-slot="{ href, navigate, isActive }">
|
||||||
@ -81,12 +81,11 @@
|
|||||||
:href="href"
|
:href="href"
|
||||||
@click="navigate"
|
@click="navigate"
|
||||||
:class="[
|
:class="[
|
||||||
'px-5 py-2 rounded-full flex justify-center items-center transition-colors',
|
'px-4 lg:px-6 py-2 rounded-full flex justify-center items-center transition-colors',
|
||||||
isActive ? 'bg-brand-green-light' : 'hover:bg-gray-100',
|
isActive ? 'bg-brand-green-light' : 'hover:bg-gray-100',
|
||||||
]"
|
]"
|
||||||
|
>營運</a
|
||||||
>
|
>
|
||||||
營運
|
|
||||||
</a>
|
|
||||||
</RouterLink>
|
</RouterLink>
|
||||||
|
|
||||||
<RouterLink to="/nursing" v-slot="{ href, navigate, isActive }">
|
<RouterLink to="/nursing" v-slot="{ href, navigate, isActive }">
|
||||||
@ -94,20 +93,21 @@
|
|||||||
:href="href"
|
:href="href"
|
||||||
@click="navigate"
|
@click="navigate"
|
||||||
:class="[
|
:class="[
|
||||||
'px-5 py-2 rounded-full flex justify-center items-center transition-colors',
|
'px-4 lg:px-6 py-2 rounded-full flex justify-center items-center transition-colors',
|
||||||
isActive ? 'bg-brand-green-light' : 'hover:bg-gray-100',
|
isActive ? 'bg-brand-green-light' : 'hover:bg-gray-100',
|
||||||
]"
|
]"
|
||||||
|
>照護</a
|
||||||
>
|
>
|
||||||
照護
|
|
||||||
</a>
|
|
||||||
</RouterLink>
|
</RouterLink>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 右側 登入區 -->
|
<!-- 右側:通知 + 使用者(手機只顯示圖示;平板顯示文字) -->
|
||||||
<div class="flex justify-end items-center gap-8">
|
<div class="hidden md:flex items-center gap-3 sm:gap-6">
|
||||||
<div
|
<button
|
||||||
class="btn text-brand-black bg-white hover:opacity-90 shadow-md border-none rounded-full p-2 flex justify-center items-center"
|
class="btn bg-white text-brand-black hover:opacity-90 shadow-md border-none rounded-full p-2"
|
||||||
|
aria-label="通知"
|
||||||
>
|
>
|
||||||
|
<!-- 鈴鐺 -->
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
width="24"
|
width="24"
|
||||||
@ -119,71 +119,262 @@
|
|||||||
d="M8 2a4.5 4.5 0 0 0-4.5 4.5v2.401l-.964 2.414A.5.5 0 0 0 3 12h3c0 1.108.892 2 2 2s2-.892 2-2h3a.5.5 0 0 0 .464-.685L12.5 8.9V6.5A4.5 4.5 0 0 0 8 2m1 10c0 .556-.444 1-1 1s-1-.444-1-1zM4.5 6.5a3.5 3.5 0 1 1 7 0v2.498a.5.5 0 0 0 .036.185L12.262 11H3.738l.726-1.817a.5.5 0 0 0 .036-.185z"
|
d="M8 2a4.5 4.5 0 0 0-4.5 4.5v2.401l-.964 2.414A.5.5 0 0 0 3 12h3c0 1.108.892 2 2 2s2-.892 2-2h3a.5.5 0 0 0 .464-.685L12.5 8.9V6.5A4.5 4.5 0 0 0 8 2m1 10c0 .556-.444 1-1 1s-1-.444-1-1zM4.5 6.5a3.5 3.5 0 1 1 7 0v2.498a.5.5 0 0 0 .036.185L12.262 11H3.738l.726-1.817a.5.5 0 0 0 .036-.185z"
|
||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</button>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="btn text-brand-black bg-white hover:opacity-90 shadow-md border-none rounded-full px-6 flex justify-center items-center gap-3"
|
class="btn bg-white text-brand-black hover:opacity-90 shadow-md border-none rounded-full px-3 md:px-5 h-9 md:h-10 gap-2 md:gap-3"
|
||||||
>
|
>
|
||||||
<span>
|
<svg
|
||||||
<svg
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
class="w-4 h-4 md:w-5 md:h-5"
|
||||||
width="16"
|
viewBox="0 0 16 16"
|
||||||
height="16"
|
>
|
||||||
viewBox="0 0 16 16"
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M11 7c0 1.66-1.34 3-3 3S5 8.66 5 7s1.34-3 3-3s3 1.34 3 3"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
fill-rule="evenodd"
|
||||||
|
d="M16 8c0 4.42-3.58 8-8 8s-8-3.58-8-8s3.58-8 8-8s8 3.58 8 8M4 13.75C4.16 13.484 5.71 11 7.99 11c2.27 0 3.83 2.49 3.99 2.75A6.98 6.98 0 0 0 14.99 8c0-3.87-3.13-7-7-7s-7 3.13-7 7c0 2.38 1.19 4.49 3.01 5.75"
|
||||||
|
clip-rule="evenodd"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<p class="hidden md:inline">使用者</p>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
class="hidden md:block w-4 h-4"
|
||||||
|
viewBox="0 0 512 512"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="m98 190.06l139.78 163.12a24 24 0 0 0 36.44 0L414 190.06c13.34-15.57 2.28-39.62-18.22-39.62h-279.6c-20.5 0-31.56 24.05-18.18 39.62"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 手機:漢堡按鈕-->
|
||||||
|
<button
|
||||||
|
class="md:hidden btn bg-white text-brand-black hover:opacity-90 shadow-md border-none rounded-md p-2"
|
||||||
|
@click="toggleMobileMenu"
|
||||||
|
:aria-expanded="isMobileMenuOpen"
|
||||||
|
aria-controls="mobile-menu"
|
||||||
|
:aria-label="isMobileMenuOpen ? '關閉主選單' : '開啟主選單'"
|
||||||
|
>
|
||||||
|
<!-- 關閉(叉叉) -->
|
||||||
|
<svg
|
||||||
|
v-if="isMobileMenuOpen"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
class="w-6 h-6"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="m12 10.586l4.95-4.95l1.414 1.414L13.414 12l4.95 4.95l-1.414 1.414L12 13.414l-4.95 4.95l-1.414-1.414L10.586 12l-4.95-4.95l1.414-1.414z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<!-- 漢堡 -->
|
||||||
|
<svg
|
||||||
|
v-else
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
class="w-6 h-6"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path fill="currentColor" d="M3 6h18v2H3zm0 5h18v2H3zm0 5h18v2H3z" />
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<!-- 手機:全螢幕 ham menu(白底,hover 灰,active 綠) -->
|
||||||
|
<div
|
||||||
|
id="mobile-menu"
|
||||||
|
class="md:hidden fixed inset-0 z-[1100] bg-white p-4 flex flex-col gap-4 transition-opacity duration-200"
|
||||||
|
:class="
|
||||||
|
isMobileMenuOpen
|
||||||
|
? 'opacity-100 pointer-events-auto'
|
||||||
|
: 'opacity-0 pointer-events-none'
|
||||||
|
"
|
||||||
|
role="dialog"
|
||||||
|
aria-modal="true"
|
||||||
|
aria-label="主選單"
|
||||||
|
@keydown.esc.prevent="closeMobileMenu"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
v-show="isMobileMenuOpen"
|
||||||
|
id="mobile-menu"
|
||||||
|
class="md:hidden fixed inset-0 z-[1100] bg-white p-4 flex flex-col gap-4"
|
||||||
|
role="dialog"
|
||||||
|
aria-modal="true"
|
||||||
|
aria-label="主選單"
|
||||||
|
@keydown.esc.prevent="closeMobileMenu"
|
||||||
|
>
|
||||||
|
<!-- 頂部:標題 + 叉叉(和右上按鈕行為一致) -->
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<p class="font-semibold text-brand-black text-base">選單</p>
|
||||||
|
<button
|
||||||
|
class="btn btn-sm bg-white border-none shadow text-brand-black"
|
||||||
|
@click="closeMobileMenu"
|
||||||
|
aria-label="關閉主選單"
|
||||||
>
|
>
|
||||||
<path
|
<svg
|
||||||
fill="currentColor"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
d="M11 7c0 1.66-1.34 3-3 3S5 8.66 5 7s1.34-3 3-3s3 1.34 3 3"
|
class="w-5 h-5"
|
||||||
/>
|
viewBox="0 0 24 24"
|
||||||
<path
|
>
|
||||||
fill="currentColor"
|
<path
|
||||||
fill-rule="evenodd"
|
fill="currentColor"
|
||||||
d="M16 8c0 4.42-3.58 8-8 8s-8-3.58-8-8s3.58-8 8-8s8 3.58 8 8M4 13.75C4.16 13.484 5.71 11 7.99 11c2.27 0 3.83 2.49 3.99 2.75A6.98 6.98 0 0 0 14.99 8c0-3.87-3.13-7-7-7s-7 3.13-7 7c0 2.38 1.19 4.49 3.01 5.75"
|
d="m12 10.586l4.95-4.95l1.414 1.414L13.414 12l4.95 4.95l-1.414 1.414L12 13.414l-4.95 4.95l-1.414-1.414L10.586 12l-4.95-4.95l1.414-1.414z"
|
||||||
clip-rule="evenodd"
|
/>
|
||||||
/>
|
</svg>
|
||||||
</svg>
|
</button>
|
||||||
</span>
|
</div>
|
||||||
<p>使用者</p>
|
|
||||||
<span>
|
<!-- 導覽(icon + 文字) -->
|
||||||
<svg
|
<nav class="space-y-2">
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
<RouterLink to="/" v-slot="{ href, navigate, isExactActive }">
|
||||||
width="16"
|
<a
|
||||||
height="16"
|
:href="href"
|
||||||
viewBox="0 0 512 512"
|
@click="
|
||||||
|
navigate;
|
||||||
|
closeMobileMenu();
|
||||||
|
"
|
||||||
|
:class="[
|
||||||
|
'flex items-center gap-3 rounded-lg px-3 py-3 transition-colors',
|
||||||
|
isExactActive ? 'bg-brand-green-light' : 'hover:bg-gray-100',
|
||||||
|
]"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="20"
|
||||||
|
height="20"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M4 19v-9q0-.475.213-.9t.587-.7l6-4.5q.525-.4 1.2-.4t1.2.4l6 4.5q.375.275.588.7T20 10v9q0 .825-.588 1.413T18 21h-3q-.425 0-.712-.288T14 20v-5q0-.425-.288-.712T13 14h-2q-.425 0-.712.288T10 15v5q0 .425-.288.713T9 21H6q-.825 0-1.412-.587T4 19"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<span class="text-brand-black">首頁</span>
|
||||||
|
</a>
|
||||||
|
</RouterLink>
|
||||||
|
|
||||||
|
<RouterLink to="/operation" v-slot="{ href, navigate, isActive }">
|
||||||
|
<a
|
||||||
|
:href="href"
|
||||||
|
@click="
|
||||||
|
navigate;
|
||||||
|
closeMobileMenu();
|
||||||
|
"
|
||||||
|
:class="[
|
||||||
|
'flex items-center gap-3 rounded-lg px-3 py-3 transition-colors',
|
||||||
|
isActive ? 'bg-brand-green-light' : 'hover:bg-gray-100',
|
||||||
|
]"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="20"
|
||||||
|
height="20"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M20 13.75a.75.75 0 0 0-.75-.75h-3a.75.75 0 0 0-.75.75v6.75H14V4.25c0-.728-.002-1.2-.048-1.546c-.044-.325-.115-.427-.172-.484s-.159-.128-.484-.172C12.949 2.002 12.478 2 11.75 2s-1.2.002-1.546.048c-.325.044-.427.115-.484.172s-.128.159-.172.484c-.046.347-.048.818-.048 1.546V20.5H8V8.75A.75.75 0 0 0 7.25 8h-3a.75.75 0 0 0-.75.75V20.5H1.75a.75.75 0 0 0 0 1.5h20a.75.75 0 0 0 0-1.5H20z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<span class="text-brand-black">營運</span>
|
||||||
|
</a>
|
||||||
|
</RouterLink>
|
||||||
|
|
||||||
|
<RouterLink to="/nursing" v-slot="{ href, navigate, isActive }">
|
||||||
|
<a
|
||||||
|
:href="href"
|
||||||
|
@click="
|
||||||
|
navigate;
|
||||||
|
closeMobileMenu();
|
||||||
|
"
|
||||||
|
:class="[
|
||||||
|
'flex items-center gap-3 rounded-lg px-3 py-3 transition-colors',
|
||||||
|
isActive ? 'bg-brand-green-light' : 'hover:bg-gray-100',
|
||||||
|
]"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="20"
|
||||||
|
height="20"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M22 9.95v4.11a1.78 1.78 0 0 1-1.78 1.78h-4.39v4.39a1.73 1.73 0 0 1-.52 1.25a1.8 1.8 0 0 1-1.26.52H9.94a1.8 1.8 0 0 1-1.26-.52a1.8 1.8 0 0 1-.52-1.25v-4.39H3.78A1.78 1.78 0 0 1 2 14.06V9.95a1.78 1.78 0 0 1 1.78-1.78h4.38V3.78a1.8 1.8 0 0 1 1.103-1.646A1.8 1.8 0 0 1 9.94 2H14a1.8 1.8 0 0 1 1.26.52a1.77 1.77 0 0 1 .52 1.26v4.39h4.39c.472.003.924.19 1.26.52A1.78 1.78 0 0 1 22 9.95"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<span class="text-brand-black">照護</span>
|
||||||
|
</a>
|
||||||
|
</RouterLink>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<hr class="border-gray-200" />
|
||||||
|
|
||||||
|
<!-- 通知 + 使用者(放在全螢幕 menu 內;同樣 hover 灰、active 綠) -->
|
||||||
|
<div class="space-y-2">
|
||||||
|
<button
|
||||||
|
class="w-full flex items-center gap-3 rounded-lg px-3 py-3 transition-colors hover:bg-gray-100 text-left"
|
||||||
|
@click="closeMobileMenu()"
|
||||||
>
|
>
|
||||||
<path
|
<svg
|
||||||
fill="currentColor"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
d="m98 190.06l139.78 163.12a24 24 0 0 0 36.44 0L414 190.06c13.34-15.57 2.28-39.62-18.22-39.62h-279.6c-20.5 0-31.56 24.05-18.18 39.62"
|
width="20"
|
||||||
/>
|
height="20"
|
||||||
</svg>
|
viewBox="0 0 20 20"
|
||||||
</span>
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M12.45 16.002a2.5 2.5 0 0 1-4.9 0zM9.998 2c3.149 0 5.744 2.335 5.984 5.355l.013.223l.005.224l-.001 3.606l.954 2.587l.025.085l.016.086l.005.089c0 .315-.196.59-.522.707l-.114.033l-.114.01H3.751a.8.8 0 0 1-.259-.047c-.287-.105-.476-.372-.482-.716l.004-.117l.034-.13l.95-2.584L4 7.793l.004-.225C4.127 4.451 6.771 2 9.998 2"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<span class="text-brand-black">通知</span>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button
|
||||||
|
class="w-full flex items-center gap-3 rounded-lg px-3 py-3 transition-colors hover:bg-gray-100 text-left"
|
||||||
|
@click="closeMobileMenu()"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="20"
|
||||||
|
height="20"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M7 7a5 5 0 1 1 10 0A5 5 0 0 1 7 7M3.5 19a5 5 0 0 1 5-5h7a5 5 0 0 1 5 5v2h-17z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<span class="text-brand-black">使用者</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-auto text-xs text-gray-500">© U-ARK</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed, onMounted, onUnmounted, defineOptions } from "vue";
|
import {
|
||||||
|
ref,
|
||||||
// modal 操作
|
computed,
|
||||||
const selectItem = (item) => {
|
onMounted,
|
||||||
selectedItem.value = item;
|
onUnmounted,
|
||||||
isOpen.value = false;
|
defineOptions,
|
||||||
};
|
nextTick,
|
||||||
|
} from "vue";
|
||||||
// 按鈕顯示文字(>4 字就加 …)
|
|
||||||
const displayLabel = computed(() => {
|
|
||||||
const label = String(selectedItem.value ?? "護祐");
|
|
||||||
return label.length > 4 ? label.slice(0, 4) + "..." : label;
|
|
||||||
});
|
|
||||||
|
|
||||||
defineOptions({ name: "NavBar" });
|
|
||||||
|
|
||||||
|
// ====== Dropdown(機構清單)======
|
||||||
const isOpen = ref(false);
|
const isOpen = ref(false);
|
||||||
const triggerRef = ref(null);
|
const triggerRef = ref(null);
|
||||||
const panelRef = ref(null);
|
const panelRef = ref(null);
|
||||||
|
|
||||||
// 機構名稱清單
|
|
||||||
const facilities = [
|
const facilities = [
|
||||||
"總部",
|
"總部",
|
||||||
"護祐護理之家",
|
"護祐護理之家",
|
||||||
@ -200,16 +391,22 @@ const facilities = [
|
|||||||
"崇智護理之家",
|
"崇智護理之家",
|
||||||
"慈祐長照中心(養護型)",
|
"慈祐長照中心(養護型)",
|
||||||
];
|
];
|
||||||
|
|
||||||
// 預設選中第一筆(同時讓按鈕顯示第一筆、li 也保持選中底色)
|
|
||||||
const selectedItem = ref(facilities[0]);
|
const selectedItem = ref(facilities[0]);
|
||||||
|
|
||||||
// 切換開/關
|
const selectItem = (item) => {
|
||||||
|
selectedItem.value = item;
|
||||||
|
isOpen.value = false;
|
||||||
|
};
|
||||||
|
const displayLabel = computed(() => {
|
||||||
|
const label = String(selectedItem.value ?? "護祐");
|
||||||
|
return label.length > 4 ? label.slice(0, 4) + "..." : label;
|
||||||
|
});
|
||||||
|
defineOptions({ name: "NavBar" });
|
||||||
|
|
||||||
const toggle = () => {
|
const toggle = () => {
|
||||||
isOpen.value = !isOpen.value;
|
isOpen.value = !isOpen.value;
|
||||||
};
|
};
|
||||||
|
|
||||||
// 點空白處關閉
|
|
||||||
const onClickOutside = (e) => {
|
const onClickOutside = (e) => {
|
||||||
const t = e.target;
|
const t = e.target;
|
||||||
if (!triggerRef.value || !panelRef.value) return;
|
if (!triggerRef.value || !panelRef.value) return;
|
||||||
@ -220,19 +417,35 @@ const onClickOutside = (e) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Esc 關閉
|
// ====== 手機版抽屜(漢堡選單)======
|
||||||
const onKeydown = (e) => {
|
const isMobileMenuOpen = ref(false);
|
||||||
if (e.key === "Escape") isOpen.value = false;
|
const toggleMobileMenu = async () => {
|
||||||
|
isMobileMenuOpen.value = !isMobileMenuOpen.value;
|
||||||
|
if (isMobileMenuOpen.value) {
|
||||||
|
await nextTick();
|
||||||
|
// 需要的話在這裡把焦點移到關閉鈕或第一個連結
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const closeMobileMenu = () => {
|
||||||
|
isMobileMenuOpen.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
// ====== 全域鍵盤(Esc 同時關閉兩種面板)======
|
||||||
|
const handleKeydown = (e) => {
|
||||||
|
if (e.key === "Escape") {
|
||||||
|
isOpen.value = false; // 關 dropdown
|
||||||
|
isMobileMenuOpen.value = false; // 關手機抽屜
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
document.addEventListener("click", onClickOutside);
|
document.addEventListener("click", onClickOutside);
|
||||||
document.addEventListener("keydown", onKeydown);
|
document.addEventListener("keydown", handleKeydown); // ✅ 只綁一次
|
||||||
});
|
});
|
||||||
|
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
document.removeEventListener("click", onClickOutside);
|
document.removeEventListener("click", onClickOutside);
|
||||||
document.removeEventListener("keydown", onKeydown);
|
document.removeEventListener("keydown", handleKeydown); // ✅ 只解一次
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ import { createPinia } from "pinia";
|
|||||||
import './style.css'
|
import './style.css'
|
||||||
import App from './App.vue'
|
import App from './App.vue'
|
||||||
import router from './router'
|
import router from './router'
|
||||||
|
import 'leaflet/dist/leaflet.css';
|
||||||
|
|
||||||
const app = createApp(App)
|
const app = createApp(App)
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
></progress>
|
></progress>
|
||||||
|
|
||||||
<span
|
<span
|
||||||
class="pointer-events-none absolute inset-y-0 flex items-center text-[20px] font-nats text-brand-black/80"
|
class="pointer-events-none absolute bottom-0 flex items-center text-[20px] font-nats text-brand-black/80"
|
||||||
:class="textPosClass"
|
:class="textPosClass"
|
||||||
>
|
>
|
||||||
{{ currentLocale }} / {{ totalLocale }}
|
{{ currentLocale }} / {{ totalLocale }}
|
||||||
|
@ -1,22 +1,22 @@
|
|||||||
<template>
|
<template>
|
||||||
<section
|
<section
|
||||||
class="grid grid-cols-3 gap-2 h-[calc(100vh-72px-32px)] justify-center text-brand-black"
|
class="grid grid-cols-3 gap-2 h-[calc(100vh-72px-32px)] justify-center"
|
||||||
>
|
>
|
||||||
<!-- 左側 -->
|
<!-- 左側 -->
|
||||||
<section class="grid grid-rows-12 gap-2">
|
<section class="grid grid-rows-12 gap-2">
|
||||||
<!-- 機構照片 + 機構說明 + 核心資料 bars + chart -->
|
<!-- 機構照片 + 機構說明 + 核心資料 bars + chart -->
|
||||||
<section
|
<section
|
||||||
class="row-span-10 bg-white/50 rounded-md shadow py-6 px-4 flex flex-col items-start gap-4"
|
class="h-[740px] row-span-9 bg-white/50 rounded-md shadow py-6 px-4 flex flex-col items-start gap-4"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="grid grid-cols-12 justify-center items-start gap-8 "
|
class="w-full h-[400px] grid grid-cols-2 justify-center items-start gap-6 px-2"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="col-span-5 grid grid-rows-12 justify-start items-start gap-6"
|
class="w-full col-span-1 grid grid-rows-12 justify-start items-start gap-6"
|
||||||
>
|
>
|
||||||
<div class="h-[240px] row-span-6">
|
<div class="h-[240px] row-span-6">
|
||||||
<img
|
<img
|
||||||
src="/img/building_photo_headquarter.png"
|
src="/img/building/headquarter.png"
|
||||||
alt="機構照片"
|
alt="機構照片"
|
||||||
class="w-full h-full rounded-md object-cover"
|
class="w-full h-full rounded-md object-cover"
|
||||||
/>
|
/>
|
||||||
@ -28,61 +28,688 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- Progress bars -->
|
<!-- Progress bars -->
|
||||||
<div class="col-span-6 flex flex-col gap-4">
|
<div class="w-full col-span-1 flex flex-col gap-6">
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
label="現在住民/全立案床數"
|
label="現在住民/全立案床數"
|
||||||
:current="240"
|
:current="240"
|
||||||
:total="360"
|
:total="360"
|
||||||
|
|
||||||
/>
|
/>
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
label="目前空床數/全立案床數"
|
label="目前空床數/全立案床數"
|
||||||
:current="120"
|
:current="120"
|
||||||
:total="360"
|
:total="360"
|
||||||
|
|
||||||
|
|
||||||
/>
|
/>
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
label="今日住院/當月累積住院"
|
label="今日住院/當月累積住院"
|
||||||
:current="8"
|
:current="8"
|
||||||
:total="50"
|
:total="50"
|
||||||
|
|
||||||
|
|
||||||
/>
|
/>
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
label="今日新人入住/當月累積入住"
|
label="今日新人入住/當月累積入住"
|
||||||
:current="12"
|
:current="12"
|
||||||
:total="50"
|
:total="50"
|
||||||
|
|
||||||
/>
|
|
||||||
<ProgressBar
|
|
||||||
label="今日離院/累積離院"
|
|
||||||
:current="8"
|
|
||||||
:total="50"
|
|
||||||
|
|
||||||
/>
|
/>
|
||||||
|
<ProgressBar label="今日離院/累積離院" :current="8" :total="50" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="bg-black">
|
<div class="w-full h-[240px] flex justify-center items-center">
|
||||||
<!-- chart -->
|
<!-- chart -->
|
||||||
|
<div ref="chartEl" class="w-full h-full"></div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<!-- 葷/素資料 -->
|
<!-- 葷/素資料 -->
|
||||||
<section class="row-span-2 grid grid-cols-2 gap-2">
|
<section class="row-span-3 grid grid-cols-2 gap-2">
|
||||||
<div class="col-span-1 bg-white/50 rounded-md shadow p-3"></div>
|
<div class="col-span-1 bg-white/50 rounded-md shadow p-6">
|
||||||
<div class="col-span-1 bg-white/50 rounded-md shadow p-3"></div>
|
<div
|
||||||
|
class="border border-brand-yellow rounded-md w-full h-full flex flex-col justify-start items-center gap-3 p-3"
|
||||||
|
>
|
||||||
|
<div class="relative text-brand-yellow">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="90"
|
||||||
|
height="90"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M13 2.05v3.03c3.39.49 6 3.39 6 6.92c0 .9-.18 1.75-.5 2.54l2.62 1.53c.56-1.24.88-2.62.88-4.07c0-5.18-3.95-9.45-9-9.95M12 19a7 7 0 0 1-7-7c0-3.53 2.61-6.43 6-6.92V2.05c-5.06.5-9 4.76-9 9.95a10 10 0 0 0 10 10c3.3 0 6.23-1.61 8.05-4.09l-2.6-1.53A6.89 6.89 0 0 1 12 19"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<p
|
||||||
|
class="w-9 h-9 flex justify-center items-center p-2 bg-brand-yellow text-brand-black absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 rounded-full"
|
||||||
|
>
|
||||||
|
葷
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="flex gap-6">
|
||||||
|
<div class="flex flex-col justify-center items-start gap-3">
|
||||||
|
<p>總數:100</p>
|
||||||
|
<p>一般:90</p>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col justify-center items-start gap-3">
|
||||||
|
<p>碎食:5</p>
|
||||||
|
<p>管灌:5</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-span-1 bg-white/50 rounded-md shadow p-6">
|
||||||
|
<div
|
||||||
|
class="border border-brand-yellow rounded-md w-full h-full flex flex-col justify-start items-center gap-3 p-3"
|
||||||
|
>
|
||||||
|
<div class="relative text-brand-yellow">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="90"
|
||||||
|
height="90"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M13 2.05v3.03c3.39.49 6 3.39 6 6.92c0 .9-.18 1.75-.5 2.54l2.62 1.53c.56-1.24.88-2.62.88-4.07c0-5.18-3.95-9.45-9-9.95M12 19a7 7 0 0 1-7-7c0-3.53 2.61-6.43 6-6.92V2.05c-5.06.5-9 4.76-9 9.95a10 10 0 0 0 10 10c3.3 0 6.23-1.61 8.05-4.09l-2.6-1.53A6.89 6.89 0 0 1 12 19"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<p
|
||||||
|
class="w-9 h-9 flex justify-center items-center p-2 bg-brand-yellow text-brand-black absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 rounded-full"
|
||||||
|
>
|
||||||
|
素
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="flex gap-6">
|
||||||
|
<div class="flex flex-col justify-center items-start gap-3">
|
||||||
|
<p>總數:100</p>
|
||||||
|
<p>一般:90</p>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col justify-center items-start gap-3">
|
||||||
|
<p>碎食:5</p>
|
||||||
|
<p>管灌:5</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</section>
|
</section>
|
||||||
<!-- 中間 -->
|
<!-- 中間 -->
|
||||||
<section class="bg-white/50 rounded-md shadow p-3"></section>
|
<section class="bg-white/50 rounded-md shadow p-3">
|
||||||
|
<div ref="mapEl" class="w-full h-full rounded-md overflow-hidden"></div>
|
||||||
|
</section>
|
||||||
<!-- 右側 -->
|
<!-- 右側 -->
|
||||||
<section class="bg-white/50 rounded-md shadow p-3"></section>
|
<section class="bg-white/50 rounded-md shadow p-3 flex flex-col gap-2">
|
||||||
|
<!-- 表格 今日活動 -->
|
||||||
|
<section class="rounded-md shadow p-3 flex flex-col min-h-0 gap-3">
|
||||||
|
<h3 class="text-xl font-bold">今日活動</h3>
|
||||||
|
<!-- 可捲動內容區(水平) -->
|
||||||
|
<div class="flex flex-col gap-4 mb-6">
|
||||||
|
<div class="w-full overflow-x-auto overflow-y-auto">
|
||||||
|
<table class="table whitespace-nowrap">
|
||||||
|
<thead
|
||||||
|
class="bg-brand-gray-light text-brand-black sticky top-0 z-[1]"
|
||||||
|
>
|
||||||
|
<tr>
|
||||||
|
<th class="w-[120px]">時間</th>
|
||||||
|
<th class="w-[160px]">機構</th>
|
||||||
|
<th class="w-[160px]">活動名稱</th>
|
||||||
|
<th class="w-[120px] text-center">操作</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr
|
||||||
|
v-for="row in pagedRows"
|
||||||
|
:key="row.id"
|
||||||
|
class="transition-colors duration-150 hover:bg-brand-gray-light focus-visible:bg-gray-100/70"
|
||||||
|
>
|
||||||
|
<td>{{ row.time }}</td>
|
||||||
|
<td>{{ row.org }}</td>
|
||||||
|
<td class="truncate">{{ row.title }}</td>
|
||||||
|
<td class="text-center">
|
||||||
|
<button
|
||||||
|
class="btn btn-link btn-xs px-0 text-brand-purple-dark !no-underline hover:!no-underline hover:opacity-80 focus-visible:!no-underline"
|
||||||
|
@click="viewDetail(row)"
|
||||||
|
>
|
||||||
|
查看詳情
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- 分頁 -->
|
||||||
|
<div class="mt-3 flex items-center justify-between px-3">
|
||||||
|
<span class="text-sm text-gray-500">
|
||||||
|
共 {{ total }} 筆,每頁 {{ pageSize }} 筆
|
||||||
|
</span>
|
||||||
|
<div class="inline-flex items-center gap-2">
|
||||||
|
<button
|
||||||
|
class="btn btn-sm btn-outline disabled:!opacity-100 disabled:!text-gray-500 disabled:!border-gray-300 disabled:cursor-not-allowed"
|
||||||
|
:disabled="currentPage === 1"
|
||||||
|
@click="currentPage--"
|
||||||
|
>
|
||||||
|
上一頁
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<span class="px-2 text-sm tabular-nums text-brand-purple-dark">
|
||||||
|
{{ currentPage }} / {{ totalPages }}
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<button
|
||||||
|
class="btn btn-sm btn-outline disabled:!opacity-100 disabled:!text-gray-500 disabled:!border-gray-300 disabled:cursor-not-allowed"
|
||||||
|
:disabled="currentPage === totalPages"
|
||||||
|
@click="currentPage++"
|
||||||
|
>
|
||||||
|
下一頁
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<!-- 表格 今日異常事件 -->
|
||||||
|
<section class="rounded-md shadow p-3 flex flex-col min-h-0 gap-3">
|
||||||
|
<h3 class="text-xl font-bold">今日異常事件</h3>
|
||||||
|
<!-- 可捲動內容區(水平) -->
|
||||||
|
<div class="flex flex-col gap-4 mb-6">
|
||||||
|
<div class="w-full overflow-x-auto overflow-y-auto">
|
||||||
|
<table class="table whitespace-nowrap">
|
||||||
|
<thead
|
||||||
|
class="bg-brand-gray-light text-brand-black sticky top-0 z-[1]"
|
||||||
|
>
|
||||||
|
<tr>
|
||||||
|
<th class="w-[100px]">時間</th>
|
||||||
|
<th class="w-[160px]">機構</th>
|
||||||
|
<th class="w-[180px]">事件</th>
|
||||||
|
|
||||||
|
<th class="w-[120px] text-center">查看詳情</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tbody>
|
||||||
|
<tr
|
||||||
|
v-for="row in pagedIncidentRows"
|
||||||
|
:key="row.id"
|
||||||
|
class="transition-colors duration-150 hover:bg-brand-gray-light focus-visible:bg-gray-100/70"
|
||||||
|
>
|
||||||
|
<td>{{ row.time }}</td>
|
||||||
|
<td class="truncate" :title="row.org">{{ row.org }}</td>
|
||||||
|
<td class="truncate" :title="row.event">{{ row.event }}</td>
|
||||||
|
|
||||||
|
<td class="text-center">
|
||||||
|
<button
|
||||||
|
class="btn btn-link btn-xs px-0 text-brand-purple-dark !no-underline hover:!no-underline hover:opacity-80 focus-visible:!no-underline"
|
||||||
|
@click="viewDetailIncident(row)"
|
||||||
|
>
|
||||||
|
查看詳情
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 分頁(固定在底) -->
|
||||||
|
<div class="mt-3 flex items-center justify-between">
|
||||||
|
<span class="ml-3 text-sm text-gray-500">
|
||||||
|
共 {{ incidentTotal }} 筆,每頁 {{ incidentPageSize }} 筆
|
||||||
|
</span>
|
||||||
|
<div class="inline-flex items-center gap-2">
|
||||||
|
<button
|
||||||
|
class="btn btn-sm btn-outline disabled:!opacity-100 disabled:!text-gray-500 disabled:!border-gray-300 disabled:cursor-not-allowed"
|
||||||
|
:disabled="currentPage === 1"
|
||||||
|
@click="currentPage--"
|
||||||
|
>
|
||||||
|
上一頁
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<span class="px-2 text-sm tabular-nums text-brand-purple-dark">
|
||||||
|
{{ currentPage }} / {{ totalPages }}
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<button
|
||||||
|
class="btn btn-sm btn-outline disabled:!opacity-100 disabled:!text-gray-500 disabled:!border-gray-300 disabled:cursor-not-allowed"
|
||||||
|
:disabled="currentPage === totalPages"
|
||||||
|
@click="currentPage++"
|
||||||
|
>
|
||||||
|
下一頁
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<!-- 表格 今日派車總表 -->
|
||||||
|
<section class="rounded-md shadow p-3 flex flex-col min-h-0 gap-3">
|
||||||
|
<h3 class="text-xl font-bold">今日派車總表</h3>
|
||||||
|
|
||||||
|
<!-- 可捲動內容區(水平) -->
|
||||||
|
<div class="flex flex-col gap-4 mb-6">
|
||||||
|
<div class="w-full overflow-x-auto">
|
||||||
|
<table class="table whitespace-nowrap">
|
||||||
|
<thead
|
||||||
|
class="bg-brand-gray-light text-brand-black sticky top-0 z-[1]"
|
||||||
|
>
|
||||||
|
<tr>
|
||||||
|
<th class="w-[120px]">時間</th>
|
||||||
|
<th class="w-[160px]">機構</th>
|
||||||
|
<th class="w-[120px]">聯絡人</th>
|
||||||
|
<th class="w-[120px] text-center">操作</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tbody>
|
||||||
|
<tr
|
||||||
|
v-for="row in pagedDispatchRows"
|
||||||
|
:key="row.id"
|
||||||
|
class="transition-colors duration-150 hover:bg-brand-gray-light focus-visible:bg-gray-100/70"
|
||||||
|
>
|
||||||
|
<td>{{ row.time }}</td>
|
||||||
|
<td class="truncate" :title="row.org">{{ row.org }}</td>
|
||||||
|
<td class="truncate" :title="row.contact">
|
||||||
|
{{ row.contact }}
|
||||||
|
</td>
|
||||||
|
<td class="text-center">
|
||||||
|
<button
|
||||||
|
class="btn btn-link btn-xs px-0 text-brand-purple-dark !no-underline hover:!no-underline hover:opacity-80 focus-visible:!no-underline"
|
||||||
|
@click="viewDispatchDetail(row)"
|
||||||
|
>
|
||||||
|
查看詳情
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 分頁(固定在底) -->
|
||||||
|
<div class="mt-3 flex items-center justify-between">
|
||||||
|
<span class="ml-3 text-sm text-gray-500">
|
||||||
|
共 {{ dispatchTotal }} 筆,每頁 {{ dispatchPageSize }} 筆
|
||||||
|
</span>
|
||||||
|
<div class="inline-flex items-center">
|
||||||
|
<button
|
||||||
|
class="btn btn-sm btn-outline disabled:!opacity-100 disabled:!text-gray-500 disabled:!border-gray-300 disabled:cursor-not-allowed"
|
||||||
|
:disabled="currentPage === 1"
|
||||||
|
@click="currentPage--"
|
||||||
|
>
|
||||||
|
上一頁
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<span class="px-2 text-sm tabular-nums text-brand-purple-dark">
|
||||||
|
{{ currentPage }} / {{ totalPages }}
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<button
|
||||||
|
class="btn btn-sm btn-outline disabled:!opacity-100 disabled:!text-gray-500 disabled:!border-gray-300 disabled:cursor-not-allowed"
|
||||||
|
:disabled="currentPage === totalPages"
|
||||||
|
@click="currentPage++"
|
||||||
|
>
|
||||||
|
下一頁
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</section>
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import ProgressBar from "./ProgressBar.vue";
|
import ProgressBar from "./ProgressBar.vue";
|
||||||
|
import { ref, computed, onMounted, onBeforeUnmount } from "vue";
|
||||||
|
import * as echarts from "echarts";
|
||||||
|
import L from "leaflet";
|
||||||
|
import "leaflet/dist/leaflet.css";
|
||||||
|
import { brand } from "@/styles/palette";
|
||||||
|
|
||||||
|
// 產生最近 7 天的標籤(M/D)
|
||||||
|
function last7DaysLabels() {
|
||||||
|
const labels = [];
|
||||||
|
const now = new Date();
|
||||||
|
for (let i = 6; i >= 0; i--) {
|
||||||
|
const d = new Date(now);
|
||||||
|
d.setDate(now.getDate() - i);
|
||||||
|
labels.push(`${d.getMonth() + 1}/${d.getDate()}`);
|
||||||
|
}
|
||||||
|
return labels;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Demo 資料(0~100,可換成你的實際資料)
|
||||||
|
const dataA = [15, 58, 25, 75, 90, 38, 76];
|
||||||
|
const dataB = [26, 78, 85, 32, 30, 52, 72];
|
||||||
|
|
||||||
|
const chartEl = ref(null);
|
||||||
|
let chart;
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
if (!chartEl.value) return;
|
||||||
|
chart = echarts.init(chartEl.value);
|
||||||
|
|
||||||
|
const labels = last7DaysLabels();
|
||||||
|
|
||||||
|
chart.setOption({
|
||||||
|
color: [brand.green, brand.purple], // 藍、綠(可換你的品牌色)
|
||||||
|
tooltip: {
|
||||||
|
trigger: "axis",
|
||||||
|
axisPointer: { type: "line" },
|
||||||
|
confine: true,
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
bottom: 8,
|
||||||
|
icon: "circle",
|
||||||
|
itemWidth: 10,
|
||||||
|
itemHeight: 10,
|
||||||
|
itemGap: 24,
|
||||||
|
textStyle: { color: brand.gray },
|
||||||
|
data: ["現在住民", "全立案人數"],
|
||||||
|
},
|
||||||
|
grid: { left: 36, right: 16, top: 16, bottom: 48, containLabel: true },
|
||||||
|
xAxis: {
|
||||||
|
type: "category",
|
||||||
|
boundaryGap: false,
|
||||||
|
data: labels,
|
||||||
|
axisLine: { lineStyle: { color: brand.gray } },
|
||||||
|
axisTick: { show: false },
|
||||||
|
axisLabel: { color: brand.gray },
|
||||||
|
splitLine: { show: false },
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: "value",
|
||||||
|
min: 0,
|
||||||
|
max: 100,
|
||||||
|
interval: 20,
|
||||||
|
axisLine: { show: false },
|
||||||
|
axisTick: { show: false },
|
||||||
|
axisLabel: { color: brand.gray },
|
||||||
|
splitLine: {
|
||||||
|
show: true,
|
||||||
|
lineStyle: { color: brand.grayLight },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: "現在住民",
|
||||||
|
type: "line",
|
||||||
|
data: dataA,
|
||||||
|
symbol: "circle",
|
||||||
|
symbolSize: 6,
|
||||||
|
lineStyle: { width: 2 },
|
||||||
|
itemStyle: { opacity: 1 },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "全立案人數",
|
||||||
|
type: "line",
|
||||||
|
data: dataB,
|
||||||
|
symbol: "circle",
|
||||||
|
symbolSize: 6,
|
||||||
|
lineStyle: { width: 2 },
|
||||||
|
itemStyle: { opacity: 1 },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
animationDuration: 500,
|
||||||
|
});
|
||||||
|
|
||||||
|
// RWD
|
||||||
|
const onResize = () => chart?.resize();
|
||||||
|
window.addEventListener("resize", onResize);
|
||||||
|
|
||||||
|
chart.__onResize = onResize;
|
||||||
|
});
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
if (chart) {
|
||||||
|
window.removeEventListener("resize", chart.__onResize);
|
||||||
|
chart.dispose();
|
||||||
|
chart = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 以 BASE_URL 為前綴,避免根目錄/子目錄路徑差異
|
||||||
|
const base = import.meta.env.BASE_URL;
|
||||||
|
const iconBase = `${base}img/leaflet/`;
|
||||||
|
|
||||||
|
const defaultIcon = L.icon({
|
||||||
|
iconUrl: `${iconBase}marker-icon.png`,
|
||||||
|
iconRetinaUrl: `${iconBase}marker-icon-2x.png`,
|
||||||
|
shadowUrl: `${iconBase}marker-shadow.png`,
|
||||||
|
iconSize: [25, 41],
|
||||||
|
iconAnchor: [12, 41],
|
||||||
|
popupAnchor: [1, -34],
|
||||||
|
shadowSize: [41, 41],
|
||||||
|
});
|
||||||
|
|
||||||
|
L.Marker.prototype.options.icon = defaultIcon;
|
||||||
|
|
||||||
|
const mapEl = ref(null);
|
||||||
|
let map = null;
|
||||||
|
|
||||||
|
// 2) 高雄「緊」與「鬆」的範圍
|
||||||
|
const KAOHSIUNG_BOUNDS_TIGHT = L.latLngBounds(
|
||||||
|
[22.45, 120.15], // SW
|
||||||
|
[22.95, 120.55] // NE
|
||||||
|
);
|
||||||
|
const KAOHSIUNG_BOUNDS_LOOSE = L.latLngBounds(
|
||||||
|
[22.35, 120.0], // SW
|
||||||
|
[23.05, 120.75] // NE
|
||||||
|
);
|
||||||
|
|
||||||
|
// 3) 六個據點(固定座標,無需再發 fetch)
|
||||||
|
const LOCATIONS = [
|
||||||
|
{
|
||||||
|
name: "崇恩護理之家",
|
||||||
|
addr: "高雄市楠梓區立仁街131、133號",
|
||||||
|
lat: 22.7409648895,
|
||||||
|
lng: 120.3354644775,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "育祐護理之家",
|
||||||
|
addr: "高雄市楠梓區常德路317巷9弄27號",
|
||||||
|
lat: 22.7366924286,
|
||||||
|
lng: 120.3363342285,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "崇祐護理之家",
|
||||||
|
addr: "高雄市楠梓區宏昌街135、137號",
|
||||||
|
lat: 22.717588,
|
||||||
|
lng: 120.29406,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "崇智護理之家",
|
||||||
|
addr: "高雄市左營區民族一路980號",
|
||||||
|
lat: 22.678054,
|
||||||
|
lng: 120.3192,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "護祐護理之家",
|
||||||
|
addr: "高雄市三民區黃興路336號",
|
||||||
|
lat: 22.651488,
|
||||||
|
lng: 120.33731,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "傳祐長照中心",
|
||||||
|
addr: "高雄市小港區沿海一路377號",
|
||||||
|
lat: 22.5644512177,
|
||||||
|
lng: 120.3544540405,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
if (!mapEl.value) return;
|
||||||
|
|
||||||
|
map = L.map(mapEl.value, {
|
||||||
|
center: [22.6273, 120.3014],
|
||||||
|
zoom: 13,
|
||||||
|
minZoom: 12,
|
||||||
|
maxZoom: 20,
|
||||||
|
zoomSnap: 0.25,
|
||||||
|
zoomDelta: 0.25,
|
||||||
|
maxBounds: KAOHSIUNG_BOUNDS_LOOSE,
|
||||||
|
maxBoundsViscosity: 0.8,
|
||||||
|
preferCanvas: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
|
||||||
|
maxZoom: 20,
|
||||||
|
attribution:
|
||||||
|
'© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
|
||||||
|
}).addTo(map);
|
||||||
|
|
||||||
|
const ICON_H = defaultIcon.options.iconSize?.[1] ?? 41; // marker 高度
|
||||||
|
const TIP_GAP = 8; // pin 與 tooltip 的縫隙
|
||||||
|
|
||||||
|
// 建立 featureGroup 以便一次調整視野
|
||||||
|
const group = L.featureGroup();
|
||||||
|
LOCATIONS.forEach((p) => {
|
||||||
|
L.marker([p.lat, p.lng])
|
||||||
|
.addTo(group)
|
||||||
|
.bindTooltip(
|
||||||
|
`<div class="tip p-2">
|
||||||
|
|
||||||
|
<div class="flex flex-col gap-2">
|
||||||
|
<!-- 第一列:icon + 名稱-->
|
||||||
|
<div class="inline-flex justify-start items-center text-brand-purple-dark font-noto gap-1">
|
||||||
|
<span>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24">
|
||||||
|
<path fill="currentColor" d="M5 19v-8.692q0-.384.172-.727t.474-.565l5.385-4.078q.423-.323.966-.323t.972.323l5.385 4.077q.303.222.474.566q.172.343.172.727V19q0 .402-.299.701T18 20h-3.384q-.344 0-.576-.232q-.232-.233-.232-.576v-4.769q0-.343-.232-.575q-.233-.233-.576-.233h-2q-.343 0-.575.233q-.233.232-.233.575v4.77q0 .343-.232.575T9.385 20H6q-.402 0-.701-.299T5 19"/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
<strong class="text-[14px]">${p.name}</strong>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 第二列:統計卡群 -->
|
||||||
|
<div class="flex justify-center items-center gap-1">
|
||||||
|
<div class="flex flex-col justify-center items-center gap-1 border p-2 rounded-md">
|
||||||
|
<div class="text-[16px]"><strong>住民</strong></div>
|
||||||
|
<div class="font-nats text-xl text-brand-purple-dark"><p>36 / 49</p></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex flex-col justify-center items-center gap-1 border p-2 rounded-md">
|
||||||
|
<div class="text-[16px]"><strong>空床</strong></div>
|
||||||
|
<div class="font-nats text-xl text-brand-purple-dark"><p>12 / 49</p></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex flex-col justify-center items-center gap-1 border p-2 rounded-md">
|
||||||
|
<div class="text-[16px]"><strong>住院</strong></div>
|
||||||
|
<div class="font-nats text-xl text-brand-purple-dark"><p>1 / 20</p></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`,
|
||||||
|
{
|
||||||
|
permanent: true, // 常駐顯示
|
||||||
|
direction: "top", // 顯示在 pin 上方
|
||||||
|
offset: [0, -(ICON_H + TIP_GAP)],
|
||||||
|
opacity: 0.9,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
group.addTo(map);
|
||||||
|
|
||||||
|
const bounds = group.getBounds().pad(0.06);
|
||||||
|
map.fitBounds(bounds, {
|
||||||
|
paddingTopLeft: [24, 140],
|
||||||
|
paddingBottomRight: [24, 24],
|
||||||
|
maxZoom: 15,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
if (map) {
|
||||||
|
map.remove();
|
||||||
|
map = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const rows = ref([
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
time: "10:00",
|
||||||
|
org: "崇祐護理之家",
|
||||||
|
title: "全人評估相關課程",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
time: "14:00",
|
||||||
|
org: "崇祐護理之家",
|
||||||
|
title: "CPR教育訓練",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
time: "20:00",
|
||||||
|
org: "傳祐長照中心",
|
||||||
|
title: "消防夜間演練",
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 分頁參數
|
||||||
|
const pageSize = 10;
|
||||||
|
const currentPage = ref(1);
|
||||||
|
const total = computed(() => rows.value.length);
|
||||||
|
const totalPages = computed(() =>
|
||||||
|
Math.max(1, Math.ceil(total.value / pageSize))
|
||||||
|
);
|
||||||
|
|
||||||
|
const pagedRows = computed(() => {
|
||||||
|
const start = (currentPage.value - 1) * pageSize;
|
||||||
|
return rows.value.slice(start, start + pageSize);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 操作:查看詳情
|
||||||
|
function viewDetail(row) {
|
||||||
|
console.log("查看詳情:", row);
|
||||||
|
}
|
||||||
|
|
||||||
|
const incidentRows = ref([
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
time: "10:00",
|
||||||
|
org: "崇恩護理之家",
|
||||||
|
event: "跌倒事件",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
time: "12:00",
|
||||||
|
event: "延遲給藥",
|
||||||
|
org: "育祐護理之家",
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 分頁
|
||||||
|
const incidentPageSize = 10;
|
||||||
|
const incidentPage = ref(1);
|
||||||
|
const incidentTotal = computed(() => incidentRows.value.length);
|
||||||
|
const incidentTotalPages = computed(() =>
|
||||||
|
Math.max(1, Math.ceil(incidentTotal.value / incidentPageSize))
|
||||||
|
);
|
||||||
|
const pagedIncidentRows = computed(() => {
|
||||||
|
const start = (incidentPage.value - 1) * incidentPageSize;
|
||||||
|
return incidentRows.value.slice(start, start + incidentPageSize);
|
||||||
|
});
|
||||||
|
|
||||||
|
function viewDetailIncident(row) {
|
||||||
|
console.log("事件詳情:", row);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 今日派車總表
|
||||||
|
const dispatchRows = ref([
|
||||||
|
{ id: 1, time: "09:30", org: "崇恩護理之家", contact: "黃國毅" },
|
||||||
|
{ id: 2, time: "10:30", org: "育祐護理之家", contact: "李佩怡" },
|
||||||
|
{ id: 3, time: "11:30", org: "崇智護理之家", contact: "陳筱安" },
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 分頁參數
|
||||||
|
const dispatchPageSize = 10;
|
||||||
|
const dispatchPage = ref(1);
|
||||||
|
const dispatchTotal = computed(() => dispatchRows.value.length);
|
||||||
|
const dispatchTotalPages = computed(() =>
|
||||||
|
Math.max(1, Math.ceil(dispatchTotal.value / dispatchPageSize))
|
||||||
|
);
|
||||||
|
const pagedDispatchRows = computed(() => {
|
||||||
|
const start = (dispatchPage.value - 1) * dispatchPageSize;
|
||||||
|
return dispatchRows.value.slice(start, start + dispatchPageSize);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 操作:查看詳情
|
||||||
|
function viewDispatchDetail(row) {
|
||||||
|
console.log("派車詳情:", row);
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped></style>
|
<style scoped></style>
|
||||||
|
@ -157,3 +157,10 @@ body {
|
|||||||
overflow-x: hidden; /* 防止偶發橫向卷軸 */
|
overflow-x: hidden; /* 防止偶發橫向卷軸 */
|
||||||
font-family: "Noto Sans TC", sans-serif;
|
font-family: "Noto Sans TC", sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 降低 Leaflet 控制層級:預設是 1000 */
|
||||||
|
.leaflet-top,
|
||||||
|
.leaflet-bottom {
|
||||||
|
z-index: 400 !important; /* 低於你的 Nav,但仍高於地圖瓦片 */
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
export const brand = {
|
export const brand = {
|
||||||
green: "#34D5C8",
|
green: "#34D5C8",
|
||||||
greenLight: "#C4FBE5",
|
greenLight: "#C4FBE5",
|
||||||
|
greenDark:"#0CA99C",
|
||||||
red: "#FF8678",
|
red: "#FF8678",
|
||||||
purple: "#A5BEFF",
|
purple: "#A5BEFF",
|
||||||
purpleLight: "#D5E1FF",
|
purpleLight: "#D5E1FF",
|
||||||
@ -10,5 +11,6 @@ export const brand = {
|
|||||||
yellow: "#E1F391",
|
yellow: "#E1F391",
|
||||||
black: "#424242",
|
black: "#424242",
|
||||||
gray: "#828282",
|
gray: "#828282",
|
||||||
grayLight: "#F0F0F0",
|
grayLight: "#E9E9E9",
|
||||||
|
grayDark: "#D2D2D2",
|
||||||
};
|
};
|
||||||
|
@ -40,7 +40,7 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
colors: {
|
colors: {
|
||||||
brand: {
|
brand: {
|
||||||
green: { DEFAULT: "#34D5C8", light: "#C4FBE5" },
|
green: { DEFAULT: "#34D5C8", light: "#C4FBE5", dark:"#0CA99C" },
|
||||||
red: "#FF8678",
|
red: "#FF8678",
|
||||||
purple: {
|
purple: {
|
||||||
DEFAULT: "#A5BEFF",
|
DEFAULT: "#A5BEFF",
|
||||||
@ -53,9 +53,9 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
black: "#424242",
|
black: "#424242",
|
||||||
gray: {
|
gray: {
|
||||||
light: "#F0F0F0",
|
|
||||||
deepLight:"#D2D2D2",
|
|
||||||
DEFAULT: "#828282",
|
DEFAULT: "#828282",
|
||||||
|
light: "#E9E9E9",
|
||||||
|
dark: "#D2D2D2",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user