import { getBookingList, getCurrentUser, getRegisteredUser, saveBookingList, saveCurrentBooking, saveCurrentUser, saveRegisteredUser } from './app-state' import { getApprovalStatusLabel, getGenderLabel } from './enum-store' import { getCurrentLanguage } from './i18n' import store from '@/store' const AUTH_STATUS_TEXT = { zh: { unsubmitted: '未实名', pending: '审核中', approved: '已通过', rejected: '已驳回' }, en: { unsubmitted: 'Not Verified', pending: 'Under Review', approved: 'Approved', rejected: 'Rejected' } } const BOOKING_STATUS_TEXT = { zh: { none: '暂无预订', pending_review: '预订审核中', approved_wait_assign: '审核通过', assigned_wait_room: '已分配管家,待分房号', rejected: '预订已驳回' }, en: { none: 'No Booking', pending_review: 'Booking Under Review', approved_wait_assign: 'Approved', assigned_wait_room: 'Butler Assigned, Awaiting Room', rejected: 'Booking Rejected' } } function resolveLanguageMap(map, language) { const currentLanguage = language || getCurrentLanguage() return currentLanguage === 'en' ? map.en : map.zh } function getFlowGenderFallback(gender, language) { const currentLanguage = language || getCurrentLanguage() if (gender === 1) { return currentLanguage === 'en' ? 'Male' : '男' } if (gender === 0) { return currentLanguage === 'en' ? 'Female' : '女' } return '' } export function mapRegistrationApprovalToAuthStatus(status) { if (status === 1) return 'approved' if (status === -1) return 'rejected' if (status === 0) return 'pending' return 'unsubmitted' } function normalizeLookupValue(value) { if (value === null || typeof value === 'undefined') { return '' } return String(value).trim() } function normalizeRegistrationCodeCandidate(value) { const normalized = normalizeLookupValue(value) if (!normalized) { return '' } // 过滤业务状态码,避免把 200/500 这类响应码误存成申请单编号 if (/^\d{1,6}$/.test(normalized)) { return '' } return normalized } export function resolveRegistrationApplicationCode(source = {}) { const raw = source && source.data ? source.data : source const candidates = [ source && source.registrationCode, source && source.data, raw && raw.code, raw && raw.registrationCode, raw, raw && raw.data && raw.data.code, raw && raw.data && raw.data.registrationCode, raw && raw.data, source && source.data && source.data.data && source.data.data.code, source && source.data && source.data.data && source.data.data.registrationCode, source && source.code ] return candidates.map(normalizeRegistrationCodeCandidate).find(Boolean) || '' } export function normalizeUser(raw = {}) { const user = raw || {} return { ...user, hasAuth: user.hasAuth === true, authStatus: user.authStatus || 'unsubmitted', authRejectReason: user.authRejectReason || '', authProfile: user.authProfile || null, bookingStatus: user.bookingStatus || 'none', bookingRejectReason: user.bookingRejectReason || '', currentBooking: user.currentBooking || null, hasCheckedIn: user.hasCheckedIn === true } } export function buildUserFromRegistrationApplication(application = {}, options = {}) { const source = application || {} const normalizedOptions = options || {} const language = normalizedOptions.language || getCurrentLanguage() const profile = { identityType: source.passportNumber ? 'foreign' : 'domestic', account: source.account || normalizedOptions.account || '', email: source.email || normalizedOptions.email || '', roleNo: source.roleNo || normalizedOptions.roleNo || '', name: source.name || normalizedOptions.name || '', gender: typeof source.gender === 'number' ? source.gender : null, genderText: source.genderDesc || getGenderLabel(source.gender, getFlowGenderFallback(source.gender, language), language), phone: source.phone || normalizedOptions.phone || '', country: source.country || normalizedOptions.country || '', idCard: source.idCard || '', workUnit: source.workUnit || '', hasHangzhouProperty: typeof source.hasHangzhouProperty === 'boolean' ? source.hasHangzhouProperty : null, dietaryHabitTags: source.dietaryHabitTags || [], hobbyTags: source.hobbyTags || [], passportNumber: source.passportNumber || '', passportExpiry: source.passportExpiry || '', school: source.school || '', religionTags: source.religionTags || [], passportAttachment: source.passportAttachment || '', idCardFrontAttachment: source.idCardFrontAttachment || '', idCardBackAttachment: source.idCardBackAttachment || '' } return normalizeUser({ id: source.convertedUserCode || source.code || normalizedOptions.id || '', code: source.code || source.convertedUserCode || normalizedOptions.code || '', userCode: source.convertedUserCode || source.userCode || source.code || normalizedOptions.userCode || '', firstChar: (source.name || normalizedOptions.name || 'U').charAt(0).toUpperCase(), name: source.name || normalizedOptions.name || '', account: source.account || normalizedOptions.account || '', username: source.account || normalizedOptions.account || '', password: normalizedOptions.password || '', email: source.email || normalizedOptions.email || '', phone: source.phone || normalizedOptions.phone || '', roleNo: source.roleNo || normalizedOptions.roleNo || '', hasAuth: source.approvalStatus === 1, authStatus: mapRegistrationApprovalToAuthStatus(source.approvalStatus), authRejectReason: source.approveReason || '', authDate: source.createTime ? new Date(source.createTime).toLocaleDateString() : '', authProfile: profile }) } export function mergeBackendUserInfo(baseUser = {}, backendUserInfo = {}) { const user = baseUser || {} const response = backendUserInfo || {} const raw = response && response.data ? response.data : response const info = raw || {} const mergedUser = { ...user, id: info.code || info.userCode || user.id || '', code: info.code || info.userCode || user.code || '', userCode: info.userCode || info.code || user.userCode || '', backendUserInfo: info, name: info.name || user.name || '', account: info.account || user.account || '', username: info.account || user.username || user.account || '', avatar: info.avatar || info.base64Face || user.avatar || '', base64Face: info.base64Face || user.base64Face || '', phone: info.phone || user.phone || '', email: info.email || user.email || '', roleNo: info.roleNo || user.roleNo || '', roles: Array.isArray(info.roles) ? info.roles : (user.roles || []), permissions: Array.isArray(info.permissions) ? info.permissions : (user.permissions || []) } if (mergedUser.authProfile) { mergedUser.authProfile = { ...mergedUser.authProfile, name: mergedUser.name || mergedUser.authProfile.name || '', account: mergedUser.account || mergedUser.authProfile.account || '', email: mergedUser.email || mergedUser.authProfile.email || '', phone: mergedUser.phone || mergedUser.authProfile.phone || '', roleNo: mergedUser.roleNo || mergedUser.authProfile.roleNo || '' } } return normalizeUser(mergedUser) } export function getStoredUser() { const storeUser = store && store.state ? store.state.vuex_user : {} if (storeUser && Object.keys(storeUser).length) { return normalizeUser(storeUser) } const currentUser = getCurrentUser() if (currentUser && Object.keys(currentUser).length) { return normalizeUser(currentUser) } const registeredUser = getRegisteredUser() return normalizeUser(registeredUser || {}) } export function saveUser(user) { const normalizedUser = normalizeUser(user) saveCurrentUser(normalizedUser) saveRegisteredUser(normalizedUser) if (store && store.commit) { store.commit('$tStore', { name: 'vuex_user', value: normalizedUser }) } return normalizedUser } export function getAuthStatusText(status, language) { const languageMap = resolveLanguageMap(AUTH_STATUS_TEXT, language) const numericMap = { pending: 0, approved: 1, rejected: -1 } if (Object.prototype.hasOwnProperty.call(numericMap, status)) { return getApprovalStatusLabel(numericMap[status], languageMap[status] || languageMap.unsubmitted, language) } return languageMap[status] || languageMap.unsubmitted } export function getBookingStatusText(status, language) { const languageMap = resolveLanguageMap(BOOKING_STATUS_TEXT, language) return languageMap[status] || languageMap.none } export function getBookingTagType(status) { if (status === 'rejected') { return 'rejected' } if (status === 'pending_review') { return 'pending' } return 'approved' } export function createBooking(payload = {}) { const source = payload || {} const now = Date.now() const status = source.status || 'pending_review' return { orderNo: `LJYD${now}`, status, statusText: getBookingStatusText(status), statusTextZh: getBookingStatusText(status, 'zh'), statusTextEn: getBookingStatusText(status, 'en'), createdAt: new Date(now).toLocaleString(), butlerName: '', roomAssignStatus: 'pending', rejectReason: '', ...source } } export function saveBooking(booking) { const normalizedBooking = booking && typeof booking === 'object' ? { ...booking, statusTextZh: booking.statusTextZh || getBookingStatusText(booking.status || 'pending_review', 'zh'), statusTextEn: booking.statusTextEn || getBookingStatusText(booking.status || 'pending_review', 'en') } : booking const bookingList = getBookingList() const nextList = [normalizedBooking, ...bookingList.filter(item => item.orderNo !== normalizedBooking.orderNo)] saveCurrentBooking(normalizedBooking) saveBookingList(nextList) return nextList }