iT邦幫忙

2026 iThome 鐵人賽

DAY 25
0
自我挑戰組

Vscode 實作:用 HTML/CSS/JS 打造醫藥健康小工具箱系列 第 25 篇

Day 25:【Tool 4 實作】倒數邏輯與動態進度條:依自訂效期計算剩餘百分比與 CSS 警示燈號切換

  • 分享至 

  • xImage
  •  

本篇文章目錄

  1. 前言:將開瓶效期轉化為動態時間軸
  2. 兩大核心機制拆解:倒數天數與動態百分比
  3. 實戰開發:自訂效期計算與 CSS 燈號切換
  4. 程式碼重點與體驗細節解析
  5. 結語

一、 前言:將開瓶效期轉化為動態時間軸

在前端開發的領域中,處理「時間」永遠是一門藝術。不管是購物車的限時搶購、倒數計時器,還是有效期限的追蹤,工程師都需要將冷冰冰的日期數據,轉化為使用者一眼就能看懂的視覺語言。

我們的 [Tool 4] 旨在解決醫療與日常保健中的一大痛點:藥品與保養品的「開封效期」管理。

許多藥品(例如眼藥水、眼軟膏或抗生素懸浮液)在未拆封時雖有兩三年的保存期,但一旦開封,使用期限就會瞬間縮短至 28 天或 30 天。如果光憑使用者的記憶去推算「到底打開幾天了」,極易造成誤用過期藥品的風險。今天我們要為 [Tool 4] 注入核心計算大腦,透過動態計算剩餘天數,結合直覺的 CSS 馬卡龍燈號,打造兼具視覺美感與實用性的時間管理模組!

二、 兩大核心機制拆解:倒數天數與動態百分比

在進入程式碼之前,我們先來拆解核心邏輯與視覺燈號的運算公式:

1. 剩餘天數計算公式(Remaining Days):

首先,我們需要取得藥品的開封日期(openDate),計算其與今日(today)的時間差(diffDays)。隨後將使用者自訂的總效期(totalExpiry)扣除已過天數:

剩餘天數 (remainDays) = 總效期 (totalExpiry) - 已過天數 (diffDays)

2. 三階段警示燈號(Traffic Light System):

為了讓使用者在開啟介面時能第一時間察覺危機程度,我們將狀態劃分為三個動態區間:

  • 安全期(Green):remainDays> 7天,顯示綠色標籤,代表狀態良好。
  • 警告期(Yellow):0 天 < remainDays < 7天,顯示黃色標籤,提示「儘速使用」。
  • 過期(Red):remainDays < 0 天,顯示紅色標籤,並計算出「已過期 N 天」。

三、 實戰開發:自訂效期計算與 CSS 燈號切換

我們在 /tool4-timer.js 中撰寫動態狀態判斷邏輯,並透過 /components.css 完成膠囊標籤與彈性卡片列的渲染:

/tool4-timer.js

// 兼容舊資料:若以往儲存的項目沒有 expiryDays,自動給予 28 天預設值
const totalExpiry = item.expiryDays || 28;
const remainDays = totalExpiry - diffDays;

// 判定狀態 Badge
let statusBadge = "";
if (remainDays < 0) {
  statusBadge = `<span class="badge badge-red">已過期 ${Math.abs(remainDays)} 天</span>`;
} else if (remainDays <= 7) {
  statusBadge = `<span class="badge badge-yellow">剩餘 ${remainDays} 天 (儘速使用)</span>`;
} else {
  statusBadge = `<span class="badge badge-green">剩餘 ${remainDays} 天</span>`;
}

/components.css

.badge {
  display: inline-block;
  padding: 3px 10px;
  border-radius: 12px;
  font-size: 0.8rem;
  font-weight: bold;
  margin-left: 8px;
  background-color: #E9ECEF;
}

.badge-green { background-color: var(--macaron-mint); }
.badge-yellow { background-color: var(--macaron-yellow); }
.badge-red { background-color: var(--macaron-pink); }

.hidden { display: none !important; }
.note { font-size: 0.8rem; color: var(--text-muted); margin-top: 10px; }

/* 表格與列表 */
.table-container { margin-top: 20px; }
.med-table { width: 100%; border-collapse: collapse; text-align: left; }
.med-table th, .med-table td { padding: 12px; border-bottom: 1px solid #E9ECEF; }
.med-table th { background-color: var(--bg-cream); font-size: 0.9rem; }
.btn-del { background: none; border: none; color: #FA5252; cursor: pointer; font-weight: bold; }

/* 定時器清單列 */
.timer-container { margin-top: 20px; display: flex; flex-direction: column; gap: 12px; }
.timer-item {
  padding: 15px;
  border-radius: var(--radius-sm);
  background-color: var(--bg-cream);
  display: flex;
  justify-content: space-between;
  align-items: center;
}

四、 程式碼重點與體驗細節解析

1. 短路邏輯預設值(Short-Circuit Evaluation)保障向前相容

軟體迭代中最怕「新功能上線,舊資料壞掉」。在以往版本中,我們儲存的物件結構可能沒有 expiryDays 這個欄位。

透過 item.expiryDays || 28 這種預設備援寫法(Fallback),當系統讀取到舊版無 expiryDays 屬性的物件時,會自然降級使用 28 天作為算式基礎,避免算出 NaN 導致 UI 崩潰。

2. Math.abs() 正數轉化與使用者語意優化

當天數小於 0(例如 -3 天)時,若直接拿變數渲染成「已過期 -3 天」,在中文語意上顯得怪異且缺乏專業感。

使用 Math.abs(remainDays) 取得負數的絕對值,動態印出「已過期 3 天」,能大幅提升人機互動的自然度。

3. OOCSS 概念下的樣式拆解與主題變數綁定

在 CSS 處理上,我們將 .badge 的結構(內距、圓角、字體大小)與色彩樣式(.badge-green、.badge-red)進行解耦。

配色更使用了 var(--macaron-mint) 與 var(--macaron-pink) 等馬卡龍主題變數,擺脫傳統高飽和度紅綠色的刺眼感,讓醫療提醒工具呈現溫和且清晰的視覺體驗。

4. Flexbox 與 CSS gap 打造零邊界雜訊排版

在 .timer-container 中使用 display: flex; flex-direction: column; gap: 12px;,能優雅地建立清單卡片之間的均勻間距,告別以往必須用 :not(:last-child) 處裡 margin-bottom 的繁瑣舊做法。

五、 結語

今天我們成功實作了 [Tool 4] 的核心倒數運算邏輯與動態 CSS 警示燈號,將開瓶時間轉化為清晰易懂的視覺化提示,確保使用者能直覺掌控藥品有效期限。

在明天的 [Day 26] 中,我們將進行 [Tool 4 跨瀏覽器 Local Storage 歷史紀錄同步與動態刪除],讓這些自訂效期的倒數項目能夠妥善持久化儲存,並支援無痛的清理與維護機制!離鐵人賽終點越來越近了,我們明天見!


上一篇
Day 24:【JS 語法】Date 物件與自訂效期:取得 <input type="date"> 與自訂效期天數 (expiryDays)
系列文
Vscode 實作:用 HTML/CSS/JS 打造醫藥健康小工具箱 共 25 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言