Files
QSY-lvjuxcx/utils/reservation-flow.js
liangjian 9fee2c3a74 feat: 优化首页服务入口与租住业务流程
补齐首页待办跳转、押金支付引导和多类租住服务页面能力,统一租客端关键业务流程体验。
2026-08-25 13:53:12 +08:00

258 lines
6.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const RESERVATION_FLOW_STEP = {
APPLICATION: 1,
INSPECTION: 2,
CONTRACT: 3,
BILL: 4,
CHECKIN: 5
}
function getLanguage(language) {
return language === 'en' ? 'en' : 'zh'
}
function parseJsonStringMaybe(value) {
if (typeof value !== 'string') {
return value
}
const text = value.trim()
if (!text) {
return value
}
const isJsonLike = (
(text.startsWith('{') && text.endsWith('}'))
|| (text.startsWith('[') && text.endsWith(']'))
)
if (!isJsonLike) {
return value
}
try {
return JSON.parse(text)
} catch (error) {
return value
}
}
function normalizeArray(value) {
if (Array.isArray(value)) {
return value
}
return []
}
export function parseReservationFlowResponse(response) {
const rawPayload = response && response.data ? response.data : response
const payload = parseJsonStringMaybe(rawPayload)
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 []
}
export function getReservationOrderNo(source = {}) {
const candidates = [
source.orderNo,
source.OrderNo,
source.reservationOrderNo,
source.searchedOrderNo,
source.bookingOrderNo
]
for (let index = 0; index < candidates.length; index += 1) {
const value = String(candidates[index] || '').trim()
if (value) {
return value
}
}
return ''
}
export function getReservationCurrentNode(flow = {}) {
const nodes = normalizeArray(flow && flow.flowNodes)
.filter(item => item && typeof item === 'object')
.sort((a, b) => Number(a.sort || 0) - Number(b.sort || 0))
if (!nodes.length) {
return null
}
const currentNodes = nodes.filter(item => item.isCurrent)
if (currentNodes.length) {
const currentCheckinNode = currentNodes.find(item => (
Number(item.step || 0) === RESERVATION_FLOW_STEP.CHECKIN
&& String(item.refNo || '').trim()
))
if (currentCheckinNode) {
return currentCheckinNode
}
// 后端偶发会把前序节点也标记成 isCurrent,优先取排序最靠后的当前节点
return currentNodes[currentNodes.length - 1]
}
const checkinNode = nodes.find(item => (
Number(item.step || 0) === RESERVATION_FLOW_STEP.CHECKIN
&& String(item.refNo || '').trim()
))
if (checkinNode) {
return checkinNode
}
return nodes[nodes.length - 1]
}
export function getReservationCurrentFlow(flowList = []) {
const flows = normalizeArray(flowList)
.filter(item => item && typeof item === 'object')
.map(item => ({
flow: item,
currentNode: getReservationCurrentNode(item)
}))
.filter(item => item.currentNode)
if (!flows.length) {
return null
}
const compareNode = (target) => {
const node = target.currentNode || {}
const step = Number(node.step || 0)
const sort = Number(node.sort || 0)
const refNo = String(node.refNo || '').trim()
const isCurrent = !!node.isCurrent
const isCheckinWithRefNo = step === RESERVATION_FLOW_STEP.CHECKIN && !!refNo
return [
isCheckinWithRefNo ? 1 : 0,
isCurrent ? 1 : 0,
step,
sort
]
}
return flows
.sort((a, b) => {
const aScore = compareNode(a)
const bScore = compareNode(b)
for (let index = 0; index < aScore.length; index += 1) {
if (aScore[index] !== bScore[index]) {
return bScore[index] - aScore[index]
}
}
return 0
})[0].flow
}
export function hasEffectiveReservationFlow(flow = {}) {
const currentNode = getReservationCurrentNode(flow)
if (!currentNode) {
return false
}
const step = Number(currentNode.step || 0)
const refNo = String(currentNode.refNo || '').trim()
// 当前步骤为申请单(1)且没有 refNo 时,视为尚未提交预约单
if (step === 1 && !refNo) {
return false
}
return step > 0
}
export function buildReservationFlowMap(flowList = []) {
return normalizeArray(flowList)
.filter(item => item && typeof item === 'object')
.reduce((result, item) => {
const orderNo = getReservationOrderNo(item)
if (!orderNo) {
return result
}
result[orderNo] = {
...item,
orderNo,
currentNode: getReservationCurrentNode(item)
}
return result
}, {})
}
export function attachReservationFlow(item = {}, flowMap = {}) {
const orderNo = getReservationOrderNo(item)
const matchedFlow = orderNo ? flowMap[orderNo] : null
return {
...item,
reservationOrderNo: orderNo,
reservationFlow: matchedFlow || null,
reservationCurrentNode: matchedFlow && matchedFlow.currentNode ? matchedFlow.currentNode : null
}
}
export function getReservationStepMeta(step, language = 'zh') {
const currentLanguage = getLanguage(language)
const map = {
[RESERVATION_FLOW_STEP.INSPECTION]: {
label: currentLanguage === 'en' ? 'Inspection' : '验房',
actionText: currentLanguage === 'en' ? 'View Inspection' : '查看验房'
},
[RESERVATION_FLOW_STEP.BILL]: {
label: currentLanguage === 'en' ? 'Bill' : '账单',
actionText: currentLanguage === 'en' ? 'Go to Payment' : '去支付'
},
[RESERVATION_FLOW_STEP.CONTRACT]: {
label: currentLanguage === 'en' ? 'Contract' : '合同',
actionText: currentLanguage === 'en' ? 'Go to Contract' : '去签约'
},
[RESERVATION_FLOW_STEP.CHECKIN]: {
label: currentLanguage === 'en' ? 'Check-in' : '入住',
actionText: currentLanguage === 'en' ? 'Go to Check-in' : '去入住'
}
}
return map[Number(step)] || {
label: currentLanguage === 'en' ? 'Current Step' : '当前步骤',
actionText: currentLanguage === 'en' ? 'View Current Step' : '查看当前步骤'
}
}
export function getReservationCurrentStepText(source = {}, language = 'zh') {
const node = source && source.reservationCurrentNode
? source.reservationCurrentNode
: getReservationCurrentNode(source)
if (!node) {
return ''
}
return String(node.stepDesc || '').trim() || getReservationStepMeta(node.step, language).label
}
export function getReservationCurrentActionText(source = {}, language = 'zh') {
const node = source && source.reservationCurrentNode
? source.reservationCurrentNode
: getReservationCurrentNode(source)
if (!node) {
return ''
}
return getReservationStepMeta(node.step, language).actionText
}
export { RESERVATION_FLOW_STEP }