utils.ts 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. import dayjs from 'dayjs';
  2. import { EnableStatus, DeleteStatus, AuditStatus } from '../share/types.ts';
  3. // 日期格式化
  4. export const formatDate = (date: string | Date, format = 'YYYY-MM-DD HH:mm:ss'): string => {
  5. if (!date) return '-';
  6. return dayjs(date).format(format);
  7. };
  8. // 格式化时间为相对时间(如:3小时前)
  9. export const formatRelativeTime = (date: string | Date): string => {
  10. if (!date) return '-';
  11. const now = dayjs();
  12. const dateObj = dayjs(date);
  13. const diffInSeconds = now.diff(dateObj, 'second');
  14. if (diffInSeconds < 60) {
  15. return `${diffInSeconds}秒前`;
  16. } else if (diffInSeconds < 3600) {
  17. return `${Math.floor(diffInSeconds / 60)}分钟前`;
  18. } else if (diffInSeconds < 86400) {
  19. return `${Math.floor(diffInSeconds / 3600)}小时前`;
  20. } else if (diffInSeconds < 2592000) {
  21. return `${Math.floor(diffInSeconds / 86400)}天前`;
  22. } else {
  23. return formatDate(date, 'YYYY-MM-DD');
  24. }
  25. };
  26. // 获取枚举的选项(用于下拉菜单等)
  27. export const getEnumOptions = (enumObj: Record<string | number, string | number>) => {
  28. return Object.entries(enumObj)
  29. .filter(([key]) => !isNaN(Number(key))) // 过滤掉映射对象中的字符串键
  30. .map(([value, label]) => ({
  31. value: Number(value),
  32. label: String(label)
  33. }));
  34. };
  35. // 获取启用状态选项
  36. export const getEnableStatusOptions = () => {
  37. return [
  38. { value: EnableStatus.ENABLED, label: '启用' },
  39. { value: EnableStatus.DISABLED, label: '禁用' }
  40. ];
  41. };
  42. // 获取删除状态选项
  43. export const getDeleteStatusOptions = () => {
  44. return [
  45. { value: DeleteStatus.NOT_DELETED, label: '未删除' },
  46. { value: DeleteStatus.DELETED, label: '已删除' }
  47. ];
  48. };
  49. // 获取审核状态选项
  50. export const getAuditStatusOptions = () => {
  51. return [
  52. { value: AuditStatus.PENDING, label: '待审核' },
  53. { value: AuditStatus.APPROVED, label: '已通过' },
  54. { value: AuditStatus.REJECTED, label: '已拒绝' }
  55. ];
  56. };
  57. // 格式化文件大小
  58. export const formatFileSize = (bytes: number): string => {
  59. if (bytes === 0) return '0 B';
  60. const k = 1024;
  61. const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
  62. const i = Math.floor(Math.log(bytes) / Math.log(k));
  63. return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
  64. };
  65. // 处理API错误
  66. export const handleApiError = (error: any): string => {
  67. if (error.response) {
  68. // 服务器响应错误
  69. const status = error.response.status;
  70. const data = error.response.data;
  71. if (status === 401) {
  72. return '您的登录已过期,请重新登录';
  73. } else if (status === 403) {
  74. return '您没有权限执行此操作';
  75. } else if (status === 404) {
  76. return '请求的资源不存在';
  77. } else if (status === 422) {
  78. // 表单验证错误
  79. return data.message || '输入数据无效';
  80. } else {
  81. return data.message || `服务器错误 (${status})`;
  82. }
  83. } else if (error.request) {
  84. // 请求发送成功但没有收到响应
  85. return '网络连接错误,请检查您的网络连接';
  86. } else {
  87. // 请求设置错误
  88. return '应用程序错误,请稍后再试';
  89. }
  90. };
  91. // 复制文本到剪贴板
  92. export const copyToClipboard = async (text: string): Promise<boolean> => {
  93. try {
  94. await navigator.clipboard.writeText(text);
  95. return true;
  96. } catch (error) {
  97. console.error('复制到剪贴板失败:', error);
  98. return false;
  99. }
  100. };
  101. // 防抖函数
  102. export const debounce = <T extends (...args: any[]) => any>(
  103. func: T,
  104. wait: number
  105. ): ((...args: Parameters<T>) => void) => {
  106. let timeout: number | null = null;
  107. return (...args: Parameters<T>) => {
  108. if (timeout) {
  109. clearTimeout(timeout);
  110. }
  111. timeout = setTimeout(() => {
  112. func(...args);
  113. }, wait) as unknown as number;
  114. };
  115. };
  116. // 生成随机颜色
  117. export const getRandomColor = (): string => {
  118. const letters = '0123456789ABCDEF';
  119. let color = '#';
  120. for (let i = 0; i < 6; i++) {
  121. color += letters[Math.floor(Math.random() * 16)];
  122. }
  123. return color;
  124. };
  125. // 获取本地存储值,带过期检查
  126. export const getLocalStorageWithExpiry = (key: string) => {
  127. const itemStr = localStorage.getItem(key);
  128. if (!itemStr) return null;
  129. const item = JSON.parse(itemStr);
  130. const now = new Date();
  131. if (item.expiry && now.getTime() > item.expiry) {
  132. localStorage.removeItem(key);
  133. return null;
  134. }
  135. return item.value;
  136. };
  137. // 设置本地存储值,带过期时间
  138. export const setLocalStorageWithExpiry = (key: string, value: any, expiryHours = 24) => {
  139. const now = new Date();
  140. const item = {
  141. value: value,
  142. expiry: now.getTime() + expiryHours * 60 * 60 * 1000
  143. };
  144. localStorage.setItem(key, JSON.stringify(item));
  145. };