完成花呗首页UI及逻辑

This commit is contained in:
tangxinyue 2026-01-20 18:30:41 +08:00
parent 7c3e22324f
commit c594174f14
9 changed files with 2554 additions and 2006 deletions

View File

@ -2,27 +2,31 @@
<view style="width: 100%;" :style="{ height: `${data.statusBarHeight + 44}px` }"></view> <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 }">
<view class="status-placeholder" :style="{ height: `${data.statusBarHeight}px` }"></view> <view class="status-placeholder" :style="{ height: `${data.statusBarHeight}px` }"></view>
<view style="width: 100%;height: 44px;" @click="openPopup">
<slot>
<uni-nav-bar backgroundColor="#00000000" class="nav-bar" :border="false" :title="title" v-bind="$attrs" <uni-nav-bar backgroundColor="#00000000" class="nav-bar" :border="false" :title="title" v-bind="$attrs"
v-on="$attrs"> v-on="$attrs">
<template v-slot:left> <template v-slot:left>
<view class="nav-bar-left"> <view class="nav-bar-left">
<slot name="left"> <slot name="left">
<view class="left-icon" @click="onBack"> <view class="left-icon" @click.stop="onBack">
<image class="nav-icon-back" src="/static/image/nav-bar/back-black.png" mode=""></image> <image class="nav-icon-back" src="/static/image/nav-bar/back-black.png" mode="">
</image>
</view> </view>
</slot> </slot>
</view> </view>
</template> </template>
<view class="nav-bar-title w100 h100 flex-1" @click="openPopup"> <view class="nav-bar-title w100 h100 flex-1" @click="openPopup" :style="{ color: textColor }">
<slot name="center"> <slot name="center">
{{ title }} {{ title }}
</slot> </slot>
</view> </view>
<template v-slot:right> <template v-slot:right>
<view class="nav-bar-right" @click="onRightClick"> <view class="nav-bar-right" @click.stop="onRightClick">
<slot name="right"> <slot name="right">
<view v-if="isRightIcon" class="right-icon"> <view v-if="isRightIcon" class="right-icon">
<image class="nav-icon-more" src="/static/image/nav-bar/more-black.png" mode=""></image> <image class="nav-icon-more" src="/static/image/nav-bar/more-black.png" mode="">
</image>
</view> </view>
<view v-if="isRightButton" class="right-button"> <view v-if="isRightButton" class="right-button">
{{ rightButtonText }} {{ rightButtonText }}
@ -31,6 +35,10 @@
</view> </view>
</template> </template>
</uni-nav-bar> </uni-nav-bar>
</slot>
</view>
<popup ref="topPopup"> <popup ref="topPopup">
<view class="button-group w100 flex-between flex-wrap"> <view class="button-group w100 flex-between flex-wrap">
<view class="button-box" v-for="button in buttonGroup" @click="buttonClick(button)"> <view class="button-box" v-for="button in buttonGroup" @click="buttonClick(button)">
@ -59,6 +67,10 @@ const props = defineProps({
type: String, type: String,
default: '#fff' default: '#fff'
}, },
textColor: {
type: String,
default: '#000'
},
title: { title: {
type: String, type: String,
default: '' default: ''

View File

@ -4,7 +4,7 @@
{ {
"path": "pages/index/index", "path": "pages/index/index",
"style": { "style": {
"navigationBarTitleText": "uni-app", "navigationBarTitleText": "支付宝模拟器首页",
"navigationStyle": "custom" "navigationStyle": "custom"
} }
} }
@ -53,6 +53,16 @@
} }
] ]
}, },
{
"root": "pages/ant-credit-pay",
"pages": [{
"path": "index",
"style": {
"navigationBarTitleText": "花呗首页",
"navigationStyle": "custom"
}
}]
},
{ {
"root": "pages/common", "root": "pages/common",
"pages": [{ "pages": [{

View File

@ -0,0 +1,525 @@
<template>
<view class="page-container">
<view class="main-container">
<NavBar title="花呗|信用购" :bgColor="data.navBar.bgColor" :buttonGroup="buttonGroup"
@button-click="clickTitlePopupButton">
<view class="nav-bar flex-between w100" :class="{ 'ios-nav-bar': $system == 'iOS' }">
<view class="flex-align-center flex-1">
<view class="left">
<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="current-month">{{ huabeiInfo.mouth }}月应还()</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="#B9D6FF"></uni-icons>
</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 v-if="!huabeiInfo.isInstallment" class="button-item primary-button"
:class="{ 'ios-button': $system == 'iOS' }">
分期还款
<view v-if="huabeiInfo.installmentBadgeText" class="badge">{{ huabeiInfo.installmentBadgeText }}
</view>
</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>
<text class="text flex-align-center">{{ huabeiInfo.descText }}
<uni-icons type="right" size="16" color="#B9D6FF"></uni-icons>
</text>
</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 class="image-box flex-1">
<image style="width:92rpx; height: 92rpx;margin-top: 16rpx;"
src="/static/image/common/upload-screenshot.png"></image>
<text style="font-size: 36rpx;color: #1777FF;">长按替换真实截图</text>
</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="digit" v-model="editHuabeiInfo.totalAmount" placeholder="请输入总计额度" />
</view>
<view class="form-item">
<text class="label">描述文本</text>
<input class="input" type="text" v-model="editHuabeiInfo.descText" placeholder="请输入描述文本" />
</view>
<view class="form-item">
<text class="label">分期气泡</text>
<input class="input" type="text" v-model="editHuabeiInfo.installmentBadgeText"
placeholder="请输入分期还款气泡文案" />
</view>
<view class="form-item flex-between">
<text class="label">是否分期</text>
<switch :checked="editHuabeiInfo.isInstallment" style="transform: scale(0.8);"
@change="e => editHuabeiInfo.isInstallment = e.detail.value" />
</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>
</template>
<script setup>
import NavBar from '@/components/nav-bar/nav-bar'
import { numberUtil } from '@/utils/common.js'
import { ref, toRefs } from 'vue';
import { onLoad } from '@dcloudio/uni-app';
const buttonGroup = [{
name: "编辑花呗数据",
click: () => {
openDialog()
}
}, {
name: "切换展示样式",
click: () => {
openStyleDialog()
}
}]
const data = ref({
navBar: {
bgColor: "#1777FF",
textColor: "#fff"
},
huabeiInfo: {
mouth: 1,
money: 100,
dueDate: 15,
totalAmount: 200000,
descText: "当前账单进度已超出预期,花超了",
isInstallment: false,
styleType: 1,
installmentBadgeText: '4折起'
},
huabeiInfoStorageKey: 'huabei_info_storage'
})
let { huabeiInfo } = toRefs(data.value)
//
const editHuabeiInfo = ref({})
const popup = ref(null)
const stylePopup = ref(null)
const styleList = [
{ label: '样式 1 (默认)', value: 1 },
{ label: '样式 2 (纯气泡)', value: 2 },
{ label: '样式 3 (带箭头气泡)', value: 3 }
]
const monthRange = Array.from({ length: 12 }, (_, i) => i + 1)
const onMonthChange = (e) => {
editHuabeiInfo.value.mouth = monthRange[e.detail.value]
}
onLoad((option) => {
console.log(option)
//
const savedInfo = uni.getStorageSync(data.value.huabeiInfoStorageKey)
if (savedInfo) {
//
data.value.huabeiInfo = { ...data.value.huabeiInfo, ...savedInfo }
}
})
//
const openDialog = () => {
//
editHuabeiInfo.value = JSON.parse(JSON.stringify(data.value.huabeiInfo))
popup.value.open()
}
//
const closeDialog = () => {
popup.value.close()
}
//
const confirmDialog = () => {
data.value.huabeiInfo = JSON.parse(JSON.stringify(editHuabeiInfo.value))
//
uni.setStorageSync(data.value.huabeiInfoStorageKey, data.value.huabeiInfo)
popup.value.close()
uni.showToast({
title: '保存成功',
icon: 'success'
})
}
//
const openStyleDialog = () => {
stylePopup.value.open()
}
//
const closeStyleDialog = () => {
stylePopup.value.close()
}
//
const confirmStyleDialog = (type) => {
data.value.huabeiInfo.styleType = type
//
uni.setStorageSync(data.value.huabeiInfoStorageKey, data.value.huabeiInfo)
stylePopup.value.close()
}
//
const clickTitlePopupButton = (button) => {
button.click()
}
</script>
<style>
@import "/common/main.css";
</style>
<style lang="less" scoped>
.page-container {
display: flex;
flex-direction: column;
background-color: #ffffff;
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;
}
}
.main-container {
background-color: #1777FF;
padding-bottom: 32rpx;
.current-month {
margin-top: 12rpx;
color: #B9D6FF;
font-size: 24rpx;
text-align: center;
}
.money-box {
text-align: center;
justify-content: center;
.money {
font-size: 64rpx;
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 {
border: 2rpx solid #66B2FD;
}
.primary-button {
background-color: #66B2FD;
margin: 0 22rpx;
position: relative;
.badge {
position: absolute;
top: -16rpx;
right: -10rpx;
background-color: #F34624;
color: #fff;
font-size: 20rpx;
padding: 0 10rpx;
height: 32rpx;
line-height: 32rpx;
border-radius: 16rpx 16rpx 16rpx 0;
z-index: 1;
}
}
.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 #75bcff;
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: #1777FF;
border-left: 1px solid #75bcff;
border-top: 1px solid #75bcff;
z-index: 1;
}
}
}
.total-info-box {
margin-top: 48rpx;
.info-item {
width: 50%;
text-align: center;
.label {
color: #ffffff;
font-size: 30rpx;
line-height: 42rpx;
}
.value {
color: #ffffff;
font-size: 26rpx;
line-height: 36rpx;
}
}
}
}
.image-box {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
}
.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: #1777FF;
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>

View File

@ -284,79 +284,79 @@
<script setup> <script setup>
import { import {
postJson postJson
} from "@/utils/requests.js" } from "@/utils/requests.js"
import { import {
ref, ref,
reactive, reactive,
getCurrentInstance, getCurrentInstance,
nextTick, nextTick,
toRefs toRefs
} from "vue"; } from "vue";
import { import {
onLoad, onLoad,
onShow, onShow,
onReady, onReady,
onBackPress, onBackPress,
onUnload onUnload
} from "@dcloudio/uni-app"; } from "@dcloudio/uni-app";
import { import {
numberUtil numberUtil
} from "@/utils/common.js"; } from "@/utils/common.js";
const { const {
appContext, appContext,
proxy proxy
} = getCurrentInstance(); } = getCurrentInstance();
const popup = ref(); const popup = ref();
const coupon = ref(); const coupon = ref();
const couponBox = ref(); const couponBox = ref();
const myCoupon = ref(); const myCoupon = ref();
const dialogVipBenefits = [{ const dialogVipBenefits = [{
name: "模拟微信", name: "模拟微信",
url: "/static/image/recharge/moniweixinDialog.png" url: "/static/image/recharge/moniweixinDialog.png"
}, },
{ {
name: "无广告", name: "无广告",
url: "/static/image/recharge/wuguanggaoDialog.png" url: "/static/image/recharge/wuguanggaoDialog.png"
}, },
{ {
name: "无水印", name: "无水印",
url: "/static/image/recharge/wushuiyinDialog.png" url: "/static/image/recharge/wushuiyinDialog.png"
}, },
{ {
name: "专属客服", name: "专属客服",
url: "/static/image/recharge/zhuanshukefuDialog.png" url: "/static/image/recharge/zhuanshukefuDialog.png"
} }
] ]
// //
const packageList = [{ const packageList = [{
name: "连续包月", name: "连续包月",
delPrice: "89", delPrice: "89",
price: "29", price: "29",
lifespan: "一月" lifespan: "一月"
}, },
{ {
name: "连续包季", name: "连续包季",
delPrice: "189", delPrice: "189",
price: "98", price: "98",
lifespan: "一季" lifespan: "一季"
}, },
{ {
name: "连续包年", name: "连续包年",
delPrice: "365", delPrice: "365",
price: "198", price: "198",
lifespan: "一年" lifespan: "一年"
} }
] ]
const data = reactive({ const data = reactive({
scrollLeft: 0, scrollLeft: 0,
active_id: 0, active_id: 0,
active_ids: 0, active_ids: 0,
@ -478,30 +478,30 @@ const data = reactive({
// //
isProcessingClick: false, isProcessingClick: false,
banner: '', banner: '',
}) })
let { let {
buttonText, buttonText,
selected, selected,
benefitList, benefitList,
noticeList, noticeList,
commentList, commentList,
paymentMethod paymentMethod
} = toRefs(data) } = toRefs(data)
/** /**
* 返回监听 * 返回监听
*/ */
onBackPress((e) => { onBackPress((e) => {
console.log(e); console.log(e);
if (e.from == 'backbutton' && data.appUser.vip == 1) { if (e.from == 'backbutton' && data.appUser.vip == 1) {
open() open()
return true; // return true; //
} }
}) })
onLoad(async () => { onLoad(async () => {
// uni.showLoading({ // uni.showLoading({
// title: '', // title: '',
// mask: true // // mask: true //
@ -590,12 +590,15 @@ onLoad(async () => {
item['isStatus'] = true item['isStatus'] = true
} }
item['expire_times'] = item.expire_time item['expire_times'] = item.expire_time
item.expire_time = item.expire_time.replace('-', '.').replace('-', '.').substring(0, 10) item.expire_time = item.expire_time.replace('-', '.').replace('-', '.').substring(
0, 10)
}) })
data.myActivity = [ data.myActivity = [
...activity.data.items.filter(item => (item.threshold == '' || zsItem.price >= (Number(item ...activity.data.items.filter(item => (item.threshold == '' || zsItem.price >= (Number(
item
.threshold) / 100)) && item.isStatus), .threshold) / 100)) && item.isStatus),
...activity.data.items.filter(item => (zsItem.price < (Number(item.threshold) / 100) && item ...activity.data.items.filter(item => (zsItem.price < (Number(item.threshold) / 100) &&
item
.threshold != '') || !item.isStatus) .threshold != '') || !item.isStatus)
] ]
data.myActivity = deduplicateKeepLast(data.myActivity) data.myActivity = deduplicateKeepLast(data.myActivity)
@ -660,19 +663,19 @@ onLoad(async () => {
console.log('接收到宿主App消息-' + event + '' + data); console.log('接收到宿主App消息-' + event + '' + data);
} }
}) })
}) })
onShow(async () => { onShow(async () => {
// paymentResult(180191, paymentMethod.value) // paymentResult(180191, paymentMethod.value)
// generateNoticeList() // generateNoticeList()
}) })
onUnload(() => { onUnload(() => {
// uni.offNativeEventReceive() // // uni.offNativeEventReceive() //
}) })
onReady(() => { onReady(() => {
try { try {
if (plus.os.name === 'Android') { if (plus.os.name === 'Android') {
@ -688,7 +691,7 @@ onReady(() => {
} }
}) })
console.log("状态栏设置完毕!"); console.log("状态栏设置完毕!");
setTimeout(function () { setTimeout(function() {
uni.setNavigationBarColor({ uni.setNavigationBarColor({
backgroundColor: '#fff', backgroundColor: '#fff',
animation: { // animation: { //
@ -697,18 +700,18 @@ onReady(() => {
} }
}) })
}, 200); }, 200);
setTimeout(function () { setTimeout(function() {
plus.navigator.setStatusBarStyle("light"); plus.navigator.setStatusBarStyle("light");
}, 200); }, 200);
} }
} catch (error) { } catch (error) {
//TODO handle the exception //TODO handle the exception
} }
}) })
function isToday(inputTime) { function isToday(inputTime) {
// //
const today = new Date(); const today = new Date();
today.setHours(0, 0, 0, 0); today.setHours(0, 0, 0, 0);
@ -721,9 +724,9 @@ function isToday(inputTime) {
// //
return inputTimestamp === todayTimestamp; return inputTimestamp === todayTimestamp;
} }
function calculateTimeRemaining(targetTime) { function calculateTimeRemaining(targetTime) {
// //
const target = new Date(targetTime).getTime(); const target = new Date(targetTime).getTime();
const now = new Date().getTime(); const now = new Date().getTime();
@ -758,9 +761,9 @@ function calculateTimeRemaining(targetTime) {
minutes: minutes, minutes: minutes,
seconds: seconds seconds: seconds
}; };
} }
function activeClick(status) { function activeClick(status) {
myCoupon.value.close() myCoupon.value.close()
if (status && data.active_ids > 0) { if (status && data.active_ids > 0) {
let item = data.activeitems let item = data.activeitems
@ -777,14 +780,14 @@ function activeClick(status) {
setPrice(true) setPrice(true)
}, 1000); }, 1000);
} }
} }
function setActiveId(item) { function setActiveId(item) {
data.active_ids = item.id data.active_ids = item.id
data.activeitems = item data.activeitems = item
} }
function setPrice(status) { function setPrice(status) {
console.log("setPrice") console.log("setPrice")
if (data.incrementTimer) { if (data.incrementTimer) {
clearInterval(data.incrementTimer); clearInterval(data.incrementTimer);
@ -805,10 +808,12 @@ function setPrice(status) {
origin_price = Number(data.goods.origin_price) origin_price = Number(data.goods.origin_price)
coupon = origin_price - price coupon = origin_price - price
} else { } else {
price = data.goods.price - (data.activeCoupon.coupon_type_name != '折扣券' ? (Number(data.activeCoupon.coupon_value) / price = data.goods.price - (data.activeCoupon.coupon_type_name != '折扣券' ? (Number(data.activeCoupon
.coupon_value) /
100) : ((1 - Number(data.activeCoupon.coupon_value)) * data.goods.price)) 100) : ((1 - Number(data.activeCoupon.coupon_value)) * data.goods.price))
coupon = (Number(data.goods.origin_price) - Number(data.goods.price)) + (Number(data.goods.price) - (data.goods coupon = (Number(data.goods.origin_price) - Number(data.goods.price)) + (Number(data.goods.price) - (data.goods
.price - (data.activeCoupon.coupon_type_name != '折扣券' ? (Number(data.activeCoupon.coupon_value) / 100) : (( .price - (data.activeCoupon.coupon_type_name != '折扣券' ? (Number(data.activeCoupon.coupon_value) /
100) : ((
1 - Number(data.activeCoupon.coupon_value)) * data.goods.price)))) 1 - Number(data.activeCoupon.coupon_value)) * data.goods.price))))
} }
data.coupon = numberUtil.toFiexd(coupon, 0) data.coupon = numberUtil.toFiexd(coupon, 0)
@ -864,9 +869,9 @@ function setPrice(status) {
console.log("最后", data.price) console.log("最后", data.price)
} }
/* 获取我的优惠券 */ /* 获取我的优惠券 */
async function getActivity() { async function getActivity() {
let activity = await proxy.$requestPromise({ let activity = await proxy.$requestPromise({
url: 'api/activity/coupon', url: 'api/activity/coupon',
method: "GET", method: "GET",
@ -889,15 +894,18 @@ async function getActivity() {
item.expire_time = item.expire_time.replace('-', '.').replace('-', '.').substring(0, 10) item.expire_time = item.expire_time.replace('-', '.').replace('-', '.').substring(0, 10)
}) })
data.myActivity = [ data.myActivity = [
...activity.data.items.filter(item => (item.threshold == '' || data.goods.price >= (Number(item.threshold) / ...activity.data.items.filter(item => (item.threshold == '' || data.goods.price >= (Number(item
.threshold) /
100) && item.isStatus)), 100) && item.isStatus)),
...activity.data.items.filter(item => (data.goods.price < (Number(item.threshold) / 100) && item.threshold != ...activity.data.items.filter(item => (data.goods.price < (Number(item.threshold) / 100) && item
.threshold !=
'') || !item.isStatus) '') || !item.isStatus)
] ]
data.myActivity = deduplicateKeepLast(data.myActivity) data.myActivity = deduplicateKeepLast(data.myActivity)
} }
} }
function deduplicateKeepLast(arr, idKey = 'id') {
function deduplicateKeepLast(arr, idKey = 'id') {
const map = new Map(); const map = new Map();
arr.forEach(item => { arr.forEach(item => {
@ -906,10 +914,10 @@ function deduplicateKeepLast(arr, idKey = 'id') {
}); });
return Array.from(map.values()); return Array.from(map.values());
} }
/* 领取优惠券 */ /* 领取优惠券 */
async function submitActivity() { async function submitActivity() {
console.log("activity_id"); console.log("activity_id");
let activity_id = '' let activity_id = ''
data.activity.forEach(item => { data.activity.forEach(item => {
@ -919,7 +927,7 @@ async function submitActivity() {
if (activity_id != "") { if (activity_id != "") {
console.log("activity_id", activity_id); console.log("activity_id", activity_id);
let activityRes = await postJson('q', 'api/activity', { let activityRes = await postJson('q', 'api/activity', {
activity_id: activity_id//activity_id+"=" activity_id: activity_id //activity_id+"="
}) })
console.log(activityRes) console.log(activityRes)
if (activityRes.code == 0) { if (activityRes.code == 0) {
@ -944,24 +952,24 @@ async function submitActivity() {
}) })
} }
} }
/** /**
* @param {Object} item * @param {Object} item
* @param {Object} index * @param {Object} index
* 选择购买套餐 * 选择购买套餐
*/ */
/* /*
防抖 防抖
*/ */
const debouncedOnSelect = debounce((items, index) => { const debouncedOnSelect = debounce((items, index) => {
onSelect(items, index); onSelect(items, index);
}, 200, false); }, 200, false);
function debounce(func, wait, immediate = true) { function debounce(func, wait, immediate = true) {
let timeout; let timeout;
return function (...args) { return function(...args) {
const later = () => { const later = () => {
timeout = null; timeout = null;
if (!immediate) func(...args); if (!immediate) func(...args);
@ -973,8 +981,8 @@ function debounce(func, wait, immediate = true) {
if (callNow) func(...args); if (callNow) func(...args);
}; };
} }
async function onSelect(items, index) { async function onSelect(items, index) {
data.active_id = 0 data.active_id = 0
data.activeCoupon = {} data.activeCoupon = {}
data.active_ids = 0 data.active_ids = 0
@ -986,8 +994,10 @@ async function onSelect(items, index) {
let defaultCoupon = data.myActivity.filter(item => item.activity_id == data.goods.default_activity) let defaultCoupon = data.myActivity.filter(item => item.activity_id == data.goods.default_activity)
if (defaultCoupon.length > 0) { if (defaultCoupon.length > 0) {
defaultCoupon.forEach(item => { defaultCoupon.forEach(item => {
if ((data.goods.price >= (Number(item.threshold) / 100) || item.threshold == '') && item.isStatus) { if ((data.goods.price >= (Number(item.threshold) / 100) || item.threshold == '') && item
item['price2'] = data.goods.price - (item.coupon_type_name != '折扣券' ? (Number(item.coupon_value) / .isStatus) {
item['price2'] = data.goods.price - (item.coupon_type_name != '折扣券' ? (Number(item
.coupon_value) /
100) : ((1 - Number(item.coupon_value)) * data.goods.price)) 100) : ((1 - Number(item.coupon_value)) * data.goods.price))
} else { } else {
item['price2'] = 10000000 item['price2'] = 10000000
@ -1009,8 +1019,10 @@ async function onSelect(items, index) {
if (id == 0 && data.goods.default_activity != '') { if (id == 0 && data.goods.default_activity != '') {
try { try {
data.myActivity.forEach(item => { data.myActivity.forEach(item => {
if ((data.goods.price >= (Number(item.threshold) / 100) || item.threshold == '') && item.isStatus) { if ((data.goods.price >= (Number(item.threshold) / 100) || item.threshold == '') &&
item['price2'] = data.goods.price - (item.coupon_type_name != '折扣券' ? (Number(item.coupon_value) / item.isStatus) {
item['price2'] = data.goods.price - (item.coupon_type_name != '折扣券' ? (Number(item
.coupon_value) /
100) : ((1 - Number(item.coupon_value)) * data.goods.price)) 100) : ((1 - Number(item.coupon_value)) * data.goods.price))
} else { } else {
item['price2'] = 10000000 item['price2'] = 10000000
@ -1043,7 +1055,8 @@ async function onSelect(items, index) {
if (list.length != 0) { if (list.length != 0) {
let listData = list.map(cell => { let listData = list.map(cell => {
return { return {
image: cell == 'weixin' ? '/static/image/recharge/wxpay.png' : '/static/image/recharge/alipay.png', image: cell == 'weixin' ? '/static/image/recharge/wxpay.png' :
'/static/image/recharge/alipay.png',
name: cell == 'weixin' ? '微信支付' : '支付宝支付', name: cell == 'weixin' ? '微信支付' : '支付宝支付',
type: cell == 'weixin' ? 'wxpay' : 'alipay' type: cell == 'weixin' ? 'wxpay' : 'alipay'
} }
@ -1076,22 +1089,22 @@ async function onSelect(items, index) {
] ]
} }
paymentMethod.value = data.payList[0].type paymentMethod.value = data.payList[0].type
setTimeout(function () { setTimeout(function() {
data.countdown = true data.countdown = true
}, 100); }, 100);
await setPrice(true) await setPrice(true)
await getActivity() await getActivity()
} }
/** /**
* @param {Object} value * @param {Object} value
* 选择支付方式 * 选择支付方式
*/ */
function onSelectPayment(value) { function onSelectPayment(value) {
paymentMethod.value = value paymentMethod.value = value
} }
function open() { function open() {
uni.setStorageSync('back_number', data.back_number + 1); uni.setStorageSync('back_number', data.back_number + 1);
// refuni-popup , type ['top','left','bottom','right','center'] // refuni-popup , type ['top','left','bottom','right','center']
@ -1135,12 +1148,12 @@ function open() {
coupon.value.open() coupon.value.open()
} }
} }
/** /**
* 随机生成通知列表 * 随机生成通知列表
*/ */
function generateNoticeList() { function generateNoticeList() {
noticeList.value = [] noticeList.value = []
for (let i = 0; i <= 10; i++) { for (let i = 0; i <= 10; i++) {
noticeList.value.push({ noticeList.value.push({
@ -1149,11 +1162,11 @@ function generateNoticeList() {
package: getRandomItem() package: getRandomItem()
}) })
} }
} }
/** /**
* 下单拉取支付 * 下单拉取支付
*/ */
async function activateVip(type = '') { async function activateVip(type = '') {
if (type == 'back') { if (type == 'back') {
proxy.$apiUserEvent('all', { proxy.$apiUserEvent('all', {
type: "click", type: "click",
@ -1187,7 +1200,7 @@ async function activateVip(type = '') {
coupon: data.active_id ? data.active_id : '', coupon: data.active_id ? data.active_id : '',
pay_type: paymentMethod.value == "wxpay" ? 'weixin' : "alipay", pay_type: paymentMethod.value == "wxpay" ? 'weixin' : "alipay",
"pay_source": paymentMethod.value == "alipay" && proxy.$system == 'iOS' ? "h5" : "app", "pay_source": paymentMethod.value == "alipay" && proxy.$system == 'iOS' ? "h5" : "app",
source: "uniapp", source: "uni_alipay",
}) })
@ -1229,13 +1242,13 @@ async function activateVip(type = '') {
uni.requestPayment({ uni.requestPayment({
provider: paymentMethod.value, provider: paymentMethod.value,
orderInfo: payData, // orderInfo: payData, //
success: function (resss) { success: function(resss) {
setTimeout(() => { setTimeout(() => {
uni.hideLoading(); uni.hideLoading();
}, 30000); }, 30000);
paymentResult(paymentRes.data.orderId, paymentMethod.value) paymentResult(paymentRes.data.orderId, paymentMethod.value)
}, },
fail: function (err) { fail: function(err) {
proxy.$apiUserEvent('all', { proxy.$apiUserEvent('all', {
type: "event", type: "event",
key: "pay_fail", key: "pay_fail",
@ -1276,11 +1289,11 @@ async function activateVip(type = '') {
setTimeout(() => { setTimeout(() => {
uni.hideLoading(); uni.hideLoading();
}, 10000); }, 10000);
} }
// //
async function paymentResult(orderId, paytype) { async function paymentResult(orderId, paytype) {
uni.hideLoading(); uni.hideLoading();
uni.showLoading({ uni.showLoading({
title: '会员发放排队中,正在实时向服务器索要,请耐心等待。', title: '会员发放排队中,正在实时向服务器索要,请耐心等待。',
@ -1386,19 +1399,19 @@ async function paymentResult(orderId, paytype) {
// //
poll(); poll();
} }
// //
function getRandomItem() { function getRandomItem() {
const list = ['月度会员', '季度会员', '年度会员']; const list = ['月度会员', '季度会员', '年度会员'];
const randomIndex = Math.floor(Math.random() * list.length); const randomIndex = Math.floor(Math.random() * list.length);
return list[randomIndex]; return list[randomIndex];
} }
/** /**
* 随机生成时间提示语 * 随机生成时间提示语
*/ */
function generateNaturalTimeAgo() { function generateNaturalTimeAgo() {
const weights = [{ const weights = [{
range: [1, 30], range: [1, 30],
weight: 30, weight: 30,
@ -1465,12 +1478,12 @@ function generateNaturalTimeAgo() {
const amount = Math.floor(Math.random() * (max - min + 1)) + min; const amount = Math.floor(Math.random() * (max - min + 1)) + min;
return `${amount}${selected.unit}`; return `${amount}${selected.unit}`;
} }
/** /**
* 随机生成电话号码 * 随机生成电话号码
*/ */
function generateMaskedPhoneNumber() { function generateMaskedPhoneNumber() {
// //
const prefixes = [ const prefixes = [
'130', '131', '132', '133', '134', '135', '136', '137', '138', '139', '130', '131', '132', '133', '134', '135', '136', '137', '138', '139',
@ -1493,13 +1506,13 @@ function generateMaskedPhoneNumber() {
// 43 + **** + 4 // 43 + **** + 4
return fullNumber.replace(/(\d{3})(\d{4})(\d{4})/, '$1****$3'); return fullNumber.replace(/(\d{3})(\d{4})(\d{4})/, '$1****$3');
} }
/** /**
* 返回 * 返回
*/ */
function back() { function back() {
proxy.$apiUserEvent('all', { proxy.$apiUserEvent('all', {
type: "click", type: "click",
key: "recharge_dialog_cancel", key: "recharge_dialog_cancel",
@ -1515,20 +1528,20 @@ function back() {
} }
}) })
uni.navigateBack(); uni.navigateBack();
} }
function Complete() { function Complete() {
data.coupon = false data.coupon = false
console.log("播放完成"); console.log("播放完成");
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
* { * {
box-sizing: content-box; box-sizing: content-box;
} }
.couponBox { .couponBox {
width: 375px; width: 375px;
height: 450px; height: 450px;
position: relative; position: relative;
@ -1639,18 +1652,18 @@ function Complete() {
top: -145px; top: -145px;
z-index: 3; z-index: 3;
} }
} }
.couponButton { .couponButton {
position: relative; position: relative;
margin-top: 37px; margin-top: 37px;
width: 305px; width: 305px;
height: 86px; height: 86px;
margin-left: calc(50% - 152.5px); margin-left: calc(50% - 152.5px);
z-index: 4 !important; z-index: 4 !important;
} }
.page-container { .page-container {
background-color: #F7F7F7; background-color: #F7F7F7;
padding-bottom: 240rpx; padding-bottom: 240rpx;
padding-bottom: calc(240rpx + constant(safe-area-inset-bottom)) !important; padding-bottom: calc(240rpx + constant(safe-area-inset-bottom)) !important;
@ -1816,9 +1829,9 @@ function Complete() {
} }
@keyframes vertical-scroll { @keyframes vertical-scroll {
from { from {
transform: translateY(100%); transform: translateY(100%);
} }
@ -1826,9 +1839,9 @@ function Complete() {
to { to {
transform: translateY(-100%); transform: translateY(-100%);
} }
} }
.footer-container { .footer-container {
position: fixed; position: fixed;
left: 0; left: 0;
right: 0; right: 0;
@ -1932,9 +1945,9 @@ function Complete() {
width: 32%; width: 32%;
} }
} }
} }
.dialog-container { .dialog-container {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
width: 80vw; width: 80vw;
@ -2059,16 +2072,16 @@ function Complete() {
} }
} }
} }
.back { .back {
position: fixed; position: fixed;
top: 100rpx; top: 100rpx;
left: 36rpx; left: 36rpx;
z-index: 1; z-index: 1;
} }
.uni-margin-wrap::after { .uni-margin-wrap::after {
// position: absolute; // position: absolute;
// content: ''; // content: '';
// left: 0; // left: 0;
@ -2077,9 +2090,9 @@ function Complete() {
// height: 18px; // height: 18px;
// background-color: #f7f7f7; // background-color: #f7f7f7;
// border-radius: 16px 16px 0px 0px; // border-radius: 16px 16px 0px 0px;
} }
.uni-margin-wrap { .uni-margin-wrap {
// position: relative; // position: relative;
height: auto; height: auto;
width: 100%; width: 100%;
@ -2133,11 +2146,11 @@ function Complete() {
padding: 0 100rpx; padding: 0 100rpx;
} }
} }
.placeholder { .placeholder {
// display: none; // display: none;
// position: relative; // position: relative;
// background-color: #f7f7f7; // background-color: #f7f7f7;
@ -2145,20 +2158,20 @@ function Complete() {
// border-radius: 1rem 1rem 0 0; // border-radius: 1rem 1rem 0 0;
// left: 0; // left: 0;
// bottom: 30rpx; // bottom: 30rpx;
} }
/* 由小到大缩放动画 */ /* 由小到大缩放动画 */
.animated-box { .animated-box {
animation: scaleIn 1s ease-out forwards; animation: scaleIn 1s ease-out forwards;
} }
/* 延迟动画 */ /* 延迟动画 */
.scale-in-delay { .scale-in-delay {
animation: scaleIn 0.5s ease-out 0.2s forwards; animation: scaleIn 0.5s ease-out 0.2s forwards;
} }
/* 动画关键帧定义 */ /* 动画关键帧定义 */
@keyframes scaleIn { @keyframes scaleIn {
0% { 0% {
transform: scale(0); transform: scale(0);
opacity: 0; opacity: 0;
@ -2172,17 +2185,17 @@ function Complete() {
transform: scale(1); transform: scale(1);
opacity: 1; opacity: 1;
} }
} }
.iosQuestion { .iosQuestion {
.titleBox { .titleBox {
.image { .image {
margin-top: 3px !important; margin-top: 3px !important;
} }
} }
} }
.question { .question {
margin: 24rpx 32rpx; margin: 24rpx 32rpx;
padding: 17px 13px; padding: 17px 13px;
background-color: #FFFFFF; background-color: #FFFFFF;
@ -2219,9 +2232,9 @@ function Complete() {
color: #AAAAAA; color: #AAAAAA;
} }
} }
} }
.myCouponList { .myCouponList {
margin: 24rpx 32rpx; margin: 24rpx 32rpx;
padding: 17px 13px; padding: 17px 13px;
@ -2289,9 +2302,9 @@ function Complete() {
} }
} }
} }
} }
.myCouponContainer { .myCouponContainer {
width: calc(100% - 52px); width: calc(100% - 52px);
height: 400px; height: 400px;
background-image: url('/static/image/recharge/myCouponContainerBg.png'); background-image: url('/static/image/recharge/myCouponContainerBg.png');
@ -2430,16 +2443,16 @@ function Complete() {
color: #fff; color: #fff;
font-size: 20px; font-size: 20px;
} }
} }
.white-flow { .white-flow {
background: linear-gradient(-45deg, transparent, transparent, transparent, transparent, transparent, transparent, transparent, rgba(255, 255, 255, 0.2), rgba(255, 255, 255, 0.2), transparent, transparent, transparent, transparent, transparent, transparent, transparent); background: linear-gradient(-45deg, transparent, transparent, transparent, transparent, transparent, transparent, transparent, rgba(255, 255, 255, 0.2), rgba(255, 255, 255, 0.2), transparent, transparent, transparent, transparent, transparent, transparent, transparent);
background-repeat: no-repeat; background-repeat: no-repeat;
background-size: 60% 100%; background-size: 60% 100%;
animation: flow 2s infinite linear; animation: flow 2s infinite linear;
} }
@keyframes flow { @keyframes flow {
0% { 0% {
background-position: -100% 0; background-position: -100% 0;
} }
@ -2447,25 +2460,25 @@ function Complete() {
100% { 100% {
background-position: 200% 0; background-position: 200% 0;
} }
} }
::v-deep .uni-countdown-day { ::v-deep .uni-countdown-day {
width: auto !important; width: auto !important;
color: #2A2617 !important; color: #2A2617 !important;
/* 例如,将文字颜色改为红色 */ /* 例如,将文字颜色改为红色 */
background-color: transparent !important; background-color: transparent !important;
margin-right: 0 !important; margin-right: 0 !important;
padding-right: 0 !important; padding-right: 0 !important;
} }
::v-deep .uni-countdown-splitor-day { ::v-deep .uni-countdown-splitor-day {
margin-left: 0 !important; margin-left: 0 !important;
} }
.yanhua { .yanhua {
position: fixed; position: fixed;
top: 170px; top: 170px;
left: 15px; left: 15px;
z-index: 999999; z-index: 999999;
} }
</style> </style>

View File

@ -147,7 +147,7 @@ const menuList = [{
icon: "huabei", icon: "huabei",
name: "花呗", name: "花呗",
isHot: false, isHot: false,
path: "" path: "/pages/ant-credit-pay/index"
}, },
] ]

Binary file not shown.

After

Width:  |  Height:  |  Size: 908 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 990 B

View File

@ -40,24 +40,8 @@ export const store = reactive({
}); });
// 定义操作方法 // 定义操作方法
export const useStore = () => { export const useStore = () => {
// 用户相关操作
const setUserInfo = (userInfo) => {
store.userInfo = userInfo;
};
const clearUserInfo = () => {
store.userInfo = null;
};
// 设置相关操作
const updateSettings = (settings) => {
store.settings = { ...store.settings, ...settings };
};
// 账单相关操作 // 账单相关操作
const addBill = (bill) => { const addBill = (bill) => {
store.billList.unshift(bill); store.billList.unshift(bill);
@ -114,23 +98,11 @@ export const useStore = () => {
{ deep: true } { deep: true }
); );
// 获取系统信息(从缓存读取)
const getSystemInfo = () => {
const cachedInfo = uni.getStorageSync('systemInfo')
if (cachedInfo) {
store.systemInfo = cachedInfo
}
};
return { return {
store, store,
setUserInfo,
clearUserInfo,
updateSettings,
addBill, addBill,
updateBill, updateBill,
deleteBill, deleteBill,
getBillList, getBillList
getSystemInfo
}; };
}; };

View File

@ -140,6 +140,22 @@ export const numberUtil = {
return number.toFixed(decimals); return number.toFixed(decimals);
}, },
/**
* 格式化金额添加千分位并保留两位小数
* @param {number|string} val - 金额
* @returns {string} 格式化后的金额字符串
*/
formatMoneyWithThousand(val) {
let num = Number(val);
if (isNaN(num)) {
return '0.00';
}
let str = num.toFixed(2);
let parts = str.split('.');
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',');
return parts.join('.');
},
/** /**
* 随机数生成 * 随机数生成
* @param {number} min - 最小值 * @param {number} min - 最小值