Files
star-erp/resources/js/utils/format.ts
sky121113 b0848a6bb8 chore: 完善模組化架構遷移與修復前端顯示錯誤
- 修正所有模組 Controller 的 Model 引用路徑 (App\Modules\...)
- 更新 ProductionOrder 與 ProductionOrderItem 模型結構以符合新版邏輯
- 修復 resources/js/utils/format.ts 在處理空值時導致 toLocaleString 崩潰的問題
- 清除全域路徑與 Controller 遷移殘留檔案
2026-01-26 10:37:47 +08:00

188 lines
5.1 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 格式化相關工具函式
*/
/**
* 格式化數字為千分位格式
*/
export const formatNumber = (num: number | null | undefined): string => {
if (num === null || num === undefined) return "0";
return num.toLocaleString();
};
/**
* 格式化貨幣NT$
*/
export const formatCurrency = (num: number | null | undefined): string => {
if (num === null || num === undefined) return "NT$ 0";
return `NT$ ${num.toLocaleString()}`;
};
/**
* 格式化日期
*/
export const formatDate = (date: string): string => {
if (!date) return "-";
// Assume date format is YYYY-MM-DD or YYYY-MM-DD HH:mm:ss
const datePart = date.split("T")[0].split(" ")[0];
// Directly return the parsed string components to guarantee no timezone shift
const parts = datePart.split("-");
if (parts.length === 3) {
return `${parts[0]}/${parts[1]}/${parts[2]}`;
}
// Fallback for unexpected formats
return datePart.replace(/-/g, "/");
};
/**
* 格式化日期並包含星期
*/
export const formatDateWithDayOfWeek = (date: string): string => {
if (!date) return "-";
const datePart = date.split("T")[0].split(" ")[0];
const parts = datePart.split("-");
if (parts.length === 3) {
const [y, m, d] = parts.map(Number);
// Use noon to safely calculate the day of week
const dt = new Date(y, m - 1, d, 12, 0, 0);
const weekDay = dt.toLocaleDateString("zh-TW", { weekday: "short" });
// Return original string parts + calculated weekday
return `${parts[0]}/${parts[1]}/${parts[2]} (${weekDay})`;
}
return datePart.replace(/-/g, "/");
};
/**
* 格式化發票號碼
* 例如AB12345678 -> AB-12345678
*/
export const formatInvoiceNumber = (invoice: string | null | undefined): string => {
if (!invoice) return "-";
const cleanInvoice = invoice.replace(/-/g, "");
if (/^[a-zA-Z]{2}\d+$/.test(cleanInvoice)) {
return `${cleanInvoice.slice(0, 2).toUpperCase()}-${cleanInvoice.slice(2)}`;
}
return invoice;
};
/**
* 獲取當前日期YYYY-MM-DD 格式)
*/
export const getCurrentDate = (): string => {
const now = new Date();
const year = now.getFullYear();
const month = String(now.getMonth() + 1).padStart(2, "0");
const day = String(now.getDate()).padStart(2, "0");
return `${year}-${month}-${day}`;
};
/**
* 生成唯一 ID
*/
export const generateId = (): string => {
return `${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
};
/**
* 生成撥補單號
*/
export const generateOrderNumber = (): string => {
return `TO${Date.now().toString().slice(-8)}`;
};
/**
* 生成批號
* 格式:{倉庫代碼}-{日期YYYYMMDD}-{流水號}
* 例如WH1-20251128-001
*/
export const generateBatchNumber = (
warehouseId: string,
date?: string,
sequence?: number
): string => {
const targetDate = date || getCurrentDate();
const dateStr = targetDate.replace(/-/g, "");
const seq = sequence || Math.floor(Math.random() * 1000);
const seqStr = seq.toString().padStart(3, "0");
return `WH${warehouseId}-${dateStr}-${seqStr}`;
};
/**
* 獲取當前日期時間YYYY-MM-DDTHH:mm 格式,用於 datetime-local input
*/
export const getCurrentDateTime = (): string => {
const now = new Date();
const year = now.getFullYear();
const month = String(now.getMonth() + 1).padStart(2, "0");
const day = String(now.getDate()).padStart(2, "0");
const hours = String(now.getHours()).padStart(2, "0");
const minutes = String(now.getMinutes()).padStart(2, "0");
return `${year}-${month}-${day}T${hours}:${minutes}`;
};
/**
* 格式化日期時間顯示
*/
export const formatDateTime = (datetime: string): string => {
if (!datetime) return "-";
return new Date(datetime).toLocaleString("zh-TW", {
year: "numeric",
month: "2-digit",
day: "2-digit",
hour: "2-digit",
minute: "2-digit",
hour12: false,
});
};
/**
* 獲取日期區間YYYY-MM-DD 格式)
* 支援: today, yesterday, this_week, this_month, last_month
*/
export const getDateRange = (type: string): { start: string, end: string } => {
const now = new Date();
// Reset time to avoid timezone issues when calculating dates
now.setHours(12, 0, 0, 0);
let start = new Date(now);
let end = new Date(now);
const format = (d: Date) => {
const year = d.getFullYear();
const month = String(d.getMonth() + 1).padStart(2, "0");
const day = String(d.getDate()).padStart(2, "0");
return `${year}-${month}-${day}`;
};
switch (type) {
case "today":
break;
case "yesterday":
start.setDate(now.getDate() - 1);
end.setDate(now.getDate() - 1);
break;
case "this_week":
// 週一為一週的第一天
const dayOfWeek = now.getDay() || 7;
start.setDate(now.getDate() - dayOfWeek + 1);
end.setDate(now.getDate() + (7 - dayOfWeek));
break;
case "this_month":
start = new Date(now.getFullYear(), now.getMonth(), 1);
end = new Date(now.getFullYear(), now.getMonth() + 1, 0);
break;
case "last_month":
start = new Date(now.getFullYear(), now.getMonth() - 1, 1);
end = new Date(now.getFullYear(), now.getMonth(), 0);
break;
}
return {
start: format(start),
end: format(end)
};
};