alipay-emulator/pages/ant-credit-pay/overdue-payment/overdue-payment.vue

900 lines
21 KiB
Vue
Raw Permalink 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.

<template>
<view class="page-container">
<view class="main-container">
<!-- 头部背景 (带弧度) -->
<view class="header-bg"></view>
<!-- 导航栏 - 降低层级以显示水印 -->
<NavBar title="花呗 | 信用购" :bgColor="data.navBar.bgColor" :textColor="data.navBar.textColor" :isFixed="true"
:zIndex="10" tipLayerType="huabei-tip" isTipLayer tipLayerText="修改花呗信息" :buttonGroup="buttonGroup"
@button-click="clickTitlePopupButton">
<!-- 使用作用域插槽自定义按钮渲染特别是switch的checked绑定 -->
<template #button="{ button }">
<view class="button flex-align-center flex-justify-center">
{{ button.name }}
<view @tap.stop>
<switch v-if="button.isSwitch" :checked="data.huabeiInfo[button.key]" @change="button.click"
style="transform: scale(0.7);"></switch>
</view>
</view>
</template>
<view class="nav-bar flex-between w100" :class="{ 'ios-nav-bar': $system == 'iOS' }">
<view class="flex-align-center flex-1">
<view class="left flex-align-center" @click.stop="goBack">
<image class=" back-icon"
:src="`/static/image/nav-bar/back-${data.isTop ? 'white' : 'black'}.png`" mode="">
</image>
</view>
<view class="title flex-align-center" :style="{ color: data.navBar.textColor }">
花呗
</view>
</view>
<view class="right flex-align-center">
<image class="icon"
:src="`/static/image/ant-credit-pay/${data.isTop ? 'service' : 'service-black'}.png`">
</image>
<image class="icon"
:src="`/static/image/ant-credit-pay/${data.isTop ? 'setting' : 'setting-black'}.png`">
</image>
</view>
</view>
</NavBar>
<view class="header-content-wrapper">
<view v-if="!huabeiInfo.isOverdueDeactivate"
class="current-month flex-align-center flex-justify-center">
逾期金额(元) |
<text style="color: #FFF3A8;margin-left: 14rpx;">
已逾期{{ huabeiInfo.daysPastDue }}天,逾期影响信用</text>
</view>
<view v-else class="current-month">{{ huabeiInfo.mouth }}月应还(元)</view>
<view class="money-box flex-align-center">
<text class="money alipay-font">{{ numberUtil.formatMoneyWithThousand(huabeiInfo.money) }}</text>
<image style="width: 32rpx;height: 32rpx;" class="icon"
src="/static/image/ant-credit-pay/overdue-payment/right-icon.png"></image>
</view>
<!-- 样式一 按钮样式 -->
<view v-if="huabeiInfo.styleType == 1 || !huabeiInfo.styleType" class="style-1 button-group">
<view class="button-item second-button" :class="{ 'ios-button': $system == 'iOS' }">立即还款</view>
</view>
<!-- 样式二 纯气泡样式 -->
<view v-if="huabeiInfo.styleType == 2" class="style-2 bubble-container">
<view class="bubble-box">
<view class="arrow"></view>
<text class="text">{{ huabeiInfo.descText }}</text>
</view>
</view>
<!-- 样式三 气泡带箭头样式 -->
<view v-if="huabeiInfo.styleType == 3" class="style-3 bubble-container">
<view class="bubble-box">
<view class="arrow"></view>
<view class="text flex-align-center">{{ huabeiInfo.descText }}
<!-- <uni-icons type="right" size="16" color="#D2DBE3"></uni-icons> -->
<image style="width: 32rpx;height: 32rpx;" class="icon"
src="/static/image/ant-credit-pay/overdue-payment/right-icon.png"></image>
</view>
</view>
</view>
<view class="total-info-box flex-align-center">
<view class="info-item">
<view class="label">总计账单</view>
<view class="value">还款日每月{{ huabeiInfo.dueDate }}日</view>
</view>
<view class="info-item">
<view class="label">总计额度</view>
<view class="value">{{
numberUtil.formatMoneyWithThousand(Number(huabeiInfo.totalAmount) -
Number(huabeiInfo.money))
}}可用
</view>
</view>
</view>
</view>
</view>
<view class="overdue-box">
<image class="bg-image" src="/static/image/ant-credit-pay/overdue-payment/overdue-bg.png" mode="widthFix">
</image>
<view class="overdue-info">
<image class="icon" src="/static/image/ant-credit-pay/overdue-payment/warring-icon.png"></image>
<view class="err-text">抱歉,您暂时无法使用该服务!服务机构将不定期评估您的使用资格,请保持良好信用行为并耐心等待通知</view>
<view v-if="!huabeiInfo.isOverdueDeactivate" class="info-text">
你已逾期{{ huabeiInfo.daysPastDue }}天,还款后花呗可恢复正常
</view>
<view v-else class="info-text-bold">可通过【额度快充】服务恢复花呗正常使用</view>
<view class="button">立即还款并恢复花呗</view>
</view>
</view>
<view class="service-box">
<view class="service-info" v-for="item in serviceList" :key="item.id">
<image class="icon" :src="item.image"></image>
<view class="name">{{ item.name }}</view>
</view>
</view>
<view class="consumption-box">
<view class="left flex-align-center">
<image class="img " src="/static/image/ant-credit-pay/overdue-payment/consume-dot.png">
</image>
<view class="text-box">{{ huabeiInfo.consumptionText }}</view>
</view>
<view class="right flex-align-center">
<view class="date">{{ huabeiInfo.consumptionDate }}</view>
<image class="icon" src="/static/image/ant-credit-pay/overdue-payment/right-icon.png"></image>
</view>
</view>
<view class="bottom-image-box">
<image class="img" src="/static/image/ant-credit-pay/overdue-payment/bottom-image-1.png" mode="widthFix">
</image>
<image class="img" src="/static/image/ant-credit-pay/overdue-payment/bottom-image-2.png" mode="widthFix">
</image>
</view>
<!-- 编辑弹窗 -->
<uni-popup ref="popup" type="center" :mask-click="false">
<view class="popup-content">
<view class="popup-title">编辑花呗数据</view>
<view class="form-item">
<text class="label">还款月份</text>
<picker :range="monthRange" :value="editHuabeiInfo.mouth - 1" @change="onMonthChange"
style="flex:1">
<view class="input">{{ editHuabeiInfo.mouth ? editHuabeiInfo.mouth + '月' : '请选择月份' }}</view>
</picker>
</view>
<view class="form-item">
<text class="label">本月应还</text>
<input class="input" type="digit" v-model="editHuabeiInfo.money" placeholder="请输入金额" />
</view>
<view class="form-item">
<text class="label">还款日</text>
<input class="input" type="number" v-model="editHuabeiInfo.dueDate" placeholder="请输入日期" />
</view>
<view class="form-item">
<text class="label">逾期天数</text>
<input class="input" type="number" v-model="editHuabeiInfo.daysPastDue" placeholder="请输入逾期天数" />
</view>
<view class="form-item">
<text class="label">总计额度</text>
<input class="input" type="digit" v-model="editHuabeiInfo.totalAmount" placeholder="请输入总计额度" />
</view>
<view v-if="huabeiInfo.styleType != 1" class="form-item">
<text class="label">气泡文本</text>
<input class="input" type="text" v-model="editHuabeiInfo.descText" placeholder="请输入描述文本" />
</view>
<!-- <text class="form-title">消费信息</text> -->
<view class="form-item">
<text class="label">消费文案</text>
<input class="input" type="text" v-model="editHuabeiInfo.consumptionText" placeholder="请输入消费文案" />
</view>
<view class="form-item">
<text class="label">消费日期</text>
<picker mode="date" :fields="$system == 'Android' ? 'day' : ''"
:value="editHuabeiInfo.consumptionDate" @change="onConsumptionDateChange"
:end="dateUtil.now('YYYY-MM-DD')" style="flex:1">
<view class="input">{{ editHuabeiInfo.consumptionDate || '请选择日期' }}</view>
</picker>
</view>
<view class="popup-btns">
<view class="btn cancel" @click="closeDialog">取消</view>
<view class="btn confirm" @click="confirmDialog">确定</view>
</view>
</view>
</uni-popup>
<!-- 样式选择弹窗 -->
<uni-popup ref="stylePopup" type="center">
<view class="popup-content">
<view class="popup-title">选择展示样式</view>
<view class="style-list">
<view class="style-item" v-for="(item, index) in styleList" :key="index"
@click="confirmStyleDialog(item.value)">
<text>{{ item.label }}</text>
<uni-icons v-if="huabeiInfo.styleType == item.value" type="checkmarkempty" size="20"
color="#1777FF"></uni-icons>
</view>
</view>
<view class="popup-btns">
<view class="btn cancel" @click="closeStyleDialog">取消</view>
</view>
</view>
</uni-popup>
</view>
<!-- 水印 -->
<view v-if="$isVip()">
<watermark :dark="data.dark" />
<liu-drag-button :canDocking="false" @clickBtn="$goRechargePage('watermark')">
<c-lottie ref="cLottieRef" :src='$watermark()' width="94px" height='74px' :loop="true"></c-lottie>
</liu-drag-button>
</view>
</template>
<script setup>
import NavBar from '@/components/nav-bar/nav-bar'
import {
numberUtil,
dateUtil,
util
} from '@/utils/common.js'
import {
ref,
toRefs,
reactive,
getCurrentInstance
} from 'vue';
import {
onLoad,
onShow,
onPageScroll
} from '@dcloudio/uni-app';
const instance = getCurrentInstance();
const { proxy } = instance;
const styleList = [{
label: '样式 1 (默认)',
value: 1
},
{
label: '样式 2 (纯气泡)',
value: 2
},
{
label: '样式 3 (带箭头气泡)',
value: 3
}
]
const buttonGroup = [{
name: "编辑花呗数据",
click: () => {
openDialog()
}
}, {
name: "切换展示样式",
click: () => {
openStyleDialog()
}
}, {
name: "逾期停用",
isSwitch: true,
key: 'isOverdueDeactivate',
click: () => {
data.huabeiInfo.isOverdueDeactivate = !data.huabeiInfo.isOverdueDeactivate
uni.setStorageSync(data.huabeiInfoStorageKey, data.huabeiInfo)
}
}, {
name: "花呗逾期",
isSwitch: true,
key: 'isOverdue',
click: () => {
data.huabeiInfo.isOverdue = !data.huabeiInfo.isOverdue
uni.setStorageSync(data.huabeiInfoStorageKey, data.huabeiInfo)
if (!data.huabeiInfo.isOverdue) {
uni.redirectTo({
url: '/pages/ant-credit-pay/index'
})
}
}
}]
const serviceList = [{
id: 1,
name: "花呗金",
image: "/static/image/ant-credit-pay/overdue-payment/huabeijin.png"
},
{
id: 2,
name: "周报",
image: "/static/image/ant-credit-pay/overdue-payment/zhoubao.png"
},
{
id: 3,
name: "生活号",
image: "/static/image/ant-credit-pay/overdue-payment/shenghuohao.png"
},
{
id: 3,
name: "分期生活",
image: "/static/image/ant-credit-pay/overdue-payment/fenqishenghuo.png"
},
{
id: 3,
name: "备用金",
image: "/static/image/ant-credit-pay/overdue-payment/beiyongjin.png"
}]
const clickTitlePopupButton = (button) => {
button.click()
}
const data = reactive({
navBar: {
bgColor: "#717E91",
textColor: "#fff"
},
huabeiInfoStorageKey: 'huabei_info_storage',
isTop: true,
huabeiInfo: {
mouth: 1,
money: 100,
dueDate: 15,
totalAmount: 200000,
descText: "当前账单进度已超出预期,花超了",
isOverdueDeactivate: false,
isInstallment: false,
styleType: 1,
installmentBadgeText: '4折起',
image: "",
isOverdue: false,
daysPastDue: 1,
consumptionDate: '2025/09/22',
consumptionText: '消费成功66.23元'
},
})
let {
huabeiInfo,
} = toRefs(data)
// 编辑表单数据
const editHuabeiInfo = ref({})
const popup = ref(null)
const stylePopup = ref(null)
// 打开样式选择弹窗
const openStyleDialog = () => {
stylePopup.value.open()
}
// 关闭样式选择弹窗
const closeStyleDialog = () => {
stylePopup.value.close()
}
// 确认样式选择
const confirmStyleDialog = (type) => {
data.huabeiInfo.styleType = type
// 保存到缓存
uni.setStorageSync(data.huabeiInfoStorageKey, data.huabeiInfo)
stylePopup.value.close()
}
const monthRange = Array.from({
length: 12
}, (_, i) => i + 1)
const onMonthChange = (e) => {
editHuabeiInfo.value.mouth = monthRange[e.detail.value]
}
const onConsumptionDateChange = (e) => {
// e.detail.value 格式通常为 YYYY-MM-DD如果需要 YYYY/MM/DD 可以转换
editHuabeiInfo.value.consumptionDate = e.detail.value.replace(/-/g, '/')
}
onLoad((option) => {
// 进入花呗逾期页面埋点
proxy.$apiUserEvent('all', {
type: 'click',
key: 'huabei_overdue',
value: "花呗逾期"
})
console.log(option)
// 读取缓存
let savedInfo = uni.getStorageSync(data.huabeiInfoStorageKey)
// savedInfo.image = ""
// uni.setStorageSync(data.huabeiInfoStorageKey, savedInfo)
console.log("savedInfo====", savedInfo)
if (savedInfo) {
// 合并默认值,防止旧数据缺少新字段
data.huabeiInfo = {
...data.huabeiInfo,
...savedInfo
}
}
})
// 监听页面滚动
onPageScroll((e) => {
// 当滚动超过40px时将导航栏背景设置为#F6F6F6
if (e.scrollTop > 40) {
data.navBar.bgColor = '#F6F6F6'
data.navBar.textColor = '#1a1a1a'
data.isTop = false
plus.navigator.setStatusBarStyle("dark");
} else {
// 回到顶部时恢复原色
data.navBar.bgColor = '#717E91'
data.navBar.textColor = '#fff'
data.isTop = true
plus.navigator.setStatusBarStyle("light");
}
})
onShow(() => {
// #ifdef APP-PLUS
util.setAndroidSystemBarColor('#F6F6F6')
setTimeout(() => {
plus.navigator.setStatusBarStyle("light");
}, 500)
// #endif
})
// 打开弹窗
const openDialog = () => {
// 深拷贝当前数据到编辑表单
editHuabeiInfo.value = JSON.parse(JSON.stringify(data.huabeiInfo))
popup.value.open()
}
// 关闭弹窗
const closeDialog = () => {
popup.value.close()
}
// 确认修改
const confirmDialog = () => {
// 校验数据: 本月应还不能大于总计额度
if (Number(editHuabeiInfo.value.money) > Number(editHuabeiInfo.value.totalAmount)) {
uni.showToast({
title: '本月应还不能大于总计额度',
icon: 'none'
})
return
}
data.huabeiInfo = JSON.parse(JSON.stringify(editHuabeiInfo.value))
// 保存到缓存
uni.setStorageSync(data.huabeiInfoStorageKey, data.huabeiInfo)
popup.value.close()
uni.showToast({
title: '保存成功',
icon: 'success'
})
}
const goBack = () => {
uni.navigateBack()
}
</script>
<style>
@import "/common/main.css";
</style>
<style lang="less" scoped>
.page-container {
position: relative;
display: flex;
flex-direction: column;
background-color: #F6F6F6;
// height: 100vh;
// overflow: hidden;
padding-bottom: 16rpx;
.nav-bar {
height: 100%;
display: flex;
align-items: center;
padding: 0 20rpx;
.title {
color: #ffffff;
font-size: 17px;
font-weight: 500;
text-align: center;
}
.right {
width: 90px;
}
.icon {
margin-left: 18rpx;
margin-right: 10rpx;
width: 24px;
height: 24px;
}
}
.ios-nav-bar {
.left {
width: 90px;
}
.title {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
}
.right {
width: 90px;
}
}
/* 头部背景 */
.header-bg {
position: absolute;
top: 0;
left: 0;
width: 100%;
background: linear-gradient(180deg, #647589 0%, #768497 100%);
/* 底部自然弧度 */
border-radius: 0 0 100% 100% / 0 0 32px 32px;
z-index: 0;
}
.header-content-wrapper {
position: relative;
z-index: 1;
}
.main-container {
background-color: #717E91;
padding-bottom: 32rpx;
.current-month {
margin-top: 12rpx;
color: #D2DBE3;
font-size: 24rpx;
text-align: center;
}
.money-box {
text-align: center;
justify-content: center;
.money {
font-size: 64rpx;
line-height: 2.5rem;
color: #ffffff;
}
}
.button-group {
margin-top: 18rpx;
display: flex;
justify-content: center;
justify-content: center;
.button-item {
height: 64rpx;
line-height: 64rpx;
border-radius: 8rpx;
color: #ffffff;
font-size: 30rpx;
padding: 0 24rpx;
}
.second-button {
background-color: #8C9BAF;
}
.ios-button {
border-radius: 33rpx !important;
}
}
.style-1 {
margin-top: 18rpx;
display: flex;
justify-content: center;
justify-content: center;
}
.bubble-container {
margin-top: 10rpx;
display: flex;
justify-content: center;
.bubble-box {
position: relative;
border: 1px solid #D2DBE3;
border-radius: 30rpx;
padding: 12rpx 24rpx;
display: flex;
align-items: center;
justify-content: center;
.text {
color: #ffffff;
font-size: 26rpx;
line-height: 1.2;
}
.arrow {
position: absolute;
top: -5px;
left: 50%;
transform: translateX(-50%) rotate(45deg);
width: 8px;
height: 8px;
background-color: #717E91;
border-left: 1px solid #D2DBE3;
border-top: 1px solid #D2DBE3;
z-index: 1;
}
}
}
.total-info-box {
margin-top: 48rpx;
.info-item {
width: 50%;
text-align: center;
.label {
color: #ffffff;
font-size: 26rpx;
line-height: 42rpx;
}
.value {
color: #D2DBE3;
font-size: 26rpx;
line-height: 36rpx;
}
}
}
}
.overdue-box {
position: relative;
width: 100%;
height: auto;
display: flex;
justify-content: center;
padding-top: 18rpx;
// background-image: url('/static/image/ant-credit-pay/overdue-payment/overdue-bg.png');
// background-size: contain;
// background-repeat: no-repeat;
margin-top: -1px;
// height: 700rpx;
.bg-image {
position: absolute;
width: 100%;
top: 0;
left: 0;
right: 0;
}
.overdue-info {
position: relative;
width: 87%;
margin: 0 48rpx;
background: linear-gradient(180deg, #FFF5F4 0%, #FFFBF7 100%);
border-radius: 20rpx 20rpx 20rpx 20rpx;
padding: 100rpx 24rpx 60rpx;
text-align: center;
// display: flex;
// align-items: center;
// flex-direction: column;
// min-height: 628rpx;
// max-height: 100%;
.icon {
position: relative;
width: 72rpx;
height: 72rpx;
}
.err-text {
margin-top: 24rpx;
font-size: 28rpx;
color: #E83443;
text-align: center;
}
.info-text {
margin-top: 50rpx;
font-size: 36rpx;
color: #333333;
text-align: center;
}
.info-text-bold {
color: #333333;
font-size: 36rpx;
font-weight: bold;
text-align: center;
margin: 0 90rpx;
}
.button {
background-color: #1777FF;
width: 100%;
height: 100rpx;
border-radius: 50rpx 50rpx 50rpx 50rpx;
font-size: 36rpx;
line-height: 100rpx;
text-align: center;
color: #ffffff;
margin-top: 38rpx;
}
}
}
.service-box {
background-color: #ffffff;
border-radius: 16rpx;
margin: 16rpx 24rpx 0;
display: flex;
// align-items: center;
flex-wrap: wrap;
padding-bottom: 12rpx;
.service-info {
width: 25%;
flex-shrink: 0;
display: flex;
flex-direction: column;
align-items: center;
margin-top: 26rpx;
padding-bottom: 20rpx;
font-size: 26rpx;
.name {
font-size: 26rpx;
color: #3D3D3D;
}
}
.icon {
width: 56rpx;
height: 56rpx;
}
}
.consumption-box {
margin: 16rpx 24rpx 16rpx;
background-color: #ffffff;
border-radius: 12rpx;
padding: 24rpx 16rpx;
display: flex;
justify-content: space-between;
align-items: center;
.left {
display: flex;
align-items: center;
.img {
width: 24rpx;
height: 24rpx;
margin-right: 12rpx;
}
.text-box {
font-size: 24rpx;
color: #333;
}
}
.right {
display: flex;
align-items: center;
.date {
color: #969696;
font-size: 24rpx;
}
.icon {
width: 28rpx;
height: 28rpx;
}
}
}
}
.back-icon {
width: 24px;
height: 24px;
}
.bottom-image-box {
padding: 0 24rpx;
display: flex;
justify-content: space-between;
padding-bottom: 16rpx;
.img {
flex-shrink: 0;
width: calc(50% - 12rpx);
}
}
</style>
<style lang="scss" scoped>
.popup-content {
background-color: #fff;
width: 600rpx;
border-radius: 16rpx;
padding: 30rpx;
.popup-title {
font-size: 32rpx;
font-weight: bold;
text-align: center;
margin-bottom: 30rpx;
}
.form-item {
display: flex;
align-items: center;
margin-bottom: 24rpx;
.label {
width: 140rpx;
font-size: 28rpx;
color: #333;
}
.input {
flex: 1;
height: 72rpx;
line-height: 72rpx;
background-color: #f5f5f5;
border-radius: 8rpx;
padding: 0 20rpx;
font-size: 28rpx;
}
}
.flex-between {
justify-content: space-between;
}
.popup-btns {
display: flex;
margin-top: 40rpx;
.btn {
flex: 1;
height: 80rpx;
line-height: 80rpx;
text-align: center;
border-radius: 12rpx;
font-size: 30rpx;
&.cancel {
background-color: #f5f5f5;
color: #666;
margin-right: 20rpx;
}
&.confirm {
background-color: #717E91;
color: #fff;
}
}
}
}
.style-list {
.style-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 30rpx 0;
border-bottom: 1px solid #f5f5f5;
font-size: 30rpx;
color: #333;
&:last-child {
border-bottom: none;
}
}
}
</style>