import { getEnums } from '@/api/index.js' import { getCurrentLanguage } from '@/utils/i18n' const ENUMS_CACHE_KEY = 'mini_enums_cache_v1' const BUILTIN_ENUMS = { zh: { IdCardTypeEnum: [ { key: 3, value: '港澳通行证', valueEn: 'Mainland Travel Permit for Hong Kong and Macao Residents' }, { key: 2, value: '护照', valueEn: 'Passport' }, { key: 99, value: '其他', valueEn: 'Other' }, { key: 1, value: '身份证', valueEn: 'ID Card' }, { key: 4, value: '台湾通行证', valueEn: 'Mainland Travel Permit for Taiwan Residents' } ] }, en: { IdCardTypeEnum: [ { key: 3, value: 'Mainland Travel Permit for Hong Kong and Macao Residents', valueZh: '港澳通行证' }, { key: 2, value: 'Passport', valueZh: '护照' }, { key: 99, value: 'Other', valueZh: '其他' }, { key: 1, value: 'ID Card', valueZh: '身份证' }, { key: 4, value: 'Mainland Travel Permit for Taiwan Residents', valueZh: '台湾通行证' } ] } } let enumsMap = {} let enumsLanguage = '' let fetchPromise = null function hasRemoteEnumData(map = {}, language) { const currentLanguage = getNormalizedLanguage(language) const builtinKeys = Object.keys(BUILTIN_ENUMS[currentLanguage] || {}) const sourceMap = map && typeof map === 'object' ? map : {} return Object.keys(sourceMap).some(code => !builtinKeys.includes(code)) } function mergeEnumOptionList(builtinList = [], customList = []) { const nextList = [] const customMap = new Map() ;(Array.isArray(customList) ? customList : []).forEach((item) => { if (!item || typeof item !== 'object') return customMap.set(String(item.key), item) }) ;(Array.isArray(builtinList) ? builtinList : []).forEach((item) => { const key = String(item && item.key) const customItem = customMap.get(key) if (customItem) { nextList.push({ ...item, ...customItem }) customMap.delete(key) return } nextList.push(item) }) customMap.forEach((item) => { nextList.push(item) }) return nextList } function mergeBuiltinEnums(map = {}, language) { const currentLanguage = getNormalizedLanguage(language) const builtinMap = BUILTIN_ENUMS[currentLanguage] || {} const mergedMap = { ...builtinMap, ...(map || {}) } Object.keys(builtinMap).forEach((code) => { if (!Array.isArray(mergedMap[code])) { mergedMap[code] = builtinMap[code] return } mergedMap[code] = mergeEnumOptionList(builtinMap[code], mergedMap[code]) }) return mergedMap } function parseJsonStringMaybe(value) { if (typeof value !== 'string') { return value } const text = value.trim() if (!text) { return value } if (!((text.startsWith('{') && text.endsWith('}')) || (text.startsWith('[') && text.endsWith(']')))) { return value } try { return JSON.parse(text) } catch (error) { return value } } function normalizeEnumMap(data) { const normalizedData = parseJsonStringMaybe(data) const map = {} if (Array.isArray(normalizedData)) { normalizedData.forEach((item) => { if (item && item.code) { map[item.code] = Array.isArray(item.data) ? item.data : [] } }) } return map } function getNormalizedLanguage(language = '') { return String(language || getCurrentLanguage() || 'zh').trim().toLowerCase() === 'en' ? 'en' : 'zh' } function readEnumsCache(language) { const cacheLanguage = getNormalizedLanguage(language) try { const cached = uni.getStorageSync(ENUMS_CACHE_KEY) if (!cached) return {} const resolveLanguageBucket = (payload) => { if (!payload || typeof payload !== 'object' || Array.isArray(payload)) { return {} } if (payload.en || payload.zh) { const bucket = payload[cacheLanguage] return bucket && typeof bucket === 'object' ? bucket : {} } return payload } if (typeof cached === 'string') { const parsed = JSON.parse(cached) return resolveLanguageBucket(parsed) } return resolveLanguageBucket(cached) } catch (error) { console.error('Failed to read enums cache', error) return {} } } function writeEnumsCache(map, language) { const cacheLanguage = getNormalizedLanguage(language) try { const cached = uni.getStorageSync(ENUMS_CACHE_KEY) let nextCache = {} if (cached && typeof cached === 'object' && !Array.isArray(cached)) { nextCache = { ...cached } } else if (typeof cached === 'string') { try { const parsed = JSON.parse(cached) if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) { nextCache = { ...parsed } } } catch (error) { nextCache = {} } } nextCache[cacheLanguage] = map uni.setStorageSync(ENUMS_CACHE_KEY, nextCache) } catch (error) { console.error('Failed to write enums cache', error) } } export function initEnumsFromCache(language) { const currentLanguage = getNormalizedLanguage(language) if (Object.keys(enumsMap).length && enumsLanguage === currentLanguage) return enumsMap enumsMap = mergeBuiltinEnums(readEnumsCache(currentLanguage), currentLanguage) enumsLanguage = currentLanguage return enumsMap } export async function fetchEnums(force = false, language) { const currentLanguage = getNormalizedLanguage(language) if (!force && Object.keys(enumsMap).length && enumsLanguage === currentLanguage && hasRemoteEnumData(enumsMap, currentLanguage)) { return enumsMap } if (fetchPromise) return fetchPromise fetchPromise = (async () => { if (!force && (!Object.keys(enumsMap).length || enumsLanguage !== currentLanguage)) { initEnumsFromCache(currentLanguage) if (Object.keys(enumsMap).length && hasRemoteEnumData(enumsMap, currentLanguage)) { return enumsMap } } try { const res = await getEnums({}, currentLanguage) const data = res && res.data ? res.data : res const map = mergeBuiltinEnums(normalizeEnumMap(data), currentLanguage) if (Object.keys(map).length) { enumsMap = map enumsLanguage = currentLanguage writeEnumsCache(map, currentLanguage) } return enumsMap } catch (error) { console.error('Failed to fetch enums', error) return enumsMap } finally { fetchPromise = null } })() return fetchPromise } export function getEnumOptions(code, language) { initEnumsFromCache(language) return enumsMap[code] || [] } export function getBuiltInEnums(language) { return mergeBuiltinEnums({}, language) } export function getEnumLabel(code, key, fallback = '', language) { const options = getEnumOptions(code, language) const matched = options.find(item => String(item.key) === String(key)) if (matched) return matched.value return fallback || key } export function getApprovalStatusLabel(status, fallback = '', language) { return getEnumLabel('ApprovalStatusEnum', status, fallback, language) } export function getGenderLabel(gender, fallback = '', language) { return getEnumLabel('GenderEnum', gender, fallback, language) } export const ACCOUNT_BILL_STATUS = { ACTIVE: 10, FINISHED: 99 } export const ACCOUNT_BILL_PAYMENT_STATUS = { UNPAID: 0, PARTIAL: 1, PAID: 2 } export const ACCOUNT_BILL_REFUND_STATUS = { NONE: 0, PARTIAL: 10, REFUNDED: 99 } export function getAccountBillStatusLabel(status, fallback = '', language) { return getEnumLabel('AccountBillStatusEnum', status, fallback, language) } export function getAccountBillPaymentStatusLabel(status, fallback = '', language) { return getEnumLabel('AccountBillPaymentStatusEnum', status, fallback, language) } export function getAccountBillRefundStatusLabel(status, fallback = '', language) { return getEnumLabel('AccountBillRefundStatusEnum', status, fallback, language) } export function getAccountReferenceTypeLabel(type, fallback = '', language) { return getEnumLabel('AccountReferenceTypeEnum', type, fallback, language) }