2025-08-26 16:20:35 +08:00
|
|
|
|
/**
|
|
|
|
|
* 生成短ID (16位字符) 类似随机数
|
|
|
|
|
*/
|
|
|
|
|
export const generateShortId = (): string => {
|
|
|
|
|
const crypto = window.crypto || (window as any).msCrypto;
|
|
|
|
|
if (crypto?.getRandomValues) {
|
|
|
|
|
return Array.from(crypto.getRandomValues(new Uint32Array(3)))
|
|
|
|
|
.map(n => n.toString(36))
|
|
|
|
|
.join('')
|
|
|
|
|
.slice(0, 16);
|
|
|
|
|
}
|
|
|
|
|
return Date.now().toString(36) + Math.random().toString(36).substr(2, 8);
|
|
|
|
|
};
|
|
|
|
|
|
2025-08-30 14:45:55 +08:00
|
|
|
|
|
|
|
|
|
// 时间转化
|
|
|
|
|
/**
|
|
|
|
|
* 时间戳转 24小时制 HH:mm
|
|
|
|
|
* @param timestamp 秒/毫秒级时间戳
|
|
|
|
|
*/
|
|
|
|
|
export const formatTimestampToHM = (timestamp: number) => {
|
|
|
|
|
if (!timestamp) return '';
|
|
|
|
|
// 秒级时间戳 → 毫秒级
|
|
|
|
|
const msTimestamp = timestamp.toString().length === 10
|
|
|
|
|
? timestamp * 1000
|
|
|
|
|
: timestamp;
|
|
|
|
|
const date = new Date(msTimestamp);
|
|
|
|
|
// 小时、分钟补零
|
|
|
|
|
const hours = date.getHours().toString().padStart(2, '0');
|
|
|
|
|
const minutes = date.getMinutes().toString().padStart(2, '0');
|
|
|
|
|
return `${hours}:${minutes}`;
|
|
|
|
|
};
|
|
|
|
|
|
2025-08-26 16:20:35 +08:00
|
|
|
|
|
|
|
|
|
// 类型定义
|
|
|
|
|
export interface DeviceStatusOptions {
|
|
|
|
|
functionMode: number;
|
|
|
|
|
batchId: string;
|
|
|
|
|
typeName: string;
|
|
|
|
|
deviceImei: string;
|
|
|
|
|
interval?: number;
|
|
|
|
|
}
|
|
|
|
|
export interface ApiResponse<T = any> {
|
|
|
|
|
code: number;
|
|
|
|
|
msg: string;
|
|
|
|
|
data: T;
|
|
|
|
|
}
|
|
|
|
|
export interface DeviceStatusData {
|
|
|
|
|
functionAccess: 'OK' | 'ACTIVE' | 'FAILED' | 'TIMEOUT' | string;
|
|
|
|
|
[key: string]: any;
|
|
|
|
|
}
|
|
|
|
|
export type ApiClientFunction = (params: any) => Promise<ApiResponse>;
|
|
|
|
|
/**
|
|
|
|
|
* 获取设备状态(带自动轮询)
|
|
|
|
|
* @param options - 配置对象
|
|
|
|
|
* @param options.functionMode - 功能模式
|
|
|
|
|
* @param options.batchId - 批次ID
|
|
|
|
|
* @param options.typeName - 类型名称
|
|
|
|
|
* @param options.deviceImei - 设备IMEI
|
|
|
|
|
* @param options.interval - 轮询间隔(毫秒),默认500
|
|
|
|
|
* @param apiClient - 接口调用函数
|
|
|
|
|
* @returns 设备状态响应
|
|
|
|
|
*/
|
|
|
|
|
export async function getDeviceStatus(
|
|
|
|
|
options: DeviceStatusOptions,
|
|
|
|
|
apiClient: ApiClientFunction
|
|
|
|
|
): Promise<ApiResponse<DeviceStatusData>> {
|
|
|
|
|
const {
|
|
|
|
|
functionMode,
|
|
|
|
|
batchId,
|
|
|
|
|
typeName,
|
|
|
|
|
deviceImei,
|
|
|
|
|
interval = 500
|
|
|
|
|
} = options;
|
|
|
|
|
// 添加最大重试次数防止无限循环
|
|
|
|
|
const checkStatus = async (): Promise<ApiResponse<DeviceStatusData>> => {
|
|
|
|
|
try {
|
|
|
|
|
const res = await apiClient({
|
|
|
|
|
functionMode,
|
|
|
|
|
batchId,
|
|
|
|
|
typeName,
|
|
|
|
|
deviceImei
|
|
|
|
|
});
|
|
|
|
|
if (res.code !== 200) {
|
|
|
|
|
throw new Error(res.msg || '请求失败');
|
|
|
|
|
}
|
|
|
|
|
switch (res.data.functionAccess) {
|
|
|
|
|
case 'OK':
|
|
|
|
|
return res;
|
|
|
|
|
case 'ACTIVE':
|
|
|
|
|
await new Promise(resolve => setTimeout(resolve, interval));
|
|
|
|
|
return checkStatus();
|
|
|
|
|
case 'FAILED':
|
|
|
|
|
throw new Error('设备操作失败');
|
|
|
|
|
case 'TIMEOUT':
|
|
|
|
|
throw new Error('设备响应超时');
|
|
|
|
|
default:
|
|
|
|
|
throw new Error(`未知状态: ${res.data.functionAccess}`);
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('设备状态轮询错误:', error);
|
|
|
|
|
throw error;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return checkStatus();
|
|
|
|
|
}
|
2025-08-30 14:45:55 +08:00
|
|
|
|
export default { generateShortId, formatTimestampToHM }
|