chore: initial import
This commit is contained in:
346
utils/session-sync.js
Normal file
346
utils/session-sync.js
Normal file
@@ -0,0 +1,346 @@
|
||||
import {
|
||||
clearBookingState,
|
||||
clearMyRoomData,
|
||||
getCurrentUser,
|
||||
getLoginStatus,
|
||||
saveBookingList,
|
||||
saveCurrentBooking,
|
||||
saveEffectiveContracts,
|
||||
saveCurrentUser,
|
||||
saveMyRoomData,
|
||||
savePendingContractCount,
|
||||
savePendingContracts,
|
||||
saveRegisteredUser,
|
||||
setCheckedInStatus
|
||||
} from './app-state'
|
||||
import {
|
||||
getMyEffectiveContracts,
|
||||
getMyPendingSignContracts,
|
||||
orderSearchedMePage
|
||||
} from '@/api/index.js'
|
||||
import store from '@/store'
|
||||
import {
|
||||
normalizeBookingList,
|
||||
parseOrderListResponse,
|
||||
pickCurrentBooking,
|
||||
pickCurrentStayOrder
|
||||
} from './booking-helper'
|
||||
import { getCurrentLanguage } from './i18n'
|
||||
|
||||
const SYNC_TTL = 3000
|
||||
|
||||
let syncStayStatePromise = null
|
||||
let lastSyncStayStateAt = 0
|
||||
|
||||
function getSessionSyncText(key = '') {
|
||||
const isEn = getCurrentLanguage() === 'en'
|
||||
const map = {
|
||||
pendingContract: isEn ? 'Pending Contract Signature' : '待签合同'
|
||||
}
|
||||
|
||||
return map[key] || ''
|
||||
}
|
||||
|
||||
function parseContractList(response) {
|
||||
const payload = response && response.data ? response.data : response
|
||||
|
||||
if (Array.isArray(payload)) {
|
||||
return payload
|
||||
}
|
||||
|
||||
if (payload && Array.isArray(payload.data)) {
|
||||
return payload.data
|
||||
}
|
||||
|
||||
if (payload && payload.data && Array.isArray(payload.data.data)) {
|
||||
return payload.data.data
|
||||
}
|
||||
|
||||
return []
|
||||
}
|
||||
|
||||
function buildLeaseText(order = {}) {
|
||||
const start = String(order.startDate || order.start || order.checkinDate || '').slice(0, 10)
|
||||
const end = String(order.endDate || order.end || order.checkoutDate || '').slice(0, 10)
|
||||
|
||||
if (start && end) {
|
||||
return `${start} - ${end}`
|
||||
}
|
||||
|
||||
return start || end || ''
|
||||
}
|
||||
|
||||
function mapOrderToRoomData(order = {}) {
|
||||
const imageUrls = Array.isArray(order.imageUrls)
|
||||
? order.imageUrls
|
||||
: typeof order.imageUrls === 'string'
|
||||
? order.imageUrls.split(',').map(item => item.trim()).filter(Boolean)
|
||||
: []
|
||||
|
||||
const roomLabel = [
|
||||
order.buildingName || order.buildingSectionName || order.unitName || '',
|
||||
order.roomNo || order.roomCode || order.roomName || ''
|
||||
].filter(Boolean).join(' ')
|
||||
|
||||
const title = [
|
||||
order.areaName || order.campusName || '',
|
||||
order.roomTypeName || order.roomType || ''
|
||||
].filter(Boolean).join(' · ')
|
||||
|
||||
return {
|
||||
...order,
|
||||
id: roomLabel || order.roomNo || order.roomCode || order.orderNo || '',
|
||||
roomLabel: roomLabel || order.roomNo || order.roomCode || '',
|
||||
titleZh: title || order.roomTypeName || order.roomName || '当前入住房间',
|
||||
titleEn: order.roomTypeNameEn || title || order.roomTypeName || 'Current Stay',
|
||||
leaseText: buildLeaseText(order),
|
||||
image: order.imageUrl || imageUrls[0] || ''
|
||||
}
|
||||
}
|
||||
|
||||
function pickFirstValue(...values) {
|
||||
for (let index = 0; index < values.length; index += 1) {
|
||||
const value = values[index]
|
||||
if (value === undefined || value === null) {
|
||||
continue
|
||||
}
|
||||
const text = String(value).trim()
|
||||
if (text) {
|
||||
return text
|
||||
}
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
function buildPendingContractQuery() {
|
||||
const user = getCurrentUser() || {}
|
||||
const userCode = pickFirstValue(user.userCode, user.code, user.UserCode)
|
||||
const query = {
|
||||
ProviderType: 'WechatMiniProgram'
|
||||
}
|
||||
|
||||
if (userCode) {
|
||||
query.UserCode = userCode
|
||||
}
|
||||
|
||||
return query
|
||||
}
|
||||
|
||||
function enrichBookingLanguageFields(booking = {}) {
|
||||
if (!booking || typeof booking !== 'object') {
|
||||
return booking
|
||||
}
|
||||
return {
|
||||
...booking,
|
||||
statusTextZh: booking.statusTextZh || '待签合同',
|
||||
statusTextEn: booking.statusTextEn || 'Pending Contract Signature'
|
||||
}
|
||||
}
|
||||
|
||||
function buildContractStepBooking(pendingContracts = []) {
|
||||
const contract = Array.isArray(pendingContracts) ? pendingContracts[0] : null
|
||||
if (!contract || typeof contract !== 'object') {
|
||||
return null
|
||||
}
|
||||
|
||||
return {
|
||||
...contract,
|
||||
orderNo: contract.orderNo || contract.OrderNo || '',
|
||||
roomName: contract.roomName || contract.roomTypeName || contract.houseTypeName || '',
|
||||
roomTypeName: contract.roomTypeName || contract.houseTypeName || contract.roomName || '',
|
||||
startDate: contract.start || contract.startDate || '',
|
||||
endDate: contract.end || contract.endDate || '',
|
||||
status: 'contract_pending_sign',
|
||||
statusKey: 'contract_pending_sign',
|
||||
statusCode: 10,
|
||||
statusText: getSessionSyncText('pendingContract'),
|
||||
statusTextZh: '待签合同',
|
||||
statusTextEn: 'Pending Contract Signature'
|
||||
}
|
||||
}
|
||||
|
||||
function syncStoredUser(hasCheckedIn, currentOrder, currentBooking) {
|
||||
const user = getCurrentUser()
|
||||
|
||||
if (!user || typeof user !== 'object' || !Object.keys(user).length) {
|
||||
return
|
||||
}
|
||||
|
||||
const nextUser = {
|
||||
...user,
|
||||
hasCheckedIn,
|
||||
currentOrder: currentOrder || null,
|
||||
currentBooking: currentBooking || null,
|
||||
bookingStatus: currentBooking ? (currentBooking.status || currentBooking.statusKey || 'none') : 'none',
|
||||
bookingRejectReason: currentBooking ? (currentBooking.rejectReasonText || currentBooking.rejectReason || '') : ''
|
||||
}
|
||||
|
||||
saveCurrentUser(nextUser)
|
||||
saveRegisteredUser(nextUser)
|
||||
|
||||
if (store && store.commit) {
|
||||
store.commit('$tStore', {
|
||||
name: 'vuex_user',
|
||||
value: {
|
||||
...(store.state && store.state.vuex_user ? store.state.vuex_user : {}),
|
||||
...nextUser
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function syncStoreState({
|
||||
hasCheckedIn = false,
|
||||
currentOrder = null,
|
||||
pendingContracts = [],
|
||||
effectiveContracts = [],
|
||||
orderList = []
|
||||
} = {}) {
|
||||
if (!store || !store.commit) {
|
||||
return
|
||||
}
|
||||
|
||||
store.commit('$tStore', {
|
||||
name: 'vuex_checkin_status',
|
||||
value: !!hasCheckedIn
|
||||
})
|
||||
store.commit('$tStore', {
|
||||
name: 'vuex_current_order',
|
||||
value: currentOrder || null
|
||||
})
|
||||
store.commit('$tStore', {
|
||||
name: 'vuex_pending_contracts',
|
||||
value: Array.isArray(pendingContracts) ? pendingContracts : []
|
||||
})
|
||||
store.commit('$tStore', {
|
||||
name: 'vuex_pending_contract_count',
|
||||
value: Array.isArray(pendingContracts) ? pendingContracts.length : 0
|
||||
})
|
||||
store.commit('$tStore', {
|
||||
name: 'vuex_effective_contracts',
|
||||
value: Array.isArray(effectiveContracts) ? effectiveContracts : []
|
||||
})
|
||||
store.commit('$tStore', {
|
||||
name: 'vuex_valid_orders',
|
||||
value: Array.isArray(orderList) ? orderList : []
|
||||
})
|
||||
}
|
||||
|
||||
function requestStayState(language = 'zh') {
|
||||
return orderSearchedMePage({
|
||||
PageIndex: 1,
|
||||
PageSize: 100,
|
||||
IsExport: false
|
||||
}, language)
|
||||
.then((orderResponse) => {
|
||||
return Promise.all([
|
||||
Promise.resolve(orderResponse),
|
||||
getMyPendingSignContracts(buildPendingContractQuery(), language).catch(() => []),
|
||||
getMyEffectiveContracts({}, language).catch(() => [])
|
||||
])
|
||||
})
|
||||
.then(([orderResponse, pendingContractsResponse, effectiveContractsResponse]) => {
|
||||
const orderList = normalizeBookingList(parseOrderListResponse(orderResponse), language)
|
||||
const currentOrder = pickCurrentStayOrder(orderList)
|
||||
const pendingContracts = parseContractList(pendingContractsResponse)
|
||||
const effectiveContracts = parseContractList(effectiveContractsResponse)
|
||||
const currentBooking = enrichBookingLanguageFields(pickCurrentBooking(orderList) || buildContractStepBooking(pendingContracts))
|
||||
|
||||
return {
|
||||
hasCheckedIn: !!currentOrder,
|
||||
currentOrder,
|
||||
currentBooking,
|
||||
orderList,
|
||||
pendingContracts,
|
||||
effectiveContracts
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export function syncLoginStayState(options = {}) {
|
||||
const { language = 'zh', force = false } = options
|
||||
|
||||
if (!getLoginStatus()) {
|
||||
return Promise.resolve({
|
||||
hasCheckedIn: false,
|
||||
currentOrder: null,
|
||||
currentBooking: null,
|
||||
orderList: []
|
||||
})
|
||||
}
|
||||
|
||||
const now = Date.now()
|
||||
|
||||
if (!force && syncStayStatePromise) {
|
||||
return syncStayStatePromise
|
||||
}
|
||||
|
||||
if (!force && lastSyncStayStateAt && now - lastSyncStayStateAt < SYNC_TTL) {
|
||||
return Promise.resolve({
|
||||
skipped: true
|
||||
})
|
||||
}
|
||||
|
||||
const syncSource = store && store.dispatch
|
||||
? store.dispatch('fetchUserGlobalStatus', {
|
||||
force,
|
||||
language
|
||||
})
|
||||
: requestStayState(language)
|
||||
|
||||
syncStayStatePromise = syncSource
|
||||
.then((result = {}) => {
|
||||
const orderList = Array.isArray(result.orderList)
|
||||
? result.orderList
|
||||
: (Array.isArray(result.validOrders) ? result.validOrders : [])
|
||||
const pendingContracts = Array.isArray(result.pendingContracts) ? result.pendingContracts : []
|
||||
const effectiveContracts = Array.isArray(result.effectiveContracts) ? result.effectiveContracts : []
|
||||
const currentOrder = result.currentOrder || pickCurrentStayOrder(orderList)
|
||||
const currentBooking = enrichBookingLanguageFields(result.currentBooking || pickCurrentBooking(orderList) || buildContractStepBooking(pendingContracts))
|
||||
const hasCheckedIn = typeof result.hasCheckedIn === 'boolean'
|
||||
? result.hasCheckedIn
|
||||
: !!currentOrder
|
||||
|
||||
saveBookingList(orderList)
|
||||
if (currentBooking) {
|
||||
saveCurrentBooking(currentBooking)
|
||||
} else {
|
||||
clearBookingState()
|
||||
saveBookingList(orderList)
|
||||
}
|
||||
setCheckedInStatus(hasCheckedIn)
|
||||
savePendingContracts(pendingContracts)
|
||||
savePendingContractCount(pendingContracts.length)
|
||||
saveEffectiveContracts(effectiveContracts)
|
||||
|
||||
if (hasCheckedIn) {
|
||||
saveMyRoomData(mapOrderToRoomData(currentOrder))
|
||||
} else {
|
||||
clearMyRoomData()
|
||||
}
|
||||
|
||||
syncStoreState({
|
||||
hasCheckedIn,
|
||||
currentOrder,
|
||||
pendingContracts,
|
||||
effectiveContracts,
|
||||
orderList
|
||||
})
|
||||
syncStoredUser(hasCheckedIn, currentOrder, currentBooking)
|
||||
lastSyncStayStateAt = Date.now()
|
||||
|
||||
return {
|
||||
hasCheckedIn,
|
||||
currentOrder,
|
||||
currentBooking,
|
||||
orderList,
|
||||
pendingContracts,
|
||||
effectiveContracts
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
syncStayStatePromise = null
|
||||
})
|
||||
|
||||
return syncStayStatePromise
|
||||
}
|
||||
Reference in New Issue
Block a user