工具函數
內容來源
本頁內容源自 appfuse-web/lib/utils/README.md,如有差異以 README 為準。
AppFuse Web 提供 10+ 工具模組,涵蓋 HTTP 請求、日期處理、國際化等常見需求。
匯入方式
所有工具函數統一從 @appfuse/appfuse-web/utils 匯入:
import { createHttpClient, time, logger, cn, i18n, cookie, environ, browser, numeral, template } from '@appfuse/appfuse-web/utils'
模組總覽
| 模組 | 用途 |
|---|---|
createHttpClient / HttpClientProvider / useHttpClient | HTTP 客戶端 |
filter | 查詢過濾器(RSQL/FIQL) |
time / toDateString | 日期時間處理 |
i18n / useTranslation / I18nProvider | 國際化 |
numeral | 數字格式化 |
cn | CSS 類別合併 |
cookie | Cookie 管理 |
browser | 瀏覽器偵測 |
environ | 環境配置 |
logger | 日誌系統 |
template | 字串模板 |
http - HTTP 客戶端
基於 axios 的 HTTP 客戶端,支援自動日期轉換和檔案上傳。
建立客戶端
import { createHttpClient } from '@appfuse/appfuse-web/utils';
const http = createHttpClient({
baseURL: '/api',
timeout: 30000,
});
基本請求
// GET
const users = await http.get<User[]>('/users');
// GET with params
const users = await http.get<User[]>('/users', {
params: { status: 'active', page: 1 }
});
// POST
const user = await http.post<User>('/users', {
name: 'John',
email: 'john@example.com'
});
// PUT
await http.put(`/users/${id}`, userData);
// DELETE
await http.delete(`/users/${id}`);
自動日期轉換
HTTP 客戶端會自動將 ISO 8601 日期字串轉換為 Date 物件:
// API 回傳
{ "createdAt": "2024-01-15T10:30:00Z" }
// 自動轉換為
{ createdAt: Date } // JavaScript Date 物件
檔案上傳
const formData = new FormData();
formData.append('file', file);
formData.append('name', 'document.pdf');
await http.post('/upload', formData, {
headers: { 'Content-Type': 'multipart/form-data' }
});
filter - 查詢過濾器
建構 RSQL/FIQL 標準的查詢字串。
基本用法
import { FilterBuilder } from '@appfuse/appfuse-web/utils';
const filter = new FilterBuilder()
.eq('status', 'active')
.like('name', 'John')
.gte('age', 18)
.build();
// 輸出: status==active;name=like=John;age>=18
支援的運算子
| 方法 | 運算子 | 說明 |
|---|---|---|
eq(field, value) | == | 等於 |
ne(field, value) | != | 不等於 |
gt(field, value) | > | 大於 |
gte(field, value) | >= | 大於等於 |
lt(field, value) | < | 小於 |
lte(field, value) | <= | 小於等於 |
like(field, value) | =like= | 模糊比對 |
in(field, values) | =in= | 包含於 |
out(field, values) | =out= | 不包含於 |
isNull(field) | =isnull= | 為空 |
isNotNull(field) | =isnotnull= | 不為空 |
組合查詢
// AND 條件
const filter = new FilterBuilder()
.eq('status', 'active')
.and()
.gte('price', 100)
.build();
// OR 條件
const filter = new FilterBuilder()
.eq('category', 'A')
.or()
.eq('category', 'B')
.build();
time - 日期時間
基於 date-fns 的日期時間處理工具。
格式化
import { formatDate, formatDateTime, formatTime } from '@appfuse/appfuse-web/utils';
const date = new Date();
formatDate(date); // "2024-01-15"
formatDateTime(date); // "2024-01-15 10:30"
formatTime(date); // "10:30"
// 自訂格式
formatDate(date, 'yyyy/MM/dd'); // "2024/01/15"
解析
import { parseDate, parseDateTime } from '@appfuse/appfuse-web/utils';
parseDate('2024-01-15'); // Date 物件
parseDateTime('2024-01-15 10:30'); // Date 物件
計算
import { addDays, addMonths, differenceInDays } from '@appfuse/appfuse-web/utils';
const today = new Date();
addDays(today, 7); // 7 天後
addMonths(today, 1); // 1 個月後
differenceInDays(date1, date2); // 兩日期相差天數
Duration
import { Duration } from '@appfuse/appfuse-web/utils';
const duration = Duration.ofMinutes(90);
duration.toHours(); // 1.5
duration.toMinutes(); // 90
// 格式化
duration.format(); // "1:30:00"
i18n - 國際化
多語言支援工具。
初始化
import { i18n } from '@appfuse/appfuse-web/utils';
// 載入語言資源
i18n.load('zh-TW', {
'Hello': '你好',
'Welcome, {name}': '歡迎,{name}',
});
// 設定語言
i18n.setLocale('zh-TW');
翻譯
import { t } from '@appfuse/appfuse-web/utils';
// 簡單翻譯
t('Hello'); // "你好"
// 帶參數
t('Welcome, {name}', { name: 'John' }); // "歡迎,John"
// 找不到翻譯時回傳原文
t('Not translated'); // "Not translated"
語言回退
// 設定回退語言
i18n.setFallbackLocale('en');
// zh-TW 找不到時會使用 en
numeral - 數字格式化
使用 Intl API 的數字格式化工具。
數字格式化
import { formatNumber, formatCurrency, formatPercent } from '@appfuse/appfuse-web/utils';
formatNumber(1234567.89); // "1,234,567.89"
formatNumber(1234567.89, 0); // "1,234,568"(無小數)
formatCurrency(1234.56); // "NT$1,234.56"
formatCurrency(1234.56, 'USD'); // "$1,234.56"
formatPercent(0.1234); // "12.34%"
formatPercent(0.1234, 0); // "12%"
cn - CSS 類別合併
智慧合併 Tailwind CSS 類別。
基本用法
import { cn } from '@appfuse/appfuse-web/utils';
// 合併類別
cn('px-4 py-2', 'bg-blue-500');
// "px-4 py-2 bg-blue-500"
// 條件類別
cn('btn', isActive && 'btn-active');
// isActive ? "btn btn-active" : "btn"
// 覆蓋衝突類別
cn('px-4', 'px-8');
// "px-8"(後者覆蓋前者)
// 物件語法
cn({
'btn': true,
'btn-primary': isPrimary,
'btn-disabled': isDisabled,
});
cookie - Cookie 管理
型別安全的 Cookie 操作。
基本操作
import { getCookie, setCookie, removeCookie } from '@appfuse/appfuse-web/utils';
// 讀取
const token = getCookie('token');
// 設定
setCookie('token', 'abc123', {
maxAge: 3600, // 1 小時
path: '/',
secure: true,
sameSite: 'strict',
});
// 刪除
removeCookie('token');
browser - 瀏覽器偵測
瀏覽器和語言偵測工具。
語言偵測
import { detectLanguage, parseLocale } from '@appfuse/appfuse-web/utils';
// 偵測瀏覽器語言
const lang = detectLanguage(); // "zh-TW"
// 解析 Locale
const locale = parseLocale('zh-TW');
// { language: 'zh', region: 'TW' }
environ - 環境配置
型別安全的環境變數管理。
讀取配置
import { getEnv, getRequiredEnv } from '@appfuse/appfuse-web/utils';
// 選填(有預設值)
const apiUrl = getEnv('VITE_API_URL', '/api');
// 必填(無值時拋錯)
const apiKey = getRequiredEnv('VITE_API_KEY');
logger - 日誌系統
基於 loglevel 的日誌工具。
基本用法
import { logger, createLogger } from '@appfuse/appfuse-web/utils';
// 使用預設 logger
logger.debug('Debug message');
logger.info('Info message');
logger.warn('Warning message');
logger.error('Error message');
// 建立模組專用 logger
const log = createLogger('MyModule');
log.info('Module started'); // [MyModule] Module started
動態設定等級
import { setLogLevel } from '@appfuse/appfuse-web/utils';
// 開發環境顯示所有日誌
setLogLevel('debug');
// 生產環境只顯示警告和錯誤
setLogLevel('warn');
template - 字串模板
字串插值工具。
位置參數
import { format } from '@appfuse/appfuse-web/utils';
format('Hello, {0}!', 'World');
// "Hello, World!"
format('{0} + {1} = {2}', 1, 2, 3);
// "1 + 2 = 3"
命名參數
format('Hello, {name}! You have {count} messages.', {
name: 'John',
count: 5
});
// "Hello, John! You have 5 messages."
Tree-shaking 匯入
除了統一匯入,也支援個別模組匯入以優化打包體積:
// 統一匯入
import { createHttpClient, logger } from '@appfuse/appfuse-web/utils'
// 個別模組匯入(僅打包使用的模組)
import { createHttpClient } from '@appfuse/appfuse-web/utils/http'
import { logger } from '@appfuse/appfuse-web/utils/logger'
最佳實踐
- 統一 HTTP 客戶端 - 應用程式只建立一個 http 實例
- 使用 FilterBuilder - 避免手動拼接查詢字串
- 日期處理 - 使用 time 工具而非直接使用 date-fns
- CSS 合併 - 使用 cn() 處理條件樣式