import { ref, computed, onUnmounted } from "vue";
|
import { onShow, onHide } from "@dcloudio/uni-app";
|
import RoutingInspectionApi from "@/api/routingInspection/routingInspection";
|
|
/**
|
* 扫码数据接口
|
*/
|
interface ScanCodeData {
|
uid?: string;
|
deviceModel?: string;
|
[key: string]: any;
|
}
|
|
// 全局监听器状态映射(确保每个事件名只有一个监听器)
|
const globalListeners = new Map<string, boolean>();
|
|
// 添加一个全局的捕获所有扫码事件的监听器(用于调试)
|
let debugListenerInitialized = false;
|
|
const initDebugListener = () => {
|
if (debugListenerInitialized) return;
|
|
// 监听所有可能的扫码事件
|
const eventNames = ["scan", "scanIndex", "scanJX", "scanLS"];
|
eventNames.forEach((eventName) => {
|
uni.$on(eventName, (data: any) => {
|
console.log(`🔍 [全局调试] 捕获到 ${eventName} 事件:`, data);
|
});
|
});
|
|
debugListenerInitialized = true;
|
console.log("🔍 [全局调试] 调试监听器已初始化");
|
};
|
|
/**
|
* 扫码管理 Composable
|
* 统一管理扫码事件监听、缓存存储和数据读取
|
* 全局监听器,不随页面切换而关闭
|
* @param eventName 监听的事件名称,默认为 "scan"
|
*/
|
export function useScanCode(eventName: string = "scan") {
|
// 当前扫码的设备 UID
|
const deviceUid = ref<string>("");
|
// 当前扫码的机台型号
|
const deviceModel = ref<string>("");
|
// 完整的扫码数据
|
const scanData = ref<ScanCodeData>({});
|
// 保存事件名称
|
const currentEventName = eventName;
|
|
/**
|
* 从本地缓存加载扫码数据
|
*/
|
const loadFromCache = () => {
|
try {
|
const cachedData = uni.getStorageSync("scanCodeData");
|
if (cachedData) {
|
scanData.value = cachedData;
|
deviceUid.value = cachedData.uid || "";
|
deviceModel.value = cachedData.deviceModel || "";
|
console.log("[useScanCode] 从缓存加载扫码数据:", cachedData);
|
return cachedData;
|
}
|
} catch (error) {
|
console.error("[useScanCode] 读取缓存失败:", error);
|
}
|
return null;
|
};
|
|
/**
|
* 保存扫码数据到缓存
|
*/
|
const saveToCache = (data: ScanCodeData) => {
|
try {
|
uni.setStorageSync("scanCodeData", data);
|
console.log("[useScanCode] 已保存到缓存:", data);
|
return true;
|
} catch (error) {
|
console.error("[useScanCode] 保存缓存失败:", error);
|
return false;
|
}
|
};
|
|
/**
|
* 清空扫码数据和缓存
|
*/
|
const clearScanData = () => {
|
try {
|
uni.removeStorageSync("scanCodeData");
|
deviceUid.value = "";
|
deviceModel.value = "";
|
scanData.value = {};
|
console.log("[useScanCode] 已清空扫码数据");
|
} catch (error) {
|
console.error("[useScanCode] 清空缓存失败:", error);
|
}
|
};
|
|
/**
|
* 验证二维码(仅调用接口,不处理返回结果)
|
*/
|
const validateQRCode = async (uid: string): Promise<void> => {
|
try {
|
console.log("[useScanCode] 调用验证二维码接口, deviceUid:", uid);
|
await RoutingInspectionApi.assertScanQR({ deviceUid: uid });
|
console.log("[useScanCode] 验证接口调用完成");
|
} catch (error: any) {
|
console.error("[useScanCode] 验证接口调用异常:", error);
|
// 即使异常也不影响后续流程
|
}
|
};
|
|
/**
|
* 处理扫码事件
|
*/
|
const handleScanEvent = async (params: any) => {
|
console.log(`========== [useScanCode][${currentEventName}] 收到扫码事件 ==========`);
|
console.log(`[useScanCode][${currentEventName}] 接收参数:`, params);
|
console.log(`[useScanCode][${currentEventName}] 触发时间:`, new Date().toLocaleTimeString());
|
|
try {
|
if (!params?.code) {
|
console.warn("[useScanCode] 扫码内容为空");
|
return;
|
}
|
|
let codeObj: ScanCodeData = {};
|
try {
|
codeObj = JSON.parse(params.code);
|
console.log("[useScanCode] 解析后的对象:", codeObj);
|
} catch (err) {
|
console.error("[useScanCode] JSON 解析失败:", err);
|
console.log("[useScanCode] 原始字符串:", params.code);
|
// 如果不是 JSON,尝试作为普通字符串处理
|
codeObj = { code: params.code };
|
}
|
|
// 检查是否有必要的字段(uid 或 deviceModel)
|
if (!codeObj.uid && !codeObj.deviceModel) {
|
console.warn("[useScanCode] 扫码数据缺少 uid 和 deviceModel,不保存缓存");
|
uni.showToast({
|
title: "扫码数据无效",
|
icon: "none",
|
});
|
return;
|
}
|
|
// 更新本地状态
|
scanData.value = codeObj;
|
deviceUid.value = codeObj.uid || "";
|
deviceModel.value = codeObj.deviceModel || "";
|
|
// 保存到缓存
|
saveToCache(codeObj);
|
|
// 如果有 uid,调用验证接口(不等待结果)
|
if (codeObj.uid) {
|
validateQRCode(codeObj.uid);
|
}
|
|
// 显示成功提示
|
uni.showToast({
|
title: "扫码成功",
|
icon: "success",
|
});
|
|
console.log("[useScanCode] 扫码数据已更新:", {
|
uid: deviceUid.value,
|
deviceModel: deviceModel.value,
|
});
|
} catch (error) {
|
console.error("[useScanCode] 处理扫码数据异常:", error);
|
}
|
};
|
|
/**
|
* 启用扫码监听(全局,每次都重新注册以确保有效)
|
*/
|
const enableListener = () => {
|
// 先移除可能存在的旧监听器
|
uni.$off(currentEventName, handleScanEvent);
|
// 添加新的监听器
|
uni.$on(currentEventName, handleScanEvent);
|
// 标记为全局已启用
|
globalListeners.set(currentEventName, true);
|
console.log(
|
`[useScanCode][${currentEventName}] ✅ 全局监听器已启用/刷新(不会随页面切换关闭)`
|
);
|
};
|
|
/**
|
* 禁用扫码监听(仅用于应用退出时清理,正常页面切换不调用)
|
*/
|
const disableListener = () => {
|
if (!globalListeners.get(currentEventName)) {
|
console.log(`[useScanCode][${currentEventName}] 监听器未启用,跳过`);
|
return;
|
}
|
|
uni.$off(currentEventName, handleScanEvent);
|
globalListeners.delete(currentEventName);
|
console.log(`[useScanCode][${currentEventName}] ❌ 全局监听器已禁用`);
|
};
|
|
/**
|
* 设置页面生命周期钩子(全局监听器模式)
|
* 监听器全局启用一次,不随页面切换关闭
|
* @param options 配置选项
|
*/
|
const setupLifecycle = (
|
options: {
|
loadCacheOnShow?: boolean; // 是否在 onShow 时加载缓存
|
} = {}
|
) => {
|
const { loadCacheOnShow = true } = options;
|
|
// 只在 onShow 时加载缓存,不禁用监听器
|
if (loadCacheOnShow) {
|
onShow(() => {
|
console.log(`[useScanCode][${currentEventName}] onShow 触发`);
|
loadFromCache();
|
});
|
}
|
|
// 注意:不再在 onHide 和 onUnmounted 中禁用监听器
|
// 监听器保持全局激活状态
|
};
|
|
// 页面加载时自动从缓存读取
|
loadFromCache();
|
|
return {
|
// 状态
|
deviceUid,
|
deviceModel,
|
scanData,
|
// 计算属性
|
hasScanned: computed(() => !!deviceUid.value),
|
displayText: computed(() => deviceModel.value || "未扫码"),
|
// 方法
|
loadFromCache,
|
saveToCache,
|
clearScanData,
|
validateQRCode,
|
enableListener,
|
disableListener,
|
setupLifecycle,
|
};
|
}
|