20260507213409
This commit is contained in:
1 parent
3070eac71b
commit
4c7f516a03
204 files changed
+3623
No files matched your search
@@ -0,0 +1,3 @@
|
||||
export function cn(...args: (string | undefined | false | null)[]) {
|
||||
return args.filter(Boolean).join(" ");
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
export function generateCode(
|
||||
length: number = 6,
|
||||
chars: string = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789",
|
||||
): string {
|
||||
let result = "";
|
||||
const max = chars.length;
|
||||
|
||||
for (let i = 0; i < length; i++) {
|
||||
result += chars.charAt(Math.floor(Math.random() * max));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
const S3_URL = process.env.EXPO_PUBLIC_G3_URL ?? "";
|
||||
const S3_BUCKET = process.env.EXPO_PUBLIC_G3_BUCKET ?? "";
|
||||
|
||||
export function isS3Key(value?: string) {
|
||||
if (!value) return false;
|
||||
|
||||
// ❗关键特征:没有 http,且是路径结构
|
||||
return !value.startsWith("http") && /^\d{4}\/\d{2}\/\d{2}\//.test(value);
|
||||
}
|
||||
|
||||
export function isS3Url(url?: string) {
|
||||
if (!url) return false;
|
||||
|
||||
try {
|
||||
const u = new URL(url);
|
||||
const base = new URL(S3_URL);
|
||||
|
||||
return u.origin === base.origin && url.includes(`/${S3_BUCKET}/`);
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
export function buildS3Url(key: string) {
|
||||
if (!key) return "";
|
||||
|
||||
// 防止重复 /
|
||||
const cleanKey = key.replace(/^\/+/, "");
|
||||
|
||||
return `${S3_URL}/${S3_BUCKET}/${cleanKey}`;
|
||||
}
|
||||
|
||||
export function buildFileUrl(keyOrUrl?: string) {
|
||||
if (!keyOrUrl) return "";
|
||||
|
||||
if (isS3Url(keyOrUrl)) return keyOrUrl;
|
||||
|
||||
if (isS3Key(keyOrUrl)) return buildS3Url(keyOrUrl);
|
||||
|
||||
return keyOrUrl;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import { axiosRequestAdapter } from "@alova/adapter-axios";
|
||||
import { createAlova } from "alova";
|
||||
|
||||
export const alovaInstance = createAlova({
|
||||
requestAdapter: axiosRequestAdapter(),
|
||||
|
||||
responded: {
|
||||
onSuccess: async (response) => response.data,
|
||||
onError: (err) => Promise.reject(err),
|
||||
},
|
||||
});
|
||||
|
||||
// ======================
|
||||
// 地区和天气
|
||||
// ======================
|
||||
export const fetchDailyInfo = () => {
|
||||
return alovaInstance.Get("https://60s.aa1.cn/60s-api/new/api/weather/");
|
||||
};
|
||||
@@ -0,0 +1,159 @@
|
||||
import dayjs from "dayjs";
|
||||
|
||||
/**
|
||||
* 获取当前日期,默认格式: YYYY-MM-DD
|
||||
*/
|
||||
export function getCurrentDate(format = "YYYY-MM-DD"): string {
|
||||
return dayjs().format(format);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前日期时间,默认格式: YYYY-MM-DD HH:mm:ss
|
||||
*/
|
||||
export function getCurrentDateTime(format = "YYYY-MM-DD HH:mm:ss"): string {
|
||||
return dayjs().format(format);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前时间,默认格式: HH:mm:ss
|
||||
*/
|
||||
export function getCurrentTime(format = "HH:mm:ss"): string {
|
||||
return dayjs().format(format);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前年月,默认格式: YYYY-MM
|
||||
*/
|
||||
export function getCurrentYearMonth(format = "YYYY-MM"): string {
|
||||
return dayjs().format(format);
|
||||
}
|
||||
|
||||
export function getCurrentYear(): string {
|
||||
return dayjs().format("YYYY");
|
||||
}
|
||||
|
||||
/** 字符串 / 数字 / Date → Date(无效返回 null) */
|
||||
export function toDate(input: string | number | Date | undefined | null): Date | undefined {
|
||||
if (input === null || input === undefined || input === "") return undefined;
|
||||
|
||||
if (input instanceof Date) return input;
|
||||
|
||||
const d = dayjs(input);
|
||||
return d.isValid() ? d.toDate() : undefined;
|
||||
}
|
||||
|
||||
/** Date → YYYY-MM-DD */
|
||||
export function toDateString(date: string | number | Date): string {
|
||||
const parsed = toDate(date);
|
||||
if (!parsed) return "";
|
||||
|
||||
return dayjs(parsed).format("YYYY-MM-DD");
|
||||
}
|
||||
|
||||
/** Date → YYYY-MM */
|
||||
export function toYearMonthString(date: string | number | Date): string {
|
||||
const parsed = toDate(date);
|
||||
if (!parsed) return "";
|
||||
|
||||
return dayjs(parsed).format("YYYY-MM");
|
||||
}
|
||||
|
||||
/** Date → HH:mm:ss */
|
||||
export function toTimeString(date: string | number | Date): string {
|
||||
const parsed = toDate(date);
|
||||
if (!parsed) return "";
|
||||
|
||||
return dayjs(parsed).format("HH:mm:ss");
|
||||
}
|
||||
|
||||
/** Date → YYYY-MM-DD HH:mm:ss */
|
||||
export function toDateTimeString(date: string | number | Date): string {
|
||||
const parsed = toDate(date);
|
||||
if (!parsed) return "";
|
||||
|
||||
return dayjs(parsed).format("YYYY-MM-DD HH:mm:ss");
|
||||
}
|
||||
|
||||
export function isInMonth(date: string, month: string): boolean {
|
||||
// date 形如 "2025-01-12"
|
||||
// month 形如 "2025-01"
|
||||
return dayjs(date).format("YYYY-MM") === month;
|
||||
}
|
||||
|
||||
// 获取本月的第一天
|
||||
export function getStartOfMonth() {
|
||||
return dayjs().startOf("month").format("YYYY-MM-DD");
|
||||
}
|
||||
|
||||
// 获取本月的最后一天
|
||||
export function getEndOfMonth() {
|
||||
return dayjs().endOf("month").format("YYYY-MM-DD");
|
||||
}
|
||||
|
||||
export function normalizeDateTime(input?: string | Date | dayjs.Dayjs): string {
|
||||
if (!input) return "";
|
||||
|
||||
const raw = typeof input === "string" ? input.trim() : input;
|
||||
let d = dayjs(raw);
|
||||
|
||||
if (!d.isValid()) return "";
|
||||
|
||||
// string 才需要“猜精度”,Date / dayjs 默认是完整的
|
||||
if (typeof raw === "string") {
|
||||
if (/^\d{4}$/.test(raw)) {
|
||||
d = d.startOf("year");
|
||||
} else if (/^\d{4}-\d{2}$/.test(raw)) {
|
||||
d = d.startOf("month");
|
||||
} else if (/^\d{4}-\d{2}-\d{2}$/.test(raw)) {
|
||||
d = d.startOf("day");
|
||||
} else if (/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}$/.test(raw)) {
|
||||
d = d.second(0);
|
||||
}
|
||||
}
|
||||
|
||||
return d.format("YYYY-MM-DD HH:mm:ss");
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化时间为相对时间
|
||||
* @param timestamp 秒级或毫秒级时间戳
|
||||
*/
|
||||
export function formatRelativeTime(timestamp: number): string {
|
||||
if (!timestamp) return "未活跃";
|
||||
|
||||
// 兼容秒级时间戳
|
||||
const time = timestamp.toString().length === 10 ? dayjs(timestamp * 1000) : dayjs(timestamp);
|
||||
|
||||
const now = dayjs();
|
||||
|
||||
const diffSeconds = now.diff(time, "second");
|
||||
const diffMinutes = now.diff(time, "minute");
|
||||
const diffHours = now.diff(time, "hour");
|
||||
const diffDays = now.diff(time, "day");
|
||||
|
||||
if (diffSeconds < 30) {
|
||||
return "刚刚";
|
||||
}
|
||||
|
||||
if (diffMinutes < 60) {
|
||||
return `${diffMinutes}分钟前`;
|
||||
}
|
||||
|
||||
if (diffHours < 24) {
|
||||
return `${diffHours}小时前`;
|
||||
}
|
||||
|
||||
if (diffDays === 1) {
|
||||
return "昨天";
|
||||
}
|
||||
|
||||
if (diffDays < 7) {
|
||||
return `${diffDays}天前`;
|
||||
}
|
||||
|
||||
if (time.year() === now.year()) {
|
||||
return time.format("MM-DD HH:mm");
|
||||
}
|
||||
|
||||
return time.format("YYYY-MM-DD");
|
||||
}
|
||||
Reference in new issue
Block a user