feat: 新增今日活動行事曆
This commit is contained in:
parent
d785ab54bd
commit
d5bc26e5a6
74
package-lock.json
generated
74
package-lock.json
generated
@ -8,6 +8,12 @@
|
|||||||
"name": "uark_front",
|
"name": "uark_front",
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@fullcalendar/core": "^6.1.19",
|
||||||
|
"@fullcalendar/daygrid": "^6.1.19",
|
||||||
|
"@fullcalendar/interaction": "^6.1.19",
|
||||||
|
"@fullcalendar/list": "^6.1.19",
|
||||||
|
"@fullcalendar/timegrid": "^6.1.19",
|
||||||
|
"@fullcalendar/vue3": "^6.1.19",
|
||||||
"axios": "^1.11.0",
|
"axios": "^1.11.0",
|
||||||
"echarts": "^6.0.0",
|
"echarts": "^6.0.0",
|
||||||
"leaflet": "^1.9.4",
|
"leaflet": "^1.9.4",
|
||||||
@ -534,6 +540,64 @@
|
|||||||
"node": ">=18"
|
"node": ">=18"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@fullcalendar/core": {
|
||||||
|
"version": "6.1.19",
|
||||||
|
"resolved": "https://registry.npmjs.org/@fullcalendar/core/-/core-6.1.19.tgz",
|
||||||
|
"integrity": "sha512-z0aVlO5e4Wah6p6mouM0UEqtRf1MZZPt4mwzEyU6kusaNL+dlWQgAasF2cK23hwT4cmxkEmr4inULXgpyeExdQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"preact": "~10.12.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@fullcalendar/daygrid": {
|
||||||
|
"version": "6.1.19",
|
||||||
|
"resolved": "https://registry.npmjs.org/@fullcalendar/daygrid/-/daygrid-6.1.19.tgz",
|
||||||
|
"integrity": "sha512-IAAfnMICnVWPjpT4zi87i3FEw0xxSza0avqY/HedKEz+l5MTBYvCDPOWDATpzXoLut3aACsjktIyw9thvIcRYQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"peerDependencies": {
|
||||||
|
"@fullcalendar/core": "~6.1.19"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@fullcalendar/interaction": {
|
||||||
|
"version": "6.1.19",
|
||||||
|
"resolved": "https://registry.npmjs.org/@fullcalendar/interaction/-/interaction-6.1.19.tgz",
|
||||||
|
"integrity": "sha512-GOciy79xe8JMVp+1evAU3ytdwN/7tv35t5i1vFkifiuWcQMLC/JnLg/RA2s4sYmQwoYhTw/p4GLcP0gO5B3X5w==",
|
||||||
|
"license": "MIT",
|
||||||
|
"peerDependencies": {
|
||||||
|
"@fullcalendar/core": "~6.1.19"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@fullcalendar/list": {
|
||||||
|
"version": "6.1.19",
|
||||||
|
"resolved": "https://registry.npmjs.org/@fullcalendar/list/-/list-6.1.19.tgz",
|
||||||
|
"integrity": "sha512-knZHpAVF0LbzZpSJSUmLUUzF0XlU/MRGK+Py2s0/mP93bCtno1k2L3XPs/kzh528hSjehwLm89RgKTSfW1P6cA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"peerDependencies": {
|
||||||
|
"@fullcalendar/core": "~6.1.19"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@fullcalendar/timegrid": {
|
||||||
|
"version": "6.1.19",
|
||||||
|
"resolved": "https://registry.npmjs.org/@fullcalendar/timegrid/-/timegrid-6.1.19.tgz",
|
||||||
|
"integrity": "sha512-OuzpUueyO9wB5OZ8rs7TWIoqvu4v3yEqdDxZ2VcsMldCpYJRiOe7yHWKr4ap5Tb0fs7Rjbserc/b6Nt7ol6BRg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@fullcalendar/daygrid": "~6.1.19"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@fullcalendar/core": "~6.1.19"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@fullcalendar/vue3": {
|
||||||
|
"version": "6.1.19",
|
||||||
|
"resolved": "https://registry.npmjs.org/@fullcalendar/vue3/-/vue3-6.1.19.tgz",
|
||||||
|
"integrity": "sha512-j5eUSxx0xIy3ADljo0f5B9PhjqXnCQ+7nUMPfsslc2eGVjp4F74YvY3dyd6OBbg13IvpsjowkjncGipYMQWmTA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"peerDependencies": {
|
||||||
|
"@fullcalendar/core": "~6.1.19",
|
||||||
|
"vue": "^3.0.11"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@isaacs/cliui": {
|
"node_modules/@isaacs/cliui": {
|
||||||
"version": "8.0.2",
|
"version": "8.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
|
||||||
@ -2561,6 +2625,16 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/preact": {
|
||||||
|
"version": "10.12.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/preact/-/preact-10.12.1.tgz",
|
||||||
|
"integrity": "sha512-l8386ixSsBdbreOAkqtrwqHwdvR35ID8c3rKPa8lCWuO86dBi32QWHV4vfsZK1utLLFMvw+Z5Ad4XLkZzchscg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/preact"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/proxy-from-env": {
|
"node_modules/proxy-from-env": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
||||||
|
@ -9,6 +9,12 @@
|
|||||||
"preview": "vite preview"
|
"preview": "vite preview"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@fullcalendar/core": "^6.1.19",
|
||||||
|
"@fullcalendar/daygrid": "^6.1.19",
|
||||||
|
"@fullcalendar/interaction": "^6.1.19",
|
||||||
|
"@fullcalendar/list": "^6.1.19",
|
||||||
|
"@fullcalendar/timegrid": "^6.1.19",
|
||||||
|
"@fullcalendar/vue3": "^6.1.19",
|
||||||
"axios": "^1.11.0",
|
"axios": "^1.11.0",
|
||||||
"echarts": "^6.0.0",
|
"echarts": "^6.0.0",
|
||||||
"leaflet": "^1.9.4",
|
"leaflet": "^1.9.4",
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
<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 pb-4">
|
<main class="w-full p-4 overflow-x-hidden">
|
||||||
<RouterView />
|
<RouterView class="h-[calc(100vh-72px-40px)]" />
|
||||||
</main>
|
</main>
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
<!-- 右側:路由內容 -->
|
<!-- 右側:路由內容 -->
|
||||||
<section class="col-span-4 h-full overflow-hidden">
|
<section class="col-span-4 h-full overflow-hidden">
|
||||||
<div class="w-full h-full">
|
<div class="w-full h-full">
|
||||||
<RouterView />
|
<RouterView class="h-[calc(100vh-72px-24px)]" />
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</section>
|
</section>
|
||||||
|
@ -530,19 +530,13 @@ const triggerRef = ref(null);
|
|||||||
const panelRef = ref(null);
|
const panelRef = ref(null);
|
||||||
|
|
||||||
const facilities = [
|
const facilities = [
|
||||||
"崇恩護理之家",
|
"A 機構",
|
||||||
"崇祐護理之家",
|
"B 機構",
|
||||||
"護祐護理之家",
|
"C 機構",
|
||||||
"育祐護理之家",
|
"D 機構",
|
||||||
"崇智護理之家",
|
"E 機構",
|
||||||
"崇恩居家護理所",
|
"F 機構",
|
||||||
"傳心日間照顧中心",
|
|
||||||
"敬慈居家服務中心",
|
|
||||||
"崇恩長照中心(養護型)",
|
|
||||||
"崇祐長照中心(養護型)",
|
|
||||||
"傳祐長照中心(養護型)",
|
|
||||||
"慈祐長照中心(養護型)",
|
|
||||||
"中安崇恩長照中心(養護型)",
|
|
||||||
];
|
];
|
||||||
const selectedItem = ref(facilities[0]);
|
const selectedItem = ref(facilities[0]);
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<section
|
<section
|
||||||
class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-2 lg:h-[calc(100vh-72px-32px)] h-auto justify-center overflow-anchor:none"
|
class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-2 justify-center"
|
||||||
>
|
>
|
||||||
<!-- 左側:照片/說明 + 進度條 + 圖表 + 葷素資料 -->
|
<!-- 左側:照片/說明 + 進度條 + 圖表 + 葷素資料 -->
|
||||||
<section
|
<section
|
||||||
@ -70,16 +70,16 @@
|
|||||||
</div>
|
</div>
|
||||||
<!-- 照片 + 說明(手機隱藏、平板/桌機顯示) -->
|
<!-- 照片 + 說明(手機隱藏、平板/桌機顯示) -->
|
||||||
<div
|
<div
|
||||||
class="w-full grid grid-rows-12 justify-start items-start gap-6 hidden sm:grid"
|
class="w-full grid grid-rows-12 justify-start items-start gap-4 hidden sm:grid"
|
||||||
>
|
>
|
||||||
<div class="h-[200px] row-span-6">
|
<div class="h-[230px] row-span-7">
|
||||||
<img
|
<img
|
||||||
:src="currentFacility.photo"
|
:src="currentFacility.photo"
|
||||||
alt="機構照片"
|
alt="機構照片"
|
||||||
class="w-full h-full rounded-sm object-cover"
|
class="w-full h-full rounded-sm object-cover"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="row-span-6">
|
<div class="row-span-5">
|
||||||
<p
|
<p
|
||||||
class="text-brand-gray bg-white/70 text-sm border rounded-sm px-2 py-3 border-brand-gray-light"
|
class="text-brand-gray bg-white/70 text-sm border rounded-sm px-2 py-3 border-brand-gray-light"
|
||||||
>
|
>
|
||||||
@ -90,8 +90,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Progress bars -->
|
<!-- Progress bars -->
|
||||||
<!-- Progress bars(加上 key 以觸發重新掛載;同時傳遞動畫相關 attrs 給子元件 <progress>) -->
|
<div class="w-full flex flex-col gap-5">
|
||||||
<div class="w-full flex flex-col gap-4">
|
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
:key="`residents-${selectedFacility}`"
|
:key="`residents-${selectedFacility}`"
|
||||||
label="現在住民/全立案床數"
|
label="現在住民/全立案床數"
|
||||||
@ -183,9 +182,9 @@
|
|||||||
<!-- 葷/素資料 -->
|
<!-- 葷/素資料 -->
|
||||||
<section class="row-span-3 grid grid-cols-2 gap-2">
|
<section class="row-span-3 grid grid-cols-2 gap-2">
|
||||||
<!-- 葷 -->
|
<!-- 葷 -->
|
||||||
<div class="col-span-1 bg-white/70 rounded-md shadow p-6">
|
<div class="col-span-1 bg-white/70 rounded-md shadow p-4">
|
||||||
<div
|
<div
|
||||||
class="border border-brand-yellow rounded-md w-full h-full flex flex-col justify-start items-center gap-3 p-3"
|
class="border border-brand-yellow rounded-md w-full h-full flex flex-col justify-center items-center gap-4"
|
||||||
>
|
>
|
||||||
<div class="relative text-brand-yellow">
|
<div class="relative text-brand-yellow">
|
||||||
<svg
|
<svg
|
||||||
@ -205,7 +204,7 @@
|
|||||||
葷
|
葷
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex gap-6">
|
<div class="flex gap-4">
|
||||||
<div class="flex flex-col justify-center items-start gap-3">
|
<div class="flex flex-col justify-center items-start gap-3">
|
||||||
<p>總數:{{ currentFacility.diet.meat.total }}</p>
|
<p>總數:{{ currentFacility.diet.meat.total }}</p>
|
||||||
<p>一般:{{ currentFacility.diet.meat.normal }}</p>
|
<p>一般:{{ currentFacility.diet.meat.normal }}</p>
|
||||||
@ -218,9 +217,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- 素 -->
|
<!-- 素 -->
|
||||||
<div class="col-span-1 bg-white/70 rounded-md shadow p-6">
|
<div class="col-span-1 bg-white/70 rounded-md shadow p-4">
|
||||||
<div
|
<div
|
||||||
class="border border-brand-yellow rounded-md w-full h-full flex flex-col justify-start items-center gap-3 p-3"
|
class="border border-brand-yellow rounded-md w-full h-full flex flex-col justify-center items-center gap-4"
|
||||||
>
|
>
|
||||||
<div class="relative text-brand-yellow">
|
<div class="relative text-brand-yellow">
|
||||||
<svg
|
<svg
|
||||||
@ -240,7 +239,7 @@
|
|||||||
素
|
素
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex gap-6">
|
<div class="flex gap-4">
|
||||||
<div class="flex flex-col justify-center items-start gap-3">
|
<div class="flex flex-col justify-center items-start gap-3">
|
||||||
<p>總數:{{ currentFacility.diet.veg.total }}</p>
|
<p>總數:{{ currentFacility.diet.veg.total }}</p>
|
||||||
<p>一般:{{ currentFacility.diet.veg.normal }}</p>
|
<p>一般:{{ currentFacility.diet.veg.normal }}</p>
|
||||||
@ -349,7 +348,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 地圖本體(刻意壓低 z-index) -->
|
<!-- 地圖本體 -->
|
||||||
<div
|
<div
|
||||||
ref="mapEl"
|
ref="mapEl"
|
||||||
class="relative z-[0] w-full flex-1 rounded-md overflow-hidden min-h-[300px] md:min-h-[360px] lg:min-h-[420px]"
|
class="relative z-[0] w-full flex-1 rounded-md overflow-hidden min-h-[300px] md:min-h-[360px] lg:min-h-[420px]"
|
||||||
@ -360,35 +359,47 @@
|
|||||||
<section class="flex flex-col gap-2 order-4 lg:order-3">
|
<section class="flex flex-col gap-2 order-4 lg:order-3">
|
||||||
<!-- 今日活動 -->
|
<!-- 今日活動 -->
|
||||||
<section
|
<section
|
||||||
class="bg-white/70 rounded-md shadow p-6 flex flex-col min-h-0 gap-3"
|
class="bg-white/70 rounded-md shadow p-6 flex flex-col min-h-0 gap-3 h-[360px]"
|
||||||
>
|
>
|
||||||
<h3 class="text-2xl font-bold">今日活動</h3>
|
<!-- ❶ 標題列:左右分佈 -->
|
||||||
<div class="flex flex-col gap-4 mb-6">
|
<div class="flex items-center justify-between">
|
||||||
<div class="w-full overflow-x-auto overflow-y-auto">
|
<h3 class="text-2xl font-bold">今日活動</h3>
|
||||||
<table class="table whitespace-nowrap">
|
<button
|
||||||
<thead
|
class="btn btn-sm bg-brand-green-light text-brand-black hover:bg-brand-purple-light border-none shadow rounded px-3 py-2 tracking-wider"
|
||||||
class="bg-brand-gray-lighter text-brand-black sticky top-0 z-[1]"
|
type="button"
|
||||||
>
|
@click="openCalendar()"
|
||||||
<tr>
|
aria-haspopup="dialog"
|
||||||
<th class="w-[120px]">時間</th>
|
aria-controls="calendar-modal"
|
||||||
<th class="w-[160px]">機構</th>
|
>
|
||||||
<th class="w-[160px]">活動名稱</th>
|
行事曆
|
||||||
</tr>
|
</button>
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr
|
|
||||||
v-for="row in pagedRows"
|
|
||||||
:key="row.id"
|
|
||||||
class="transition-colors duration-150 hover:bg-brand-gray-lighter focus-visible:bg-gray-100/70"
|
|
||||||
>
|
|
||||||
<td>{{ row.time }}</td>
|
|
||||||
<td>{{ row.org }}</td>
|
|
||||||
<td class="truncate">{{ row.title }}</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<!-- 表格區 -->
|
||||||
|
<div class="flex-1 overflow-y-auto">
|
||||||
|
<table class="table whitespace-nowrap">
|
||||||
|
<thead
|
||||||
|
class="bg-brand-gray-lighter text-brand-black sticky top-0 z-[1]"
|
||||||
|
>
|
||||||
|
<tr>
|
||||||
|
<th class="w-[120px]">時間</th>
|
||||||
|
<th class="w-[160px]">機構名稱</th>
|
||||||
|
<th class="w-[160px]">活動名稱</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr
|
||||||
|
v-for="row in pagedRows"
|
||||||
|
:key="row.id"
|
||||||
|
class="transition-colors duration-150 hover:bg-brand-gray-lighter focus-visible:bg-gray-100/70"
|
||||||
|
>
|
||||||
|
<td>{{ row.time }}</td>
|
||||||
|
<td>{{ row.org }}</td>
|
||||||
|
<td class="truncate">{{ row.title }}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="mt-3 flex items-center justify-between px-3">
|
<div class="mt-3 flex items-center justify-between px-3">
|
||||||
<span class="text-sm text-brand-gray"
|
<span class="text-sm text-brand-gray"
|
||||||
>共 {{ total }} 筆,每頁 {{ pageSize }} 筆</span
|
>共 {{ total }} 筆,每頁 {{ pageSize }} 筆</span
|
||||||
@ -415,37 +426,81 @@
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<!-- 今日異常事件 -->
|
<!-- FullCalendar Modal -->
|
||||||
<section
|
<transition name="fade">
|
||||||
class="bg-white/70 rounded-md shadow p-6 flex flex-col min-h-0 gap-3"
|
<div
|
||||||
>
|
v-if="isCalendarOpen"
|
||||||
<h3 class="text-2xl font-bold">今日異常事件</h3>
|
id="calendar-modal"
|
||||||
<div class="flex flex-col gap-4 mb-6">
|
role="dialog"
|
||||||
<div class="w-full overflow-x-auto overflow-y-auto">
|
aria-modal="true"
|
||||||
<table class="table whitespace-nowrap">
|
class="fixed inset-0 z-[2000] flex items-center justify-center"
|
||||||
<thead
|
@keydown.esc="closeCalendar()"
|
||||||
class="bg-brand-gray-lighter text-brand-black sticky top-0 z-[1]"
|
>
|
||||||
|
<!-- 背景遮罩 -->
|
||||||
|
<div
|
||||||
|
class="absolute inset-0 bg-black/40"
|
||||||
|
@click="closeCalendar()"
|
||||||
|
></div>
|
||||||
|
|
||||||
|
<!-- 置中面板 -->
|
||||||
|
<div
|
||||||
|
class="relative bg-white rounded-lg shadow-xl w-[48vw] max-w-6xl h-[84vh] p-6 flex flex-col gap-6"
|
||||||
|
>
|
||||||
|
<!-- FullCalendar 容器 -->
|
||||||
|
<div class="flex justify-start items-center">
|
||||||
|
<h4 class="text-2xl font-semibold">今日活動行事曆</h4>
|
||||||
|
</div>
|
||||||
|
<div class="flex-1 min-h-0">
|
||||||
|
<div
|
||||||
|
:style="[fcThemeVars, fcButtonVars, fcSizeVars]"
|
||||||
|
class="h-full w-full"
|
||||||
>
|
>
|
||||||
<tr>
|
<FullCalendar :options="calendarOptions" />
|
||||||
<th class="w-[100px]">時間</th>
|
</div>
|
||||||
<th class="w-[160px]">機構</th>
|
</div>
|
||||||
<th class="w-[100px]">事件</th>
|
<div class="flex items-center justify-end">
|
||||||
</tr>
|
<button
|
||||||
</thead>
|
class="btn btn-sm btn-outline border-brand-purple-dark text-brand-purple-dark hover:bg-brand-purple hover:text-white hover:border-brand-purple"
|
||||||
<tbody>
|
type="button"
|
||||||
<tr
|
@click="closeCalendar()"
|
||||||
v-for="row in pagedIncidentRows"
|
>
|
||||||
:key="row.id"
|
關閉
|
||||||
class="transition-colors duration-150 hover:bg-brand-gray-lighter focus-visible:bg-gray-100/70"
|
</button>
|
||||||
>
|
</div>
|
||||||
<td>{{ row.time }}</td>
|
|
||||||
<td class="truncate" :title="row.org">{{ row.org }}</td>
|
|
||||||
<td class="truncate" :title="row.event">{{ row.event }}</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</transition>
|
||||||
|
|
||||||
|
<!-- 今日異常事件 -->
|
||||||
|
<section
|
||||||
|
class="bg-white/70 rounded-md shadow p-6 flex flex-col min-h-0 gap-3 h-[360px]"
|
||||||
|
>
|
||||||
|
<h3 class="text-2xl font-bold">今日異常事件</h3>
|
||||||
|
<div class="flex-1 overflow-y-auto">
|
||||||
|
<table class="table whitespace-nowrap min-w-full">
|
||||||
|
<thead
|
||||||
|
class="bg-brand-gray-lighter text-brand-black sticky top-0 z-[1]"
|
||||||
|
>
|
||||||
|
<tr>
|
||||||
|
<th class="w-[100px]">時間</th>
|
||||||
|
<th class="w-[160px]">機構名稱</th>
|
||||||
|
<th class="w-[100px]">事件</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr
|
||||||
|
v-for="row in pagedIncidentRows"
|
||||||
|
:key="row.id"
|
||||||
|
class="hover:bg-brand-gray-lighter"
|
||||||
|
>
|
||||||
|
<td>{{ row.time }}</td>
|
||||||
|
<td class="truncate">{{ row.org }}</td>
|
||||||
|
<td class="truncate">{{ row.event }}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="mt-3 flex items-center justify-between">
|
<div class="mt-3 flex items-center justify-between">
|
||||||
<span class="ml-3 text-sm text-brand-gray"
|
<span class="ml-3 text-sm text-brand-gray"
|
||||||
>共 {{ incidentTotal }} 筆,每頁 {{ incidentPageSize }} 筆</span
|
>共 {{ incidentTotal }} 筆,每頁 {{ incidentPageSize }} 筆</span
|
||||||
@ -474,36 +529,32 @@
|
|||||||
|
|
||||||
<!-- 今日派車總表 -->
|
<!-- 今日派車總表 -->
|
||||||
<section
|
<section
|
||||||
class="bg-white/70 rounded-md shadow p-6 flex flex-col min-h-0 gap-3"
|
class="bg-white/70 rounded-md shadow p-6 flex flex-col min-h-0 gap-3 h-[360px]"
|
||||||
>
|
>
|
||||||
<h3 class="text-2xl font-bold">今日派車總表</h3>
|
<h3 class="text-2xl font-bold">今日派車總表</h3>
|
||||||
<div class="flex flex-col gap-4 mb-6">
|
<div class="flex-1 overflow-y-auto">
|
||||||
<div class="w-full overflow-x-auto">
|
<table class="table whitespace-nowrap min-w-full">
|
||||||
<table class="table whitespace-nowrap">
|
<thead
|
||||||
<thead
|
class="bg-brand-gray-lighter text-brand-black sticky top-0 z-[1]"
|
||||||
class="bg-brand-gray-lighter text-brand-black sticky top-0 z-[1]"
|
>
|
||||||
|
<tr>
|
||||||
|
<th class="w-[120px]">時間</th>
|
||||||
|
<th class="w-[160px]">機構名稱</th>
|
||||||
|
<th class="w-[120px]">聯絡人</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr
|
||||||
|
v-for="row in pagedDispatchRows"
|
||||||
|
:key="row.id"
|
||||||
|
class="hover:bg-brand-gray-lighter"
|
||||||
>
|
>
|
||||||
<tr>
|
<td>{{ row.time }}</td>
|
||||||
<th class="w-[120px]">時間</th>
|
<td class="truncate">{{ row.org }}</td>
|
||||||
<th class="w-[160px]">機構</th>
|
<td class="truncate">{{ row.contact }}</td>
|
||||||
<th class="w-[120px]">聯絡人</th>
|
</tr>
|
||||||
</tr>
|
</tbody>
|
||||||
</thead>
|
</table>
|
||||||
<tbody>
|
|
||||||
<tr
|
|
||||||
v-for="row in pagedDispatchRows"
|
|
||||||
:key="row.id"
|
|
||||||
class="transition-colors duration-150 hover:bg-brand-gray-lighter 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>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-3 flex items-center justify-between">
|
<div class="mt-3 flex items-center justify-between">
|
||||||
<span class="ml-3 text-sm text-brand-gray"
|
<span class="ml-3 text-sm text-brand-gray"
|
||||||
@ -536,6 +587,12 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
// ===== Imports =====
|
// ===== Imports =====
|
||||||
|
import FullCalendar from "@fullcalendar/vue3";
|
||||||
|
import dayGridPlugin from "@fullcalendar/daygrid";
|
||||||
|
import timeGridPlugin from "@fullcalendar/timegrid";
|
||||||
|
import interactionPlugin from "@fullcalendar/interaction";
|
||||||
|
import listPlugin from "@fullcalendar/list";
|
||||||
|
import zhTw from "@fullcalendar/core/locales/zh-tw";
|
||||||
import ProgressBar from "./ProgressBar.vue";
|
import ProgressBar from "./ProgressBar.vue";
|
||||||
import {
|
import {
|
||||||
ref,
|
ref,
|
||||||
@ -558,37 +615,37 @@ const KAOHSIUNG_BOUNDS_LOOSE = L.latLngBounds([22.35, 120.0], [23.05, 120.75]);
|
|||||||
// 六個據點(固定座標,無需發 fetch)
|
// 六個據點(固定座標,無需發 fetch)
|
||||||
const LOCATIONS = [
|
const LOCATIONS = [
|
||||||
{
|
{
|
||||||
name: "崇恩護理之家",
|
name: "A 機構",
|
||||||
addr: "高雄市楠梓區立仁街131、133號",
|
addr: "高雄市楠梓區立仁街131、133號",
|
||||||
lat: 22.7409648895,
|
lat: 22.7409648895,
|
||||||
lng: 120.3354644775,
|
lng: 120.3354644775,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "育祐護理之家",
|
name: "B 機構",
|
||||||
addr: "高雄市楠梓區常德路317巷9弄27號",
|
addr: "高雄市楠梓區常德路317巷9弄27號",
|
||||||
lat: 22.7366924286,
|
lat: 22.7366924286,
|
||||||
lng: 120.3363342285,
|
lng: 120.3363342285,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "崇祐護理之家",
|
name: "C 機構",
|
||||||
addr: "高雄市楠梓區宏昌街135、137號",
|
addr: "高雄市楠梓區宏昌街135、137號",
|
||||||
lat: 22.717588,
|
lat: 22.717588,
|
||||||
lng: 120.29406,
|
lng: 120.29406,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "崇智護理之家",
|
name: "D 機構",
|
||||||
addr: "高雄市左營區民族一路980號",
|
addr: "高雄市左營區民族一路980號",
|
||||||
lat: 22.678054,
|
lat: 22.678054,
|
||||||
lng: 120.3192,
|
lng: 120.3192,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "護祐護理之家",
|
name: "E 機構",
|
||||||
addr: "高雄市三民區黃興路336號",
|
addr: "高雄市三民區黃興路336號",
|
||||||
lat: 22.651488,
|
lat: 22.651488,
|
||||||
lng: 120.33731,
|
lng: 120.33731,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "傳祐長照中心",
|
name: "F 機構",
|
||||||
addr: "高雄市小港區沿海一路377號",
|
addr: "高雄市小港區沿海一路377號",
|
||||||
lat: 22.5644512177,
|
lat: 22.5644512177,
|
||||||
lng: 120.3544540405,
|
lng: 120.3544540405,
|
||||||
@ -601,13 +658,13 @@ const iconBase = `${base}img/leaflet/`;
|
|||||||
|
|
||||||
// building_1 = 總部,2~7 = 六家機構
|
// building_1 = 總部,2~7 = 六家機構
|
||||||
const FACILITY_ASSETS = {
|
const FACILITY_ASSETS = {
|
||||||
ALL: `${base}img/building/building_1.jpg`, // 或想用總部圖:`${base}img/building/headquarter.png`
|
ALL: `${base}img/building/building_1.jpg`, // 或想用總部圖:`${base}img/building/headquarter.png`
|
||||||
崇恩護理之家: `${base}img/building/building_2.jpg`,
|
"A 機構": `${base}img/building/building_2.jpg`,
|
||||||
育祐護理之家: `${base}img/building/building_3.jpg`,
|
"B 機構": `${base}img/building/building_3.jpg`,
|
||||||
崇祐護理之家: `${base}img/building/building_4.jpg`,
|
"C 機構": `${base}img/building/building_4.jpg`,
|
||||||
崇智護理之家: `${base}img/building/building_5.jpg`,
|
"D 機構": `${base}img/building/building_5.jpg`,
|
||||||
護祐護理之家: `${base}img/building/building_6.jpg`,
|
"E 機構": `${base}img/building/building_6.jpg`,
|
||||||
傳祐長照中心: `${base}img/building/building_7.jpg`,
|
"F 機構": `${base}img/building/building_7.jpg`,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Leaflet 預設圖標
|
// Leaflet 預設圖標
|
||||||
@ -625,8 +682,7 @@ L.Marker.prototype.options.icon = defaultIcon;
|
|||||||
// ===== Facility Mock Data (單一真實來源) =====
|
// ===== Facility Mock Data (單一真實來源) =====
|
||||||
const FACILITY_DATA = {
|
const FACILITY_DATA = {
|
||||||
ALL: {
|
ALL: {
|
||||||
photo: "/img/building/headquarter.png",
|
desc: "OO長期照顧集團——在全台各地皆有眾多據點,整合醫護團隊與專業照護人員,提供高齡照護服務總部。",
|
||||||
desc: "崇恩長期照顧集團——大南部在地深耕,整合醫護團隊與專業照護人員,提供高齡照護服務總部。",
|
|
||||||
progress: {
|
progress: {
|
||||||
residents: { current: 240, total: 360 },
|
residents: { current: 240, total: 360 },
|
||||||
vacancy: { current: 120, total: 360 },
|
vacancy: { current: 120, total: 360 },
|
||||||
@ -666,9 +722,8 @@ const FACILITY_DATA = {
|
|||||||
veg: { total: 367, normal: 318, soft: 26, tube: 23 },
|
veg: { total: 367, normal: 318, soft: 26, tube: 23 },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
崇恩護理之家: {
|
"A 機構": {
|
||||||
photo: "/img/building/chong-en.png",
|
desc: "A 機構重視跨專業合作,提供 24 小時專業護理與生活照顧服務,Lorem ipsum dolor sit amet consectetur adipisicing elit。",
|
||||||
desc: "崇恩護理之家重視跨專業合作,提供 24 小時專業護理與生活照顧服務。",
|
|
||||||
progress: {
|
progress: {
|
||||||
residents: { current: 36, total: 49 },
|
residents: { current: 36, total: 49 },
|
||||||
vacancy: { current: 12, total: 49 },
|
vacancy: { current: 12, total: 49 },
|
||||||
@ -708,9 +763,8 @@ const FACILITY_DATA = {
|
|||||||
veg: { total: 82, normal: 72, soft: 5, tube: 5 },
|
veg: { total: 82, normal: 72, soft: 5, tube: 5 },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
育祐護理之家: {
|
"B 機構": {
|
||||||
photo: "/img/building/yu-you.png",
|
desc: "B 機構以長者需求為中心,打造安全舒適的照護環境,Lorem ipsum dolor sit amet, consectetur adipisicing elit.。",
|
||||||
desc: "育祐護理之家以長者需求為中心,打造安全舒適的照護環境。",
|
|
||||||
progress: {
|
progress: {
|
||||||
residents: { current: 42, total: 60 },
|
residents: { current: 42, total: 60 },
|
||||||
vacancy: { current: 8, total: 60 },
|
vacancy: { current: 8, total: 60 },
|
||||||
@ -750,9 +804,8 @@ const FACILITY_DATA = {
|
|||||||
veg: { total: 61, normal: 53, soft: 5, tube: 3 },
|
veg: { total: 61, normal: 53, soft: 5, tube: 3 },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
崇祐護理之家: {
|
"C 機構": {
|
||||||
photo: "/img/building/chong-you.png",
|
desc: "C 機構強調復健與社會參與,陪伴長者建立日常節奏,Lorem ipsum dolor sit amet consectetur adipisicing elit。",
|
||||||
desc: "崇祐護理之家強調復健與社會參與,陪伴長者建立日常節奏。",
|
|
||||||
progress: {
|
progress: {
|
||||||
residents: { current: 50, total: 70 },
|
residents: { current: 50, total: 70 },
|
||||||
vacancy: { current: 15, total: 70 },
|
vacancy: { current: 15, total: 70 },
|
||||||
@ -792,9 +845,8 @@ const FACILITY_DATA = {
|
|||||||
veg: { total: 71, normal: 62, soft: 5, tube: 4 },
|
veg: { total: 71, normal: 62, soft: 5, tube: 4 },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
崇智護理之家: {
|
"D 機構": {
|
||||||
photo: "/img/building/chong-zhi.png",
|
desc: "D 機構導入智慧照護設備,提升照護品質與效率,Lorem ipsum dolor sit amet consectetur adipisicing elit. Porro, enim。",
|
||||||
desc: "崇智護理之家導入智慧照護設備,提升照護品質與效率。",
|
|
||||||
progress: {
|
progress: {
|
||||||
residents: { current: 38, total: 55 },
|
residents: { current: 38, total: 55 },
|
||||||
vacancy: { current: 10, total: 55 },
|
vacancy: { current: 10, total: 55 },
|
||||||
@ -834,9 +886,8 @@ const FACILITY_DATA = {
|
|||||||
veg: { total: 51, normal: 44, soft: 3, tube: 5 },
|
veg: { total: 51, normal: 44, soft: 3, tube: 5 },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
護祐護理之家: {
|
"E 機構": {
|
||||||
photo: "/img/building/hu-you.png",
|
desc: "E 機構著重個別化照護計畫,維護長者尊嚴與生活品質,Lorem ipsum dolor sit amet, consectetur adipisicing elit.。",
|
||||||
desc: "護祐護理之家著重個別化照護計畫,維護長者尊嚴與生活品質。",
|
|
||||||
progress: {
|
progress: {
|
||||||
residents: { current: 45, total: 62 },
|
residents: { current: 45, total: 62 },
|
||||||
vacancy: { current: 9, total: 62 },
|
vacancy: { current: 9, total: 62 },
|
||||||
@ -876,9 +927,8 @@ const FACILITY_DATA = {
|
|||||||
veg: { total: 57, normal: 49, soft: 5, tube: 3 },
|
veg: { total: 57, normal: 49, soft: 5, tube: 3 },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
傳祐長照中心: {
|
"F 機構": {
|
||||||
photo: "/img/building/chuan-you.png",
|
desc: "F 機構以社區融入為核心,串連日照與居家照護資源,Lorem ipsum dolor sit amet consectetur adipisicing elit. Porro, enim。",
|
||||||
desc: "傳祐長照中心以社區融入為核心,串連日照與居家照護資源。",
|
|
||||||
progress: {
|
progress: {
|
||||||
residents: { current: 30, total: 40 },
|
residents: { current: 30, total: 40 },
|
||||||
vacancy: { current: 6, total: 40 },
|
vacancy: { current: 6, total: 40 },
|
||||||
@ -931,7 +981,7 @@ const currentFacility = computed(() => {
|
|||||||
const key = selectedFacility.value || "ALL";
|
const key = selectedFacility.value || "ALL";
|
||||||
return {
|
return {
|
||||||
...data,
|
...data,
|
||||||
photo: FACILITY_ASSETS[key] || FACILITY_ASSETS.ALL,
|
photo: FACILITY_ASSETS[key] || FACILITY_ASSETS.ALL,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -1209,10 +1259,10 @@ function syncTooltips() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const m = map;
|
||||||
if (map?.invalidateSize) {
|
if (m?.invalidateSize) {
|
||||||
requestAnimationFrame(() => {
|
requestAnimationFrame(() => {
|
||||||
map.invalidateSize();
|
m?.invalidateSize?.();
|
||||||
refreshAllTooltips();
|
refreshAllTooltips();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -1269,9 +1319,10 @@ onMounted(() => {
|
|||||||
|
|
||||||
// 初始後多次 invalidateSize,避免白屏
|
// 初始後多次 invalidateSize,避免白屏
|
||||||
requestAnimationFrame(() => {
|
requestAnimationFrame(() => {
|
||||||
map?.invalidateSize?.();
|
const m = map; // 先「快照」目前的 map
|
||||||
|
m?.invalidateSize?.();
|
||||||
requestAnimationFrame(() => {
|
requestAnimationFrame(() => {
|
||||||
map?.invalidateSize?.();
|
m?.invalidateSize?.();
|
||||||
refreshAllTooltips();
|
refreshAllTooltips();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -1328,10 +1379,20 @@ watch(selectedFacility, () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// ===== Right Pane Tables (保留原有假資料與分頁) =====
|
// ===== Right Pane Tables (保留原有假資料與分頁) =====
|
||||||
|
// ====== 今日活動:擴充為六家機構的「今日」假資料 ======
|
||||||
|
const today = new Date();
|
||||||
|
const yyyy = today.getFullYear();
|
||||||
|
const mm = String(today.getMonth() + 1).padStart(2, "0");
|
||||||
|
const dd = String(today.getDate()).padStart(2, "0");
|
||||||
|
const todayISO = `${yyyy}-${mm}-${dd}`;
|
||||||
|
|
||||||
const rows = ref([
|
const rows = ref([
|
||||||
{ id: 1, time: "10:00", org: "崇祐護理之家", title: "全人評估相關課程" },
|
{ id: 1, time: "09:15", org: "A 機構", title: "全人評估相關課程" },
|
||||||
{ id: 2, time: "14:00", org: "崇祐護理之家", title: "CPR教育訓練" },
|
{ id: 2, time: "10:00", org: "B 機構", title: "CPR 教育訓練" },
|
||||||
{ id: 3, time: "20:00", org: "傳祐長照中心", title: "消防夜間演練" },
|
{ id: 3, time: "10:30", org: "C 機構", title: "消防夜間演練說明會" },
|
||||||
|
{ id: 4, time: "13:00", org: "D 機構", title: "長照照護法規研習" },
|
||||||
|
{ id: 5, time: "14:30", org: "E 機構", title: "復健團體活動" },
|
||||||
|
{ id: 6, time: "15:45", org: "F 機構", title: "營養衛教與點心時間" },
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const pageSize = 10;
|
const pageSize = 10;
|
||||||
@ -1346,10 +1407,93 @@ const pagedRows = computed(() =>
|
|||||||
(currentPage.value - 1) * pageSize + pageSize
|
(currentPage.value - 1) * pageSize + pageSize
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
// ===== FullCalendar Theme Vars(只用你的 brand)=====
|
||||||
|
const FC_FONT =
|
||||||
|
'"Noto Sans TC","Noto Sans",ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,"PingFang TC","Microsoft JhengHei",sans-serif';
|
||||||
|
|
||||||
|
// 綁到外層容器 style(會往下套用到 .fc )
|
||||||
|
const fcThemeVars = computed(() => ({
|
||||||
|
// 字體
|
||||||
|
"--fc-page-font-family": FC_FONT,
|
||||||
|
|
||||||
|
// 事件(原預設藍)
|
||||||
|
"--fc-event-bg-color": brand.purpleLight,
|
||||||
|
"--fc-event-border-color": brand.purple,
|
||||||
|
"--fc-event-text-color": brand.black,
|
||||||
|
|
||||||
|
// Buttons(左上角月/週/天/活動列表、前後/今天)
|
||||||
|
"--fc-button-text-color": brand.white,
|
||||||
|
"--fc-button-bg-color": brand.purpleDark, // 預設底色
|
||||||
|
"--fc-button-border-color": brand.purpleDark,
|
||||||
|
|
||||||
|
"--fc-button-hover-bg-color": brand.purple, // 滑過
|
||||||
|
"--fc-button-hover-border-color": brand.purple,
|
||||||
|
|
||||||
|
"--fc-button-active-bg-color": brand.purple, // 被選取(current view)
|
||||||
|
"--fc-button-active-border-color": brand.purple,
|
||||||
|
|
||||||
|
// 今天背景(原本淡黃);#RRGGBBAA 的 66 ≈ 40% 透明
|
||||||
|
"--fc-today-bg-color": `${brand.yellow}30`,
|
||||||
|
|
||||||
|
// 中性區塊/邊框/hover
|
||||||
|
"--fc-neutral-bg-color": brand.grayLighter,
|
||||||
|
"--fc-neutral-text-color": brand.gray,
|
||||||
|
"--fc-border-color": brand.grayLight,
|
||||||
|
"--fc-list-event-hover-bg-color": brand.grayLighter,
|
||||||
|
|
||||||
|
// 現在時間指示線
|
||||||
|
"--fc-now-indicator-color": brand.red,
|
||||||
|
}));
|
||||||
|
|
||||||
|
// ===== Calendar state / methods =====
|
||||||
|
const isCalendarOpen = ref(false);
|
||||||
|
const openCalendar = () => (isCalendarOpen.value = true);
|
||||||
|
const closeCalendar = () => (isCalendarOpen.value = false);
|
||||||
|
|
||||||
|
// 這裡假設你已有 todayISO / rows
|
||||||
|
const calendarEvents = computed(() =>
|
||||||
|
rows.value.map((r) => ({
|
||||||
|
id: String(r.id),
|
||||||
|
title: `[${r.org}] ${r.title}`,
|
||||||
|
start: `${todayISO}T${r.time}`,
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
|
||||||
|
const fcFontSizePx = ref(14);
|
||||||
|
const fcSizeVars = computed(() => ({
|
||||||
|
fontSize: `${fcFontSizePx.value}px`,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const fcButtonVars = computed(() => ({
|
||||||
|
"--btn-px": "12px",
|
||||||
|
"--btn-py": "8px",
|
||||||
|
"--btn-h": "32px",
|
||||||
|
"--btn-font": "14px",
|
||||||
|
"--btn-radius": "5px",
|
||||||
|
"--btn-minw": "40px",
|
||||||
|
}));
|
||||||
|
|
||||||
|
const calendarOptions = computed(() => ({
|
||||||
|
plugins: [dayGridPlugin, timeGridPlugin, interactionPlugin, listPlugin],
|
||||||
|
locale: zhTw,
|
||||||
|
initialDate: todayISO,
|
||||||
|
initialView: "listWeek", // 預設選擇「活動列表」
|
||||||
|
height: "100%",
|
||||||
|
expandRows: true,
|
||||||
|
headerToolbar: {
|
||||||
|
left: "prev,next today",
|
||||||
|
center: "title",
|
||||||
|
right: "dayGridMonth,timeGridWeek,timeGridDay,listWeek",
|
||||||
|
},
|
||||||
|
selectable: false,
|
||||||
|
editable: false,
|
||||||
|
events: calendarEvents.value,
|
||||||
|
nowIndicator: true,
|
||||||
|
}));
|
||||||
|
|
||||||
const incidentRows = ref([
|
const incidentRows = ref([
|
||||||
{ id: 1, time: "10:00", org: "崇恩護理之家", event: "跌倒事件" },
|
{ id: 1, time: "10:00", org: "B 機構", event: "跌倒事件" },
|
||||||
{ id: 2, time: "12:00", org: "育祐護理之家", event: "延遲給藥" },
|
{ id: 2, time: "12:00", org: "F 機構", event: "延遲給藥" },
|
||||||
]);
|
]);
|
||||||
const incidentPageSize = 10;
|
const incidentPageSize = 10;
|
||||||
const incidentPage = ref(1);
|
const incidentPage = ref(1);
|
||||||
@ -1365,9 +1509,9 @@ const pagedIncidentRows = computed(() =>
|
|||||||
);
|
);
|
||||||
|
|
||||||
const dispatchRows = ref([
|
const dispatchRows = ref([
|
||||||
{ id: 1, time: "09:30", org: "崇恩護理之家", contact: "黃國毅" },
|
{ id: 1, time: "09:30", org: "A 機構", contact: "黃國毅" },
|
||||||
{ id: 2, time: "10:30", org: "育祐護理之家", contact: "李佩怡" },
|
{ id: 2, time: "10:30", org: "C 機構", contact: "李佩怡" },
|
||||||
{ id: 3, time: "11:30", org: "崇智護理之家", contact: "陳筱安" },
|
{ id: 3, time: "11:30", org: "E 機構", contact: "陳筱安" },
|
||||||
]);
|
]);
|
||||||
const dispatchPageSize = 10;
|
const dispatchPageSize = 10;
|
||||||
const dispatchPage = ref(1);
|
const dispatchPage = ref(1);
|
||||||
@ -1387,11 +1531,12 @@ const pagedDispatchRows = computed(() =>
|
|||||||
function setInfoMode(mode) {
|
function setInfoMode(mode) {
|
||||||
infoMode.value = mode;
|
infoMode.value = mode;
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
if (!map) return;
|
const m = map;
|
||||||
|
if (!m) return;
|
||||||
requestAnimationFrame(() => {
|
requestAnimationFrame(() => {
|
||||||
map.invalidateSize();
|
m?.invalidateSize?.();
|
||||||
requestAnimationFrame(() => {
|
requestAnimationFrame(() => {
|
||||||
map.invalidateSize();
|
m?.invalidateSize?.();
|
||||||
refreshAllTooltips();
|
refreshAllTooltips();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -1399,4 +1544,82 @@ function setInfoMode(mode) {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped></style>
|
<style scoped>
|
||||||
|
/* 簡易轉場 */
|
||||||
|
.fade-enter-active,
|
||||||
|
.fade-leave-active {
|
||||||
|
transition: opacity 0.15s ease;
|
||||||
|
}
|
||||||
|
.fade-enter-from,
|
||||||
|
.fade-leave-to {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
/* 去掉 hover/focus 的外框/陰影,改用變數控制底色 */
|
||||||
|
:deep(.fc .fc-button:hover),
|
||||||
|
:deep(.fc .fc-button:focus),
|
||||||
|
:deep(.fc .fc-button:focus-visible) {
|
||||||
|
box-shadow: none !important;
|
||||||
|
outline: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 小動畫更順眼 */
|
||||||
|
:deep(.fc .fc-button) {
|
||||||
|
transition: background-color 0.15s ease, border-color 0.15s ease,
|
||||||
|
color 0.15s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 強化「被選取」按鈕(current view)以防某些主題覆蓋不到 */
|
||||||
|
:deep(.fc .fc-button.fc-button-active) {
|
||||||
|
background-color: var(--fc-button-active-bg-color) !important;
|
||||||
|
border-color: var(--fc-button-active-border-color) !important;
|
||||||
|
color: var(--fc-button-text-color) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 基本按鈕尺寸:用自訂變數控制 */
|
||||||
|
:deep(.fc .fc-button) {
|
||||||
|
padding: var(--btn-py) var(--btn-px);
|
||||||
|
height: var(--btn-h);
|
||||||
|
font-size: var(--btn-font);
|
||||||
|
line-height: 1; /* 防止高度被行高撐開 */
|
||||||
|
border-radius: var(--btn-radius);
|
||||||
|
transition: background-color 0.15s ease, border-color 0.15s ease,
|
||||||
|
color 0.15s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 視圖切換那一排(⽉/週/天/活動列表)統一寬度 */
|
||||||
|
:deep(.fc .fc-toolbar .fc-button-group .fc-button) {
|
||||||
|
min-width: var(--btn-minw);
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 上一週 / 下一週:做成正方形 icon 鈕 */
|
||||||
|
:deep(.fc .fc-prev-button),
|
||||||
|
:deep(.fc .fc-next-button) {
|
||||||
|
width: var(--btn-h);
|
||||||
|
padding: 0; /* 讓寬高精準=btn-h */
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 調整箭頭圖示大小(FullCalendar 內建 .fc-icon) */
|
||||||
|
:deep(.fc .fc-button .fc-icon) {
|
||||||
|
font-size: var(--btn-icon);
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 「今天」按鈕可自由跟其他一致(也能給不同 min-width) */
|
||||||
|
:deep(.fc .fc-today-button) {
|
||||||
|
min-width: calc(var(--btn-minw) - 20px);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 先前做過:去掉 hover/focus 黑框 */
|
||||||
|
:deep(.fc .fc-button:hover),
|
||||||
|
:deep(.fc .fc-button:focus),
|
||||||
|
:deep(.fc .fc-button:focus-visible) {
|
||||||
|
box-shadow: none !important;
|
||||||
|
outline: none !important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<section
|
<section
|
||||||
class="flex flex-col gap-2 h-[calc(100vh-72px-32px)] overflow-hidden text-brand-black"
|
class="flex flex-col gap-2 overflow-hidden text-brand-black"
|
||||||
>
|
>
|
||||||
<!-- 高度比重:2 -->
|
<!-- 高度比重:2 -->
|
||||||
<section class="flex-[2] grid grid-cols-3 gap-2">
|
<section class="flex-[2] grid grid-cols-3 gap-2">
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<section
|
<section
|
||||||
class="flex flex-col gap-2 h-[calc(100vh-72px-32px)] overflow-hidden"
|
class="flex flex-col gap-2 overflow-hidden"
|
||||||
>
|
>
|
||||||
<!-- 高度比重:2 -->
|
<!-- 高度比重:2 -->
|
||||||
<div class="flex-[2] grid grid-cols-3 gap-2">
|
<div class="flex-[2] grid grid-cols-3 gap-2">
|
||||||
|
@ -2,6 +2,10 @@
|
|||||||
@tailwind components;
|
@tailwind components;
|
||||||
@tailwind utilities;
|
@tailwind utilities;
|
||||||
@plugin "daisyui";
|
@plugin "daisyui";
|
||||||
|
@import "@fullcalendar/core/index.css";
|
||||||
|
@import "@fullcalendar/daygrid/index.css";
|
||||||
|
@import "@fullcalendar/timegrid/index.css";
|
||||||
|
@import "@fullcalendar/list/index.css";
|
||||||
|
|
||||||
/* 匯入 Noto Sans TC 所有字重 */
|
/* 匯入 Noto Sans TC 所有字重 */
|
||||||
@font-face {
|
@font-face {
|
||||||
|
Loading…
Reference in New Issue
Block a user