feat: 新增大戰情首頁
This commit is contained in:
parent
cb74fdb0f2
commit
d1b51dcc9d
@ -13,7 +13,7 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>諾亞克 U-ARK 戰情中心</title>
|
||||
</head>
|
||||
<body class="w-screen bg-brand-neutral">
|
||||
<body class="w-screen bg-brand-gray-light">
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.js"></script>
|
||||
</body>
|
||||
|
BIN
public/img/building_photo_headquarter.png
Normal file
BIN
public/img/building_photo_headquarter.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 541 KiB |
53
src/App.vue
53
src/App.vue
@ -1,42 +1,23 @@
|
||||
<template>
|
||||
<section id="app" class="flex flex-col min-h-screen">
|
||||
<NavBar />
|
||||
|
||||
<!-- 兩欄 Grid,各佔 50% -->
|
||||
<section class="w-full px-4 py-4">
|
||||
<div
|
||||
class="grid grid-cols-7 gap-4 h-[calc(100vh-72px-32px)] overflow-hidden"
|
||||
>
|
||||
<!-- 左側:地圖區 -->
|
||||
<section
|
||||
class="col-span-3 bg-white bg-opacity-50 rounded-xl shadow p-3 h-full overflow-hidden"
|
||||
>
|
||||
<div
|
||||
class="w-full h-full flex items-center justify-center text-gray-500"
|
||||
>
|
||||
<Forge />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 右側:路由切換內容(預留;不滾動) -->
|
||||
<main class="col-span-4 h-full overflow-hidden">
|
||||
<div class="w-full h-full">
|
||||
<!-- 右側內容會依路由切換:Home / Operation / Nursing / SocialWorker / Nutrition -->
|
||||
<RouterView />
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
<!-- 依據 route.meta.layout 動態載入對應 Layout -->
|
||||
<component :is="layoutComponent" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import NavBar from "@/layouts/NavBar.vue";
|
||||
import Forge from "@/components/forge/Forge.vue";
|
||||
// import ForgeForSystem from "@/components/forge/ForgeForSystem.vue";
|
||||
<script setup>
|
||||
import { computed, defineAsyncComponent } from "vue";
|
||||
import { useRoute } from "vue-router";
|
||||
|
||||
export default {
|
||||
name: "App",
|
||||
components: { NavBar, Forge },
|
||||
// 懶載入各 Layout
|
||||
const layouts = {
|
||||
headquarter: defineAsyncComponent(() => import("@/layouts/HeadquarterLayout.vue")),
|
||||
map: defineAsyncComponent(() => import("@/layouts/MapLayout.vue")),
|
||||
};
|
||||
|
||||
const route = useRoute();
|
||||
|
||||
// 預設使用 map 版型;若該路由有 meta.layout 就切換
|
||||
const layoutComponent = computed(() => {
|
||||
const key = route.meta?.layout ?? "map";
|
||||
return layouts[key] ?? layouts.map;
|
||||
});
|
||||
</script>
|
||||
|
@ -587,7 +587,7 @@ onUnmounted(() => {
|
||||
@click="bringToFrontById(L.id)"
|
||||
>
|
||||
<div
|
||||
class="pointer-events-auto relative bg-white/95 border border-gray-300 rounded-lg shadow px-3 py-2 text-sm cursor-pointer"
|
||||
class="pointer-events-auto relative bg-white/95 border border-gray-300 rounded-md shadow px-3 py-2 text-sm cursor-pointer"
|
||||
style="will-change: transform"
|
||||
@click.stop="openResidentModal(L, $event)"
|
||||
role="button"
|
||||
|
12
src/layouts/HeadquarterLayout.vue
Normal file
12
src/layouts/HeadquarterLayout.vue
Normal file
@ -0,0 +1,12 @@
|
||||
<template>
|
||||
<section id="app" class="flex flex-col min-h-screen ">
|
||||
<NavBar class="fixed" />
|
||||
<main class="w-full p-4 overflow-x-hidden pt-[72px] pb-4">
|
||||
<RouterView />
|
||||
</main>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import NavBar from "@/layouts/NavBar.vue";
|
||||
</script>
|
30
src/layouts/MapLayout.vue
Normal file
30
src/layouts/MapLayout.vue
Normal file
@ -0,0 +1,30 @@
|
||||
<template>
|
||||
<section id="app" class="flex flex-col min-h-screen">
|
||||
<NavBar class="fixed" />
|
||||
|
||||
<main class="w-full p-4 mt-[72px]">
|
||||
<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">
|
||||
<div class="w-full h-full flex items-center justify-center text-gray-500">
|
||||
<Forge />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 右側:路由內容 -->
|
||||
<section class="col-span-4 h-full overflow-hidden">
|
||||
<div class="w-full h-full">
|
||||
<RouterView />
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
</main>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import NavBar from "@/layouts/NavBar.vue";
|
||||
// 延遲載入,避免首頁沒用到也被打包
|
||||
import { defineAsyncComponent } from "vue";
|
||||
const Forge = defineAsyncComponent(() => import("@/components/forge/Forge.vue"));
|
||||
</script>
|
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<nav
|
||||
class="w-full h-[72px] bg-white bg-opacity-50 shadow-md flex justify-between items-center px-8"
|
||||
class="w-full h-[64px] bg-white bg-opacity-50 shadow-md flex justify-between items-center px-8"
|
||||
>
|
||||
<!-- 左側 logo、選單區 -->
|
||||
<div class="flex justify-start items-center gap-12">
|
||||
@ -9,7 +9,6 @@
|
||||
</RouterLink>
|
||||
|
||||
<div class="relative">
|
||||
<!-- 你的按鈕(保留原本樣式),加上可存取屬性與事件 -->
|
||||
<div
|
||||
ref="triggerRef"
|
||||
class="btn text-white bg-brand-green hover:opacity-90 shadow-md border-none rounded-full px-8 tracking-widest"
|
||||
@ -37,11 +36,11 @@
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Modal:定位在按鈕右下方 top-8 left-16 -->
|
||||
<!-- Modal:定位在按鈕右下方 -->
|
||||
<div
|
||||
v-show="isOpen"
|
||||
ref="panelRef"
|
||||
class="absolute top-16 left-0 z-50 w-64 rounded-xl border border-gray-100 bg-white shadow-lg p-2"
|
||||
class="absolute top-16 left-0 z-50 w-64 rounded-md border border-gray-100 bg-white shadow-lg p-2"
|
||||
@click.stop
|
||||
>
|
||||
<ul class="max-h-48 overflow-y-auto text-brand-black">
|
||||
@ -60,75 +59,48 @@
|
||||
</div>
|
||||
|
||||
<!-- 中間 導覽按鈕區 -->
|
||||
<div>
|
||||
<div
|
||||
class="w-[450px] text-brand-black bg-white shadow-md rounded-full grid grid-cols-5 items-center"
|
||||
>
|
||||
<RouterLink to="/" v-slot="{ href, navigate, isExactActive }">
|
||||
<a
|
||||
:href="href"
|
||||
@click="navigate"
|
||||
:class="[
|
||||
'px-5 py-2 rounded-full flex justify-center items-center transition-colors',
|
||||
isExactActive ? 'bg-brand-green-light' : 'hover:bg-gray-100',
|
||||
]"
|
||||
>
|
||||
首頁
|
||||
</a>
|
||||
</RouterLink>
|
||||
|
||||
<RouterLink to="/operation" v-slot="{ href, navigate, isActive }">
|
||||
<a
|
||||
:href="href"
|
||||
@click="navigate"
|
||||
:class="[
|
||||
'px-5 py-2 rounded-full flex justify-center items-center transition-colors',
|
||||
isActive ? 'bg-brand-green-light' : 'hover:bg-gray-100',
|
||||
]"
|
||||
>
|
||||
營運
|
||||
</a>
|
||||
</RouterLink>
|
||||
<div
|
||||
class="min-w-[300px] text-brand-black bg-white shadow-md rounded-full grid grid-cols-3 items-center"
|
||||
>
|
||||
<RouterLink to="/" v-slot="{ href, navigate, isExactActive }">
|
||||
<a
|
||||
:href="href"
|
||||
@click="navigate"
|
||||
:class="[
|
||||
'px-5 py-2 rounded-full flex justify-center items-center transition-colors',
|
||||
isExactActive ? 'bg-brand-green-light' : 'hover:bg-gray-100',
|
||||
]"
|
||||
>
|
||||
首頁
|
||||
</a>
|
||||
</RouterLink>
|
||||
|
||||
<RouterLink to="/nursing" v-slot="{ href, navigate, isActive }">
|
||||
<a
|
||||
:href="href"
|
||||
@click="navigate"
|
||||
:class="[
|
||||
'px-5 py-2 rounded-full flex justify-center items-center transition-colors',
|
||||
isActive ? 'bg-brand-green-light' : 'hover:bg-gray-100',
|
||||
]"
|
||||
>
|
||||
護理
|
||||
</a>
|
||||
</RouterLink>
|
||||
<RouterLink to="/operation" v-slot="{ href, navigate, isActive }">
|
||||
<a
|
||||
:href="href"
|
||||
@click="navigate"
|
||||
:class="[
|
||||
'px-5 py-2 rounded-full flex justify-center items-center transition-colors',
|
||||
isActive ? 'bg-brand-green-light' : 'hover:bg-gray-100',
|
||||
]"
|
||||
>
|
||||
營運
|
||||
</a>
|
||||
</RouterLink>
|
||||
|
||||
<RouterLink to="/social-worker" v-slot="{ href, navigate, isActive }">
|
||||
<a
|
||||
:href="href"
|
||||
@click="navigate"
|
||||
:class="[
|
||||
'px-5 py-2 rounded-full flex justify-center items-center transition-colors',
|
||||
isActive ? 'bg-brand-green-light' : 'hover:bg-gray-100',
|
||||
]"
|
||||
>
|
||||
社工
|
||||
</a>
|
||||
</RouterLink>
|
||||
|
||||
<RouterLink to="/nutrition" v-slot="{ href, navigate, isActive }">
|
||||
<a
|
||||
:href="href"
|
||||
@click="navigate"
|
||||
:class="[
|
||||
'px-5 py-2 rounded-full flex justify-center items-center transition-colors',
|
||||
isActive ? 'bg-brand-green-light' : 'hover:bg-gray-100',
|
||||
]"
|
||||
>
|
||||
營養
|
||||
</a>
|
||||
</RouterLink>
|
||||
</div>
|
||||
<RouterLink to="/nursing" v-slot="{ href, navigate, isActive }">
|
||||
<a
|
||||
:href="href"
|
||||
@click="navigate"
|
||||
:class="[
|
||||
'px-5 py-2 rounded-full flex justify-center items-center transition-colors',
|
||||
isActive ? 'bg-brand-green-light' : 'hover:bg-gray-100',
|
||||
]"
|
||||
>
|
||||
照護
|
||||
</a>
|
||||
</RouterLink>
|
||||
</div>
|
||||
|
||||
<!-- 右側 登入區 -->
|
||||
@ -213,6 +185,7 @@ const panelRef = ref(null);
|
||||
|
||||
// 機構名稱清單
|
||||
const facilities = [
|
||||
"總部",
|
||||
"護祐護理之家",
|
||||
"崇祐護理之家",
|
||||
"崇祐長照中心(養護型)",
|
||||
|
60
src/pages/home/ProgressBar.vue
Normal file
60
src/pages/home/ProgressBar.vue
Normal file
@ -0,0 +1,60 @@
|
||||
<template>
|
||||
<div class="space-y-2">
|
||||
<!-- 標題列(可選 icon 插槽) -->
|
||||
<div class="flex items-center gap-2">
|
||||
<label class="block font-medium">{{ label }}</label>
|
||||
<slot name="icon" />
|
||||
</div>
|
||||
|
||||
<!-- 進度條(文字覆蓋在進度條上,預設靠左) -->
|
||||
<div class="relative">
|
||||
<progress
|
||||
v-bind="$attrs"
|
||||
class="progress w-full h-5 bg-brand-gray-light text-brand-green-light text-left rounded-none [&::-webkit-progress-bar]:rounded-none [&::-webkit-progress-value]:rounded-none [&::-moz-progress-bar]:rounded-none"
|
||||
:class="heightClass"
|
||||
:value="current"
|
||||
:max="total"
|
||||
role="progressbar"
|
||||
:aria-valuenow="current"
|
||||
aria-valuemin="0"
|
||||
:aria-valuemax="total"
|
||||
></progress>
|
||||
|
||||
<span
|
||||
class="pointer-events-none absolute inset-y-0 flex items-center text-[20px] font-nats text-brand-black/80"
|
||||
:class="textPosClass"
|
||||
>
|
||||
{{ currentLocale }} / {{ totalLocale }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed } from "vue";
|
||||
|
||||
defineOptions({ inheritAttrs: false });
|
||||
|
||||
const props = defineProps({
|
||||
label: { type: String, required: true },
|
||||
current: { type: Number, required: true },
|
||||
total: { type: Number, required: true },
|
||||
textAlign: { type: String, default: "left" }, // left | center | right
|
||||
});
|
||||
|
||||
const heightClass = computed(() => `h-${props.height}`);
|
||||
|
||||
const textPosClass = computed(() => {
|
||||
switch (props.textAlign) {
|
||||
case "center":
|
||||
return "left-1/2 -translate-x-1/2";
|
||||
case "right":
|
||||
return "right-2";
|
||||
default:
|
||||
return "left-2";
|
||||
}
|
||||
});
|
||||
|
||||
const currentLocale = computed(() => props.current.toLocaleString());
|
||||
const totalLocale = computed(() => props.total.toLocaleString());
|
||||
</script>
|
@ -1,631 +1,88 @@
|
||||
<template>
|
||||
<section
|
||||
class="flex flex-col gap-2 h-[calc(100vh-72px-32px)] overflow-hidden"
|
||||
class="grid grid-cols-3 gap-2 h-[calc(100vh-72px-32px)] justify-center text-brand-black"
|
||||
>
|
||||
<!-- 高度比重:2 -->
|
||||
<div class="flex-[2] grid grid-cols-4 gap-2">
|
||||
<!-- 住民人數 Card -->
|
||||
<div
|
||||
class="col-span-1 cursor-pointer active:opacity-80 text-white bg-brand-green rounded-xl shadow px-4 pt-3 flex flex-col justify-center items-start tracking-widest"
|
||||
@click="openModal('residents')"
|
||||
<!-- 左側 -->
|
||||
<section class="grid grid-rows-12 gap-2">
|
||||
<!-- 機構照片 + 機構說明 + 核心資料 bars + chart -->
|
||||
<section
|
||||
class="row-span-10 bg-white/50 rounded-md shadow py-6 px-4 flex flex-col items-start gap-4"
|
||||
>
|
||||
<div class="flex justify-center items-center gap-4">
|
||||
<p class="text-sm">住民人數</p>
|
||||
<span>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M12 9a3 3 0 0 0-3 3a3 3 0 0 0 3 3a3 3 0 0 0 3-3a3 3 0 0 0-3-3m0 8a5 5 0 0 1-5-5a5 5 0 0 1 5-5a5 5 0 0 1 5 5a5 5 0 0 1-5 5m0-12.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex justify-center items-baseline gap-1">
|
||||
<p class="text-[36px] xl:text-[40px] font-nats">36/49</p>
|
||||
<p class="text-[12px]">人</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 住院人數 Card -->
|
||||
<div
|
||||
class="col-span-1 cursor-pointer active:opacity-80 text-white bg-brand-green rounded-xl shadow px-4 pt-3 flex flex-col justify-center items-start tracking-widest"
|
||||
@click="openModal('inpatients')"
|
||||
>
|
||||
<div class="flex justify-center items-center gap-4">
|
||||
<p class="text-sm">住院人數</p>
|
||||
<span>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M12 9a3 3 0 0 0-3 3a3 3 0 0 0 3 3a3 3 0 0 0 3-3a3 3 0 0 0-3-3m0 8a5 5 0 0 1-5-5a5 5 0 0 1 5-5a5 5 0 0 1 5 5a5 5 0 0 1-5 5m0-12.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex justify-center items-baseline gap-1">
|
||||
<p class="text-[36px] xl:text-[40px] font-nats">1/36</p>
|
||||
<p class="text-[12px]">人</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ===== Modal(放在同一個 <template> 中,建議貼在最底部)===== -->
|
||||
<div
|
||||
v-if="showModal"
|
||||
class="fixed inset-0 z-[100] flex items-center justify-center"
|
||||
@keydown.esc="closeModal"
|
||||
tabindex="0"
|
||||
>
|
||||
<!-- backdrop -->
|
||||
<div class="absolute inset-0 bg-black/40" @click="closeModal"></div>
|
||||
|
||||
<!-- dialog -->
|
||||
<div
|
||||
class="relative bg-white w-[92vw] max-w-5xl max-h-[86vh] overflow-auto rounded-2xl shadow-xl px-12 py-8"
|
||||
role="dialog"
|
||||
aria-modal="true"
|
||||
class="grid grid-cols-12 justify-center items-start gap-8 "
|
||||
>
|
||||
<!-- header -->
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<h3 class="text-2xl font-bold text-gray-800">
|
||||
{{ modalTitle }}
|
||||
</h3>
|
||||
<button
|
||||
class="p-2 rounded hover:bg-gray-100"
|
||||
@click="closeModal"
|
||||
aria-label="關閉"
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- body:住民資訊(A/B 區 + 表格) -->
|
||||
<div v-if="modalType === 'residents'" class="space-y-8">
|
||||
<section>
|
||||
<h4 class="text-lg font-semibold text-gray-700 mb-3">A 區</h4>
|
||||
<div class="overflow-x-auto">
|
||||
<table class="min-w-full text-sm text-brand-black">
|
||||
<thead>
|
||||
<tr class="text-left bg-gray-50">
|
||||
<th class="px-3 py-2">床位</th>
|
||||
<th class="px-3 py-2">姓名</th>
|
||||
<th class="px-3 py-2">性別</th>
|
||||
<th class="px-3 py-2">年齡</th>
|
||||
<th class="px-3 py-2">身體狀況</th>
|
||||
<th class="px-3 py-2">備註</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr
|
||||
v-for="r in residentsA"
|
||||
:key="r.bed"
|
||||
class="border-b last:border-b-0 hover:bg-gray-50"
|
||||
>
|
||||
<td class="px-3 py-2 font-mono">{{ r.bed }}</td>
|
||||
<td class="px-3 py-2">{{ r.name }}</td>
|
||||
<td class="px-3 py-2">{{ r.gender }}</td>
|
||||
<td class="px-3 py-2">{{ r.age }}</td>
|
||||
<td class="px-3 py-2">{{ r.condition }}</td>
|
||||
<td class="px-3 py-2">{{ r.note }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h4 class="text-lg font-semibold text-gray-700 mb-3">B 區</h4>
|
||||
<div class="overflow-x-auto">
|
||||
<table class="min-w-full text-sm text-brand-black">
|
||||
<thead>
|
||||
<tr class="text-left bg-gray-50">
|
||||
<th class="px-3 py-2">床位</th>
|
||||
<th class="px-3 py-2">姓名</th>
|
||||
<th class="px-3 py-2">性別</th>
|
||||
<th class="px-3 py-2">年齡</th>
|
||||
<th class="px-3 py-2">身體狀況</th>
|
||||
<th class="px-3 py-2">備註</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr
|
||||
v-for="r in residentsB"
|
||||
:key="r.bed"
|
||||
class="border-b last:border-b-0 hover:bg-gray-50"
|
||||
>
|
||||
<td class="px-3 py-2 font-mono">{{ r.bed }}</td>
|
||||
<td class="px-3 py-2">{{ r.name }}</td>
|
||||
<td class="px-3 py-2">{{ r.gender }}</td>
|
||||
<td class="px-3 py-2">{{ r.age }}</td>
|
||||
<td class="px-3 py-2">{{ r.condition }}</td>
|
||||
<td class="px-3 py-2">{{ r.note }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<!-- body:住院資訊 -->
|
||||
<div v-else-if="modalType === 'inpatients'">
|
||||
<h4 class="text-lg font-semibold text-gray-700 mb-3">清單</h4>
|
||||
<div class="overflow-x-auto">
|
||||
<table class="min-w-full text-sm text-brand-black">
|
||||
<thead>
|
||||
<tr class="text-left bg-gray-50">
|
||||
<th class="px-3 py-2">床位</th>
|
||||
<th class="px-3 py-2">姓名</th>
|
||||
<th class="px-3 py-2">醫院與科別</th>
|
||||
<th class="px-3 py-2">病歷號</th>
|
||||
<th class="px-3 py-2">狀況</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr
|
||||
v-for="p in inpatients"
|
||||
:key="p.recordNo"
|
||||
class="border-b last:border-b-0 hover:bg-gray-50"
|
||||
>
|
||||
<td class="px-3 py-2 font-mono">{{ p.bed }}</td>
|
||||
<td class="px-3 py-2">{{ p.name }}</td>
|
||||
<td class="px-3 py-2">{{ p.hospitalDept }}</td>
|
||||
<td class="px-3 py-2 font-mono">{{ p.recordNo }}</td>
|
||||
<td class="px-3 py-2">{{ p.status }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div
|
||||
class="col-span-5 grid grid-rows-12 justify-start items-start gap-6"
|
||||
>
|
||||
<div class="h-[240px] row-span-6">
|
||||
<img
|
||||
src="/img/building_photo_headquarter.png"
|
||||
alt="機構照片"
|
||||
class="w-full h-full rounded-md object-cover"
|
||||
/>
|
||||
</div>
|
||||
<div class="row-span-4">
|
||||
<p class="text-brand-gray text-sm">
|
||||
崇恩長期照顧集團是國內第一家取得ISO認證的長期照顧機構,集合了醫師群與資深護理群及照顧服務員們,在大南部地區照顧每一位需要我們的長輩。
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- footer -->
|
||||
<div class="mt-6 text-right">
|
||||
<button
|
||||
class="btn bg-brand-green text-white px-4 py-2 rounded-lg"
|
||||
@click="closeModal"
|
||||
>
|
||||
關閉
|
||||
</button>
|
||||
<!-- Progress bars -->
|
||||
<div class="col-span-6 flex flex-col gap-4">
|
||||
<ProgressBar
|
||||
label="現在住民/全立案床數"
|
||||
:current="240"
|
||||
:total="360"
|
||||
|
||||
/>
|
||||
<ProgressBar
|
||||
label="目前空床數/全立案床數"
|
||||
:current="120"
|
||||
:total="360"
|
||||
|
||||
|
||||
/>
|
||||
<ProgressBar
|
||||
label="今日住院/當月累積住院"
|
||||
:current="8"
|
||||
:total="50"
|
||||
|
||||
|
||||
/>
|
||||
<ProgressBar
|
||||
label="今日新人入住/當月累積入住"
|
||||
:current="12"
|
||||
:total="50"
|
||||
|
||||
/>
|
||||
<ProgressBar
|
||||
label="今日離院/累積離院"
|
||||
:current="8"
|
||||
:total="50"
|
||||
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bg-black">
|
||||
<!-- chart -->
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div
|
||||
class="col-span-1 cursor-pointer active:opacity-80 text-white bg-brand-green rounded-xl shadow px-4 pt-3 flex flex-col justify-center items-start tracking-widest"
|
||||
>
|
||||
<div class="flex justify-center items-center gap-4">
|
||||
<p class="text-sm">其他人數</p>
|
||||
<span>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M12 9a3 3 0 0 0-3 3a3 3 0 0 0 3 3a3 3 0 0 0 3-3a3 3 0 0 0-3-3m0 8a5 5 0 0 1-5-5a5 5 0 0 1 5-5a5 5 0 0 1 5 5a5 5 0 0 1-5 5m0-12.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex justify-center items-baseline gap-1">
|
||||
<p class="text-[36px] xl:text-[40px] font-nats">0/49</p>
|
||||
<p class="text-[12px]">人</p>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="col-span-1 cursor-pointer active:opacity-80 text-white bg-brand-green rounded-xl shadow px-4 pt-3 flex flex-col justify-center items-start tracking-widest"
|
||||
>
|
||||
<div class="flex justify-center items-center gap-4">
|
||||
<p class="text-sm">其他人數</p>
|
||||
<span>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M12 9a3 3 0 0 0-3 3a3 3 0 0 0 3 3a3 3 0 0 0 3-3a3 3 0 0 0-3-3m0 8a5 5 0 0 1-5-5a5 5 0 0 1 5-5a5 5 0 0 1 5 5a5 5 0 0 1-5 5m0-12.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex justify-center items-baseline gap-1">
|
||||
<p class="text-[36px] xl:text-[40px] font-nats">0/49</p>
|
||||
<p class="text-[12px]">人</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 高度比重:5 -->
|
||||
<div class="flex-[5] grid grid-cols-2 gap-2">
|
||||
<div
|
||||
class="col-span-1 bg-white bg-opacity-70 rounded-xl shadow p-5 flex flex-col justify-center items-start"
|
||||
>
|
||||
<h4 class="text-xl text-gray-600 font-bold">近三個月比較</h4>
|
||||
<div ref="chartARef" class="w-full h-full"></div>
|
||||
</div>
|
||||
<div
|
||||
class="col-span-1 bg-white bg-opacity-70 rounded-xl shadow p-5 flex flex-col justify-center items-start"
|
||||
>
|
||||
<h4 class="text-xl text-gray-600 font-bold">近六個月比較</h4>
|
||||
<div ref="chartBRef" class="w-full h-full"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 高度比重:5 -->
|
||||
<div
|
||||
class="bg-white bg-opacity-70 rounded-xl shadow p-5 flex flex-col justify-center items-start flex-[5]"
|
||||
>
|
||||
<h4 class="text-xl text-gray-600 font-bold">與去年同期比較</h4>
|
||||
<div ref="chartCRef" class="w-full h-full"></div>
|
||||
</div>
|
||||
<!-- 葷/素資料 -->
|
||||
<section class="row-span-2 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-3"></div>
|
||||
</section>
|
||||
</section>
|
||||
<!-- 中間 -->
|
||||
<section class="bg-white/50 rounded-md shadow p-3"></section>
|
||||
<!-- 右側 -->
|
||||
<section class="bg-white/50 rounded-md shadow p-3"></section>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, onMounted, onUnmounted, nextTick } from "vue";
|
||||
import * as echarts from "echarts";
|
||||
import { brand } from "@/styles/palette";
|
||||
|
||||
// ---- DOM Refs ----
|
||||
const chartARef = ref(null);
|
||||
const chartBRef = ref(null);
|
||||
const chartCRef = ref(null);
|
||||
|
||||
// ---- Chart instances ----
|
||||
let chartA, chartB, chartC;
|
||||
|
||||
// 假資料工具
|
||||
function genTrend(len, start = 50, drift = 0.6, noise = 20) {
|
||||
const arr = [];
|
||||
let v = start;
|
||||
for (let i = 0; i < len; i++) {
|
||||
v = v + drift + (Math.random() * noise * 2 - noise);
|
||||
arr.push(Number(v.toFixed(1)));
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
const commonGrid = {
|
||||
left: 40,
|
||||
right: 20,
|
||||
top: 50,
|
||||
bottom: 30,
|
||||
containLabel: true,
|
||||
};
|
||||
const commonTooltip = { trigger: "axis", axisPointer: { type: "shadow" } };
|
||||
|
||||
// A:三個月趨勢
|
||||
function buildOptionA() {
|
||||
const x = Array.from({ length: 8 }, (_, i) => `op${i + 1}`);
|
||||
const legends = ["6月", "7月", "8月"];
|
||||
const series = legends.map((label, idx) => ({
|
||||
name: label,
|
||||
type: "bar",
|
||||
emphasis: { focus: "series" },
|
||||
data: genTrend(x.length, 40 + idx * 2, 0.5 + idx * 0.1, 1.5),
|
||||
barWidth: 5,
|
||||
}));
|
||||
|
||||
return {
|
||||
legend: { top: 10 },
|
||||
tooltip: commonTooltip,
|
||||
grid: commonGrid,
|
||||
xAxis: { type: "category", data: x },
|
||||
yAxis: { type: "value" },
|
||||
// 指定顏色
|
||||
color: [brand.green, brand.greenLight, brand.yellow],
|
||||
series,
|
||||
};
|
||||
}
|
||||
|
||||
// B:六個月趨勢
|
||||
function buildOptionB() {
|
||||
const x = Array.from({ length: 8 }, (_, i) => `op${i + 1}`);
|
||||
const legends = ["3月", "4月", "5月", "6月", "7月", "8月"];
|
||||
const series = legends.map((label, idx) => ({
|
||||
name: label,
|
||||
type: "bar",
|
||||
emphasis: { focus: "series" },
|
||||
data: genTrend(x.length, 35 + idx * 1.5, 0.4 + idx * 0.06, 1.6),
|
||||
barWidth: 5,
|
||||
}));
|
||||
|
||||
return {
|
||||
legend: { type: "scroll", top: 10 },
|
||||
tooltip: commonTooltip,
|
||||
grid: commonGrid,
|
||||
xAxis: { type: "category", data: x },
|
||||
yAxis: { type: "value" },
|
||||
color: [
|
||||
brand.green,
|
||||
brand.greenLight,
|
||||
brand.yellow,
|
||||
brand.purpleLight,
|
||||
brand.purple,
|
||||
brand.purpleDark,
|
||||
],
|
||||
series,
|
||||
};
|
||||
}
|
||||
|
||||
// C:與去年同期比較
|
||||
function buildOptionC() {
|
||||
const months = Array.from({ length: 12 }, (_, i) => `${i + 1}月`);
|
||||
const lastYear = genTrend(12, 36, 0.8, 2);
|
||||
const thisYear = lastYear.map(
|
||||
(v, i) => Number((v + 5 + Math.sin(i / 2) * 3).toFixed(1)) // 加大偏移與震盪
|
||||
);
|
||||
|
||||
return {
|
||||
legend: { top: 10, data: ["去年", "今年"] },
|
||||
tooltip: { trigger: "axis" },
|
||||
grid: commonGrid,
|
||||
xAxis: { type: "category", data: months, boundaryGap: false },
|
||||
yAxis: { type: "value" },
|
||||
color: [brand.purple, brand.green],
|
||||
series: [
|
||||
{
|
||||
name: "去年",
|
||||
type: "line",
|
||||
smooth: true,
|
||||
data: lastYear,
|
||||
},
|
||||
{ name: "今年", type: "line", smooth: true, data: thisYear },
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
// 初始化 & resize
|
||||
function initCharts() {
|
||||
if (chartARef.value && !chartA) {
|
||||
chartA = echarts.init(chartARef.value);
|
||||
chartA.setOption(buildOptionA());
|
||||
}
|
||||
if (chartBRef.value && !chartB) {
|
||||
chartB = echarts.init(chartBRef.value);
|
||||
chartB.setOption(buildOptionB());
|
||||
}
|
||||
if (chartCRef.value && !chartC) {
|
||||
chartC = echarts.init(chartCRef.value);
|
||||
chartC.setOption(buildOptionC());
|
||||
}
|
||||
handleResize();
|
||||
}
|
||||
|
||||
let resizeObserver;
|
||||
function handleResize() {
|
||||
const resize = () => {
|
||||
chartA && chartA.resize();
|
||||
chartB && chartB.resize();
|
||||
chartC && chartC.resize();
|
||||
};
|
||||
window.addEventListener("resize", resize);
|
||||
|
||||
const rootEl = document.querySelector("section.flex.flex-col");
|
||||
if (rootEl) {
|
||||
resizeObserver = new ResizeObserver(resize);
|
||||
resizeObserver.observe(rootEl);
|
||||
}
|
||||
}
|
||||
|
||||
function disposeCharts() {
|
||||
resizeObserver && resizeObserver.disconnect();
|
||||
window.removeEventListener("resize", handleResize);
|
||||
chartA && chartA.dispose();
|
||||
chartB && chartB.dispose();
|
||||
chartC && chartC.dispose();
|
||||
chartA = chartB = chartC = null;
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
await nextTick();
|
||||
initCharts();
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
disposeCharts();
|
||||
});
|
||||
|
||||
/* ===== Modal 狀態 ===== */
|
||||
const showModal = ref(false);
|
||||
const modalType = ref(null);
|
||||
|
||||
const modalTitle = computed(() => {
|
||||
if (modalType.value === "residents") return "住民資訊";
|
||||
if (modalType.value === "inpatients") return "住院資訊";
|
||||
return "";
|
||||
});
|
||||
|
||||
function openModal(type) {
|
||||
modalType.value = type;
|
||||
showModal.value = true;
|
||||
nextTick(() => {
|
||||
const dialog = document.querySelector('[role="dialog"]');
|
||||
if (dialog) dialog.focus();
|
||||
});
|
||||
}
|
||||
function closeModal() {
|
||||
showModal.value = false;
|
||||
modalType.value = null;
|
||||
}
|
||||
|
||||
/* ===== 工具:產生不含「4」的床位號 ===== */
|
||||
function generateBeds(count, start = 1001) {
|
||||
const arr = [];
|
||||
let n = start;
|
||||
while (arr.length < count) {
|
||||
if (!String(n).includes("4")) arr.push(n);
|
||||
n++;
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
/* ===== 假資料:住民 ===== */
|
||||
const bedsResidents = generateBeds(12, 1001);
|
||||
const residentsAll = [
|
||||
{
|
||||
bed: bedsResidents[0],
|
||||
name: "王小明",
|
||||
gender: "男",
|
||||
age: 78,
|
||||
condition: "穩定",
|
||||
note: "喜歡下棋",
|
||||
area: "A",
|
||||
},
|
||||
{
|
||||
bed: bedsResidents[1],
|
||||
name: "陳美麗",
|
||||
gender: "女",
|
||||
age: 82,
|
||||
condition: "需輕度協助",
|
||||
note: "糖尿病控制中",
|
||||
area: "A",
|
||||
},
|
||||
{
|
||||
bed: bedsResidents[2],
|
||||
name: "林大志",
|
||||
gender: "男",
|
||||
age: 74,
|
||||
condition: "穩定",
|
||||
note: "行動慢",
|
||||
area: "A",
|
||||
},
|
||||
{
|
||||
bed: bedsResidents[3],
|
||||
name: "張翠華",
|
||||
gender: "女",
|
||||
age: 80,
|
||||
condition: "復健中",
|
||||
note: "膝關節置換術後",
|
||||
area: "A",
|
||||
},
|
||||
{
|
||||
bed: bedsResidents[4],
|
||||
name: "黃國榮",
|
||||
gender: "男",
|
||||
age: 85,
|
||||
condition: "需中度協助",
|
||||
note: "夜間易醒",
|
||||
area: "A",
|
||||
},
|
||||
{
|
||||
bed: bedsResidents[5],
|
||||
name: "李佩珊",
|
||||
gender: "女",
|
||||
age: 76,
|
||||
condition: "穩定",
|
||||
note: "對花粉過敏",
|
||||
area: "A",
|
||||
},
|
||||
{
|
||||
bed: bedsResidents[6],
|
||||
name: "吳大同",
|
||||
gender: "男",
|
||||
age: 79,
|
||||
condition: "穩定",
|
||||
note: "喜歡園藝",
|
||||
area: "B",
|
||||
},
|
||||
{
|
||||
bed: bedsResidents[7],
|
||||
name: "周怡君",
|
||||
gender: "女",
|
||||
age: 81,
|
||||
condition: "需輕度協助",
|
||||
note: "高血壓",
|
||||
area: "B",
|
||||
},
|
||||
{
|
||||
bed: bedsResidents[8],
|
||||
name: "曾文龍",
|
||||
gender: "男",
|
||||
age: 77,
|
||||
condition: "復健中",
|
||||
note: "髖關節手術後",
|
||||
area: "B",
|
||||
},
|
||||
{
|
||||
bed: bedsResidents[9],
|
||||
name: "蔡淑芬",
|
||||
gender: "女",
|
||||
age: 83,
|
||||
condition: "穩定",
|
||||
note: "喜歡編織",
|
||||
area: "B",
|
||||
},
|
||||
{
|
||||
bed: bedsResidents[10],
|
||||
name: "許建宏",
|
||||
gender: "男",
|
||||
age: 75,
|
||||
condition: "需中度協助",
|
||||
note: "睡眠品質不佳",
|
||||
area: "B",
|
||||
},
|
||||
{
|
||||
bed: bedsResidents[11],
|
||||
name: "簡婉婷",
|
||||
gender: "女",
|
||||
age: 78,
|
||||
condition: "穩定",
|
||||
note: "對海鮮過敏",
|
||||
area: "B",
|
||||
},
|
||||
];
|
||||
|
||||
const residentsA = residentsAll.filter((r) => r.area === "A");
|
||||
const residentsB = residentsAll.filter((r) => r.area === "B");
|
||||
|
||||
/* ===== 假資料:住院 ===== */
|
||||
const bedsInpatient = generateBeds(4, 1020);
|
||||
const inpatients = [
|
||||
{
|
||||
bed: bedsInpatient[0],
|
||||
name: "劉書豪",
|
||||
hospitalDept: "台大醫院/心臟內科",
|
||||
recordNo: "A1023001",
|
||||
status: "加護中",
|
||||
},
|
||||
{
|
||||
bed: bedsInpatient[1],
|
||||
name: "高雅筑",
|
||||
hospitalDept: "榮總/新陳代謝科",
|
||||
recordNo: "B1023007",
|
||||
status: "住院觀察",
|
||||
},
|
||||
{
|
||||
bed: bedsInpatient[2],
|
||||
name: "方志明",
|
||||
hospitalDept: "長庚/骨科",
|
||||
recordNo: "C1023011",
|
||||
status: "術後恢復",
|
||||
},
|
||||
{
|
||||
bed: bedsInpatient[3],
|
||||
name: "鄭于庭",
|
||||
hospitalDept: "國泰/神經內科",
|
||||
recordNo: "D1023020",
|
||||
status: "檢查中",
|
||||
},
|
||||
];
|
||||
|
||||
/* ESC 關閉 */
|
||||
function onKeydown(e) {
|
||||
if (e.key === "Escape") closeModal();
|
||||
}
|
||||
onMounted(() => window.addEventListener("keydown", onKeydown));
|
||||
onUnmounted(() => window.removeEventListener("keydown", onKeydown));
|
||||
import ProgressBar from "./ProgressBar.vue";
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
|
@ -1,11 +1,11 @@
|
||||
<template>
|
||||
<section
|
||||
class="flex flex-col gap-2 h-[calc(100vh-72px-32px)] overflow-hidden"
|
||||
class="flex flex-col gap-2 h-[calc(100vh-72px-24px)] overflow-hidden"
|
||||
>
|
||||
<!-- 高度比重:2 -->
|
||||
<div class="flex-[2] grid grid-cols-4 gap-2">
|
||||
<div
|
||||
class="col-span-1 cursor-pointer active:opacity-80 text-white bg-brand-green rounded-xl shadow px-4 pt-3 flex flex-col justify-center items-start tracking-widest"
|
||||
class="col-span-1 cursor-pointer active:opacity-80 text-white bg-brand-green rounded-md shadow px-4 pt-3 flex flex-col justify-center items-start tracking-widest"
|
||||
>
|
||||
<div class="flex justify-center items-center gap-4">
|
||||
<p class="text-sm">住民人數</p>
|
||||
@ -29,7 +29,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="col-span-1 cursor-pointer active:opacity-80 text-white bg-brand-green rounded-xl shadow px-4 pt-3 flex flex-col justify-center items-start tracking-widest"
|
||||
class="col-span-1 cursor-pointer active:opacity-80 text-white bg-brand-green rounded-md shadow px-4 pt-3 flex flex-col justify-center items-start tracking-widest"
|
||||
>
|
||||
<div class="flex justify-center items-center gap-4">
|
||||
<p class="text-sm">住院人數</p>
|
||||
@ -53,7 +53,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="col-span-1 cursor-pointer active:opacity-80 text-white bg-brand-green rounded-xl shadow px-4 pt-3 flex flex-col justify-center items-start tracking-widest"
|
||||
class="col-span-1 cursor-pointer active:opacity-80 text-white bg-brand-green rounded-md shadow px-4 pt-3 flex flex-col justify-center items-start tracking-widest"
|
||||
>
|
||||
<div class="flex justify-center items-center gap-4">
|
||||
<p class="text-sm">其他人數</p>
|
||||
@ -77,7 +77,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="col-span-1 cursor-pointer active:opacity-80 text-white bg-brand-green rounded-xl shadow px-4 pt-3 flex flex-col justify-center items-start tracking-widest"
|
||||
class="col-span-1 cursor-pointer active:opacity-80 text-white bg-brand-green rounded-md shadow px-4 pt-3 flex flex-col justify-center items-start tracking-widest"
|
||||
>
|
||||
<div class="flex justify-center items-center gap-4">
|
||||
<p class="text-sm">其他人數</p>
|
||||
@ -105,7 +105,7 @@
|
||||
<!-- 高度比重:2 -->
|
||||
<div class="flex-[2] grid grid-cols-4 gap-2">
|
||||
<div
|
||||
class="col-span-1 bg-white bg-opacity-70 text-brand-green rounded-xl shadow px-4 pt-3 flex flex-col justify-center items-start tracking-widest"
|
||||
class="col-span-1 bg-white bg-opacity-70 text-brand-green rounded-md shadow px-4 pt-3 flex flex-col justify-center items-start tracking-widest"
|
||||
>
|
||||
<div class="flex justify-center items-center gap-4">
|
||||
<p class="text-sm">其他人數</p>
|
||||
@ -129,7 +129,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="col-span-1 bg-white bg-opacity-70 text-brand-green rounded-xl shadow px-4 pt-3 flex flex-col justify-center items-start tracking-widest"
|
||||
class="col-span-1 bg-white bg-opacity-70 text-brand-green rounded-md shadow px-4 pt-3 flex flex-col justify-center items-start tracking-widest"
|
||||
>
|
||||
<div class="flex justify-center items-center gap-4">
|
||||
<p class="text-sm">其他人數</p>
|
||||
@ -153,7 +153,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="col-span-1 bg-white bg-opacity-70 text-brand-green rounded-xl shadow px-4 pt-3 flex flex-col justify-center items-start tracking-widest"
|
||||
class="col-span-1 bg-white bg-opacity-70 text-brand-green rounded-md shadow px-4 pt-3 flex flex-col justify-center items-start tracking-widest"
|
||||
>
|
||||
<div class="flex justify-center items-center gap-4">
|
||||
<p class="text-sm">其他人數</p>
|
||||
@ -177,7 +177,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="col-span-1 bg-white bg-opacity-70 text-brand-green rounded-xl shadow px-4 pt-3 flex flex-col justify-center items-start tracking-widest"
|
||||
class="col-span-1 bg-white bg-opacity-70 text-brand-green rounded-md shadow px-4 pt-3 flex flex-col justify-center items-start tracking-widest"
|
||||
>
|
||||
<div class="flex justify-center items-center gap-4">
|
||||
<p class="text-sm">其他人數</p>
|
||||
@ -205,14 +205,14 @@
|
||||
<!-- 高度比重:5 -->
|
||||
<div class="flex-[5] grid grid-cols-2 gap-2 text-gray-300">
|
||||
<div
|
||||
class="col-span-1 bg-white bg-opacity-70 rounded-xl shadow px-4 py-3 flex flex-col justify-center items-center"
|
||||
class="col-span-1 bg-white bg-opacity-70 rounded-md shadow px-4 py-3 flex flex-col justify-center items-center"
|
||||
>
|
||||
<p>暫無內容</p>
|
||||
<!-- <h4 class="text-xl text-gray-600 font-bold">近三個月比較</h4>
|
||||
<div ref="chartARef" class="w-[90%] h-[90%]"></div> -->
|
||||
</div>
|
||||
<div
|
||||
class="col-span-1 bg-white bg-opacity-70 rounded-xl shadow px-4 py-3 flex flex-col justify-center items-center"
|
||||
class="col-span-1 bg-white bg-opacity-70 rounded-md shadow px-4 py-3 flex flex-col justify-center items-center"
|
||||
>
|
||||
<p>暫無內容</p>
|
||||
<!-- <h4 class="text-xl text-gray-600 font-bold">近六個月比較</h4>
|
||||
@ -222,7 +222,7 @@
|
||||
|
||||
<!-- 高度比重:5 -->
|
||||
<div
|
||||
class="bg-white bg-opacity-70 text-gray-300 rounded-xl shadow px-4 py-3 flex flex-col justify-center items-center flex-[5]"
|
||||
class="bg-white bg-opacity-70 text-gray-300 rounded-md shadow px-4 py-3 flex flex-col justify-center items-center flex-[5]"
|
||||
>
|
||||
<p>暫無內容</p>
|
||||
<!-- <h4 class="text-xl text-gray-600 font-bold">與去年同期比較</h4>
|
||||
|
@ -1,400 +0,0 @@
|
||||
<template>
|
||||
<section
|
||||
class="flex flex-col gap-2 h-[calc(100vh-72px-32px)] overflow-hidden"
|
||||
>
|
||||
<!-- 高度比重:2 -->
|
||||
<div class="flex-[2] grid grid-cols-4 gap-2">
|
||||
<div
|
||||
class="col-span-1 cursor-pointer active:opacity-80 text-white bg-brand-green rounded-xl shadow px-4 pt-3 flex flex-col justify-center items-start tracking-widest"
|
||||
>
|
||||
<div class="flex justify-center items-center gap-4">
|
||||
<p class="text-sm">住民人數</p>
|
||||
<span>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M12 9a3 3 0 0 0-3 3a3 3 0 0 0 3 3a3 3 0 0 0 3-3a3 3 0 0 0-3-3m0 8a5 5 0 0 1-5-5a5 5 0 0 1 5-5a5 5 0 0 1 5 5a5 5 0 0 1-5 5m0-12.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex justify-center items-baseline gap-1">
|
||||
<p class="text-[36px] xl:text-[40px] font-nats">36/49</p>
|
||||
<p class="text-[12px]">人</p>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="col-span-1 cursor-pointer active:opacity-80 text-white bg-brand-green rounded-xl shadow px-4 pt-3 flex flex-col justify-center items-start tracking-widest"
|
||||
>
|
||||
<div class="flex justify-center items-center gap-4">
|
||||
<p class="text-sm">住院人數</p>
|
||||
<span>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M12 9a3 3 0 0 0-3 3a3 3 0 0 0 3 3a3 3 0 0 0 3-3a3 3 0 0 0-3-3m0 8a5 5 0 0 1-5-5a5 5 0 0 1 5-5a5 5 0 0 1 5 5a5 5 0 0 1-5 5m0-12.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex justify-center items-baseline gap-1">
|
||||
<p class="text-[36px] xl:text-[40px] font-nats">1/36</p>
|
||||
<p class="text-[12px]">人</p>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="col-span-1 cursor-pointer active:opacity-80 text-white bg-brand-green rounded-xl shadow px-4 pt-3 flex flex-col justify-center items-start tracking-widest"
|
||||
>
|
||||
<div class="flex justify-center items-center gap-4">
|
||||
<p class="text-sm">其他人數</p>
|
||||
<span>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M12 9a3 3 0 0 0-3 3a3 3 0 0 0 3 3a3 3 0 0 0 3-3a3 3 0 0 0-3-3m0 8a5 5 0 0 1-5-5a5 5 0 0 1 5-5a5 5 0 0 1 5 5a5 5 0 0 1-5 5m0-12.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex justify-center items-baseline gap-1">
|
||||
<p class="text-[36px] xl:text-[40px] font-nats">0/49</p>
|
||||
<p class="text-[12px]">人</p>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="col-span-1 cursor-pointer active:opacity-80 text-white bg-brand-green rounded-xl shadow px-4 pt-3 flex flex-col justify-center items-start tracking-widest"
|
||||
>
|
||||
<div class="flex justify-center items-center gap-4">
|
||||
<p class="text-sm">其他人數</p>
|
||||
<span>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M12 9a3 3 0 0 0-3 3a3 3 0 0 0 3 3a3 3 0 0 0 3-3a3 3 0 0 0-3-3m0 8a5 5 0 0 1-5-5a5 5 0 0 1 5-5a5 5 0 0 1 5 5a5 5 0 0 1-5 5m0-12.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex justify-center items-baseline gap-1">
|
||||
<p class="text-[36px] xl:text-[40px] font-nats">0/49</p>
|
||||
<p class="text-[12px]">人</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 高度比重:2 -->
|
||||
<div class="flex-[2] grid grid-cols-4 gap-2">
|
||||
<div
|
||||
class="col-span-1 bg-white bg-opacity-70 text-brand-green rounded-xl shadow px-4 pt-3 flex flex-col justify-center items-start tracking-widest"
|
||||
>
|
||||
<div class="flex justify-center items-center gap-4">
|
||||
<p class="text-sm">其他人數</p>
|
||||
<span>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M12 9a3 3 0 0 0-3 3a3 3 0 0 0 3 3a3 3 0 0 0 3-3a3 3 0 0 0-3-3m0 8a5 5 0 0 1-5-5a5 5 0 0 1 5-5a5 5 0 0 1 5 5a5 5 0 0 1-5 5m0-12.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex justify-center items-baseline gap-1">
|
||||
<p class="text-[36px] font-nats">36/49</p>
|
||||
<p class="text-[12px]">人</p>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="col-span-1 bg-white bg-opacity-70 text-brand-green rounded-xl shadow px-4 pt-3 flex flex-col justify-center items-start tracking-widest"
|
||||
>
|
||||
<div class="flex justify-center items-center gap-4">
|
||||
<p class="text-sm">其他人數</p>
|
||||
<span>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M12 9a3 3 0 0 0-3 3a3 3 0 0 0 3 3a3 3 0 0 0 3-3a3 3 0 0 0-3-3m0 8a5 5 0 0 1-5-5a5 5 0 0 1 5-5a5 5 0 0 1 5 5a5 5 0 0 1-5 5m0-12.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex justify-center items-baseline gap-1">
|
||||
<p class="text-[36px] font-nats">1/36</p>
|
||||
<p class="text-[12px]">人</p>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="col-span-1 bg-white bg-opacity-70 text-brand-green rounded-xl shadow px-4 pt-3 flex flex-col justify-center items-start tracking-widest"
|
||||
>
|
||||
<div class="flex justify-center items-center gap-4">
|
||||
<p class="text-sm">其他人數</p>
|
||||
<span>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M12 9a3 3 0 0 0-3 3a3 3 0 0 0 3 3a3 3 0 0 0 3-3a3 3 0 0 0-3-3m0 8a5 5 0 0 1-5-5a5 5 0 0 1 5-5a5 5 0 0 1 5 5a5 5 0 0 1-5 5m0-12.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex justify-center items-baseline gap-1">
|
||||
<p class="text-[36px] font-nats">0/49</p>
|
||||
<p class="text-[12px]">人</p>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="col-span-1 bg-white bg-opacity-70 text-brand-green rounded-xl shadow px-4 pt-3 flex flex-col justify-center items-start tracking-widest"
|
||||
>
|
||||
<div class="flex justify-center items-center gap-4">
|
||||
<p class="text-sm">其他人數</p>
|
||||
<span>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M12 9a3 3 0 0 0-3 3a3 3 0 0 0 3 3a3 3 0 0 0 3-3a3 3 0 0 0-3-3m0 8a5 5 0 0 1-5-5a5 5 0 0 1 5-5a5 5 0 0 1 5 5a5 5 0 0 1-5 5m0-12.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex justify-center items-baseline gap-1">
|
||||
<p class="text-[36px] font-nats">0/49</p>
|
||||
<p class="text-[12px]">人</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 高度比重:5 -->
|
||||
<div class="flex-[5] grid grid-cols-2 gap-2 text-gray-300">
|
||||
<div
|
||||
class="col-span-1 bg-white bg-opacity-70 rounded-xl shadow px-4 py-3 flex flex-col justify-center items-center"
|
||||
>
|
||||
<p>暫無內容</p>
|
||||
<!-- <h4 class="text-xl text-gray-600 font-bold">近三個月比較</h4>
|
||||
<div ref="chartARef" class="w-[90%] h-[90%]"></div> -->
|
||||
</div>
|
||||
<div
|
||||
class="col-span-1 bg-white bg-opacity-70 rounded-xl shadow px-4 py-3 flex flex-col justify-center items-center"
|
||||
>
|
||||
<p>暫無內容</p>
|
||||
<!-- <h4 class="text-xl text-gray-600 font-bold">近六個月比較</h4>
|
||||
<div ref="chartBRef" class="w-[90%] h-[90%]"></div> -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 高度比重:5 -->
|
||||
<div class="flex-[5] grid grid-cols-2 gap-2 text-gray-300">
|
||||
<div
|
||||
class="col-span-1 bg-white bg-opacity-70 rounded-xl shadow px-4 py-3 flex flex-col justify-center items-center"
|
||||
>
|
||||
<p>暫無內容</p>
|
||||
<!-- <h4 class="text-xl text-gray-600 font-bold">近三個月比較</h4>
|
||||
<div ref="chartARef" class="w-[90%] h-[90%]"></div> -->
|
||||
</div>
|
||||
<div
|
||||
class="col-span-1 bg-white bg-opacity-70 rounded-xl shadow px-4 py-3 flex flex-col justify-center items-center"
|
||||
>
|
||||
<p>暫無內容</p>
|
||||
<!-- <h4 class="text-xl text-gray-600 font-bold">近六個月比較</h4>
|
||||
<div ref="chartBRef" class="w-[90%] h-[90%]"></div> -->
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted, onUnmounted, nextTick } from "vue";
|
||||
import * as echarts from "echarts";
|
||||
import { brand } from "@/styles/palette";
|
||||
|
||||
// ---- DOM Refs ----
|
||||
const chartARef = ref(null);
|
||||
const chartBRef = ref(null);
|
||||
const chartCRef = ref(null);
|
||||
|
||||
// ---- Chart instances ----
|
||||
let chartA, chartB, chartC;
|
||||
|
||||
// 假資料工具
|
||||
function genTrend(len, start = 50, drift = 0.6, noise = 20) {
|
||||
const arr = [];
|
||||
let v = start;
|
||||
for (let i = 0; i < len; i++) {
|
||||
v = v + drift + (Math.random() * noise * 2 - noise);
|
||||
arr.push(Number(v.toFixed(1)));
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
const commonGrid = {
|
||||
left: 40,
|
||||
right: 20,
|
||||
top: 50,
|
||||
bottom: 30,
|
||||
containLabel: true,
|
||||
};
|
||||
const commonTooltip = { trigger: "axis", axisPointer: { type: "shadow" } };
|
||||
|
||||
// A:三個月趨勢
|
||||
function buildOptionA() {
|
||||
const x = Array.from({ length: 8 }, (_, i) => `週${i + 1}`);
|
||||
const legends = ["6月", "7月", "8月"];
|
||||
const series = legends.map((label, idx) => ({
|
||||
name: label,
|
||||
type: "bar",
|
||||
emphasis: { focus: "series" },
|
||||
data: genTrend(x.length, 40 + idx * 2, 0.5 + idx * 0.1, 1.5),
|
||||
}));
|
||||
|
||||
return {
|
||||
legend: { top: 10 },
|
||||
tooltip: commonTooltip,
|
||||
grid: commonGrid,
|
||||
xAxis: { type: "category", data: x },
|
||||
yAxis: { type: "value" },
|
||||
// 指定顏色
|
||||
color: [brand.green, brand.greenLight, brand.yellow],
|
||||
series,
|
||||
};
|
||||
}
|
||||
|
||||
// B:六個月趨勢
|
||||
function buildOptionB() {
|
||||
const x = Array.from({ length: 8 }, (_, i) => `週${i + 1}`);
|
||||
const legends = ["3月", "4月", "5月", "6月", "7月", "8月"];
|
||||
const series = legends.map((label, idx) => ({
|
||||
name: label,
|
||||
type: "bar",
|
||||
emphasis: { focus: "series" },
|
||||
data: genTrend(x.length, 35 + idx * 1.5, 0.4 + idx * 0.06, 1.6),
|
||||
}));
|
||||
|
||||
return {
|
||||
legend: { type: "scroll", top: 10 },
|
||||
tooltip: commonTooltip,
|
||||
grid: commonGrid,
|
||||
xAxis: { type: "category", data: x },
|
||||
yAxis: { type: "value" },
|
||||
color: [
|
||||
brand.green,
|
||||
brand.greenLight,
|
||||
brand.yellow,
|
||||
brand.purpleLight,
|
||||
brand.purple,
|
||||
brand.gray,
|
||||
],
|
||||
series,
|
||||
};
|
||||
}
|
||||
|
||||
// C:與去年同期比較
|
||||
function buildOptionC() {
|
||||
const months = Array.from({ length: 12 }, (_, i) => `${i + 1}月`);
|
||||
const lastYear = genTrend(12, 48, 0.3, 1.8);
|
||||
const thisYear = lastYear.map((v, i) =>
|
||||
Number((v + 1 + Math.sin(i / 2)).toFixed(1))
|
||||
);
|
||||
|
||||
return {
|
||||
legend: { top: 10, data: ["去年", "今年"] },
|
||||
tooltip: { trigger: "axis" },
|
||||
grid: commonGrid,
|
||||
xAxis: { type: "category", data: months, boundaryGap: false },
|
||||
yAxis: { type: "value" },
|
||||
color: [brand.green, brand.purple],
|
||||
series: [
|
||||
{ name: "去年", type: "line", smooth: true, data: lastYear },
|
||||
{ name: "今年", type: "line", smooth: true, data: thisYear },
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
// 初始化 & resize
|
||||
function initCharts() {
|
||||
if (chartARef.value && !chartA) {
|
||||
chartA = echarts.init(chartARef.value);
|
||||
chartA.setOption(buildOptionA());
|
||||
}
|
||||
if (chartBRef.value && !chartB) {
|
||||
chartB = echarts.init(chartBRef.value);
|
||||
chartB.setOption(buildOptionB());
|
||||
}
|
||||
if (chartCRef.value && !chartC) {
|
||||
chartC = echarts.init(chartCRef.value);
|
||||
chartC.setOption(buildOptionC());
|
||||
}
|
||||
handleResize();
|
||||
}
|
||||
|
||||
let resizeObserver;
|
||||
function handleResize() {
|
||||
const resize = () => {
|
||||
chartA && chartA.resize();
|
||||
chartB && chartB.resize();
|
||||
chartC && chartC.resize();
|
||||
};
|
||||
window.addEventListener("resize", resize);
|
||||
|
||||
const rootEl = document.querySelector("section.flex.flex-col");
|
||||
if (rootEl) {
|
||||
resizeObserver = new ResizeObserver(resize);
|
||||
resizeObserver.observe(rootEl);
|
||||
}
|
||||
}
|
||||
|
||||
function disposeCharts() {
|
||||
resizeObserver && resizeObserver.disconnect();
|
||||
window.removeEventListener("resize", handleResize);
|
||||
chartA && chartA.dispose();
|
||||
chartB && chartB.dispose();
|
||||
chartC && chartC.dispose();
|
||||
chartA = chartB = chartC = null;
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
await nextTick();
|
||||
initCharts();
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
disposeCharts();
|
||||
});
|
||||
</script>
|
@ -6,7 +6,7 @@
|
||||
<div class="flex-[2] grid grid-cols-4 gap-2">
|
||||
<!-- 住民人數 Card -->
|
||||
<div
|
||||
class="col-span-1 cursor-pointer active:opacity-80 text-white bg-brand-green rounded-xl shadow px-4 pt-3 flex flex-col justify-center items-start tracking-widest"
|
||||
class="col-span-1 cursor-pointer active:opacity-80 text-white bg-brand-green rounded-md shadow px-4 pt-3 flex flex-col justify-center items-start tracking-widest"
|
||||
@click="openModal('residents')"
|
||||
>
|
||||
<div class="flex justify-center items-center gap-4">
|
||||
@ -33,7 +33,7 @@
|
||||
|
||||
<!-- 住院人數 Card -->
|
||||
<div
|
||||
class="col-span-1 cursor-pointer active:opacity-80 text-white bg-brand-green rounded-xl shadow px-4 pt-3 flex flex-col justify-center items-start tracking-widest"
|
||||
class="col-span-1 cursor-pointer active:opacity-80 text-white bg-brand-green rounded-md shadow px-4 pt-3 flex flex-col justify-center items-start tracking-widest"
|
||||
@click="openModal('inpatients')"
|
||||
>
|
||||
<div class="flex justify-center items-center gap-4">
|
||||
@ -189,7 +189,7 @@
|
||||
<!-- footer -->
|
||||
<div class="mt-6 text-right">
|
||||
<button
|
||||
class="btn bg-brand-green text-white px-4 py-2 rounded-lg"
|
||||
class="btn bg-brand-green text-white px-4 py-2 rounded-md "
|
||||
@click="closeModal"
|
||||
>
|
||||
關閉
|
||||
@ -199,7 +199,7 @@
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="col-span-1 cursor-pointer active:opacity-80 text-white bg-brand-green rounded-xl shadow px-4 pt-3 flex flex-col justify-center items-start tracking-widest"
|
||||
class="col-span-1 cursor-pointer active:opacity-80 text-white bg-brand-green rounded-md shadow px-4 pt-3 flex flex-col justify-center items-start tracking-widest"
|
||||
>
|
||||
<div class="flex justify-center items-center gap-4">
|
||||
<p class="text-sm">其他人數</p>
|
||||
@ -223,7 +223,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="col-span-1 cursor-pointer active:opacity-80 text-white bg-brand-green rounded-xl shadow px-4 pt-3 flex flex-col justify-center items-start tracking-widest"
|
||||
class="col-span-1 cursor-pointer active:opacity-80 text-white bg-brand-green rounded-md shadow px-4 pt-3 flex flex-col justify-center items-start tracking-widest"
|
||||
>
|
||||
<div class="flex justify-center items-center gap-4">
|
||||
<p class="text-sm">其他人數</p>
|
||||
@ -251,13 +251,13 @@
|
||||
<!-- 高度比重:5 -->
|
||||
<div class="flex-[5] grid grid-cols-2 gap-2">
|
||||
<div
|
||||
class="col-span-1 bg-white bg-opacity-70 rounded-xl shadow p-5 flex flex-col justify-center items-start"
|
||||
class="col-span-1 bg-white bg-opacity-70 rounded-md shadow p-5 flex flex-col justify-center items-start"
|
||||
>
|
||||
<h4 class="text-xl text-gray-600 font-bold">近三個月比較</h4>
|
||||
<div ref="chartARef" class="w-full h-full"></div>
|
||||
</div>
|
||||
<div
|
||||
class="col-span-1 bg-white bg-opacity-70 rounded-xl shadow p-5 flex flex-col justify-center items-start"
|
||||
class="col-span-1 bg-white bg-opacity-70 rounded-md shadow p-5 flex flex-col justify-center items-start"
|
||||
>
|
||||
<h4 class="text-xl text-gray-600 font-bold">近六個月比較</h4>
|
||||
<div ref="chartBRef" class="w-full h-full"></div>
|
||||
@ -266,7 +266,7 @@
|
||||
|
||||
<!-- 高度比重:5 -->
|
||||
<div
|
||||
class="bg-white bg-opacity-70 rounded-xl shadow p-5 flex flex-col justify-center items-start flex-[5]"
|
||||
class="bg-white bg-opacity-70 rounded-md shadow p-5 flex flex-col justify-center items-start flex-[5]"
|
||||
>
|
||||
<h4 class="text-xl text-gray-600 font-bold">與去年同期比較</h4>
|
||||
<div ref="chartCRef" class="w-full h-full"></div>
|
||||
|
@ -1,382 +0,0 @@
|
||||
<template>
|
||||
<section
|
||||
class="flex flex-col gap-2 h-[calc(100vh-72px-32px)] overflow-hidden"
|
||||
>
|
||||
<!-- 高度比重:2 -->
|
||||
<div class="flex-[2] grid grid-cols-4 gap-2">
|
||||
<div
|
||||
class="col-span-1 cursor-pointer active:opacity-80 text-white bg-brand-green rounded-xl shadow px-4 pt-3 flex flex-col justify-center items-start tracking-widest"
|
||||
>
|
||||
<div class="flex justify-center items-center gap-4">
|
||||
<p class="text-sm">住民人數</p>
|
||||
<span>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M12 9a3 3 0 0 0-3 3a3 3 0 0 0 3 3a3 3 0 0 0 3-3a3 3 0 0 0-3-3m0 8a5 5 0 0 1-5-5a5 5 0 0 1 5-5a5 5 0 0 1 5 5a5 5 0 0 1-5 5m0-12.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex justify-center items-baseline gap-1">
|
||||
<p class="text-[36px] xl:text-[40px] font-nats">36/49</p>
|
||||
<p class="text-[12px]">人</p>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="col-span-1 cursor-pointer active:opacity-80 text-white bg-brand-green rounded-xl shadow px-4 pt-3 flex flex-col justify-center items-start tracking-widest"
|
||||
>
|
||||
<div class="flex justify-center items-center gap-4">
|
||||
<p class="text-sm">住院人數</p>
|
||||
<span>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M12 9a3 3 0 0 0-3 3a3 3 0 0 0 3 3a3 3 0 0 0 3-3a3 3 0 0 0-3-3m0 8a5 5 0 0 1-5-5a5 5 0 0 1 5-5a5 5 0 0 1 5 5a5 5 0 0 1-5 5m0-12.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex justify-center items-baseline gap-1">
|
||||
<p class="text-[36px] xl:text-[40px] font-nats">1/36</p>
|
||||
<p class="text-[12px]">人</p>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="col-span-1 cursor-pointer active:opacity-80 text-white bg-brand-green rounded-xl shadow px-4 pt-3 flex flex-col justify-center items-start tracking-widest"
|
||||
>
|
||||
<div class="flex justify-center items-center gap-4">
|
||||
<p class="text-sm">其他人數</p>
|
||||
<span>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M12 9a3 3 0 0 0-3 3a3 3 0 0 0 3 3a3 3 0 0 0 3-3a3 3 0 0 0-3-3m0 8a5 5 0 0 1-5-5a5 5 0 0 1 5-5a5 5 0 0 1 5 5a5 5 0 0 1-5 5m0-12.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex justify-center items-baseline gap-1">
|
||||
<p class="text-[36px] xl:text-[40px] font-nats">0/49</p>
|
||||
<p class="text-[12px]">人</p>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="col-span-1 cursor-pointer active:opacity-80 text-white bg-brand-green rounded-xl shadow px-4 pt-3 flex flex-col justify-center items-start tracking-widest"
|
||||
>
|
||||
<div class="flex justify-center items-center gap-4">
|
||||
<p class="text-sm">其他人數</p>
|
||||
<span>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M12 9a3 3 0 0 0-3 3a3 3 0 0 0 3 3a3 3 0 0 0 3-3a3 3 0 0 0-3-3m0 8a5 5 0 0 1-5-5a5 5 0 0 1 5-5a5 5 0 0 1 5 5a5 5 0 0 1-5 5m0-12.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex justify-center items-baseline gap-1">
|
||||
<p class="text-[36px] xl:text-[40px] font-nats">0/49</p>
|
||||
<p class="text-[12px]">人</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 高度比重:2 -->
|
||||
<div class="flex-[2] grid grid-cols-4 gap-2">
|
||||
<div
|
||||
class="col-span-1 bg-white bg-opacity-70 text-brand-green rounded-xl shadow px-4 pt-3 flex flex-col justify-center items-start tracking-widest"
|
||||
>
|
||||
<div class="flex justify-center items-center gap-4">
|
||||
<p class="text-sm">其他人數</p>
|
||||
<span>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M12 9a3 3 0 0 0-3 3a3 3 0 0 0 3 3a3 3 0 0 0 3-3a3 3 0 0 0-3-3m0 8a5 5 0 0 1-5-5a5 5 0 0 1 5-5a5 5 0 0 1 5 5a5 5 0 0 1-5 5m0-12.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex justify-center items-baseline gap-1">
|
||||
<p class="text-[36px] font-nats">36/49</p>
|
||||
<p class="text-[12px]">人</p>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="col-span-1 bg-white bg-opacity-70 text-brand-green rounded-xl shadow px-4 pt-3 flex flex-col justify-center items-start tracking-widest"
|
||||
>
|
||||
<div class="flex justify-center items-center gap-4">
|
||||
<p class="text-sm">其他人數</p>
|
||||
<span>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M12 9a3 3 0 0 0-3 3a3 3 0 0 0 3 3a3 3 0 0 0 3-3a3 3 0 0 0-3-3m0 8a5 5 0 0 1-5-5a5 5 0 0 1 5-5a5 5 0 0 1 5 5a5 5 0 0 1-5 5m0-12.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex justify-center items-baseline gap-1">
|
||||
<p class="text-[36px] font-nats">1/36</p>
|
||||
<p class="text-[12px]">人</p>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="col-span-1 bg-white bg-opacity-70 text-brand-green rounded-xl shadow px-4 pt-3 flex flex-col justify-center items-start tracking-widest"
|
||||
>
|
||||
<div class="flex justify-center items-center gap-4">
|
||||
<p class="text-sm">其他人數</p>
|
||||
<span>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M12 9a3 3 0 0 0-3 3a3 3 0 0 0 3 3a3 3 0 0 0 3-3a3 3 0 0 0-3-3m0 8a5 5 0 0 1-5-5a5 5 0 0 1 5-5a5 5 0 0 1 5 5a5 5 0 0 1-5 5m0-12.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex justify-center items-baseline gap-1">
|
||||
<p class="text-[36px] font-nats">0/49</p>
|
||||
<p class="text-[12px]">人</p>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="col-span-1 bg-white bg-opacity-70 text-brand-green rounded-xl shadow px-4 pt-3 flex flex-col justify-center items-start tracking-widest"
|
||||
>
|
||||
<div class="flex justify-center items-center gap-4">
|
||||
<p class="text-sm">其他人數</p>
|
||||
<span>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M12 9a3 3 0 0 0-3 3a3 3 0 0 0 3 3a3 3 0 0 0 3-3a3 3 0 0 0-3-3m0 8a5 5 0 0 1-5-5a5 5 0 0 1 5-5a5 5 0 0 1 5 5a5 5 0 0 1-5 5m0-12.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex justify-center items-baseline gap-1">
|
||||
<p class="text-[36px] font-nats">0/49</p>
|
||||
<p class="text-[12px]">人</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 高度比重:5 -->
|
||||
<div class="flex-[5] grid grid-cols-2 gap-2 text-gray-300">
|
||||
<div
|
||||
class="col-span-1 bg-white bg-opacity-70 rounded-xl shadow px-4 py-3 flex flex-col justify-center items-center"
|
||||
>
|
||||
<p>暫無內容</p>
|
||||
<!-- <h4 class="text-xl text-gray-600 font-bold">近三個月比較</h4>
|
||||
<div ref="chartARef" class="w-[90%] h-[90%]"></div> -->
|
||||
</div>
|
||||
<div
|
||||
class="col-span-1 bg-white bg-opacity-70 rounded-xl shadow px-4 py-3 flex flex-col justify-center items-center"
|
||||
>
|
||||
<p>暫無內容</p>
|
||||
<!-- <h4 class="text-xl text-gray-600 font-bold">近六個月比較</h4>
|
||||
<div ref="chartBRef" class="w-[90%] h-[90%]"></div> -->
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted, onUnmounted, nextTick } from "vue";
|
||||
import * as echarts from "echarts";
|
||||
import { brand } from "@/styles/palette";
|
||||
|
||||
// ---- DOM Refs ----
|
||||
const chartARef = ref(null);
|
||||
const chartBRef = ref(null);
|
||||
const chartCRef = ref(null);
|
||||
|
||||
// ---- Chart instances ----
|
||||
let chartA, chartB, chartC;
|
||||
|
||||
// 假資料工具
|
||||
function genTrend(len, start = 50, drift = 0.6, noise = 20) {
|
||||
const arr = [];
|
||||
let v = start;
|
||||
for (let i = 0; i < len; i++) {
|
||||
v = v + drift + (Math.random() * noise * 2 - noise);
|
||||
arr.push(Number(v.toFixed(1)));
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
const commonGrid = {
|
||||
left: 40,
|
||||
right: 20,
|
||||
top: 50,
|
||||
bottom: 30,
|
||||
containLabel: true,
|
||||
};
|
||||
const commonTooltip = { trigger: "axis", axisPointer: { type: "shadow" } };
|
||||
|
||||
// A:三個月趨勢
|
||||
function buildOptionA() {
|
||||
const x = Array.from({ length: 8 }, (_, i) => `週${i + 1}`);
|
||||
const legends = ["6月", "7月", "8月"];
|
||||
const series = legends.map((label, idx) => ({
|
||||
name: label,
|
||||
type: "bar",
|
||||
emphasis: { focus: "series" },
|
||||
data: genTrend(x.length, 40 + idx * 2, 0.5 + idx * 0.1, 1.5),
|
||||
}));
|
||||
|
||||
return {
|
||||
legend: { top: 10 },
|
||||
tooltip: commonTooltip,
|
||||
grid: commonGrid,
|
||||
xAxis: { type: "category", data: x },
|
||||
yAxis: { type: "value" },
|
||||
// 指定顏色
|
||||
color: [brand.green, brand.greenLight, brand.yellow],
|
||||
series,
|
||||
};
|
||||
}
|
||||
|
||||
// B:六個月趨勢
|
||||
function buildOptionB() {
|
||||
const x = Array.from({ length: 8 }, (_, i) => `週${i + 1}`);
|
||||
const legends = ["3月", "4月", "5月", "6月", "7月", "8月"];
|
||||
const series = legends.map((label, idx) => ({
|
||||
name: label,
|
||||
type: "bar",
|
||||
emphasis: { focus: "series" },
|
||||
data: genTrend(x.length, 35 + idx * 1.5, 0.4 + idx * 0.06, 1.6),
|
||||
}));
|
||||
|
||||
return {
|
||||
legend: { type: "scroll", top: 10 },
|
||||
tooltip: commonTooltip,
|
||||
grid: commonGrid,
|
||||
xAxis: { type: "category", data: x },
|
||||
yAxis: { type: "value" },
|
||||
color: [
|
||||
brand.green,
|
||||
brand.greenLight,
|
||||
brand.yellow,
|
||||
brand.purpleLight,
|
||||
brand.purple,
|
||||
brand.gray,
|
||||
],
|
||||
series,
|
||||
};
|
||||
}
|
||||
|
||||
// C:與去年同期比較
|
||||
function buildOptionC() {
|
||||
const months = Array.from({ length: 12 }, (_, i) => `${i + 1}月`);
|
||||
const lastYear = genTrend(12, 48, 0.3, 1.8);
|
||||
const thisYear = lastYear.map((v, i) =>
|
||||
Number((v + 1 + Math.sin(i / 2)).toFixed(1))
|
||||
);
|
||||
|
||||
return {
|
||||
legend: { top: 10, data: ["去年", "今年"] },
|
||||
tooltip: { trigger: "axis" },
|
||||
grid: commonGrid,
|
||||
xAxis: { type: "category", data: months, boundaryGap: false },
|
||||
yAxis: { type: "value" },
|
||||
color: [brand.green, brand.purple],
|
||||
series: [
|
||||
{ name: "去年", type: "line", smooth: true, data: lastYear },
|
||||
{ name: "今年", type: "line", smooth: true, data: thisYear },
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
// 初始化 & resize
|
||||
function initCharts() {
|
||||
if (chartARef.value && !chartA) {
|
||||
chartA = echarts.init(chartARef.value);
|
||||
chartA.setOption(buildOptionA());
|
||||
}
|
||||
if (chartBRef.value && !chartB) {
|
||||
chartB = echarts.init(chartBRef.value);
|
||||
chartB.setOption(buildOptionB());
|
||||
}
|
||||
if (chartCRef.value && !chartC) {
|
||||
chartC = echarts.init(chartCRef.value);
|
||||
chartC.setOption(buildOptionC());
|
||||
}
|
||||
handleResize();
|
||||
}
|
||||
|
||||
let resizeObserver;
|
||||
function handleResize() {
|
||||
const resize = () => {
|
||||
chartA && chartA.resize();
|
||||
chartB && chartB.resize();
|
||||
chartC && chartC.resize();
|
||||
};
|
||||
window.addEventListener("resize", resize);
|
||||
|
||||
const rootEl = document.querySelector("section.flex.flex-col");
|
||||
if (rootEl) {
|
||||
resizeObserver = new ResizeObserver(resize);
|
||||
resizeObserver.observe(rootEl);
|
||||
}
|
||||
}
|
||||
|
||||
function disposeCharts() {
|
||||
resizeObserver && resizeObserver.disconnect();
|
||||
window.removeEventListener("resize", handleResize);
|
||||
chartA && chartA.dispose();
|
||||
chartB && chartB.dispose();
|
||||
chartC && chartC.dispose();
|
||||
chartA = chartB = chartC = null;
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
await nextTick();
|
||||
initCharts();
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
disposeCharts();
|
||||
});
|
||||
</script>
|
@ -1,21 +1,58 @@
|
||||
import { createRouter, createWebHistory } from "vue-router";
|
||||
|
||||
// 匯入各 page
|
||||
import HomePage from "@/pages/home/index.vue";
|
||||
import OperationPage from "@/pages/operation/index.vue";
|
||||
import NursingPage from "@/pages/nursing/index.vue";
|
||||
import SocialWorkerPage from "@/pages/socialWorker/index.vue";
|
||||
import NutritionPage from "@/pages/nutrition/index.vue";
|
||||
// Lazy-loaded pages
|
||||
const HomePage = () => import("@/pages/home/index.vue");
|
||||
const OperationPage = () => import("@/pages/operation/index.vue");
|
||||
const NursingPage = () => import("@/pages/nursing/index.vue");
|
||||
|
||||
const routes = [
|
||||
{ path: "/", name: "Home", component: HomePage },
|
||||
{ path: "/operation", name: "Operation", component: OperationPage },
|
||||
{ path: "/nursing", name: "Nursing", component: NursingPage },
|
||||
{ path: "/social-worker", name: "SocialWorker", component: SocialWorkerPage },
|
||||
{ path: "/nutrition", name: "Nutrition", component: NutritionPage },
|
||||
// 首頁 → 使用 HeadquarterLayout(無 Forge)
|
||||
{
|
||||
path: "/",
|
||||
name: "Home",
|
||||
component: HomePage,
|
||||
meta: {
|
||||
layout: "headquarter",
|
||||
title: "Home",
|
||||
keepAlive: true, // 可選:若要保留捲動/表單狀態
|
||||
},
|
||||
},
|
||||
|
||||
// 其他頁 → 預設使用 MapLayout(有地圖)
|
||||
{
|
||||
path: "/operation",
|
||||
name: "Operation",
|
||||
component: OperationPage,
|
||||
meta: { layout: "map", title: "Operation" },
|
||||
},
|
||||
{
|
||||
path: "/nursing",
|
||||
name: "Nursing",
|
||||
component: NursingPage,
|
||||
meta: { layout: "map", title: "Nursing" },
|
||||
},
|
||||
|
||||
// 404
|
||||
// {
|
||||
// path: "/:pathMatch(.*)*",
|
||||
// name: "NotFound",
|
||||
// component: () => import("@/pages/_errors/NotFound.vue"),
|
||||
// meta: { layout: "headquarter", title: "404 Not Found" },
|
||||
// },
|
||||
];
|
||||
|
||||
export default createRouter({
|
||||
history: createWebHistory(),
|
||||
const router = createRouter({
|
||||
history: createWebHistory(import.meta.env.BASE_URL),
|
||||
routes,
|
||||
// 回上一頁可保留位置,否則回到頂端
|
||||
scrollBehavior(to, from, saved) {
|
||||
return saved || { top: 0 };
|
||||
},
|
||||
});
|
||||
|
||||
router.afterEach((to) => {
|
||||
const base = "UARK";
|
||||
document.title = to.meta?.title ? `${to.meta.title}|${base}` : base;
|
||||
});
|
||||
|
||||
export default router;
|
||||
|
@ -132,7 +132,7 @@
|
||||
/* ========== 卡片/區塊:品牌一致性 ========== */
|
||||
@layer components {
|
||||
.card-brand {
|
||||
@apply rounded-xl shadow-sm border border-gray-100 bg-white;
|
||||
@apply rounded-md shadow-sm border border-gray-100 bg-white;
|
||||
}
|
||||
.chip-brand {
|
||||
@apply inline-flex items-center gap-2 rounded-full px-3 py-1 text-sm bg-brand-green-light text-brand-black;
|
||||
@ -146,7 +146,14 @@
|
||||
}
|
||||
}
|
||||
|
||||
/* 設定全域字體 */
|
||||
html,
|
||||
body,
|
||||
#app {
|
||||
height: 100%;
|
||||
}
|
||||
body {
|
||||
margin: 0;
|
||||
width: 100%; /* 別用 100vw */
|
||||
overflow-x: hidden; /* 防止偶發橫向卷軸 */
|
||||
font-family: "Noto Sans TC", sans-serif;
|
||||
}
|
||||
|
@ -9,5 +9,6 @@ export const brand = {
|
||||
purpleDark: "#7089CA",
|
||||
yellow: "#E1F391",
|
||||
black: "#424242",
|
||||
neutral: "#F0F0F0",
|
||||
};
|
||||
gray: "#828282",
|
||||
grayLight: "#F0F0F0",
|
||||
};
|
||||
|
@ -52,8 +52,10 @@ module.exports = {
|
||||
dark: "#C4E920",
|
||||
},
|
||||
black: "#424242",
|
||||
neutral: {
|
||||
DEFAULT: "#F0F0F0",
|
||||
gray: {
|
||||
light: "#F0F0F0",
|
||||
deepLight:"#D2D2D2",
|
||||
DEFAULT: "#828282",
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -67,7 +69,7 @@ module.exports = {
|
||||
primary: "#34D5C8",
|
||||
secondary: "#C4FBE5",
|
||||
accent: "#A5BEFF",
|
||||
neutral: "#424242",
|
||||
neutral: "#828282",
|
||||
"base-100": "#ffffff",
|
||||
warning: "FF8678",
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user