diff --git a/package-lock.json b/package-lock.json index 8214a7b..f871c6a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,12 @@ "name": "uark_front", "version": "0.0.0", "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", "echarts": "^6.0.0", "leaflet": "^1.9.4", @@ -534,6 +540,64 @@ "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": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", @@ -2561,6 +2625,16 @@ "dev": true, "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": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", diff --git a/package.json b/package.json index da2364a..d4f4c08 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,12 @@ "preview": "vite preview" }, "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", "echarts": "^6.0.0", "leaflet": "^1.9.4", diff --git a/src/layouts/HeadquarterLayout.vue b/src/layouts/HeadquarterLayout.vue index e7a9f19..c2c9ec5 100644 --- a/src/layouts/HeadquarterLayout.vue +++ b/src/layouts/HeadquarterLayout.vue @@ -1,8 +1,8 @@ - + - - + + diff --git a/src/layouts/MapLayout.vue b/src/layouts/MapLayout.vue index f0c79af..79c0c64 100644 --- a/src/layouts/MapLayout.vue +++ b/src/layouts/MapLayout.vue @@ -14,7 +14,7 @@ - + diff --git a/src/layouts/NavBar.vue b/src/layouts/NavBar.vue index 4391352..59a205d 100644 --- a/src/layouts/NavBar.vue +++ b/src/layouts/NavBar.vue @@ -530,19 +530,13 @@ const triggerRef = ref(null); const panelRef = ref(null); const facilities = [ - "崇恩護理之家", - "崇祐護理之家", - "護祐護理之家", - "育祐護理之家", - "崇智護理之家", - "崇恩居家護理所", - "傳心日間照顧中心", - "敬慈居家服務中心", - "崇恩長照中心(養護型)", - "崇祐長照中心(養護型)", - "傳祐長照中心(養護型)", - "慈祐長照中心(養護型)", - "中安崇恩長照中心(養護型)", + "A 機構", + "B 機構", + "C 機構", + "D 機構", + "E 機構", + "F 機構", + ]; const selectedItem = ref(facilities[0]); diff --git a/src/pages/home/index.vue b/src/pages/home/index.vue index 1fb23aa..65e6dbf 100644 --- a/src/pages/home/index.vue +++ b/src/pages/home/index.vue @@ -1,6 +1,6 @@ - + - + @@ -90,8 +90,7 @@ - - + - + - + 總數:{{ currentFacility.diet.meat.total }} 一般:{{ currentFacility.diet.meat.normal }} @@ -218,9 +217,9 @@ - + - + 總數:{{ currentFacility.diet.veg.total }} 一般:{{ currentFacility.diet.veg.normal }} @@ -349,7 +348,7 @@ - + - 今日活動 - - - - - - 時間 - 機構 - 活動名稱 - - - - - {{ row.time }} - {{ row.org }} - {{ row.title }} - - - - + + + 今日活動 + + 行事曆 + + + + + + + 時間 + 機構名稱 + 活動名稱 + + + + + {{ row.time }} + {{ row.org }} + {{ row.title }} + + + + + 共 {{ total }} 筆,每頁 {{ pageSize }} 筆 - - - 今日異常事件 - - - - + + + + + + + + + + 今日活動行事曆 + + + - - 時間 - 機構 - 事件 - - - - - {{ row.time }} - {{ row.org }} - {{ row.event }} - - - + + + + + + 關閉 + + + + + + + 今日異常事件 + + + + + 時間 + 機構名稱 + 事件 + + + + + {{ row.time }} + {{ row.org }} + {{ row.event }} + + + + + 共 {{ incidentTotal }} 筆,每頁 {{ incidentPageSize }} 筆 今日派車總表 - - - - + + + + 時間 + 機構名稱 + 聯絡人 + + + + - - 時間 - 機構 - 聯絡人 - - - - - {{ row.time }} - {{ row.org }} - - {{ row.contact }} - - - - - + {{ row.time }} + {{ row.org }} + {{ row.contact }} + + + // ===== 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 { ref, @@ -558,37 +615,37 @@ const KAOHSIUNG_BOUNDS_LOOSE = L.latLngBounds([22.35, 120.0], [23.05, 120.75]); // 六個據點(固定座標,無需發 fetch) const LOCATIONS = [ { - name: "崇恩護理之家", + name: "A 機構", addr: "高雄市楠梓區立仁街131、133號", lat: 22.7409648895, lng: 120.3354644775, }, { - name: "育祐護理之家", + name: "B 機構", addr: "高雄市楠梓區常德路317巷9弄27號", lat: 22.7366924286, lng: 120.3363342285, }, { - name: "崇祐護理之家", + name: "C 機構", addr: "高雄市楠梓區宏昌街135、137號", lat: 22.717588, lng: 120.29406, }, { - name: "崇智護理之家", + name: "D 機構", addr: "高雄市左營區民族一路980號", lat: 22.678054, lng: 120.3192, }, { - name: "護祐護理之家", + name: "E 機構", addr: "高雄市三民區黃興路336號", lat: 22.651488, lng: 120.33731, }, { - name: "傳祐長照中心", + name: "F 機構", addr: "高雄市小港區沿海一路377號", lat: 22.5644512177, lng: 120.3544540405, @@ -601,13 +658,13 @@ const iconBase = `${base}img/leaflet/`; // building_1 = 總部,2~7 = 六家機構 const FACILITY_ASSETS = { -ALL: `${base}img/building/building_1.jpg`, // 或想用總部圖:`${base}img/building/headquarter.png` -崇恩護理之家: `${base}img/building/building_2.jpg`, -育祐護理之家: `${base}img/building/building_3.jpg`, -崇祐護理之家: `${base}img/building/building_4.jpg`, -崇智護理之家: `${base}img/building/building_5.jpg`, -護祐護理之家: `${base}img/building/building_6.jpg`, -傳祐長照中心: `${base}img/building/building_7.jpg`, + ALL: `${base}img/building/building_1.jpg`, // 或想用總部圖:`${base}img/building/headquarter.png` + "A 機構": `${base}img/building/building_2.jpg`, + "B 機構": `${base}img/building/building_3.jpg`, + "C 機構": `${base}img/building/building_4.jpg`, + "D 機構": `${base}img/building/building_5.jpg`, + "E 機構": `${base}img/building/building_6.jpg`, + "F 機構": `${base}img/building/building_7.jpg`, }; // Leaflet 預設圖標 @@ -625,8 +682,7 @@ L.Marker.prototype.options.icon = defaultIcon; // ===== Facility Mock Data (單一真實來源) ===== const FACILITY_DATA = { ALL: { - photo: "/img/building/headquarter.png", - desc: "崇恩長期照顧集團——大南部在地深耕,整合醫護團隊與專業照護人員,提供高齡照護服務總部。", + desc: "OO長期照顧集團——在全台各地皆有眾多據點,整合醫護團隊與專業照護人員,提供高齡照護服務總部。", progress: { residents: { current: 240, total: 360 }, vacancy: { current: 120, total: 360 }, @@ -666,9 +722,8 @@ const FACILITY_DATA = { veg: { total: 367, normal: 318, soft: 26, tube: 23 }, }, }, - 崇恩護理之家: { - photo: "/img/building/chong-en.png", - desc: "崇恩護理之家重視跨專業合作,提供 24 小時專業護理與生活照顧服務。", + "A 機構": { + desc: "A 機構重視跨專業合作,提供 24 小時專業護理與生活照顧服務,Lorem ipsum dolor sit amet consectetur adipisicing elit。", progress: { residents: { current: 36, total: 49 }, vacancy: { current: 12, total: 49 }, @@ -708,9 +763,8 @@ const FACILITY_DATA = { veg: { total: 82, normal: 72, soft: 5, tube: 5 }, }, }, - 育祐護理之家: { - photo: "/img/building/yu-you.png", - desc: "育祐護理之家以長者需求為中心,打造安全舒適的照護環境。", + "B 機構": { + desc: "B 機構以長者需求為中心,打造安全舒適的照護環境,Lorem ipsum dolor sit amet, consectetur adipisicing elit.。", progress: { residents: { current: 42, total: 60 }, vacancy: { current: 8, total: 60 }, @@ -750,9 +804,8 @@ const FACILITY_DATA = { veg: { total: 61, normal: 53, soft: 5, tube: 3 }, }, }, - 崇祐護理之家: { - photo: "/img/building/chong-you.png", - desc: "崇祐護理之家強調復健與社會參與,陪伴長者建立日常節奏。", + "C 機構": { + desc: "C 機構強調復健與社會參與,陪伴長者建立日常節奏,Lorem ipsum dolor sit amet consectetur adipisicing elit。", progress: { residents: { current: 50, total: 70 }, vacancy: { current: 15, total: 70 }, @@ -792,9 +845,8 @@ const FACILITY_DATA = { veg: { total: 71, normal: 62, soft: 5, tube: 4 }, }, }, - 崇智護理之家: { - photo: "/img/building/chong-zhi.png", - desc: "崇智護理之家導入智慧照護設備,提升照護品質與效率。", + "D 機構": { + desc: "D 機構導入智慧照護設備,提升照護品質與效率,Lorem ipsum dolor sit amet consectetur adipisicing elit. Porro, enim。", progress: { residents: { current: 38, total: 55 }, vacancy: { current: 10, total: 55 }, @@ -834,9 +886,8 @@ const FACILITY_DATA = { veg: { total: 51, normal: 44, soft: 3, tube: 5 }, }, }, - 護祐護理之家: { - photo: "/img/building/hu-you.png", - desc: "護祐護理之家著重個別化照護計畫,維護長者尊嚴與生活品質。", + "E 機構": { + desc: "E 機構著重個別化照護計畫,維護長者尊嚴與生活品質,Lorem ipsum dolor sit amet, consectetur adipisicing elit.。", progress: { residents: { current: 45, total: 62 }, vacancy: { current: 9, total: 62 }, @@ -876,9 +927,8 @@ const FACILITY_DATA = { veg: { total: 57, normal: 49, soft: 5, tube: 3 }, }, }, - 傳祐長照中心: { - photo: "/img/building/chuan-you.png", - desc: "傳祐長照中心以社區融入為核心,串連日照與居家照護資源。", + "F 機構": { + desc: "F 機構以社區融入為核心,串連日照與居家照護資源,Lorem ipsum dolor sit amet consectetur adipisicing elit. Porro, enim。", progress: { residents: { current: 30, total: 40 }, vacancy: { current: 6, total: 40 }, @@ -931,7 +981,7 @@ const currentFacility = computed(() => { const key = selectedFacility.value || "ALL"; return { ...data, - photo: FACILITY_ASSETS[key] || FACILITY_ASSETS.ALL, + photo: FACILITY_ASSETS[key] || FACILITY_ASSETS.ALL, }; }); @@ -1209,10 +1259,10 @@ function syncTooltips() { } } } - - if (map?.invalidateSize) { + const m = map; + if (m?.invalidateSize) { requestAnimationFrame(() => { - map.invalidateSize(); + m?.invalidateSize?.(); refreshAllTooltips(); }); } @@ -1269,9 +1319,10 @@ onMounted(() => { // 初始後多次 invalidateSize,避免白屏 requestAnimationFrame(() => { - map?.invalidateSize?.(); + const m = map; // 先「快照」目前的 map + m?.invalidateSize?.(); requestAnimationFrame(() => { - map?.invalidateSize?.(); + m?.invalidateSize?.(); refreshAllTooltips(); }); }); @@ -1328,10 +1379,20 @@ watch(selectedFacility, () => { }); // ===== 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([ - { id: 1, time: "10:00", org: "崇祐護理之家", title: "全人評估相關課程" }, - { id: 2, time: "14:00", org: "崇祐護理之家", title: "CPR教育訓練" }, - { id: 3, time: "20:00", org: "傳祐長照中心", title: "消防夜間演練" }, + { id: 1, time: "09:15", org: "A 機構", title: "全人評估相關課程" }, + { id: 2, time: "10:00", org: "B 機構", title: "CPR 教育訓練" }, + { 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; @@ -1346,10 +1407,93 @@ const pagedRows = computed(() => (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([ - { id: 1, time: "10:00", org: "崇恩護理之家", event: "跌倒事件" }, - { id: 2, time: "12:00", org: "育祐護理之家", event: "延遲給藥" }, + { id: 1, time: "10:00", org: "B 機構", event: "跌倒事件" }, + { id: 2, time: "12:00", org: "F 機構", event: "延遲給藥" }, ]); const incidentPageSize = 10; const incidentPage = ref(1); @@ -1365,9 +1509,9 @@ const pagedIncidentRows = computed(() => ); const dispatchRows = ref([ - { id: 1, time: "09:30", org: "崇恩護理之家", contact: "黃國毅" }, - { id: 2, time: "10:30", org: "育祐護理之家", contact: "李佩怡" }, - { id: 3, time: "11:30", org: "崇智護理之家", contact: "陳筱安" }, + { id: 1, time: "09:30", org: "A 機構", contact: "黃國毅" }, + { id: 2, time: "10:30", org: "C 機構", contact: "李佩怡" }, + { id: 3, time: "11:30", org: "E 機構", contact: "陳筱安" }, ]); const dispatchPageSize = 10; const dispatchPage = ref(1); @@ -1387,11 +1531,12 @@ const pagedDispatchRows = computed(() => function setInfoMode(mode) { infoMode.value = mode; nextTick(() => { - if (!map) return; + const m = map; + if (!m) return; requestAnimationFrame(() => { - map.invalidateSize(); + m?.invalidateSize?.(); requestAnimationFrame(() => { - map.invalidateSize(); + m?.invalidateSize?.(); refreshAllTooltips(); }); }); @@ -1399,4 +1544,82 @@ function setInfoMode(mode) { } - + diff --git a/src/pages/nursing/index.vue b/src/pages/nursing/index.vue index 93c9848..fa660ad 100644 --- a/src/pages/nursing/index.vue +++ b/src/pages/nursing/index.vue @@ -1,6 +1,6 @@ diff --git a/src/pages/operation/index.vue b/src/pages/operation/index.vue index e942a5a..19e15d2 100644 --- a/src/pages/operation/index.vue +++ b/src/pages/operation/index.vue @@ -1,6 +1,6 @@ diff --git a/src/style.css b/src/style.css index e301a83..95aa288 100644 --- a/src/style.css +++ b/src/style.css @@ -2,6 +2,10 @@ @tailwind components; @tailwind utilities; @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 所有字重 */ @font-face {
@@ -90,8 +90,7 @@
總數:{{ currentFacility.diet.meat.total }}
一般:{{ currentFacility.diet.meat.normal }}
總數:{{ currentFacility.diet.veg.total }}
一般:{{ currentFacility.diet.veg.normal }}