| | |
| | | |
| | | 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 |
| | | }); |
| | | }; |
| | | |
| | |
| | | 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', |
| | |
| | | |
| | | 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; |
| | | }; |