Files
cunkebao_v3/Cunkebao/src/utils/common.ts
超级老白兔 e7b795f744 refactor(websocket): 优化websocket消息处理及状态检查逻辑
移除调试日志输出并优化微信账号状态检查逻辑
添加深拷贝工具函数并应用于客服列表处理
将状态检查改为间隔10秒的轮询方式
2025-09-02 10:18:25 +08:00

158 lines
4.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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;
}