118 行
2.8 KiB
TypeScript
118 行
2.8 KiB
TypeScript
type NotificationTarget = {
|
|
targetType: string | null;
|
|
targetId: string | null;
|
|
};
|
|
|
|
function encodeSegment(value: string) {
|
|
return encodeURIComponent(value);
|
|
}
|
|
|
|
export function resolveNotificationTargetLink(item: NotificationTarget) {
|
|
if (!item.targetType || !item.targetId) return null;
|
|
|
|
if (item.targetType === "workflow_task") {
|
|
return `/workflow/tasks/${item.targetId}`;
|
|
}
|
|
|
|
if (item.targetType === "reimbursement_form") {
|
|
return `/reimbursements/${item.targetId}`;
|
|
}
|
|
|
|
if (item.targetType === "leave_request") {
|
|
return `/leave-requests?highlight=${item.targetId}`;
|
|
}
|
|
|
|
if (item.targetType === "attendance_correction") {
|
|
return "/attendance";
|
|
}
|
|
|
|
if (item.targetType === "purchase_request") {
|
|
return `/purchase-requests?highlight=${item.targetId}`;
|
|
}
|
|
|
|
if (item.targetType === "travel_request") {
|
|
return `/travel-requests?highlight=${item.targetId}`;
|
|
}
|
|
|
|
if (item.targetType === "asset" || item.targetType === "asset_card") {
|
|
return `/assets?highlight=${item.targetId}`;
|
|
}
|
|
|
|
if (item.targetType === "inventory_check") {
|
|
return `/inventory-checks?highlight=${item.targetId}`;
|
|
}
|
|
|
|
if (item.targetType === "employee") {
|
|
return "/settings/profile";
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
export function resolveMobileNotificationTargetLink(item: NotificationTarget) {
|
|
if (!item.targetType || !item.targetId) return null;
|
|
|
|
if (item.targetType === "workflow_task") {
|
|
return `/mobile/approvals/${encodeSegment(item.targetId)}`;
|
|
}
|
|
|
|
if (item.targetType === "reimbursement_form") {
|
|
return `/mobile/reimbursements/${encodeSegment(item.targetId)}`;
|
|
}
|
|
|
|
if (item.targetType === "leave_request") {
|
|
return `/mobile/leave/${encodeSegment(item.targetId)}`;
|
|
}
|
|
|
|
if (item.targetType === "attendance_correction") {
|
|
return "/mobile/attendance";
|
|
}
|
|
|
|
if (item.targetType === "purchase_request") {
|
|
return `/mobile/purchase-requests/${encodeSegment(item.targetId)}`;
|
|
}
|
|
|
|
if (item.targetType === "asset" || item.targetType === "asset_card" || item.targetType === "inventory_check") {
|
|
return "/mobile/assets/scan";
|
|
}
|
|
|
|
if (item.targetType === "employee") {
|
|
return "/mobile/profile";
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
export function formatNotificationRelativeTime(value: string | null) {
|
|
if (!value) {
|
|
return "-";
|
|
}
|
|
|
|
const timestamp = new Date(value).getTime();
|
|
if (Number.isNaN(timestamp)) {
|
|
return "-";
|
|
}
|
|
|
|
const diffMs = Date.now() - timestamp;
|
|
if (diffMs < 60 * 1000) {
|
|
return "刚刚";
|
|
}
|
|
|
|
const diffMinutes = Math.floor(diffMs / (60 * 1000));
|
|
if (diffMinutes < 60) {
|
|
return `${diffMinutes} 分钟前`;
|
|
}
|
|
|
|
const diffHours = Math.floor(diffMinutes / 60);
|
|
if (diffHours < 24) {
|
|
return `${diffHours} 小时前`;
|
|
}
|
|
|
|
const diffDays = Math.floor(diffHours / 24);
|
|
if (diffDays < 7) {
|
|
return `${diffDays} 天前`;
|
|
}
|
|
|
|
return new Date(value).toLocaleDateString("zh-CN");
|
|
}
|