進入專案開發下半場(Day 16~30),我們的重點將從「基礎核心功能串接」轉向「使用者體驗(UX)、無障礙設計(Accessibility)與系統穩定度提升」。
對於高齡長者來說,傳統智慧型手機介面常因字體過小、顏色對比不足或按鈕層級複雜而造成使用障礙。今天我們將針對 PrescriptionVLM 的 LINE 聊天室與 Web 儀表板,進行專為銀髮族打造的無障礙介面(Silver Accessibility UI/UX)升級。完成項目包含:
根據高齡無障礙設計規範(WCAG 2.1 AAA 級標準),針對高齡使用者設計產品時應遵循以下原則:
app.py)原本的推播使用的是純文字訊息,長輩閱讀較為吃力。今天我們改用 LINE Flex Message,將解析成果包裝成專為長輩設計的高對比大字卡片。
1. 匯入 LINE Flex Message 模組
請開啟 app.py,確認頂部 LINE SDK 匯入區塊包含 Flex 相關物件:
from linebot.v3.messaging import (
Configuration,
ApiClient,
MessagingApi,
PushMessageRequest,
ReplyMessageRequest,
TextMessage,
FlexMessage,
FlexContainer
)
2. 新增 Flex Message 卡片建構函式
在 app.py 中新增 create_elderly_flex_card 函式:
def create_elderly_flex_card(summary, medicines_count, safety_warnings, audio_url):
"""打造專為高齡長輩設計的大字體高對比 Flex Message 卡片 JSON"""
warning_contents = []
if safety_warnings:
warning_contents = [
{
"type": "box",
"layout": "vertical",
"backgroundColor": "#FFE2E2",
"cornerRadius": "md",
"paddingAll": "md",
"margin": "md",
"contents": [
{
"type": "text",
"text": "⚠️ 用藥安全特別提醒:",
"weight": "bold",
"color": "#CC0000",
"size": "md"
},
{
"type": "text",
"text": ";".join(safety_warnings),
"color": "#990000",
"size": "sm",
"wrap": True,
"margin": "xs"
}
]
}
]
card_json = {
"type": "bubble",
"header": {
"type": "box",
"layout": "vertical",
"backgroundColor": "#4F46E5",
"paddingAll": "lg",
"contents": [
{
"type": "text",
"text": "💊 服藥提醒與藥單摘要",
"color": "#FFFFFF",
"weight": "bold",
"size": "xl"
}
]
},
"body": {
"type": "box",
"layout": "vertical",
"spacing": "md",
"contents": [
{
"type": "text",
"text": f"本次藥單共包含 {medicines_count} 種藥品",
"weight": "bold",
"size": "lg",
"color": "#1F2937"
},
*warning_contents,
{
"type": "text",
"text": "📢 播報摘要:",
"weight": "bold",
"color": "#4B5563",
"margin": "top"
},
{
"type": "text",
"text": summary,
"wrap": True,
"size": "md",
"color": "#111827"
}
]
},
"footer": {
"type": "box",
"layout": "vertical",
"contents": [
{
"type": "button",
"action": {
"type": "message",
"label": "✅ 我已按時吃藥",
"text": "已吃藥"
},
"style": "primary",
"color": "#059669",
"height": "sm"
}
]
}
}
return card_json
3. 更新 LINE 推播邏輯
修改 send_line_notification 函式,改為發送 Flex Message:
# 3. 更新 LINE 推播邏輯
# 修改 send_line_notification 函式,帶入預設值 audio_url="" 防止少傳參數導致 500 錯誤:
def send_line_notification(summary, medicines_count, safety_warnings, audio_url=""):
if not line_bot_api or not line_user_id:
logger.warning("未設定 LINE Token 或 User ID,跳過推播")
return
try:
flex_card = create_elderly_flex_card(summary, medicines_count, safety_warnings, audio_url)
flex_message = FlexMessage(
alt_text="💊 長輩用藥關懷通知",
contents=FlexContainer.from_dict(flex_card)
)
push_message_request = PushMessageRequest(
to=line_user_id,
messages=[flex_message]
)
line_bot_api.push_message(push_message_request)
logger.info("LINE 高齡無障礙 Flex 卡片發送成功")
except Exception as e:
logger.error(f"LINE Flex 推播發送失敗: {str(e)}")
接著更新 Web 前端介面,在頂部導覽列加入「放大字級 / 切換高對比」選單,並在音訊播放器旁加入調速按鈕。
更新 templates/dashboard.html 的 與 JavaScript 區塊:
<!-- 頂部導覽列:新增無障礙切換按鈕 -->
<header class="bg-indigo-600 text-white shadow-lg py-4 px-6 mb-8">
<div class="max-w-7xl mx-auto flex justify-between items-center flex-wrap gap-4">
<h1 class="text-2xl font-bold flex items-center gap-2" id="header-title">
<span>💊</span> PrescriptionVLM 關懷儀表板
</h1>
<div class="flex items-center gap-3">
<button onclick="toggleElderlyMode()" class="bg-amber-400 hover:bg-amber-500 text-slate-900 font-bold px-4 py-2 rounded-xl shadow transition text-sm flex items-center gap-1">
🔍 一鍵切換大字長輩模式
</button>
<span class="bg-indigo-500 text-xs px-3 py-1 rounded-full">系統運作中 (Online)</span>
</div>
</div>
</header>
前端 JavaScript 中新增動態縮放與語音調速控制:
// 切換高齡大字視覺模式
let isElderlyMode = false;
function toggleElderlyMode() {
isElderlyMode = !isElderlyMode;
const body = document.body;
if (isElderlyMode) {
body.classList.add('text-lg');
document.querySelectorAll('h2').forEach(el => el.classList.add('text-2xl'));
document.querySelectorAll('p').forEach(el => el.classList.add('text-base', 'font-medium'));
alert("已啟動【長輩大字模式】:放大字體與提升色彩對比!");
} else {
body.classList.remove('text-lg');
document.querySelectorAll('h2').forEach(el => el.classList.remove('text-2xl'));
document.querySelectorAll('p').forEach(el => el.classList.remove('text-base', 'font-medium'));
}
}
// 動態調整音訊播放速率 (例如設定為 0.8 倍速慢速播放)
function setAudioSpeed(audioId, speed) {
const audio = document.getElementById(audioId);
if (audio) {
audio.playbackRate = speed;
}
}
在動態渲染音訊播放器時,加入倍速切換按鈕:
<div>
<h4 class="text-sm font-semibold text-slate-500 mb-1">🎧 語音檔播放(支援慢速播報):</h4>
<div class="flex items-center gap-2">
<audio id="audio-${item.id}" controls class="w-full h-8">
<source src="${item.audio_url}" type="audio/mpeg">
</audio>
<button onclick="setAudioSpeed('audio-${item.id}', 0.8)" class="bg-slate-200 hover:bg-slate-300 text-xs px-2.5 py-1.5 rounded-lg whitespace-nowrap font-bold">
🐢 0.8x 慢速
</button>
<button onclick="setAudioSpeed('audio-${item.id}', 1.0)" class="bg-slate-200 hover:bg-slate-300 text-xs px-2.5 py-1.5 rounded-lg whitespace-nowrap font-bold">
▶️ 1.0x 常速
</button>
</div>
</div>
1. 重新構建並啟動 Docker 容器
在 Terminal 執行重新編譯:
docker rm -f prescription_service
docker build -t prescription-vlm:v1.0 .
docker run -d -p 5000:5000 --env-file .env --name prescription_service prescription-vlm:v1.0
2. 驗證無障礙功能
💡 避坑小提示(Troubleshooting):
若在執行
curl測試時遇到503 UNAVAILABLE (This model is currently experiencing high demand)錯誤,代表 Google 雲端 API 處於尖峰流量狀態,此為外部伺服器瞬時負載現象,並非程式碼錯誤。稍候數秒重試或程式內建重試(Retry)即可順利完成解析。
測試通過後,將 Day 16 的修改提交至 GitHub:
git add .
git commit -m "保留雙引號 改填寫自己要記錄的標記 ex.鐵人賽第十六天"
git push
今天我們針對高齡族群的使用情境進行了完整的介面與互動優化,包含 LINE 視覺化 Flex 大字卡片、Web 一鍵大字模式 以及 0.8x 語音慢速播放功能,讓系統不僅技術到位,在體驗層面上更具備社會關懷的人本溫度。
明天(Day 17),我們將進一步強化系統的安全與穩定性,導入 靜態型別檢查(Mypy/Pydantic)與輸入資料防禦校驗,確保多模態 VLM 在面對模糊、破損藥袋圖片時依然能穩定運作不崩潰!