158 lines
4.3 KiB
TypeScript
158 lines
4.3 KiB
TypeScript
import { Modal } from "antd-mobile";
|
||
import { getSetting } from "@/store/module/settings";
|
||
export function formatWechatTime(timestamp) {
|
||
if (!timestamp) {
|
||
return "";
|
||
}
|
||
// 处理时间戳(兼容秒级/毫秒级)
|
||
const date = new Date(
|
||
timestamp.toString().length === 10 ? timestamp * 1000 : timestamp,
|
||
);
|
||
const now = new Date();
|
||
|
||
// 获取消息时间的年月日时分
|
||
const messageYear = date.getFullYear();
|
||
const messageMonth = date.getMonth();
|
||
const messageDate = date.getDate();
|
||
const messageHour = date.getHours().toString().padStart(2, "0");
|
||
const messageMinute = date.getMinutes().toString().padStart(2, "0");
|
||
|
||
// 获取当前时间的年月日
|
||
const nowYear = now.getFullYear();
|
||
const nowMonth = now.getMonth();
|
||
const nowDate = now.getDate();
|
||
|
||
// 创建当天0点的时间对象,用于比较是否同一天
|
||
const today = new Date(nowYear, nowMonth, nowDate, 0, 0, 0);
|
||
const yesterday = new Date(today);
|
||
yesterday.setDate(yesterday.getDate() - 1);
|
||
const weekAgo = new Date(today);
|
||
weekAgo.setDate(weekAgo.getDate() - 6); // 7天前(包括今天)
|
||
|
||
// 消息日期(不含时间)
|
||
const messageDay = new Date(messageYear, messageMonth, messageDate, 0, 0, 0);
|
||
|
||
// 当天消息:只显示时分
|
||
if (messageDay.getTime() === today.getTime()) {
|
||
return `${messageHour}:${messageMinute}`;
|
||
}
|
||
|
||
// 昨天消息:显示"昨天 时分"
|
||
if (messageDay.getTime() === yesterday.getTime()) {
|
||
return `昨天 ${messageHour}:${messageMinute}`;
|
||
}
|
||
|
||
// 一周内消息:显示"星期X 时分"
|
||
if (messageDay.getTime() >= weekAgo.getTime()) {
|
||
const weekdays = ["周日", "周一", "周二", "周三", "周四", "周五", "周六"];
|
||
return `${weekdays[date.getDay()]} ${messageHour}:${messageMinute}`;
|
||
}
|
||
|
||
// 超过一周:显示"年月日 时分"
|
||
return `${messageYear}年${messageMonth + 1}月${messageDate}日 ${messageHour}:${messageMinute}`;
|
||
}
|
||
/**
|
||
* 通用js调用弹窗,Promise风格
|
||
* @param content 弹窗内容
|
||
* @param config 配置项(title, cancelText, confirmText)
|
||
* @returns Promise<void>
|
||
*/
|
||
export const comfirm = (
|
||
content: string,
|
||
config?: {
|
||
title?: string;
|
||
cancelText?: string;
|
||
confirmText?: string;
|
||
},
|
||
): Promise<void> => {
|
||
return new Promise((resolve, reject) => {
|
||
Modal.show({
|
||
title: config?.title || "提示",
|
||
content,
|
||
closeOnAction: true,
|
||
actions: [
|
||
{
|
||
key: "cancel",
|
||
text: config?.cancelText || "取消",
|
||
onClick: () => reject(),
|
||
},
|
||
{
|
||
key: "confirm",
|
||
text: config?.confirmText || "确认",
|
||
danger: true,
|
||
onClick: () => resolve(),
|
||
},
|
||
],
|
||
});
|
||
});
|
||
};
|
||
|
||
export function getSafeAreaHeight() {
|
||
// 1. 优先使用 CSS 环境变量
|
||
if (CSS.supports("padding-top", "env(safe-area-inset-top)")) {
|
||
const safeAreaTop = getComputedStyle(
|
||
document.documentElement,
|
||
).getPropertyValue("env(safe-area-inset-top)");
|
||
const height = parseInt(safeAreaTop) || 0;
|
||
if (height > 0) return height;
|
||
}
|
||
|
||
// 2. 设备检测
|
||
const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent);
|
||
const isAndroid = /Android/.test(navigator.userAgent);
|
||
const isAppMode = getSetting("isAppMode");
|
||
if (isIOS && isAppMode) {
|
||
// iOS 设备
|
||
const isIPhoneX = window.screen.height >= 812;
|
||
return isIPhoneX ? 44 : 20;
|
||
} else if (isAndroid) {
|
||
// Android 设备
|
||
return 24;
|
||
}
|
||
|
||
// 3. 默认值
|
||
return 0;
|
||
}
|
||
|
||
/**
|
||
* 深拷贝函数,支持对象、数组、Date、RegExp等类型
|
||
* @param obj 要拷贝的对象
|
||
* @returns 深拷贝后的对象
|
||
*/
|
||
export function deepCopy<T>(obj: T): T {
|
||
// 处理 null 和 undefined
|
||
if (obj === null || obj === undefined) {
|
||
return obj;
|
||
}
|
||
|
||
// 处理基本数据类型
|
||
if (typeof obj !== "object") {
|
||
return obj;
|
||
}
|
||
|
||
// 处理 Date 对象
|
||
if (obj instanceof Date) {
|
||
return new Date(obj.getTime()) as T;
|
||
}
|
||
|
||
// 处理 RegExp 对象
|
||
if (obj instanceof RegExp) {
|
||
return new RegExp(obj.source, obj.flags) as T;
|
||
}
|
||
|
||
// 处理 Array
|
||
if (Array.isArray(obj)) {
|
||
return obj.map(item => deepCopy(item)) as T;
|
||
}
|
||
|
||
// 处理普通对象
|
||
const clonedObj = {} as T;
|
||
for (const key in obj) {
|
||
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
||
clonedObj[key] = deepCopy(obj[key]);
|
||
}
|
||
}
|
||
|
||
return clonedObj;
|
||
}
|