花呗完成逾期页面

This commit is contained in:
tangxinyue 2026-01-21 18:44:53 +08:00
parent 44625d9e5d
commit fcbe904dbe
14 changed files with 709 additions and 15 deletions

View File

@ -1,6 +1,6 @@
<template>
<view style="width: 100%;" :style="{ height: `${data.statusBarHeight + 44}px` }"></view>
<view class="nav-bar-container" :style="{ backgroundColor: bgColor }">
<view class="nav-bar-container" :style="{ backgroundColor: bgColor, zIndex: zIndex }">
<view class="status-placeholder" :style="{ height: `${data.statusBarHeight}px` }"></view>
<view style="width: 100%;height: 44px;" @click="openPopup">
<slot>
@ -41,10 +41,19 @@
<popup ref="topPopup">
<view class="button-group w100 flex-between flex-wrap">
<view class="button-box" v-for="button in buttonGroup" @click="buttonClick(button)">
<view class="button">
<view class="button-box" v-for="(button, index) in buttonGroup" :key="index"
@click="buttonClick(button)">
<!-- 使用作用域插槽允许父组件自定义按钮内容 -->
<!-- 默认渲染 -->
<view class="button flex-align-center flex-justify-center">
<slot name="button" :button="button" :index="index">
{{ button.name }}
<switch v-if="button.isSwitch" :checked="button.value" @change="buttonClick(button)"
style="transform: scale(0.7);"></switch>
</slot>
</view>
</view>
</view>
</popup>
@ -90,6 +99,10 @@ const props = defineProps({
rightButtonText: {
type: String,
default: '确定'
},
zIndex: {
type: Number,
default: 999
}
})

View File

@ -61,7 +61,15 @@
"navigationBarTitleText": "花呗首页",
"navigationStyle": "custom"
}
}]
},
{
"path": "overdue-payment/overdue-payment",
"style": {
"navigationBarTitleText": "花呗逾期",
"navigationStyle": "custom"
}
}
]
},
{
"root": "pages/common",

View File

@ -10,6 +10,17 @@
<view class="main-container">
<NavBar v-if="!selectedImage" title="花呗" :bgColor="data.navBar.bgColor" :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.isOverdue" @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" @click.stop="goBack">
@ -76,7 +87,8 @@
@longpress="chooseImage">
<view v-if="!huabeiInfo.image" class="flex-align-center flex-column">
<image style="width:92rpx; height: 92rpx;margin-top: 16rpx;"
src="/static/image/common/upload-screenshot.png"></image>
src="/static/image/common/upload-screenshot.png">
</image>
<text style="font-size: 36rpx;color: #1777FF;">长按替换真实截图</text>
</view>
<view v-else class="w100 h100">
@ -168,7 +180,8 @@
<script setup>
import NavBar from '@/components/nav-bar/nav-bar'
import {
numberUtil
numberUtil,
util
} from '@/utils/common.js'
import {
ref,
@ -177,7 +190,8 @@ import {
reactive
} from 'vue';
import {
onLoad
onLoad,
onShow
} from '@dcloudio/uni-app';
const instance = getCurrentInstance();
@ -199,6 +213,18 @@ const buttonGroup = [{
data.huabeiInfo.image = ""
uni.setStorageSync(data.huabeiInfoStorageKey, data.huabeiInfo)
}
}, {
name: "花呗逾期",
isSwitch: true,
click: () => {
data.huabeiInfo.isOverdue = !data.huabeiInfo.isOverdue
uni.setStorageSync(data.huabeiInfoStorageKey, data.huabeiInfo)
if (data.huabeiInfo.isOverdue) {
uni.redirectTo({
url: '/pages/ant-credit-pay/overdue-payment/overdue-payment'
})
}
}
}]
const data = reactive({
@ -217,7 +243,8 @@ const data = reactive({
styleType: 1,
installmentBadgeText: '4折起',
image: "",
isOverdue: false
isOverdue: false,
daysPastDue: 1
},
selectedImage: '',
showMask: false
@ -276,6 +303,13 @@ onLoad((option) => {
}
})
onShow(() => {
// #ifdef APP-PLUS
util.setAndroidSystemBarColor('#ffffff')
plus.navigator.setStatusBarStyle("light");
// #endif
})
//
const openDialog = () => {
//
@ -364,7 +398,6 @@ const confirmImage = () => {
0, sTop, sWidth, sHeight, //
0, 0, canvasW, canvasH //
)
ctx.draw(false, () => {
uni.canvasToTempFilePath({
canvasId: 'crop-canvas',

View File

@ -0,0 +1,635 @@
<template>
<view class="page-container">
<view class="main-container">
<!-- 头部背景 (带弧度) -->
<view class="header-bg"></view>
<!-- 导航栏 - 降低层级以显示水印 -->
<NavBar title="花呗 | 信用购" :bgColor="'transparent'" textColor="#fff" :isFixed="true" :zIndex="10"
: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.isOverdue" @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" @click.stop="goBack">
<image class=" back-icon" src="/static/image/nav-bar/back-white.png" mode="">
</image>
</view>
<view class="title ">
花呗
</view>
</view>
<view class="right">
<image class="icon" src="/static/image/ant-credit-pay/service.png"></image>
<image class="icon" src="/static/image/ant-credit-pay/setting.png"></image>
</view>
</view>
</NavBar>
<view class="header-content-wrapper">
<view class="current-month flex-align-center flex-justify-center">逾期金额() | <text
style="color: #FFF3A8;margin-left: 14rpx;">
已逾期{{ huabeiInfo.daysPastDue }},逾期影响信用</text>
</view>
<view class="money-box flex-align-center">
<text class="money alipay-font">{{ numberUtil.formatMoneyWithThousand(huabeiInfo.money) }}</text>
<uni-icons type="right" size="16" color="#D2DBE3"></uni-icons>
</view>
<view class="style-1 button-group">
<view class="button-item second-button" :class="{ 'ios-button': $system == 'iOS' }">立即还款</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">
<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 class="info-text">你已逾期{{ huabeiInfo.daysPastDue }}还款后花呗可恢复正常</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">消费记录</view>
</view>
<view class="right flex-align-center">
<view class="date">2025/09/22</view>
<image class="icon" src="/static/image/ant-credit-pay/overdue-payment/right-icon.png"></image>
</view>
</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 class="popup-btns">
<view class="btn cancel" @click="closeDialog">取消</view>
<view class="btn confirm" @click="confirmDialog">确定</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,
util
} from '@/utils/common.js'
import {
ref,
toRefs,
reactive
} from 'vue';
import {
onLoad,
onShow
} from '@dcloudio/uni-app';
const buttonGroup = [{
name: "编辑花呗数据",
click: () => {
openDialog()
}
}, {
name: "花呗逾期",
isSwitch: true,
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',
huabeiInfo: {
mouth: 1,
money: 100,
dueDate: 15,
totalAmount: 200000,
descText: "当前账单进度已超出预期,花超了",
isInstallment: false,
styleType: 1,
installmentBadgeText: '4折起',
image: "",
isOverdue: false,
daysPastDue: 1
},
})
let {
huabeiInfo,
} = toRefs(data)
//
const editHuabeiInfo = ref({})
const popup = ref(null)
const monthRange = Array.from({
length: 12
}, (_, i) => i + 1)
const onMonthChange = (e) => {
editHuabeiInfo.value.mouth = monthRange[e.detail.value]
}
onLoad((option) => {
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
}
}
})
onShow(() => {
// #ifdef APP-PLUS
util.setAndroidSystemBarColor('#F6F6F6')
// #endif
})
//
const openDialog = () => {
//
editHuabeiInfo.value = JSON.parse(JSON.stringify(data.huabeiInfo))
popup.value.open()
}
//
const closeDialog = () => {
popup.value.close()
}
//
const confirmDialog = () => {
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;
.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: 80px;
}
.icon {
margin-left: 18rpx;
margin-right: 10rpx;
width: 24px;
height: 24px;
}
}
.ios-nav-bar {
.left {
width: 80px;
}
.title {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
}
.right {
width: 80px;
}
}
/* 头部背景 */
.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;
}
.total-info-box {
margin-top: 48rpx;
.info-item {
width: 50%;
text-align: center;
.label {
color: #ffffff;
font-size: 30rpx;
line-height: 42rpx;
}
.value {
color: #D2DBE3;
font-size: 26rpx;
line-height: 36rpx;
}
}
}
}
.overdue-box {
display: flex;
align-items: center;
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;
.overdue-info {
width: 654rpx;
height: 628rpx;
background: linear-gradient(180deg, #FFF5F4 0%, #FFFBF7 100%);
border-radius: 20rpx 20rpx 20rpx 20rpx;
padding: 100rpx 24rpx 60rpx;
display: flex;
align-items: center;
flex-direction: column;
.icon {
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;
}
.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;
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;
}
</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>

View File

@ -301,7 +301,12 @@ const clickMenu = (item) => {
if (!item.path) {
uiUtil.showError('开发中')
} else {
util.goPage(item.path)
const isOverdue = storage.get("huabei_info_storage").isOverdue || false
let url = item.path
if (item.name == "花呗" && isOverdue) {
url = "/pages/ant-credit-pay/overdue-payment/overdue-payment"
}
util.goPage(url)
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 423 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 628 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 337 B