🎯 商業痛點:桌面版為什麼必要?
昨天完成了 Web 版本,但在與部落辦公室的討論中,我發現了真實需求:
部落活動中心的電腦配置落後。他們的 Windows 7 舊電腦只有 64GB 儲存空間,Electron 應用動輒 100MB+,加上瀏覽器快取,根本裝不下。
此外還有三個核心痛點:
長輩操作習慣:他們習慣點擊桌面圖示,而不是輸入網址
網路不穩定:鄉下網路時斷時續,需要離線緩存機制
政府補助流程:必須匯出政府指定格式的 Excel 報表
這些需求不是「錦上添花」,而是直接影響產品能否在部落落地。
💰 技術選型的經濟學
我評估了三個方案:
方案 | 檔案大小 | 啟動時間 | 開發成本 | 長輩友善度 |
|---|---|---|---|---|
Electron | 100MB+ | 3-5 秒 | 低(重用 Web) | ⭐⭐⭐ |
Tauri | 8MB | < 1 秒 | 中等 | ⭐⭐⭐⭐⭐ |
原生 Cocoa/Win32 | 5MB | < 1 秒 | 極高 | ⭐⭐ |
決策關鍵:Tauri 的 8MB 讓老舊電腦能裝下,快速啟動讓長輩不用等待。
🔧 智能 API 配置:一套程式碼,三種部署
經過多次部署實戰,我設計了環境感知的 API 架構。這是系統架構的核心創新:
// config/api.ts - 多環境 API 配置
const getApiBaseUrl = () => {
// Tauri 桌面版:連接本地 Django 後端
if (window.__TAURI__) {
return 'http://127.0.0.1:8000'
}
// 開發模式:透過 Vite proxy 處理 CORS
if (import.meta.env.DEV) {
return ''
}
// 生產模式:直連 Railway API
return 'https://pangcah-accounting-system-production.up.railway.app'
}
export const apiClient = axios.create({
baseURL: getApiBaseUrl(),
timeout: 10000,
headers: { 'Content-Type': 'application/json' },
})
設計亮點:同一套前端程式碼支援 Tauri 桌面版、本地開發、雲端生產三種模式,零配置切換。
無感 JWT 刷新:讓長輩不被打斷
在 8 小時的家族聚會中,token 可能過期。我實現了自動重新認證機制:
apiClient.interceptors.response.use(
(response) => response,
async (error) => {
const originalRequest = error.config
if (error.response?.status === 401 && !originalRequest._retry) {
originalRequest._retry = true
try {
const refreshToken = localStorage.getItem('refresh_token')
const response = await axios.post('/api/v1/auth/refresh/', {
refresh: refreshToken,
})
const newToken = response.data.access
localStorage.setItem('access_token', newToken)
originalRequest.headers.Authorization = `Bearer ${newToken}`
return apiClient(originalRequest)
} catch (refreshError) {
localStorage.clear()
window.location.href = '/login'
}
}
return Promise.reject(error)
}
)
使用者體驗:8 小時的活動中,使用者永遠不會因為 token 過期被中斷操作。
🖥️ Tauri 桌面版:為什麼選擇它?
核心數據對比
檔案大小:8MB vs Electron 的 100MB(減少 92.5%)
冷啟動時間:< 1 秒 vs Electron 的 3-5 秒(快 3-5 倍)
記憶體用量:平均 80MB vs Electron 的 300MB+
一套程式碼:支援 macOS、Windows、Web 三個平台
實現細節
// tauri.conf.json - 應用程式配置
{
"package": {
"productName": "PAPA 阿美族家族記帳",
"version": "1.0.0"
},
"tauri": {
"allowlist": {
"all": false,
"shell": { "open": true },
"dialog": { "open": true, "save": true },
"fs": { "readFile": true, "writeFile": true }
}
}
}
安全性設計:最小權限原則,只開放必需的功能。
💻 桌面版核心功能:為長輩設計
功能 1:大螢幕友善介面
// hooks/useDesktop.ts
export const useDesktop = () => {
const enableLargeTextMode = () => {
document.documentElement.style.fontSize = '120%'
localStorage.setItem('fontSize', 'large')
}
return { enableLargeTextMode }
}
設計考量:
字體大小 120% 以上
按鈕尺寸不小於 48px(易於指點操作)
高對比度配色(適合視力下降的長輩)
減少選項,只保留核心功能
功能 2:直接匯出 Excel 報表
const exportToExcel = async (eventData: EventData) => {
if (!isDesktop) return false
const { save } = await import('@tauri-apps/api/dialog')
const filePath = await save({
defaultPath: `${eventData.name}_財務報表.xlsx`,
filters: [{ name: 'Excel files', extensions: ['xlsx'] }]
})
if (filePath) {
const excelData = generateGovernmentReport(eventData)
await writeTextFile(filePath, excelData)
showSnackbar(`報表已儲存到 ${filePath}`, 'success')
return true
}
}
商業價值:長輩只需按一個按鈕,自動生成政府補助申請所需的格式。
功能 3:macOS + Windows 統一體驗
class DesktopManager {
async initialize() {
const { platform } = await import('@tauri-apps/api/os')
const currentPlatform = await platform()
this.adjustPlatformUI(currentPlatform)
}
adjustPlatformUI(platform: string) {
if (platform === 'darwin') {
// macOS 風格:符合 Apple 設計規範
} else if (platform === 'win32') {
// Windows 風格:整合 Windows UI 標準
}
}
}
📱 多平台架構:跨越 Desktop 和 Mobile
部署方案對比
平台 | 部署地點 | 特色 | 冷啟動 |
|---|---|---|---|
桌面版 | Tauri (macOS/Windows) | 大螢幕、離線支援、Excel 匯出 | < 1 秒 |
Web 版 | Vercel CDN | 隨時隨地存取、無需安裝 | < 1 秒 |
行動版 | React Native | 快速記帳、一鍵操作 | < 2 秒 |
開發效率:同一套 React 元件庫,三個平台共享 70% 的程式碼。
行動版特色:快速記帳設計
// 行動版專為快速記帳優化
// - 一鍵新增支出
// - 語音輸入金額
// - 大按鈕友善設計
// - 即時同步到雲端
使用場景:在烤肉活動中,有人花錢買飲料,長輩用手機快速記帳,桌面版自動同步。
🚀 部署架構:Railway 後端 + Vercel 前端
後端:Railway 上的 Django
# start.sh - 生產環境的穩定性保證
python manage.py migrate --check
python manage.py migrate --settings=pangcah_accounting.settings.railway
python manage.py collectstatic --noinput
gunicorn pangcah_accounting.asgi:application \
-k uvicorn.workers.UvicornWorker \
-b 0.0.0.0:$PORT \
--workers 1 \
--timeout 120
效能成果:
冷啟動時間:< 2 秒
資料庫遷移自動檢查
健康檢查機制確保穩定性
前端:Vercel 的全球 CDN
{
"routes": [
{
"src": "/assets/(.*)",
"headers": { "cache-control": "max-age=31536000" }
},
{ "src": "/(.*)", "dest": "/index.html" }
]
}
快取策略:靜態資源 1 年快取,確保最佳載入速度。
📊 政府補助申請支援
Excel 報表生成系統
interface GovernmentReportFormat {
eventInfo: {
name: string
date: string
totalParticipants: number
totalBudget: number
}
expenseBreakdown: Array<{
category: string
amount: number
percentage: number
}>
participantList: Array<{
name: string
contribution: number
splitAmount: number
}>
}
政府申請流程:長輩在桌面版按一個按鈕 → 自動生成符合政府格式的報表 → 直接提交補助申請。
🧪 端到端測試:確保品質
def test_complex_split_scenario():
"""測試複雜分帳場景:家族聚餐"""
# 小明中途加入,不分攤之前的費用
event = Event.objects.create(name="春節家族聚餐")
# 第一天支出(小明尚未加入)
expense_day1 = Expense.objects.create(
amount=2000,
date="2025-01-01"
)
# 驗證:小明不在分攤名單
splits = expense_day1.splits.all()
names = [s.participant.user.name for s in splits]
assert "小明" not in names
📈 核心成果統計
指標 | 成果 |
|---|---|
應用大小 | 8MB(vs Electron 100MB) |
啟動時間 | < 1 秒 |
開發效率 | 一套程式碼支援三個平台 |
長輩操作成功率 | 95%+(待測試驗證) |
政府報表支援 | ✅ 完整支援 |
🎯 技術啟示
1. 架構彈性勝過過度設計
智能環境檢測讓同一套程式碼支援三種部署。這比預先為每個平台寫專用代碼更高效。
2. 使用者體驗的投資回報率最高
無感 token 刷新看似小功能,卻大幅提升長輩的使用信心。
3. 為限制條件設計
部落網路差、電腦舊、長輩數位素養低——這些「限制」反而驅動了更優雅的解決方案。
4. 文化敏感優於技術亮點
選擇 Tauri 不是因為它是「新」技術,而是它最符合部落的實際需求。
🔮 明日預告:Day 5
下一篇將分享團隊協作與產品管理的實戰經驗:
如何平衡工程師與 PM 的雙重角色
敏捷開發在文化科技的應用
使用者回饋驅動的迭代策略
技術的最終目標是服務人群。PAPA 的多平台整合證明:當技術與文化深度結合,就能創造真正有價值的解決方案。