365 lines
10 KiB
JavaScript
365 lines
10 KiB
JavaScript
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(order = {}) {
|
|
const safeOrder = order || {}
|
|
const orderNo = pickFirstValue(safeOrder.orderNo, safeOrder.no, safeOrder.code, safeOrder.OrderNo)
|
|
if (!orderNo) {
|
|
return null
|
|
}
|
|
return {
|
|
ProviderType: 'WechatMiniProgram',
|
|
OrderNo: orderNo
|
|
}
|
|
}
|
|
|
|
function buildEffectiveContractQuery(order = {}) {
|
|
const safeOrder = order || {}
|
|
const orderNo = pickFirstValue(safeOrder.orderNo, safeOrder.no, safeOrder.code, safeOrder.OrderNo)
|
|
if (!orderNo) {
|
|
return null
|
|
}
|
|
return {
|
|
ProviderType: 'WechatMiniProgram',
|
|
OrderNo: orderNo
|
|
}
|
|
}
|
|
|
|
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) => {
|
|
const orderList = normalizeBookingList(parseOrderListResponse(orderResponse), language)
|
|
const currentOrder = pickCurrentStayOrder(orderList)
|
|
const pendingContractQuery = buildPendingContractQuery(currentOrder)
|
|
const effectiveContractQuery = buildEffectiveContractQuery(currentOrder)
|
|
|
|
return Promise.all([
|
|
Promise.resolve(orderList),
|
|
Promise.resolve(currentOrder),
|
|
pendingContractQuery
|
|
? getMyPendingSignContracts(pendingContractQuery, language).catch(() => [])
|
|
: Promise.resolve([]),
|
|
effectiveContractQuery
|
|
? getMyEffectiveContracts(effectiveContractQuery, language).catch(() => [])
|
|
: Promise.resolve([])
|
|
])
|
|
})
|
|
.then(([orderList, currentOrder, pendingContractsResponse, effectiveContractsResponse]) => {
|
|
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
|
|
}
|