Skip to content

Tools 工具函数

约 659 字大约 2 分钟

2025-05-23

Calendar 日历生成

/**
 * 日历生成器的基础配置
 * @typedef {Object} CalendarConfig
 * @property {function} adjustDay - 调整星期几的计算方法
 */

/**
 * 日历格式策略
 * @type {Object.<string, CalendarConfig>}
 */
const CALENDAR_STRATEGIES = {
  // 一二三四五六日
  DEFAULT: {
    adjustDay: (day) => (day === 0 ? 6 : day - 1),
  },
  // 日一二三四五六
  UTC: {
    adjustDay: (day) => day,
  },
};

/**
 * 获取月份的第一天和最后一天
 * @param {Number} year 年份
 * @param {Number} month 月份
 * @returns {Object} 包含首末日期和天数的对象
 */
function getMonthBoundary(year, month) {
  const firstDay = new Date(year, month - 1, 1);
  const lastDay = new Date(year, month, 0);
  return {
    firstDay,
    lastDay,
    totalDays: lastDay.getDate(),
  };
}

/**
 * 填充日历行
 * @param {Array} row 当前行数组
 * @param {Number} targetLength 目标长度
 * @param {*} fillValue 填充值
 * @returns {Array} 填充后的数组
 */
function padRow(row, targetLength, fillValue = null) {
  if (row.length >= targetLength) return row;
  return [...row, ...Array(targetLength - row.length).fill(fillValue)];
}

/**
 * 生成日历数组
 * @param {Number} [year] 年份
 * @param {Number} [month] 月份
 * @param {string} [format='DEFAULT'] 日历格式
 * @returns {Array} 返回日历数组
 */
export function generateCalendar(year, month, format = "DEFAULT") {
  // 默认使用当前日期
  year ??= new Date().getFullYear();
  month ??= new Date().getMonth() + 1;

  // 获取日历策略
  const strategy = CALENDAR_STRATEGIES[format] || CALENDAR_STRATEGIES.DEFAULT;

  // 获取月份信息
  const { firstDay, totalDays } = getMonthBoundary(year, month);

  // 计算起始天的偏移
  const startDay = strategy.adjustDay(firstDay.getDay());

  // 生成日历数组
  const result = [];
  let currentRow = Array(startDay).fill(null);

  for (let day = 1; day <= totalDays; day++) {
    currentRow.push(day);

    if (currentRow.length === 7) {
      result.push(currentRow);
      currentRow = [];
    }
  }

  // 处理最后一行
  if (currentRow.length > 0) {
    result.push(padRow(currentRow, 7));
  }

  return result;
}

// 为保持向后兼容,保留原有的函数名
export const generateUTCCalendar = (year, month) =>
  generateCalendar(year, month, "UTC");

File 文件 URL

/**
 * 文件工具类
 */

// 定义文件扩展名和MIME类型的映射
const MIME_TYPE_MAP = {
  jpg: "image/jpeg",
  jpeg: "image/jpeg",
  png: "image/png",
  gif: "image/gif",
  bmp: "image/bmp",
  svg: "image/svg+xml",
  mp4: "video/mp4",
  mov: "video/quicktime",
  avi: "video/x-msvideo",
  mkv: "video/x-matroska",
  wmv: "video/x-ms-wmv",
  mp3: "audio/mpeg",
  wav: "audio/wav",
  aac: "audio/aac",
  flac: "audio/flac",
  ogg: "audio/ogg",
  pdf: "application/pdf",
  doc: "application/msword",
  docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
  xls: "application/vnd.ms-excel",
  xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
  ppt: "application/vnd.ms-powerpoint",
  pptx: "application/vnd.openxmlformats-officedocument.presentationml.presentation",
  txt: "text/plain",
  json: "application/json",
  xml: "application/xml",
  zip: "application/zip",
  rar: "application/x-rar-compressed",
};

/**
 * 将文件或ArrayBuffer转换为Bolb
 * @param {File | ArrayBuffer} file
 * @param {string} [filePath]
 */
export const fileToBolb = (file, filePath) => {
  let type = "image/*";
  if (file instanceof File) {
    type = file.type;
  }
  if (filePath) {
    const extension = getFileExtension(filePath);
    type = inferFileType(extension) || type;
  }
  return new Blob([file], { type });
};

/**
 * 将文件或ArrayBuffer转换为BolbUrl,记得使用完要释放URL.createObjectURL
 * @param {File | ArrayBuffer} file
 * @param {string} [filePath]
 */
export const fileToBolbUrl = (file, filePath) => {
  return URL.createObjectURL(fileToBolb(file, filePath));
};

/**
 * 将文件或ArrayBuffer转换为DataURL
 * @param {File | ArrayBuffer} file
 * @param {string} [filePath]
 */
export const fileToDataUrl = (file) => {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = () => resolve(reader.result);
    reader.onerror = reject;
    reader.readAsDataURL(fileToBolb(file, filePath));
  });
};

/**
 * 获取文件扩展名
 * @param {String} filePath
 * @returns
 */
function getFileExtension(filePath) {
  const match = filePath.match(/\.([^.]+)$/);
  if (!match) {
    return "";
  }
  return match[1];
}

/**
 * 根据文件扩展名推断文件MIME类型
 * @param {string} fileExtension
 * @returns {string|null}
 */
function inferFileType(fileExtension) {
  fileExtension = fileExtension.toLowerCase();

  if (MIME_TYPE_MAP.hasOwnProperty(fileExtension)) {
    return MIME_TYPE_MAP[fileExtension];
  }
  return null;
}

豫ICP备18027433号 萌ICP备20240840号 本网站由又拍云提供CDN加速/云存储服务