跳至主要内容

工具函數

內容來源

本頁內容源自 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 / useHttpClientHTTP 客戶端
filter查詢過濾器(RSQL/FIQL)
time / toDateString日期時間處理
i18n / useTranslation / I18nProvider國際化
numeral數字格式化
cnCSS 類別合併
cookieCookie 管理
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 操作。

基本操作

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'

最佳實踐

  1. 統一 HTTP 客戶端 - 應用程式只建立一個 http 實例
  2. 使用 FilterBuilder - 避免手動拼接查詢字串
  3. 日期處理 - 使用 time 工具而非直接使用 date-fns
  4. CSS 合併 - 使用 cn() 處理條件樣式

下一步