feat: 优化首页服务入口与租住业务流程
补齐首页待办跳转、押金支付引导和多类租住服务页面能力,统一租客端关键业务流程体验。
This commit is contained in:
@@ -130,6 +130,15 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view
|
||||
v-if="shouldShowApplicationPaymentStatus(item)"
|
||||
class="payment-status-banner tn-margin-top-lg"
|
||||
:class="`payment-status-banner--${getApplicationPaymentStatusType(item)}`"
|
||||
>
|
||||
<text class="payment-status-banner__label">{{ $tr('支付状态') }}</text>
|
||||
<text class="payment-status-banner__value">{{ getApplicationPaymentStatusText(item) }}</text>
|
||||
</view>
|
||||
|
||||
<view class="card-body tn-margin-top-lg">
|
||||
<view class="info-row tn-flex tn-flex-row-between">
|
||||
<text class="info-label">{{ $tr('所属公寓') }}</text>
|
||||
@@ -223,7 +232,7 @@
|
||||
:data-reference-type-no="resolveReferenceTypeNo(item)"
|
||||
@click.stop="payDepositAction"
|
||||
>
|
||||
<text class="tn-text-bold">{{ $tr('支付定金') }}</text>
|
||||
<text class="tn-text-bold">{{ $tr('去支付') }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -296,12 +305,29 @@
|
||||
</view>
|
||||
</view>
|
||||
</tn-popup>
|
||||
|
||||
<tn-action-sheet
|
||||
v-model="showPaymentMethodSheet"
|
||||
:list="getPaymentMethodSheetOptions()"
|
||||
:tips="{ text: getPaymentMethodSheetTipText() }"
|
||||
:borderRadius="32"
|
||||
:safeAreaInsetBottom="true"
|
||||
@click="handlePaymentMethodSheetClick"
|
||||
></tn-action-sheet>
|
||||
|
||||
<deposit-other-payment-popup
|
||||
v-model="showOfflinePaymentNotice"
|
||||
:config="depositOtherPaymentConfig"
|
||||
:loading="depositOtherPaymentConfigLoading"
|
||||
/>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { applicationFormDetail, applicationFormMePage, accountQueryBill, accountQueryBillPreview, accountQueryBills, contractDetail, orderSearchedMePage, orderSearchedReservationFlow, paymentBillPay, paymentPayingBills, roomInspectionDetail, userDetailCancel } from '@/api/index.js'
|
||||
import DepositOtherPaymentPopup from '@/components/DepositOtherPaymentPopup.vue'
|
||||
import { applicationFormDetail, applicationFormMePage, accountQueryBill, accountQueryBillPreview, accountQueryBills, contractDetail, orderSearchedDetail, orderSearchedMePage, orderSearchedReservationFlow, paymentBillPay, paymentPayingBills, roomInspectionDetail, userDetailCancel } from '@/api/index.js'
|
||||
import { getMyApplicationList, saveActiveApplicationCode, saveMyApplicationList } from '@/utils/app-state'
|
||||
import { createDefaultDepositOtherPaymentConfig, loadDepositOtherPaymentConfig } from '@/utils/deposit-other-payment'
|
||||
import {
|
||||
RESERVATION_FLOW_STEP,
|
||||
attachReservationFlow,
|
||||
@@ -312,7 +338,7 @@ import {
|
||||
getReservationOrderNo,
|
||||
parseReservationFlowResponse
|
||||
} from '@/utils/reservation-flow'
|
||||
import { getOrderStatusCode, normalizeBookingList, parseOrderListResponse } from '@/utils/booking-helper'
|
||||
import { getOrderStatusCode, normalizeBookingDetail, normalizeBookingList, parseOrderDetailResponse, parseOrderListResponse } from '@/utils/booking-helper'
|
||||
import { localizePayMethodText } from '@/utils/select-room-normalizers'
|
||||
|
||||
function formatPageResponse(response) {
|
||||
@@ -410,7 +436,47 @@ function padCountdownUnit(value) {
|
||||
return String(Math.max(0, Number(value) || 0)).padStart(2, '0')
|
||||
}
|
||||
|
||||
function resolveApplicationPaymentStatusInfo(item = {}) {
|
||||
if (!item || item.isViewingApplication) {
|
||||
return {
|
||||
key: 'exempt',
|
||||
desc: ''
|
||||
}
|
||||
}
|
||||
|
||||
const desc = String(item.payStatusDesc || item.paymentStatusDesc || '').trim()
|
||||
const status = Number(
|
||||
item.payStatus !== undefined && item.payStatus !== null
|
||||
? item.payStatus
|
||||
: item.paymentStatus
|
||||
)
|
||||
|
||||
if (status === 10 || /已支付|paid/i.test(desc)) {
|
||||
return { key: 'paid', desc }
|
||||
}
|
||||
if (/退款|refunded?/i.test(desc)) {
|
||||
return { key: 'refunded', desc }
|
||||
}
|
||||
if (/失败|failed?/i.test(desc)) {
|
||||
return { key: 'failed', desc }
|
||||
}
|
||||
if (/处理中|processing/i.test(desc)) {
|
||||
return { key: 'processing', desc }
|
||||
}
|
||||
if (status === 0 || /待支付|未支付|unpaid|pending/i.test(desc)) {
|
||||
return { key: 'pending', desc }
|
||||
}
|
||||
|
||||
return {
|
||||
key: desc ? 'processing' : 'pending',
|
||||
desc
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
components: {
|
||||
DepositOtherPaymentPopup
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
currentIndex: 0,
|
||||
@@ -423,12 +489,17 @@ export default {
|
||||
loadingMore: false,
|
||||
hasMore: true,
|
||||
showDepositNotice: false,
|
||||
showPaymentMethodSheet: false,
|
||||
showOfflinePaymentNotice: false,
|
||||
pendingDepositReferenceTypeNo: '',
|
||||
pendingPaymentMethodContext: null,
|
||||
pendingDepositPaymentContext: null,
|
||||
paymentNoticeSourceItem: null,
|
||||
paymentNoticeSourceLoading: false,
|
||||
paymentNoticeBillLoading: false,
|
||||
paymentNoticeBillDetail: null,
|
||||
depositOtherPaymentConfig: createDefaultDepositOtherPaymentConfig(),
|
||||
depositOtherPaymentConfigLoading: false,
|
||||
reservationBillDetailMap: {},
|
||||
reservationContractDetailMap: {},
|
||||
reservationInspectionDetailMap: {},
|
||||
@@ -441,6 +512,7 @@ export default {
|
||||
watch: {
|
||||
language() {
|
||||
this.reloadList(true)
|
||||
this.loadDepositOtherPaymentConfig()
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@@ -464,6 +536,7 @@ export default {
|
||||
},
|
||||
onShow() {
|
||||
this.load()
|
||||
this.loadDepositOtherPaymentConfig()
|
||||
},
|
||||
mounted() {
|
||||
this.startCountdownTimer()
|
||||
@@ -522,15 +595,65 @@ export default {
|
||||
isPaidApplication(item = {}) {
|
||||
return !item.isViewingApplication && Number(item.payStatus) === 10
|
||||
},
|
||||
shouldShowApplicationPaymentStatus(item = {}) {
|
||||
return !item.isViewingApplication
|
||||
},
|
||||
getApplicationPaymentStatusText(item = {}) {
|
||||
if (this.isWaitingButlerRoomAssignment(item)) {
|
||||
return this.$tr('等待管家排房')
|
||||
}
|
||||
const statusInfo = resolveApplicationPaymentStatusInfo(item)
|
||||
if (this.$getLanguage() !== 'en' && statusInfo.desc) {
|
||||
return statusInfo.desc
|
||||
}
|
||||
const textMap = {
|
||||
exempt: this.$tr('无需支付'),
|
||||
paid: this.$tr('已支付'),
|
||||
refunded: this.$tr('已退款'),
|
||||
failed: this.$tr('支付失败'),
|
||||
processing: this.$tr('处理中'),
|
||||
pending: this.$tr('待支付')
|
||||
}
|
||||
return textMap[statusInfo.key] || statusInfo.desc || this.$tr('待支付')
|
||||
},
|
||||
getApplicationPaymentStatusType(item = {}) {
|
||||
if (this.isWaitingButlerRoomAssignment(item)) {
|
||||
return 'info'
|
||||
}
|
||||
const statusInfo = resolveApplicationPaymentStatusInfo(item)
|
||||
const typeMap = {
|
||||
exempt: 'neutral',
|
||||
paid: 'success',
|
||||
refunded: 'neutral',
|
||||
failed: 'danger',
|
||||
processing: 'info',
|
||||
pending: 'warning'
|
||||
}
|
||||
return typeMap[statusInfo.key] || 'warning'
|
||||
},
|
||||
shouldPayDeposit(item = {}) {
|
||||
return !item.isViewingApplication
|
||||
&& Number(item.status) === 0
|
||||
&& Number(item.payStatus) !== 10
|
||||
},
|
||||
shouldQueryPendingDepositBill(item = {}) {
|
||||
return this.shouldPayDeposit(item) && !!this.resolveReferenceTypeNo(item)
|
||||
},
|
||||
hasResolvedPendingDepositBill(item = {}) {
|
||||
return !!(item && item.pendingDepositBillQueried)
|
||||
},
|
||||
hasPendingDepositBill(item = {}) {
|
||||
return !!String(this.getBillNo(item && item.pendingDepositBill ? item.pendingDepositBill : {}) || '').trim()
|
||||
},
|
||||
isWaitingButlerRoomAssignment(item = {}) {
|
||||
return this.shouldQueryPendingDepositBill(item)
|
||||
&& this.hasResolvedPendingDepositBill(item)
|
||||
&& !this.hasPendingDepositBill(item)
|
||||
},
|
||||
isWaitingRoomAssignment(item = {}) {
|
||||
return !item.isViewingApplication
|
||||
&& Number(item.status) === 0
|
||||
&& Number(item.payStatus) === 10
|
||||
&& (Number(item.payStatus) === 10 || this.isWaitingButlerRoomAssignment(item))
|
||||
},
|
||||
getStatusReminderText(item = {}) {
|
||||
if (this.isReservationContractAwaitingReview(item)) {
|
||||
@@ -544,11 +667,14 @@ export default {
|
||||
if (reservationStepText) {
|
||||
return reservationStepText
|
||||
}
|
||||
if (this.isWaitingButlerRoomAssignment(item)) {
|
||||
return this.$tr('等待管家排房')
|
||||
}
|
||||
if (this.shouldPayDeposit(item)) {
|
||||
return this.$tr('请支付定金')
|
||||
}
|
||||
if (this.isWaitingRoomAssignment(item)) {
|
||||
return this.$tr('等待预订中心分配房间')
|
||||
return this.$tr('等待管家排房')
|
||||
}
|
||||
return ''
|
||||
},
|
||||
@@ -901,7 +1027,7 @@ export default {
|
||||
return this.formatPendingPaymentCountdown(this.getPendingPaymentRemainingSeconds(order))
|
||||
},
|
||||
getPendingPaymentActionText(item = {}) {
|
||||
return this.isApplicationPendingPaymentExpired(item) ? this.$tr('支付定金') : this.$tr('继续支付')
|
||||
return this.$tr('去支付')
|
||||
},
|
||||
getReservationOrderNoFromItem(item = {}) {
|
||||
return getReservationOrderNo(item)
|
||||
@@ -1270,7 +1396,7 @@ export default {
|
||||
this._pendingPaymentRequestToken = requestToken
|
||||
|
||||
await Promise.all(baseList.map(async (item, index) => {
|
||||
if (!this.canViewBill(item)) {
|
||||
if (!this.shouldQueryPendingDepositBill(item)) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1289,17 +1415,6 @@ export default {
|
||||
})
|
||||
const billList = this.normalizeBillList(billRes)
|
||||
const bill = Array.isArray(billList) && billList.length ? billList[0] : null
|
||||
if (!bill || this._pendingPaymentRequestToken !== requestToken) {
|
||||
return
|
||||
}
|
||||
|
||||
const billNo = this.getBillNo(bill)
|
||||
if (!billNo) {
|
||||
return
|
||||
}
|
||||
|
||||
console.log('[MyApplicationTab] query payment/paying-bills', billNo)
|
||||
const pendingPaymentOrder = await this.getPendingPaymentOrder(billNo).catch(() => null)
|
||||
if (this._pendingPaymentRequestToken !== requestToken) {
|
||||
return
|
||||
}
|
||||
@@ -1309,10 +1424,38 @@ export default {
|
||||
return
|
||||
}
|
||||
|
||||
if (!bill) {
|
||||
this.$set(this.list, index, {
|
||||
...currentItem,
|
||||
pendingDepositBill: null,
|
||||
pendingPaymentOrder: null,
|
||||
pendingDepositBillQueried: true
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
const billNo = this.getBillNo(bill)
|
||||
if (!billNo) {
|
||||
this.$set(this.list, index, {
|
||||
...currentItem,
|
||||
pendingDepositBill: null,
|
||||
pendingPaymentOrder: null,
|
||||
pendingDepositBillQueried: true
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
console.log('[MyApplicationTab] query payment/paying-bills', billNo)
|
||||
const pendingPaymentOrder = await this.getPendingPaymentOrder(billNo).catch(() => null)
|
||||
if (this._pendingPaymentRequestToken !== requestToken) {
|
||||
return
|
||||
}
|
||||
|
||||
const updatedItem = {
|
||||
...currentItem,
|
||||
pendingDepositBill: bill,
|
||||
pendingPaymentOrder
|
||||
pendingPaymentOrder,
|
||||
pendingDepositBillQueried: true
|
||||
}
|
||||
this.$set(this.list, index, updatedItem)
|
||||
} catch (error) {
|
||||
@@ -1404,7 +1547,8 @@ export default {
|
||||
.map(item => ({
|
||||
...item,
|
||||
pendingDepositBill: item && item.pendingDepositBill ? item.pendingDepositBill : null,
|
||||
pendingPaymentOrder: item && item.pendingPaymentOrder ? item.pendingPaymentOrder : null
|
||||
pendingPaymentOrder: item && item.pendingPaymentOrder ? item.pendingPaymentOrder : null,
|
||||
pendingDepositBillQueried: !!(item && item.pendingDepositBillQueried)
|
||||
}))
|
||||
|
||||
this.total = total
|
||||
@@ -1457,14 +1601,28 @@ export default {
|
||||
return item.detailCode || ''
|
||||
},
|
||||
canViewBill(item = {}) {
|
||||
return !item.isViewingApplication
|
||||
&& (this.shouldPayDeposit(item) || this.isReservationBillStep(item))
|
||||
&& this.resolveReferenceTypeNo(item)
|
||||
if (item.isViewingApplication || !this.resolveReferenceTypeNo(item)) {
|
||||
return false
|
||||
}
|
||||
if (this.isReservationBillStep(item)) {
|
||||
return true
|
||||
}
|
||||
if (!this.shouldQueryPendingDepositBill(item)) {
|
||||
return false
|
||||
}
|
||||
return this.hasPendingDepositBill(item)
|
||||
},
|
||||
canCancelApplication(item = {}) {
|
||||
return !!(this.resolveReferenceTypeNo(item)
|
||||
&& Number(item.status) === 0
|
||||
&& (item.isViewingApplication || Number(item.payStatus) !== 10))
|
||||
if (!this.resolveReferenceTypeNo(item) || Number(item.status) !== 0) {
|
||||
return false
|
||||
}
|
||||
if (item.isViewingApplication) {
|
||||
return true
|
||||
}
|
||||
if (Number(item.payStatus) === 10) {
|
||||
return false
|
||||
}
|
||||
return this.hasPendingDepositBill(item)
|
||||
},
|
||||
canCancelOrder(item = {}) {
|
||||
return this.canCancelApplication(item)
|
||||
@@ -1504,7 +1662,8 @@ export default {
|
||||
status: 99,
|
||||
statusDesc: this.$tr('已结束'),
|
||||
pendingDepositBill: null,
|
||||
pendingPaymentOrder: null
|
||||
pendingPaymentOrder: null,
|
||||
pendingDepositBillQueried: false
|
||||
}
|
||||
}
|
||||
this.list = normalizeApplicationList(this.list.map(updateItem))
|
||||
@@ -1566,7 +1725,15 @@ export default {
|
||||
})
|
||||
return
|
||||
}
|
||||
this.payDepositByReferenceTypeNo(referenceTypeNo)
|
||||
const currentItem = (Array.isArray(this.list) ? this.list : []).find((item) => {
|
||||
return String(this.resolveReferenceTypeNo(item)) === referenceTypeNo
|
||||
}) || {}
|
||||
this.openPaymentMethodSelector({
|
||||
referenceTypeNo,
|
||||
description: this.$tr('支付定金'),
|
||||
mode: 'deposit',
|
||||
sourceItem: currentItem
|
||||
})
|
||||
},
|
||||
resolvePreferredReferenceTypeNo(list = []) {
|
||||
const sortedList = [...list]
|
||||
@@ -1595,13 +1762,65 @@ export default {
|
||||
const currentItem = (Array.isArray(this.list) ? this.list : []).find((item) => {
|
||||
return String(this.resolveReferenceTypeNo(item)) === referenceTypeNo
|
||||
}) || {}
|
||||
this.openDepositNoticeForPayment({
|
||||
this.openPaymentMethodSelector({
|
||||
referenceTypeNo,
|
||||
description: this.$tr('支付定金'),
|
||||
mode: 'deposit',
|
||||
sourceItem: currentItem
|
||||
})
|
||||
},
|
||||
getPaymentMethodSheetOptions() {
|
||||
return [
|
||||
{
|
||||
text: this.language === 'en' ? 'WeChat Pay' : '微信支付',
|
||||
subText: this.language === 'en'
|
||||
? 'The system will continue by opening WeChat for payment.'
|
||||
: '系统将继续拉起微信完成支付'
|
||||
},
|
||||
{
|
||||
text: this.language === 'en' ? 'Other Payment Methods' : '其他支付方式',
|
||||
subText: this.language === 'en'
|
||||
? 'View the corporate bank account details when WeChat Pay is unavailable.'
|
||||
: '无法使用微信支付时查看对公账户信息'
|
||||
}
|
||||
]
|
||||
},
|
||||
getPaymentMethodSheetTipText() {
|
||||
return this.language === 'en' ? 'Please select a payment method' : '请选择支付方式'
|
||||
},
|
||||
openPaymentMethodSelector(context = {}) {
|
||||
this.pendingPaymentMethodContext = context || null
|
||||
this.showPaymentMethodSheet = true
|
||||
},
|
||||
handlePaymentMethodSheetClick(index) {
|
||||
const context = this.pendingPaymentMethodContext || {}
|
||||
this.pendingPaymentMethodContext = null
|
||||
if (Number(index) === 0) {
|
||||
this.openDepositNoticeForPayment(context)
|
||||
return
|
||||
}
|
||||
if (Number(index) === 1) {
|
||||
this.showOfflinePaymentNotice = true
|
||||
this.loadDepositOtherPaymentConfig()
|
||||
}
|
||||
},
|
||||
closeOfflinePaymentNotice() {
|
||||
this.showOfflinePaymentNotice = false
|
||||
},
|
||||
loadDepositOtherPaymentConfig() {
|
||||
this.depositOtherPaymentConfigLoading = true
|
||||
return loadDepositOtherPaymentConfig(this.language)
|
||||
.then((config) => {
|
||||
this.depositOtherPaymentConfig = config || createDefaultDepositOtherPaymentConfig()
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('load deposit other payment config failed', error)
|
||||
this.depositOtherPaymentConfig = createDefaultDepositOtherPaymentConfig()
|
||||
})
|
||||
.finally(() => {
|
||||
this.depositOtherPaymentConfigLoading = false
|
||||
})
|
||||
},
|
||||
getPaymentContextMode(context = {}) {
|
||||
const explicitMode = String(context.mode || '').trim()
|
||||
if (explicitMode) {
|
||||
@@ -1802,19 +2021,18 @@ export default {
|
||||
|| ''
|
||||
).trim()
|
||||
},
|
||||
loadPaymentNoticeSourceDetail(referenceTypeNo = '', fallbackSource = null) {
|
||||
const fallbackReferenceTypeNo = fallbackSource ? this.getApplicationDetailCodeFromOrder(fallbackSource) : ''
|
||||
const normalizedReferenceTypeNo = String(referenceTypeNo || fallbackReferenceTypeNo || '').trim()
|
||||
if (!normalizedReferenceTypeNo) {
|
||||
loadPaymentNoticeSourceDetail(orderNo = '', fallbackSource = null) {
|
||||
const normalizedOrderNo = String(orderNo || this.resolvePaymentNoticeOrderNo({}, fallbackSource) || '').trim()
|
||||
if (!normalizedOrderNo) {
|
||||
this.paymentNoticeSourceLoading = false
|
||||
this.paymentNoticeSourceItem = fallbackSource || this.paymentNoticeSourceItem || null
|
||||
return Promise.resolve(this.paymentNoticeSourceItem)
|
||||
}
|
||||
|
||||
this.paymentNoticeSourceLoading = true
|
||||
return this.resolveApplicationDetailPaymentContext(normalizedReferenceTypeNo)
|
||||
.then((context) => {
|
||||
const detail = context && context.detail ? context.detail : null
|
||||
return orderSearchedDetail(normalizedOrderNo, this.language)
|
||||
.then((response) => {
|
||||
const detail = normalizeBookingDetail(parseOrderDetailResponse(response), this.language)
|
||||
this.paymentNoticeSourceItem = detail
|
||||
? {
|
||||
...(fallbackSource || {}),
|
||||
@@ -1903,16 +2121,17 @@ export default {
|
||||
).trim()
|
||||
this.pendingDepositPaymentContext.referenceTypeNo = nextReferenceTypeNo
|
||||
this.pendingDepositReferenceTypeNo = nextReferenceTypeNo
|
||||
return this.loadPaymentNoticeSourceDetail(nextReferenceTypeNo, mergedSource)
|
||||
return this.loadPaymentNoticeSourceDetail(paymentOrderNo, mergedSource)
|
||||
})
|
||||
.catch(() => {
|
||||
this.loadPaymentNoticeSourceDetail(this.pendingDepositPaymentContext.referenceTypeNo, this.paymentNoticeSourceItem)
|
||||
this.loadPaymentNoticeSourceDetail(paymentOrderNo, this.paymentNoticeSourceItem)
|
||||
})
|
||||
this.showDepositNotice = true
|
||||
},
|
||||
closeDepositNotice() {
|
||||
this.showDepositNotice = false
|
||||
this.pendingDepositReferenceTypeNo = ''
|
||||
this.pendingPaymentMethodContext = null
|
||||
this.pendingDepositPaymentContext = null
|
||||
this.paymentNoticeSourceItem = null
|
||||
this.paymentNoticeSourceLoading = false
|
||||
@@ -2225,7 +2444,7 @@ export default {
|
||||
const paymentContext = this.resolveReservationBillPaymentContext(currentItem || {}, {
|
||||
referenceTypeNo
|
||||
})
|
||||
this.openDepositNoticeForPayment(paymentContext)
|
||||
this.openPaymentMethodSelector(paymentContext)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -2686,6 +2905,72 @@ export default {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.payment-status-banner {
|
||||
padding: 20rpx 24rpx;
|
||||
border-radius: 20rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 16rpx;
|
||||
border: 1rpx solid transparent;
|
||||
}
|
||||
|
||||
.payment-status-banner__label {
|
||||
font-size: 24rpx;
|
||||
color: #64748B;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.payment-status-banner__value {
|
||||
font-size: 28rpx;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.payment-status-banner--warning {
|
||||
background: linear-gradient(180deg, rgba(255, 247, 237, 0.96) 0%, rgba(255, 251, 245, 0.98) 100%);
|
||||
border-color: rgba(249, 115, 22, 0.16);
|
||||
}
|
||||
|
||||
.payment-status-banner--warning .payment-status-banner__value {
|
||||
color: #C2410C;
|
||||
}
|
||||
|
||||
.payment-status-banner--success {
|
||||
background: linear-gradient(180deg, rgba(236, 253, 245, 0.96) 0%, rgba(240, 253, 250, 0.98) 100%);
|
||||
border-color: rgba(16, 185, 129, 0.16);
|
||||
}
|
||||
|
||||
.payment-status-banner--success .payment-status-banner__value {
|
||||
color: #047857;
|
||||
}
|
||||
|
||||
.payment-status-banner--info {
|
||||
background: linear-gradient(180deg, rgba(239, 246, 255, 0.96) 0%, rgba(248, 250, 252, 0.98) 100%);
|
||||
border-color: rgba(59, 130, 246, 0.14);
|
||||
}
|
||||
|
||||
.payment-status-banner--info .payment-status-banner__value {
|
||||
color: #1D4ED8;
|
||||
}
|
||||
|
||||
.payment-status-banner--danger {
|
||||
background: linear-gradient(180deg, rgba(254, 242, 242, 0.96) 0%, rgba(255, 245, 245, 0.98) 100%);
|
||||
border-color: rgba(239, 68, 68, 0.16);
|
||||
}
|
||||
|
||||
.payment-status-banner--danger .payment-status-banner__value {
|
||||
color: #B91C1C;
|
||||
}
|
||||
|
||||
.payment-status-banner--neutral {
|
||||
background: linear-gradient(180deg, rgba(241, 245, 249, 0.96) 0%, rgba(248, 250, 252, 0.98) 100%);
|
||||
border-color: rgba(148, 163, 184, 0.16);
|
||||
}
|
||||
|
||||
.payment-status-banner--neutral .payment-status-banner__value {
|
||||
color: #475569;
|
||||
}
|
||||
|
||||
.status-pending {
|
||||
color: #b45309;
|
||||
background: rgba(245, 158, 11, 0.12);
|
||||
@@ -3082,4 +3367,118 @@ export default {
|
||||
transform: scale(0.98);
|
||||
}
|
||||
|
||||
.offline-payment-sheet {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 24rpx;
|
||||
}
|
||||
|
||||
.offline-payment-intro {
|
||||
padding: 24rpx 28rpx;
|
||||
border-radius: 28rpx;
|
||||
background: linear-gradient(180deg, rgba($brand-primary, 0.08) 0%, rgba(31, 111, 229, 0.04) 100%);
|
||||
border: 1rpx solid rgba($brand-primary, 0.08);
|
||||
}
|
||||
|
||||
.offline-payment-intro__zh {
|
||||
font-size: 28rpx;
|
||||
line-height: 1.6;
|
||||
color: #22324D;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.offline-payment-intro__en {
|
||||
margin-top: 12rpx;
|
||||
font-size: 22rpx;
|
||||
line-height: 1.7;
|
||||
color: #5B6B86;
|
||||
}
|
||||
|
||||
.offline-payment-card {
|
||||
padding: 24rpx 28rpx;
|
||||
border-radius: 28rpx;
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
border: 1rpx solid rgba($brand-primary, 0.08);
|
||||
box-shadow: 0 16rpx 36rpx rgba($brand-primary, 0.08);
|
||||
}
|
||||
|
||||
.offline-payment-row {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12rpx;
|
||||
padding: 22rpx 0;
|
||||
}
|
||||
|
||||
.offline-payment-row + .offline-payment-row {
|
||||
border-top: 1rpx solid rgba($brand-primary, 0.08);
|
||||
}
|
||||
|
||||
.offline-payment-label-group,
|
||||
.offline-payment-value-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8rpx;
|
||||
}
|
||||
|
||||
.offline-payment-label {
|
||||
font-size: 24rpx;
|
||||
line-height: 1.5;
|
||||
color: #6B7A92;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.offline-payment-label-en {
|
||||
font-size: 20rpx;
|
||||
line-height: 1.6;
|
||||
color: #8B97AA;
|
||||
}
|
||||
|
||||
.offline-payment-value {
|
||||
font-size: 28rpx;
|
||||
line-height: 1.6;
|
||||
color: #22324D;
|
||||
font-weight: 600;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.offline-payment-value-en {
|
||||
font-size: 22rpx;
|
||||
line-height: 1.7;
|
||||
color: #4F5F79;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.offline-payment-note-title {
|
||||
font-size: 28rpx;
|
||||
line-height: 1.4;
|
||||
color: #22324D;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.offline-payment-note-title-en {
|
||||
margin-top: 8rpx;
|
||||
font-size: 22rpx;
|
||||
line-height: 1.6;
|
||||
color: #6B7A92;
|
||||
}
|
||||
|
||||
.offline-payment-note {
|
||||
margin-top: 22rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8rpx;
|
||||
}
|
||||
|
||||
.offline-payment-note__zh {
|
||||
font-size: 25rpx;
|
||||
line-height: 1.7;
|
||||
color: #22324D;
|
||||
}
|
||||
|
||||
.offline-payment-note__en {
|
||||
font-size: 21rpx;
|
||||
line-height: 1.7;
|
||||
color: #5B6B86;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<template>
|
||||
<template>
|
||||
<view class="profile-page tn-safe-area-inset-bottom">
|
||||
|
||||
<!-- 头部背景与用户信息 (悬浮质感设计) -->
|
||||
@@ -308,7 +308,7 @@ export default {
|
||||
return '-'
|
||||
}
|
||||
const currentOrder = this.getCurrentOrder() || {}
|
||||
const startText = currentOrder.startDate || currentOrder.start || currentOrder.checkinDate || ''
|
||||
const startText = currentOrder.contractStartTime || currentOrder.startDate || currentOrder.start || currentOrder.checkinDate || ''
|
||||
if (!startText) {
|
||||
return '--'
|
||||
}
|
||||
@@ -509,6 +509,12 @@ export default {
|
||||
this.goToRegistrationRecords()
|
||||
return
|
||||
}
|
||||
if (item.key === 'lock') {
|
||||
uni.navigateTo({
|
||||
url: '/pkgService/lock_control/lock_control'
|
||||
})
|
||||
return
|
||||
}
|
||||
if (item.key === 'butler') {
|
||||
this.goToSubmitRequest(itemTitle, itemDesc, {
|
||||
businessType: 'butler-contact',
|
||||
|
||||
@@ -252,6 +252,10 @@ export default {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
isActive: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
language: {
|
||||
type: String,
|
||||
default: 'zh'
|
||||
@@ -348,7 +352,14 @@ export default {
|
||||
})
|
||||
},
|
||||
handleBannerChange(e) {
|
||||
this.$emit('banner-change', e.detail.current)
|
||||
if (!this.isActive) {
|
||||
return
|
||||
}
|
||||
const nextIndex = Number(e && e.detail && e.detail.current)
|
||||
if (!Number.isFinite(nextIndex)) {
|
||||
return
|
||||
}
|
||||
this.$emit('banner-change', nextIndex)
|
||||
},
|
||||
openStoreDetail(area) {
|
||||
uni.navigateTo({
|
||||
|
||||
@@ -91,6 +91,10 @@ export default {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
isActive: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
language: {
|
||||
type: String,
|
||||
default: 'zh'
|
||||
@@ -144,9 +148,19 @@ export default {
|
||||
.trim()
|
||||
},
|
||||
handleBannerChange(e) {
|
||||
this.$emit('banner-change', e.detail.current)
|
||||
if (!this.isActive) {
|
||||
return
|
||||
}
|
||||
const nextIndex = Number(e && e.detail && e.detail.current)
|
||||
if (!Number.isFinite(nextIndex)) {
|
||||
return
|
||||
}
|
||||
this.$emit('banner-change', nextIndex)
|
||||
},
|
||||
switchBanner(index) {
|
||||
if (!this.isActive) {
|
||||
return
|
||||
}
|
||||
this.$emit('banner-switch', index)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
>
|
||||
<swiper-item>
|
||||
<SelectRoomHero
|
||||
:is-active="currentScreen === 0"
|
||||
:language="currentLang"
|
||||
:banner-list="bannerList"
|
||||
:current-banner="currentBanner"
|
||||
@@ -48,6 +49,7 @@
|
||||
:show-scrollbar="false"
|
||||
>
|
||||
<SelectRoomAreaPanel
|
||||
:is-active="currentScreen === 1"
|
||||
:language="currentLang"
|
||||
:banner-list="bannerList"
|
||||
:current-banner-index="currentBannerIndex"
|
||||
@@ -431,10 +433,18 @@ export default {
|
||||
})
|
||||
},
|
||||
handleBannerChange(index) {
|
||||
this.currentBannerIndex = index
|
||||
const nextIndex = Number(index)
|
||||
if (!Number.isFinite(nextIndex) || nextIndex === this.currentBannerIndex) {
|
||||
return
|
||||
}
|
||||
this.currentBannerIndex = nextIndex
|
||||
},
|
||||
switchBanner(index) {
|
||||
this.currentBannerIndex = index
|
||||
const nextIndex = Number(index)
|
||||
if (!Number.isFinite(nextIndex) || nextIndex === this.currentBannerIndex) {
|
||||
return
|
||||
}
|
||||
this.currentBannerIndex = nextIndex
|
||||
},
|
||||
collapseToTopBanner() {
|
||||
this.currentScreen = 1
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user