From cc2f6601aa3fef21173c40534687f6fd50c520de Mon Sep 17 00:00:00 2001
From: zjk <852185829@qq.com>
Date: 星期四, 23 七月 2026 18:25:23 +0800
Subject: [PATCH] feat: 优化扫码逻辑,重构弹窗与员工验证缓存
---
api/employee.js | 165 ++++++++++++++++++++++++++++++++++++++++++++++++++----
1 files changed, 151 insertions(+), 14 deletions(-)
diff --git a/api/employee.js b/api/employee.js
index 2259f57..88160a6 100644
--- a/api/employee.js
+++ b/api/employee.js
@@ -3,10 +3,57 @@
const EMPLOYEE_VERIFY_LIST_KEY = 'employee_verify_list';
const EMPLOYEE_FACE_IMAGE_DIR = 'employee-face-images';
+let employeeVerifyListSyncPromise = null;
const yieldMainThread = (delay = 0) => {
return new Promise((resolve) => {
setTimeout(resolve, delay);
+ });
+};
+
+const saveEmployeeVerifyListCache = async (employeeList = []) => {
+ await saveOfflineConfig(EMPLOYEE_VERIFY_LIST_KEY, employeeList);
+ uni.setStorageSync(EMPLOYEE_VERIFY_LIST_KEY, employeeList);
+};
+
+const getCurrentNetworkType = async () => {
+ return new Promise((resolve) => {
+ uni.getNetworkType({
+ success: (res) => resolve(res.networkType),
+ fail: () => resolve('unknown'),
+ });
+ });
+};
+
+const isLocalEmployeeFacePath = (value = '') => {
+ const normalizedValue = String(value || '').trim();
+ return /^(file:\/\/|_doc\/|\/storage\/)/.test(normalizedValue);
+};
+
+const isLocalFileExists = (filePath = '') => {
+ return new Promise((resolve) => {
+ const normalizedFilePath = String(filePath || '').trim();
+ if (!normalizedFilePath) {
+ resolve(false);
+ return;
+ }
+
+ // #ifdef APP-PLUS
+ if (typeof plus === 'undefined' || !plus.io || !plus.io.resolveLocalFileSystemURL) {
+ resolve(false);
+ return;
+ }
+
+ plus.io.resolveLocalFileSystemURL(normalizedFilePath, () => {
+ resolve(true);
+ }, () => {
+ resolve(false);
+ });
+ // #endif
+
+ // #ifndef APP-PLUS
+ resolve(true);
+ // #endif
});
};
@@ -156,6 +203,80 @@
return [];
};
+const sanitizeEmployeeFaceImageCache = async (employee = {}) => {
+ if (!employee || typeof employee !== 'object') {
+ return {
+ employee,
+ invalidLocalFaceImage: false,
+ };
+ }
+
+ const normalizedEmployee = { ...employee };
+ const normalizedFaceImage = String(employee.faceImage || '').trim();
+ if (!isLocalEmployeeFacePath(normalizedFaceImage)) {
+ return {
+ employee: normalizedEmployee,
+ invalidLocalFaceImage: false,
+ };
+ }
+
+ const isFaceImageFileExists = await isLocalFileExists(normalizedFaceImage);
+ if (isFaceImageFileExists) {
+ return {
+ employee: normalizedEmployee,
+ invalidLocalFaceImage: false,
+ };
+ }
+
+ // 本地图片文件被系统清理后,必须立刻清空失效路径,避免离线状态继续拿脏地址做人脸比对。
+ normalizedEmployee.faceImage = '';
+ return {
+ employee: normalizedEmployee,
+ invalidLocalFaceImage: true,
+ };
+};
+
+const sanitizeEmployeeVerifyListCache = async (employeeList = []) => {
+ const sanitizedEmployeeList = [];
+ let hasInvalidLocalFaceImage = false;
+
+ for (let index = 0; index < employeeList.length; index += 1) {
+ const sanitizeResult = await sanitizeEmployeeFaceImageCache(employeeList[index]);
+ sanitizedEmployeeList.push(sanitizeResult.employee);
+ hasInvalidLocalFaceImage = hasInvalidLocalFaceImage || sanitizeResult.invalidLocalFaceImage;
+ }
+
+ return {
+ employeeList: sanitizedEmployeeList,
+ hasInvalidLocalFaceImage,
+ };
+};
+
+const performSyncEmployeeVerifyList = async () => {
+ const res = await getAllEmployeeVerifyAPI();
+ if (res && res.code === 200) {
+ const employeeList = normalizeEmployeeListResponse(res.data);
+ const normalizedEmployeeList = await normalizeEmployeeListFaceImages(employeeList);
+ await saveEmployeeVerifyListCache(normalizedEmployeeList);
+ return normalizedEmployeeList;
+ }
+
+ throw new Error(res?.msg || '同步员工验证列表失败');
+};
+
+const runEmployeeVerifyListSync = async () => {
+ if (employeeVerifyListSyncPromise) {
+ return employeeVerifyListSyncPromise;
+ }
+
+ employeeVerifyListSyncPromise = performSyncEmployeeVerifyList();
+ try {
+ return await employeeVerifyListSyncPromise;
+ } finally {
+ employeeVerifyListSyncPromise = null;
+ }
+};
+
export const getAllEmployeeVerifyAPI = (data = {}) => {
return request({
url: '/api/employee/verify/allEmployee',
@@ -166,27 +287,43 @@
export const syncEmployeeVerifyList = async () => {
try {
- const res = await getAllEmployeeVerifyAPI();
- if (res && res.code === 200) {
- const employeeList = normalizeEmployeeListResponse(res.data);
- const normalizedEmployeeList = await normalizeEmployeeListFaceImages(employeeList);
- await saveOfflineConfig(EMPLOYEE_VERIFY_LIST_KEY, normalizedEmployeeList);
- uni.setStorageSync(EMPLOYEE_VERIFY_LIST_KEY, normalizedEmployeeList);
- return normalizedEmployeeList;
- }
+ return await runEmployeeVerifyListSync();
} catch (error) {
console.error('同步员工验证列表失败:', error);
+ return [];
}
-
- return [];
};
export const getLocalEmployeeVerifyList = async () => {
const offlineEmployeeList = await getOfflineConfig(EMPLOYEE_VERIFY_LIST_KEY);
- if (Array.isArray(offlineEmployeeList)) {
- return offlineEmployeeList;
+ const storageEmployeeList = uni.getStorageSync(EMPLOYEE_VERIFY_LIST_KEY);
+ const localEmployeeList = Array.isArray(offlineEmployeeList)
+ ? offlineEmployeeList
+ : (Array.isArray(storageEmployeeList) ? storageEmployeeList : []);
+
+ if (!Array.isArray(localEmployeeList) || localEmployeeList.length === 0) {
+ return [];
}
- const storageEmployeeList = uni.getStorageSync(EMPLOYEE_VERIFY_LIST_KEY);
- return Array.isArray(storageEmployeeList) ? storageEmployeeList : [];
+ const {
+ employeeList: sanitizedEmployeeList,
+ hasInvalidLocalFaceImage,
+ } = await sanitizeEmployeeVerifyListCache(localEmployeeList);
+
+ if (!hasInvalidLocalFaceImage) {
+ return sanitizedEmployeeList;
+ }
+
+ await saveEmployeeVerifyListCache(sanitizedEmployeeList);
+
+ const networkType = await getCurrentNetworkType();
+ if (networkType !== 'none') {
+ try {
+ return await runEmployeeVerifyListSync();
+ } catch (error) {
+ console.error('员工人脸缓存失效后自动重同步失败:', error);
+ }
+ }
+
+ return sanitizedEmployeeList;
};
--
Gitblit v1.7.1