支付宝理财页面40%

This commit is contained in:
tangxinyue 2026-01-26 17:39:03 +08:00
parent 19ddea7165
commit 2147da46ac
36 changed files with 2657 additions and 1968 deletions

View File

@ -6,6 +6,7 @@ export default {
recentNativeData: 0 //
},
onLaunch: function (options) {
uni.setStorageSync('onNativeEventReceive', "no")
const startTime = Date.now()
console.log('App Launch', options)

View File

@ -272,6 +272,11 @@
justify-content: space-between;
}
.flex-justify-between {
display: flex;
justify-content: space-between;
}
.flex-align-center {
display: flex;
align-items: center;

View File

@ -4,8 +4,9 @@
<view class="item" v-for="(item, index) in tabList" :key="item.id"
:class="{ 'active': index === activeIndex }" @click="onTabChange(index)">
<view class="left">
<view class="triangle-concave-transparent ">
</view>
<!-- <view class="triangle-concave-transparent ">
</view> -->
<image src="/static/image/recharge/tabLine.png" mode=""></image>
</view>
<view class="box" v-show="index != activeIndex">
{{ item.label }}
@ -17,8 +18,9 @@
<image class="vipImage" v-else src="/static/image/template/close.png" mode=""></image>
</view>
<view class="right">
<view class="triangle-concave-transparent leftBox">
</view>
<image src="/static/image/recharge/tabLine.png" mode=""></image>
<!-- <view class="triangle-concave-transparent leftBox">
</view> -->
</view>
</view>
</view>
@ -492,7 +494,7 @@ export default {
<style lang="scss" scoped>
.container {
margin:0 20px 20px 20px;
margin:0 32rpx 32rpx 32rpx;
overflow: hidden;
}
@ -508,7 +510,7 @@ export default {
width: 100%;
height: 42px;
// background-color: #;
border-radius: 14px 14px 0 0;
border-radius: 12px 12px 0 0;
position: relative;
line-height: 47px;
text-align: center;
@ -538,22 +540,27 @@ export default {
}
.left,.right{
image{
width: 19px;
height: 30px;
}
}
.left {
display: none;
position: absolute;
bottom: 0;
left: -25px;
top: 12px;
left: -19px;
// transition: all 0.3s ease-in-out;
transform-origin: right center;
// transform: scaleX(0);
// transform-origin: right center;
transform: scaleX(-1);
}
.right {
display: none;
position: absolute;
bottom: 0;
right: -25px;
top: 12px;
right: -19px;
// transition: all 0.3s ease-in-out;
transform-origin: left center;
// transform: scaleX(0);

View File

@ -2,7 +2,7 @@
<view style="width: 100%;" :style="{ height: `${data.statusBarHeight + 44}px` }"></view>
<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">
<view style="width: 100%;height: 88rpx;" @click="openPopup">
<slot>
<uni-nav-bar backgroundColor="#00000000" class="nav-bar" :border="false" :title="title" v-bind="$attrs"
v-on="$attrs">

View File

@ -27,7 +27,7 @@ export function createApp() {
const systemInfo = uni.getStorageSync('systemInfo') || {}
app.config.globalProperties.$system = systemInfo.platform == 'ios' ? 'iOS' : 'Android'
app.config.globalProperties.$systemInfo = systemInfo
uni.setStorageSync('version', '1.0.0.sp2')
uni.setStorageSync('version', '1.0.0.sp3')
app.config.globalProperties.$version = uni.getStorageSync('version')
app.use(globalMethods);

View File

@ -262,11 +262,11 @@ const onConsumptionDateChange = (e) => {
}
onLoad((option) => {
//
//
proxy.$apiUserEvent('all', {
type: 'click',
key: 'huabei',
value: "花呗"
key: 'huabei_overdue',
value: "花呗逾期"
})
console.log(option)
//

View File

@ -241,7 +241,8 @@ import {
reactive,
toRefs,
ref,
nextTick
nextTick,
getCurrentInstance
} from 'vue'
import {
onLoad,
@ -257,6 +258,9 @@ const {
updateBill
} = useStore()
const instance = getCurrentInstance();
const { proxy } = instance;
const billManagementPopupRef = ref(null)
const buttonGroup = [{
@ -326,6 +330,12 @@ onShow(() => {
})
onLoad((option) => {
//
proxy.$apiUserEvent('all', {
type: 'click',
key: 'bill_details',
value: "账单详情"
})
console.log(option)
if (option.id) {
data.billId = option.id

View File

@ -260,57 +260,76 @@
<script setup>
import customTab from "@/components/custom-tab/custom-tab.vue"
import countUp from "@/components/countUp/countUp.vue"
import { postJson } from "@/utils/requests.js"
import { ref, reactive, getCurrentInstance, watch, nextTick, toRefs } from "vue";
import { onLoad, onShow, onReady, onPullDownRefresh, onReachBottom, onBackPress, onUnload } from "@dcloudio/uni-app";
const { appContext, proxy } = getCurrentInstance();
const popup = ref();
const coupon = ref();
const couponBox = ref();
const myCoupon = ref();
const dialogVipBenefits = [{
import customTab from "@/components/custom-tab/custom-tab.vue"
import countUp from "@/components/countUp/countUp.vue"
import {
postJson
} from "@/utils/requests.js"
import {
ref,
reactive,
getCurrentInstance,
watch,
nextTick,
toRefs
} from "vue";
import {
onLoad,
onShow,
onReady,
onPullDownRefresh,
onReachBottom,
onBackPress,
onUnload
} from "@dcloudio/uni-app";
const {
appContext,
proxy
} = getCurrentInstance();
const popup = ref();
const coupon = ref();
const couponBox = ref();
const myCoupon = ref();
const dialogVipBenefits = [{
name: "模拟微信",
url: "/static/image/recharge/moniweixinDialog.png"
},
{
},
{
name: "无广告",
url: "/static/image/recharge/wuguanggaoDialog.png"
},
{
},
{
name: "无水印",
url: "/static/image/recharge/wushuiyinDialog.png"
},
{
},
{
name: "专属客服",
url: "/static/image/recharge/zhuanshukefuDialog.png"
}
]
}
]
//
const packageList = [{
//
const packageList = [{
name: "连续包月",
delPrice: "89",
price: "29",
lifespan: "一月"
},
{
},
{
name: "连续包季",
delPrice: "189",
price: "98",
lifespan: "一季"
},
{
},
{
name: "连续包年",
delPrice: "365",
price: "198",
lifespan: "一年"
}
]
}
]
const data = reactive({
const data = reactive({
scrollLeft: 0,
active_id: 0,
active_ids: 0,
@ -414,22 +433,29 @@ const data = reactive({
//
isProcessingClick: false,
banner: '/static/image/recharge/banner1.png',
})
})
let { buttonText, selected, benefitList, noticeList, commentList, paymentMethod } = toRefs(data)
let {
buttonText,
selected,
benefitList,
noticeList,
commentList,
paymentMethod
} = toRefs(data)
/**
/**
* 返回监听
*/
onBackPress((e) => {
onBackPress((e) => {
if (e.from == 'backbutton' && data.appUser.vip == 1) {
open()
return true; //
}
})
})
onLoad(async () => {
onLoad(async () => {
const config = uni.getStorageSync('config').config
const themeConfig = config?.['client.uniapp.theme']
if (themeConfig?.enable) {
@ -498,12 +524,15 @@ onLoad(async () => {
item['isStatus'] = true
}
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 = [
...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),
...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)
]
data.myActivity = deduplicateKeepLast(data.myActivity)
@ -534,6 +563,8 @@ onLoad(async () => {
data.isBack = false
}
uni.hideLoading();
if (uni.getStorageSync('onNativeEventReceive') != 'ok') {
uni.setStorageSync('onNativeEventReceive', 'ok')
//宿
uni.onNativeEventReceive((event, data) => {
if (event) {
@ -562,15 +593,17 @@ onLoad(async () => {
console.log('接收到宿主App消息-' + event + '' + data);
}
})
})
}
onShow(async () => {
})
})
onUnload(() => {
uni.offNativeEventReceive()
})
onReady(() => {
onShow(async () => {
})
onUnload(() => {
// uni.offNativeEventReceive()
})
onReady(() => {
try {
if (plus.os.name === 'Android') {
let color = plus.android.newObject("android.graphics.Color");
@ -585,7 +618,7 @@ onReady(() => {
}
})
console.log("状态栏设置完毕!");
setTimeout(function () {
setTimeout(function() {
uni.setNavigationBarColor({
backgroundColor: '#fff',
animation: { //
@ -594,18 +627,18 @@ onReady(() => {
}
})
}, 200);
setTimeout(function () {
setTimeout(function() {
plus.navigator.setStatusBarStyle("light");
}, 200);
}
} catch (error) {
//TODO handle the exception
}
})
})
function isToday(inputTime) {
function isToday(inputTime) {
//
const today = new Date();
today.setHours(0, 0, 0, 0);
@ -618,9 +651,9 @@ function isToday(inputTime) {
//
return inputTimestamp === todayTimestamp;
}
}
function calculateTimeRemaining(targetTime) {
function calculateTimeRemaining(targetTime) {
//
const target = new Date(targetTime).getTime();
const now = new Date().getTime();
@ -655,9 +688,9 @@ function calculateTimeRemaining(targetTime) {
minutes: minutes,
seconds: seconds
};
}
}
function activeClick(status) {
function activeClick(status) {
myCoupon.value.close()
if (status && data.active_ids > 0) {
let item = data.activeitems
@ -674,14 +707,14 @@ function activeClick(status) {
setPrice(true)
}, 1000);
}
}
}
function setActiveId(item) {
function setActiveId(item) {
data.active_ids = item.id
data.activeitems = item
}
}
function setPrice(status) {
function setPrice(status) {
console.log("setPrice")
if (data.incrementTimer) {
clearInterval(data.incrementTimer);
@ -702,10 +735,12 @@ function setPrice(status) {
origin_price = Number(data.goods.origin_price)
coupon = origin_price - price
} 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))
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))))
}
data.coupon = proxy.$toFiexd(coupon, 0)
@ -761,9 +796,9 @@ function setPrice(status) {
console.log("最后", data.price)
}
/* 获取我的优惠券 */
async function getActivity() {
}
/* 获取我的优惠券 */
async function getActivity() {
let activity = await proxy.$requestPromise({
url: 'api/activity/coupon',
method: "GET",
@ -786,15 +821,18 @@ async function getActivity() {
item.expire_time = item.expire_time.replace('-', '.').replace('-', '.').substring(0, 10)
})
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)),
...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)
]
data.myActivity = deduplicateKeepLast(data.myActivity)
}
}
function deduplicateKeepLast(arr, idKey = 'id') {
}
function deduplicateKeepLast(arr, idKey = 'id') {
const map = new Map();
arr.forEach(item => {
@ -803,10 +841,10 @@ function deduplicateKeepLast(arr, idKey = 'id') {
});
return Array.from(map.values());
}
}
/* 领取优惠券 */
async function submitActivity() {
/* 领取优惠券 */
async function submitActivity() {
console.log("activity_id");
let activity_id = ''
data.activity.forEach(item => {
@ -816,7 +854,7 @@ async function submitActivity() {
if (activity_id != "") {
console.log("activity_id", activity_id);
let activityRes = await postJson('q', 'api/activity', {
activity_id: activity_id//activity_id+"="
activity_id: activity_id //activity_id+"="
})
console.log(activityRes)
if (activityRes.code == 0) {
@ -841,24 +879,24 @@ async function submitActivity() {
})
}
}
/**
}
/**
* @param {Object} item
* @param {Object} index
* 选择购买套餐
*/
/*
防抖
*/
const debouncedOnSelect = debounce((items, index) => {
/*
防抖
*/
const debouncedOnSelect = debounce((items, index) => {
onSelect(items, index);
}, 200, false);
}, 200, false);
function debounce(func, wait, immediate = true) {
function debounce(func, wait, immediate = true) {
let timeout;
return function (...args) {
return function(...args) {
const later = () => {
timeout = null;
if (!immediate) func(...args);
@ -870,8 +908,8 @@ function debounce(func, wait, immediate = true) {
if (callNow) func(...args);
};
}
async function onSelect(items, index) {
}
async function onSelect(items, index) {
data.active_id = 0
data.activeCoupon = {}
data.active_ids = 0
@ -883,8 +921,10 @@ async function onSelect(items, index) {
let defaultCoupon = data.myActivity.filter(item => item.activity_id == data.goods.default_activity)
if (defaultCoupon.length > 0) {
defaultCoupon.forEach(item => {
if ((data.goods.price >= (Number(item.threshold) / 100) || item.threshold == '') && item.isStatus) {
item['price2'] = data.goods.price - (item.coupon_type_name != '折扣券' ? (Number(item.coupon_value) /
if ((data.goods.price >= (Number(item.threshold) / 100) || item.threshold == '') && item
.isStatus) {
item['price2'] = data.goods.price - (item.coupon_type_name != '折扣券' ? (Number(item
.coupon_value) /
100) : ((1 - Number(item.coupon_value)) * data.goods.price))
} else {
item['price2'] = 10000000
@ -906,8 +946,10 @@ async function onSelect(items, index) {
if (id == 0 && data.goods.default_activity != '') {
try {
data.myActivity.forEach(item => {
if ((data.goods.price >= (Number(item.threshold) / 100) || item.threshold == '') && item.isStatus) {
item['price2'] = data.goods.price - (item.coupon_type_name != '折扣券' ? (Number(item.coupon_value) /
if ((data.goods.price >= (Number(item.threshold) / 100) || item.threshold == '') &&
item.isStatus) {
item['price2'] = data.goods.price - (item.coupon_type_name != '折扣券' ? (Number(item
.coupon_value) /
100) : ((1 - Number(item.coupon_value)) * data.goods.price))
} else {
item['price2'] = 10000000
@ -940,7 +982,8 @@ async function onSelect(items, index) {
if (list.length != 0) {
let listData = list.map(cell => {
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' ? '微信支付' : '支付宝支付',
type: cell == 'weixin' ? 'wxpay' : 'alipay'
}
@ -973,22 +1016,22 @@ async function onSelect(items, index) {
]
}
paymentMethod.value = data.payList[0].type
setTimeout(function () {
setTimeout(function() {
data.countdown = true
}, 100);
await setPrice(true)
await getActivity()
}
/**
}
/**
* @param {Object} value
* 选择支付方式
*/
function onSelectPayment(value) {
function onSelectPayment(value) {
paymentMethod.value = value
}
}
function open() {
function open() {
uni.setStorageSync('back_number', data.back_number + 1);
// refuni-popup , type ['top','left','bottom','right','center']
@ -1018,12 +1061,12 @@ function open() {
coupon.value.open()
}
}
}
/**
/**
* 随机生成通知列表
*/
function generateNoticeList() {
function generateNoticeList() {
noticeList.value = []
for (let i = 0; i <= 10; i++) {
noticeList.value.push({
@ -1032,11 +1075,11 @@ function generateNoticeList() {
package: getRandomItem()
})
}
}
/**
}
/**
* 下单拉取支付
*/
async function activateVip(type = '') {
async function activateVip(type = '') {
if (type == 'back') {
proxy.$apiUserEvent('all', {
type: "click",
@ -1111,13 +1154,13 @@ async function activateVip(type = '') {
uni.requestPayment({
provider: paymentMethod.value,
orderInfo: payData, //
success: function (resss) {
success: function(resss) {
setTimeout(() => {
uni.hideLoading();
}, 30000);
paymentResult(paymentRes.data.orderId, paymentMethod.value)
},
fail: function (err) {
fail: function(err) {
proxy.$apiUserEvent('all', {
type: "event",
key: "pay_fail",
@ -1158,11 +1201,11 @@ async function activateVip(type = '') {
setTimeout(() => {
uni.hideLoading();
}, 10000);
}
}
//
async function paymentResult(orderId, paytype) {
//
async function paymentResult(orderId, paytype) {
uni.hideLoading();
uni.showLoading({
title: '会员发放排队中,正在实时向服务器索要,请耐心等待。',
@ -1268,19 +1311,19 @@ async function paymentResult(orderId, paytype) {
//
poll();
}
}
//
function getRandomItem() {
//
function getRandomItem() {
const list = ['月度会员', '季度会员', '年度会员'];
const randomIndex = Math.floor(Math.random() * list.length);
return list[randomIndex];
}
}
/**
/**
* 随机生成时间提示语
*/
function generateNaturalTimeAgo() {
function generateNaturalTimeAgo() {
const weights = [{
range: [1, 30],
weight: 30,
@ -1347,12 +1390,12 @@ function generateNaturalTimeAgo() {
const amount = Math.floor(Math.random() * (max - min + 1)) + min;
return `${amount}${selected.unit}`;
}
}
/**
/**
* 随机生成电话号码
*/
function generateMaskedPhoneNumber() {
function generateMaskedPhoneNumber() {
//
const prefixes = [
'130', '131', '132', '133', '134', '135', '136', '137', '138', '139',
@ -1375,13 +1418,13 @@ function generateMaskedPhoneNumber() {
// 43 + **** + 4
return fullNumber.replace(/(\d{3})(\d{4})(\d{4})/, '$1****$3');
}
}
/**
/**
* 返回
*/
function back() {
function back() {
proxy.$apiUserEvent('all', {
type: "click",
key: "recharge_dialog_cancel",
@ -1397,13 +1440,14 @@ function back() {
}
})
uni.navigateBack();
}
}
function Complete() {
function Complete() {
data.coupon = false
console.log("播放完成");
}
function shouldBeTrue(obj) {
}
function shouldBeTrue(obj) {
// 1: features true
if (!('features' in obj)) {
return false;
@ -1421,15 +1465,15 @@ function shouldBeTrue(obj) {
// 4: features alipay false
return true;
}
}
</script>
<style lang="scss" scoped>
* {
* {
box-sizing: content-box;
}
}
.couponBox {
.couponBox {
width: 375px;
height: 450px;
position: relative;
@ -1540,18 +1584,18 @@ function shouldBeTrue(obj) {
top: -145px;
z-index: 3;
}
}
}
.couponButton {
.couponButton {
position: relative;
margin-top: 37px;
width: 305px;
height: 86px;
margin-left: calc(50% - 152.5px);
z-index: 4 !important;
}
}
.page-container {
.page-container {
background-color: #F7F7F7;
padding-bottom: 240rpx;
padding-bottom: calc(240rpx + constant(safe-area-inset-bottom)) !important;
@ -1714,9 +1758,9 @@ function shouldBeTrue(obj) {
}
}
@keyframes vertical-scroll {
@keyframes vertical-scroll {
from {
transform: translateY(100%);
}
@ -1724,9 +1768,9 @@ function shouldBeTrue(obj) {
to {
transform: translateY(-100%);
}
}
}
.footer-container {
.footer-container {
position: fixed;
left: 0;
right: 0;
@ -1830,9 +1874,9 @@ function shouldBeTrue(obj) {
width: 32%;
}
}
}
}
.dialog-container {
.dialog-container {
display: flex;
flex-direction: column;
width: 80vw;
@ -1957,16 +2001,16 @@ function shouldBeTrue(obj) {
}
}
}
}
.back {
.back {
position: fixed;
top: 100rpx;
left: 36rpx;
z-index: 1;
}
}
.uni-margin-wrap::after {
.uni-margin-wrap::after {
// position: absolute;
// content: '';
// left: 0;
@ -1975,9 +2019,9 @@ function shouldBeTrue(obj) {
// height: 18px;
// background-color: #f7f7f7;
// border-radius: 16px 16px 0px 0px;
}
}
.uni-margin-wrap {
.uni-margin-wrap {
// position: relative;
height: auto;
width: 100%;
@ -2031,11 +2075,11 @@ function shouldBeTrue(obj) {
padding: 0 100rpx;
}
}
}
.placeholder {
.placeholder {
// display: none;
// position: relative;
// background-color: #f7f7f7;
@ -2043,20 +2087,20 @@ function shouldBeTrue(obj) {
// border-radius: 1rem 1rem 0 0;
// left: 0;
// bottom: 30rpx;
}
}
/* 由小到大缩放动画 */
.animated-box {
/* 由小到大缩放动画 */
.animated-box {
animation: scaleIn 1s ease-out forwards;
}
}
/* 延迟动画 */
.scale-in-delay {
/* 延迟动画 */
.scale-in-delay {
animation: scaleIn 0.5s ease-out 0.2s forwards;
}
}
/* 动画关键帧定义 */
@keyframes scaleIn {
/* 动画关键帧定义 */
@keyframes scaleIn {
0% {
transform: scale(0);
opacity: 0;
@ -2070,17 +2114,17 @@ function shouldBeTrue(obj) {
transform: scale(1);
opacity: 1;
}
}
}
.iosQuestion {
.iosQuestion {
.titleBox {
.image {
margin-top: 3px !important;
}
}
}
}
.question {
.question {
margin: 24rpx 32rpx;
padding: 17px 13px;
background-color: #FFFFFF;
@ -2117,9 +2161,9 @@ function shouldBeTrue(obj) {
color: #AAAAAA;
}
}
}
}
.myCouponList {
.myCouponList {
margin: 24rpx 32rpx;
padding: 17px 13px;
@ -2187,9 +2231,9 @@ function shouldBeTrue(obj) {
}
}
}
}
}
.myCouponContainer {
.myCouponContainer {
width: calc(100% - 52px);
height: 400px;
background-image: url('/static/image/recharge/myCouponContainerBg.png');
@ -2327,16 +2371,16 @@ function shouldBeTrue(obj) {
color: #fff;
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-repeat: no-repeat;
background-size: 60% 100%;
animation: flow 2s infinite linear;
}
}
@keyframes flow {
@keyframes flow {
0% {
background-position: -100% 0;
}
@ -2344,25 +2388,25 @@ function shouldBeTrue(obj) {
100% {
background-position: 200% 0;
}
}
}
::v-deep .uni-countdown-day {
::v-deep .uni-countdown-day {
width: auto !important;
color: #2A2617 !important;
/* 例如,将文字颜色改为红色 */
background-color: transparent !important;
margin-right: 0 !important;
padding-right: 0 !important;
}
}
::v-deep .uni-countdown-splitor-day {
::v-deep .uni-countdown-splitor-day {
margin-left: 0 !important;
}
}
.yanhua {
.yanhua {
position: fixed;
top: 170px;
left: 15px;
z-index: 999999;
}
}
</style>

View File

@ -1,6 +1,15 @@
<template>
<view class="container">
<view class="main-info-container">
<!-- 水印 -->
<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>
<view class="container flex flex-column" @touchstart="handleTouchStart" @touchmove.stop.prevent="handleTouchMove"
@touchend="handleTouchEnd">
<view class="main-info-container" :class="{ 'open': isOpen }"
:style="{ 'padding-bottom': `${cardArrowHeight}px` }">
<!-- 导航栏 placeholder -->
<NavBar bgColor="transparent">
<view class="nav-bar flex-align-center h100">
@ -36,10 +45,13 @@
</view>
<view class="total-money flex-align-center" style="margin-top: 10px;">
<view class="total-money-value flex-align-center">
<text>{{ financeInfo.totalMoney }}</text>
<text class="alipay-font">{{ numberUtil.formatMoneyWithThousand(totalMoney) }}</text>
</view>
<view class="total-money-value flex-align-center">
<text>{{ financeInfo.yesterdayIncome }}</text>
<text class="alipay-font">{{ yesterdayIncome > 0 ? "+" +
numberUtil.formatMoneyWithThousand(yesterdayIncome) :
numberUtil.formatMoneyWithThousand(yesterdayIncome)
}}</text>
</view>
</view>
</view>
@ -48,14 +60,55 @@
<text>家庭保障</text>
</view>
<view class=" flex-align-end" style="margin-top: 10px;">
<text class="value">{{ financeInfo.familyProtection }}</text>
<text class="value alipay-font">{{ familyProtection }}</text>
<text class="text"></text>
</view>
</view>
</view>
<view class="data-box">
<view v-for="item in myAssets" :key="item.title">
<view v-if="item.title" class="title second-color">{{ item.title }}</view>
<view class="group-data flex-justify-between">
<template v-for="subItem in item.items" :key="subItem.label">
<view v-if="financeInfo[item.key][subItem.key].labelSub"
class="item flex-align-center flex-justify-between">
<view class="flex-align-center">
<text class="label primary-color">{{ subItem.label }}</text>
<text v-if="financeInfo[item.key][subItem.key].type == 'text'"
class="label-sub second-color">
{{ formatTextWithNumber(financeInfo[item.key][subItem.key].labelSub) }}
</text>
<text v-else class="label-sub second-color">
{{
numberUtil.formatMoneyWithThousand(financeInfo[item.key][subItem.key].labelSub)
}}</text>
</view>
<text v-if="financeInfo[item.key][subItem.key].value" class="value primary-color">{{
financeInfo[item.key][subItem.key].value > 0 ? "+" +
numberUtil.formatMoneyWithThousand(financeInfo[item.key][subItem.key].value) :
numberUtil.formatMoneyWithThousand(financeInfo[item.key][subItem.key].value)
}}</text>
</view>
</template>
<view v-if="item.groupId == '1'" class="item flex-align-center flex-justify-between">
<view class="flex-align-center">
<text class="label primary-color">更多资产服务</text>
</view>
<text class="value primary-color">去看看</text>
</view>
</view>
</view>
</view>
</view>
<view class="image-service-box flex-column"
:style="{ top: topHeight + 'px', 'min-height': `calc(100vh - ${imageCardBoxtopHeight}px)` }">
<view class="card-arrow-box">
<view class="arrow-box">
<image class="arrow-icon" src="/static/image/finance-management/arrow-down.png"></image>
<image @click="data.isOpen = !data.isOpen" class="arrow-icon"
:src="`/static/image/finance-management/arrow-${isOpen ? 'up' : 'down'}.png`">
</image>
</view>
<view class="card-box flex-column">
@ -63,14 +116,18 @@
<view class="wealth-card-box flex">
<!-- 占位图片设置为透明 -->
<image class="wealth-card-opacity0" src="/static/image/finance-management/v1/bg.png"
mode="widthFix" />
mode="widthFix" @load="updateTopHeight" />
<!-- 背景图片高度自适应 -->
<image class="wealth-card" src="/static/image/finance-management/v1/bg.png" mode="widthFix" />
<image class="wealth-card"
:src="`/static/image/finance-management/${financeInfo.vipLevel}/bg.png`" mode="widthFix" />
<view class="card-info">
<image class="logo" src="/static/image/finance-management/v1/logo.png" mode="scaleToFill" />
<image class="logo"
:src="`/static/image/finance-management/${financeInfo.vipLevel}/logo.png`"
mode="scaleToFill" />
<view class="name-box flex-align-center">
<image class="card-holder-icon" src="/static/image/finance-management/v1/card-holder.png"
<image class="card-holder-icon"
:src="`/static/image/finance-management/${financeInfo.vipLevel}/card-holder.png`"
mode="scaleToFill" />
<view class="card-holder-name sacramento-font">{{ financeInfo.cardHolderName }}</view>
</view>
@ -78,24 +135,54 @@
</view>
<view class="enjoy-benefits flex-align-center">
<text class="benefits-text">{{ financeInfo.benefitsText }}</text>
<image class="arrow-icon" src="/static/image/finance-management/v1/arrow.png"></image>
<image class="arrow-icon"
:src="`/static/image/finance-management/${financeInfo.vipLevel}/arrow.png`"></image>
</view>
</view>
<view class="content-box">
<view class="service-icons">
<view class="service-icon" v-for="item in serviceIcons" :key="item.name">
<image class="icon"
:src="`/static/image/finance-management/service-icon/${item.icon}.png`"
mode="scaleToFill" />
<text class="name">{{ item.name }}</text>
</view>
</view>
</view>
</view>
</view>
<view class="content flex-1 flex-align-center flex-justify-center">
<view class="flex-align-center flex-column">
<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>
</view>
</view>
<view class="content-box"></view>
</view>
</view>
<view class="content">
<view class="bottom-box"
:class="`navigation-menu-${financeInfo.navigationMenuStyle}`, { 'ios-bottom-box': $system == 'iOS' }">
<view class="bottom-item" v-for="item in navigationMenu" :key="item.name">
<image
:src="`/static/image/finance-management/navigation-menu/${financeInfo.navigationMenuStyle}/${item.icon}.png`">
</image>
<text>{{ item.name }}</text>
</view>
</view>
</view>
</template>
<script setup>
import NavBar from '@/components/nav-bar/nav-bar.vue'
import { ref, toRefs, reactive, onMounted } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import { ref, toRefs, reactive, onMounted, watch, computed } from 'vue'
import { onLoad, onReady } from '@dcloudio/uni-app'
import { serviceIcons, navigationMenu, myAssets } from '@/static/json/fortune.json'
import { numberUtil } from '@/utils/common.js'
onLoad(() => {
//
@ -106,18 +193,245 @@ onLoad(() => {
// })
})
const data = reactive({
financeInfo: {
totalMoney: 100000000,
yesterdayIncome: 22222,
familyProtection: 1,
benefitsText: '尊享礼遇18000元/年',
cardHolderName: 'LiXing',
vipLevel: 1,
}
onReady(() => {
statusBarHeight.value = uni.getSystemInfoSync().statusBarHeight;
uni.createSelectorQuery().select('.total-money-box').boundingClientRect((data) => {
console.log("total-money-box height: " + (data ? data.height : "null"));
topHeight.value = data ? data.height + 44 + statusBarHeight.value : 44 + statusBarHeight.value;
imageCardBoxtopHeight.value = data ? data.height + 44 + statusBarHeight.value : 44 + statusBarHeight.value;
}).exec()
})
let { financeInfo } = toRefs(data)
const updateTopHeight = () => {
setTimeout(() => {
uni.createSelectorQuery().select('.card-arrow-box').boundingClientRect((data) => {
console.log("card-arrow-box height: " + (data ? data.height : "null"));
cardArrowHeight.value = data ? data.height - 20 : 0;
}).exec()
}, 500)
}
//
const totalMoney = computed(() => {
let totalMoney = 0;
for (const key in financeInfo.value.fortune) {
if (!Object.hasOwn(financeInfo.value.fortune, key)) continue;
const element = financeInfo.value.fortune[key];
totalMoney += Number(element.labelSub)
}
return totalMoney
})
//
const yesterdayIncome = computed(() => {
let yesterdayIncome = 0;
for (const key in financeInfo.value.fortune) {
if (!Object.hasOwn(financeInfo.value.fortune, key)) continue;
const element = financeInfo.value.fortune[key];
yesterdayIncome += Number(element.value)
}
return yesterdayIncome
})
//
const familyProtection = computed(() => {
return parseInt(financeInfo.value.myAssets.baoxian.labelSub)
})
const data = reactive({
financeInfo: {
benefitsText: '尊享礼遇18000元/年',
cardHolderName: 'LiXing',
vipLevel: "v3",
navigationMenuStyle: "style-1",
fortune: {
yuebao: {
value: 3.53,
labelSub: "100000",
},
dingqi: {
value: 50,
labelSub: "100000",
},
jijin: {
value: 5000,
labelSub: "100000",
},
huangjin: {
value: -300,
labelSub: "100000",
},
yulingbao: {
value: 20,
labelSub: "100000",
}
},
myAssets: {
baoxian: {
labelSub: "3份保单保障中",
type: "text"
}
},
myQuota: {
huabei: {
labelSub: "可用100000",
type: "text"
},
jubei: {
labelSub: "可用100000",
type: "text"
},
beizhi: {
labelSub: "可用100000",
type: "text"
},
wangshangdai: {
labelSub: "预计可借100000",
type: "text"
}
}
},
topHeight: 0,
statusBarHeight: 0,
cardArrowHeight: 0,
imageCardBoxtopHeight: 0,
isOpen: false
})
let { financeInfo, topHeight, statusBarHeight, cardArrowHeight, imageCardBoxtopHeight, isOpen } = toRefs(data)
const formatTextWithNumber = (str) => {
if (!str) return '';
return str.replace(/(\d+(\.\d+)?)/g, (match) => {
return match > 100 ? numberUtil.formatMoneyWithThousand(match) : match;
});
}
let startY = 0;
let startTop = 0;
let minTop = 0;
let maxTop = 0;
// isOpen topHeight
watch(() => isOpen.value, () => {
updateHeightByState();
})
const handleTouchStart = (e) => {
startY = e.touches[0].clientY;
startTop = topHeight.value;
//
if (!minTop || !maxTop) {
const systemInfo = uni.getSystemInfoSync();
const statusBar = systemInfo.statusBarHeight;
//
const query = uni.createSelectorQuery();
query.select('.total-money-box').boundingClientRect();
query.select('.main-info-container').boundingClientRect();
query.exec(([totalMoneyBox, mainInfoContainer]) => {
if (totalMoneyBox) {
// total-money-box + + -
minTop = totalMoneyBox.height + 44 + statusBar;
}
if (mainInfoContainer) {
// main-info-container -
// isOpen /
// /
//
// ~160px
// ~400px
// 使 'isOpen=true' maxTop
// data.height (main-info-container )
// main-info-container
// 'isOpen=true' topHeight main-info-container
// /使
// minTop topHeight
// maxTop topHeight
// **
// onReady/updateTopHeight
//
// DOM 使
// minTop 44 + statusBar + totalMoneyBoxHeight
// maxTop mainContainerHeight
}
// 使 handleTouchEnd
// handleTouchEnd init
});
}
}
const handleTouchMove = (e) => {
let currentY = e.touches[0].clientY;
let delta = currentY - startY;
let newTop = startTop + delta;
// 0
if (minTop === 0 && !isOpen.value) minTop = startTop;
if (maxTop === 0 && isOpen.value) maxTop = startTop;
//
if (minTop && maxTop) {
if (newTop < minTop) newTop = minTop;
if (newTop > maxTop) newTop = maxTop;
}
//
topHeight.value = newTop;
}
const updateHeightByState = () => {
statusBarHeight.value = uni.getSystemInfoSync().statusBarHeight;
if (isOpen.value) {
// main-info-container
uni.createSelectorQuery().select('.main-info-container').boundingClientRect((data) => {
if (data) {
const targetH = data.height - cardArrowHeight.value;
topHeight.value = targetH;
maxTop = targetH; // maxTop
}
}).exec()
} else {
// total-money-box
uni.createSelectorQuery().select('.total-money-box').boundingClientRect((data) => {
if (data) {
const targetH = data.height + 44 + statusBarHeight.value;
topHeight.value = targetH;
minTop = targetH; // minTop
}
}).exec()
}
}
const handleTouchEnd = (e) => {
let endY = e.changedTouches[0].clientY;
let diff = endY - startY;
let targetState = isOpen.value;
//
if (diff > 50) {
targetState = true;
} else if (diff < -50) {
targetState = false;
}
// watch /
if (targetState !== isOpen.value) {
isOpen.value = targetState;
} else {
//
updateHeightByState();
}
}
</script>
@ -127,13 +441,12 @@ let { financeInfo } = toRefs(data)
<style lang="less" scoped>
.container {
height: 100vh;
background-color: #f5f5f5;
background-color: #ffffff;
overflow: hidden;
}
.main-info-container {
background: linear-gradient(191deg, #0B1028 5.48%, #0B1028 30.26%, #18336C 60.18%, #18336C 100%);
background: linear-gradient(348deg, #0B1028 49%, #0B1028 76.26%, #18336C 86.18%, #18336C 100%);
.nav-bar {
padding: 20rpx;
@ -192,6 +505,7 @@ let { financeInfo } = toRefs(data)
.total-money-box {
padding-top: 10rpx;
padding-bottom: 6rpx;
margin-bottom: 32rpx;
.revenue-box {
padding: 0 24rpx;
@ -234,6 +548,7 @@ let { financeInfo } = toRefs(data)
.family-protection {
display: flex;
flex-direction: column;
flex-shrink: 0;
height: 100%;
padding: 0 28rpx;
border-left: 1rpx solid #172139;
@ -256,6 +571,52 @@ let { financeInfo } = toRefs(data)
}
}
.data-box {
padding: 0 26rpx 0;
font-size: 26rpx;
.title {
margin-bottom: 40rpx;
}
.group-data {
// margin-top: 8rpx;
flex-wrap: wrap;
.item {
width: calc(50% - 15rpx);
flex-shrink: 0;
margin-bottom: 40rpx;
.label {
margin-right: 18rpx;
flex-shrink: 0;
}
}
}
.second-color {
color: #787174;
}
.primary-color {
color: #EAD2B8;
}
}
}
.open {
// background: #08112E;
background: linear-gradient(146deg, #0B1028 49%, #08112E 71.26%, #18336C 83.18%, #18336C 96%)
}
.image-service-box {
position: absolute;
display: flex;
flex-direction: column;
top: 20%;
width: 100%;
.arrow-box {
display: flex;
align-items: center;
@ -291,7 +652,7 @@ let { financeInfo } = toRefs(data)
.name-box {
display: flex;
align-items: center;
align-items: flex-start;
}
.card-holder-icon {
@ -338,8 +699,33 @@ let { financeInfo } = toRefs(data)
.content-box {
margin-top: -1px;
background-color: #ffffff;
background: linear-gradient(180deg, #FFFFFF 56.37%, #F0F4F9 100%);
padding: 20rpx;
.service-icons {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
.service-icon {
display: flex;
flex-direction: column;
align-items: center;
width: 20%;
margin-top: 22rpx;
margin-bottom: 8rpx;
.icon {
width: 62rpx;
height: 62rpx;
}
.name {
font-size: 26rpx;
color: #5D5D5D;
}
}
}
}
@ -347,6 +733,66 @@ let { financeInfo } = toRefs(data)
}
.content {
background-color: #ffffff;
padding: 20rpx;
margin-top: -1px;
}
.bottom-box {
position: fixed;
bottom: 0;
width: 100%;
height: 100rpx;
background-color: #ffffff;
display: flex;
justify-content: space-around;
align-items: center;
padding: 4rpx 0;
.bottom-item {
display: flex;
flex-direction: column;
align-items: center;
image {
width: 56rpx;
height: 56rpx;
}
text {
margin-top: 12rpx;
font-size: 20rpx;
line-height: 25rpx;
color: #333;
}
}
}
.ios-bottom-box {
padding-bottom: constant(safe-area-inset-bottom); // IOS<11.2
padding-bottom: env(safe-area-inset-bottom); // IOS>11.2
}
.navigation-menu-style-1 {
background-color: #ffffff;
.bottom-item:nth-child(2) {
text {
color: #A27140;
}
}
}
.navigation-menu-style-2 {
background-color: #F8F8F8;
border-top: 1rpx solid #C3CED1;
padding: 6rpx 0;
.bottom-item:nth-child(2) {
text {
color: #0075FF;
}
}
}
</style>

View File

@ -95,8 +95,6 @@
<text class="vision-text">版本:{{ vision }}</text>
</view>
</view>
</view>
</template>
<script setup>
@ -108,21 +106,51 @@ import {
storage
} from '@/utils/storage.js'
import {
get
get,
postJson
} from '@/utils/requests.js'
import {
ref,
reactive,
toRefs,
getCurrentInstance
toRefs
} from 'vue';
import {
onLoad,
onShow
} from '@dcloudio/uni-app';
const instance = getCurrentInstance();
const { proxy } = instance;
// 内部埋点方法
const apiUserEvent = async (type, adminData) => {
let uni_version = uni.getStorageSync("version")
if (type != 'uni') {
await postJson('a', 'api/user/event', {
type: adminData.type,
key: adminData.type + ".uni.alipay." + adminData.key,
value: adminData.value,
extra: JSON.stringify({
uni_version: uni_version,
...adminData.extra
}),
})
}
}
// 内部跳转充值页方法
const goRechargePage = () => {
// 进入页面
apiUserEvent('all', {
type: "event",
key: "payment_onload",
value: "进入充值页面",
extra: {
from: "支付宝模拟器首页"
}
})
uni.navigateTo({
url: '/pages/common/recharge/index'
});
}
// 菜单列表
const menuList = [{
@ -141,8 +169,8 @@ const menuList = [{
icon: "licaiheika",
name: "理财黑卡",
isHot: true,
// path: "/pages/finance-management/index"
path: ""
path: "/pages/finance-management/index"
// path: ""
},
{
icon: "huabei",
@ -311,9 +339,10 @@ const clickMenu = (item) => {
}
}
// 开通vip
const openVip = () => {
console.log('openVip')
util.goPage('/pages/common/recharge/index')
goRechargePage()
}
/**

Binary file not shown.

After

Width:  |  Height:  |  Size: 373 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 554 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 759 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 767 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 718 B

145
static/json/fortune.json Normal file
View File

@ -0,0 +1,145 @@
{
"serviceIcons": [
{
"name": "余额宝",
"icon": "yuebao"
},
{
"name": "稳健理财",
"icon": "wenjianlicai"
},
{
"name": "基金",
"icon": "jijin"
},
{
"name": "黄金",
"icon": "huangjin"
},
{
"name": "股票",
"icon": "gupiao"
},
{
"name": "定期",
"icon": "dingqi"
},
{
"name": "保险",
"icon": "baoxian"
},
{
"name": "高端理财",
"icon": "gaoduanlicai"
},
{
"name": "全球投资",
"icon": "quanqiutouzi"
},
{
"name": "更多",
"icon": "gengduo"
}
],
"navigationMenu": [
{
"name": "首页",
"icon": "shouye"
},
{
"name": "理财",
"icon": "licai"
},
{
"name": "视频",
"icon": "shipin"
},
{
"name": "消息",
"icon": "xiaoxi"
},
{
"name": "我的",
"icon": "wode"
}
],
"myAssets": [
{
"groupId": "1",
"key": "fortune",
"title": "",
"items": [
{
"label": "余额宝",
"labelSub": "",
"value": "",
"key": "yuebao"
},
{
"label": "定期",
"labelSub": "",
"value": "",
"key": "dingqi"
},
{
"label": "基金",
"labelSub": "",
"value": "",
"key": "jijin"
},
{
"label": "黄金",
"labelSub": "",
"value": "",
"key": "huangjin"
},
{
"label": "余利宝",
"labelSub": "",
"value": "",
"key": "yulingbao"
}
]
},
{
"groupId": "2",
"title": "我的保障资产",
"key": "myAssets",
"items": [
{
"label": "保险",
"labelSub": "1份保单保障中",
"value": "",
"key": "baoxian"
}
]
},
{
"groupId": "3",
"title": "我的额度",
"key": "myQuota",
"items": [
{
"label": "花呗",
"labelSub": "",
"key": "huabei"
},
{
"label": "借呗",
"labelSub": "",
"key": "jubei"
},
{
"label": "备用金",
"labelSub": "",
"key": "beizhi"
},
{
"label": "网商贷",
"labelSub": "",
"key": "wangshangdai"
}
]
}
]
}

View File

@ -42,6 +42,7 @@ export default {
let currentPage = pages[pages.length - 1];
let currentUrl = currentPage.route;
currentUrl = pageData[currentUrl]
if (type) {
// 点击水印
app.config.globalProperties.$apiUserEvent('all', {
type: "click",
@ -56,6 +57,7 @@ export default {
page: currentUrl
}
})
}
// 进入页面
app.config.globalProperties.$apiUserEvent('all', {
type: "event",