bm-bmt/pages/assets/points-convert.vue

338 lines
7.2 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="asset-page asset-theme points-page">
<asset-page-shell title="积分转换" />
<view class="asset-scroll points-scroll">
<view class="hero-card">
<view class="hero-card__content">
<view class="hero-card__coin-row">
<view class="hero-card__coin">
<image
class="hero-card__coin-image"
:src="pageIcon('points')"
mode="aspectFit"
></image>
</view>
<text class="hero-card__coin-text">积分</text>
</view>
<text class="hero-card__label">可用积分:</text>
<text class="hero-card__value">{{ displayAvailablePoints }}</text>
</view>
</view>
<view class="pending-card">
<text class="pending-card__label">未转换积分释放中的积分</text>
<text class="pending-card__value">{{ displayPendingPoints }}</text>
</view>
<view class="tips-block">
<view
v-for="(tip, index) in detail.tips"
:key="tip"
class="tips-block__item"
>
<text class="tips-block__index">{{ index + 1 }}.</text>
<text class="tips-block__text">{{ tip }}</text>
</view>
</view>
<view class="action-wrap">
<view
class="action-button"
:class="{ 'action-button--disabled': !canSubmit || submitting }"
@click="submit"
>
{{ submitting ? "转换中..." : "转换可用积分" }}
</view>
</view>
</view>
</view>
</template>
<script>
import AssetPageShell from "../../components/asset-page-shell.vue";
import {
fetchPointsConvertDetail,
submitAssetPointsConvert,
} from "../../api/assets";
export default {
components: {
AssetPageShell,
},
data() {
return {
hasShown: false,
detail: {
availablePoints: "0.00",
pendingPoints: "0",
ids: [],
tips: [],
},
submitting: false,
};
},
onLoad() {
this.loadPage(true);
},
onShow() {
if (this.hasShown) {
this.loadPage();
return;
}
this.hasShown = true;
},
computed: {
pendingPointsValue() {
return Number(this.detail.pendingPoints || 0);
},
canSubmit() {
return this.pendingPointsValue > 0;
},
displayAvailablePoints() {
return this.formatAmount(this.detail.availablePoints, 2);
},
displayPendingPoints() {
return this.formatAmount(this.detail.pendingPoints, 0);
},
},
methods: {
pageIcon(type) {
const iconMap = {
points: "https://imgs.agrimedia.cn/bm-bmt/j-w.png",
voucher: "https://imgs.agrimedia.cn/bm-bmt/quan-icon.png",
coupon: "https://imgs.agrimedia.cn/bm-bmt/xiaofei-icon.png",
power: "https://imgs.agrimedia.cn/bm-bmt/s.png",
bmt: "https://imgs.agrimedia.cn/bm-bmt/b.png",
};
return iconMap[type] || "";
},
formatAmount(value, digits) {
const number = Number(value || 0);
if (!Number.isFinite(number)) {
return digits > 0 ? Number(0).toFixed(digits) : "0";
}
if (digits > 0) {
const fixed = number.toFixed(digits);
const parts = fixed.split(".");
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",");
return parts.join(".");
}
return Math.floor(number)
.toString()
.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
},
async loadPage(showLoading) {
try {
this.detail = await fetchPointsConvertDetail(
showLoading
? {
showLoading: true,
loadingText: "加载中",
}
: null,
);
} catch (error) {
uni.showToast({
title: error.message || "页面加载失败",
icon: "none",
});
}
},
async submit() {
if (this.submitting) {
return;
}
if (!this.canSubmit) {
uni.showToast({
title: "暂无可转换积分",
icon: "none",
});
return;
}
this.submitting = true;
try {
const result = await submitAssetPointsConvert({
pendingPoints: this.pendingPointsValue,
ids: this.detail.ids,
}, {
showLoading: true,
loadingText: "转换中",
});
uni.showToast({
title: result.message || "转换成功",
icon: "none",
});
this.loadPage();
} catch (error) {
uni.showToast({
title: error.message || "转换失败",
icon: "none",
});
} finally {
this.submitting = false;
}
},
},
};
</script>
<style lang="scss" scoped>
@import "../../styles/tokens.scss";
@import "../../styles/common.scss";
.points-page {
min-height: 100vh;
background: #191e32;
}
.points-scroll {
min-height: calc(100vh - env(safe-area-inset-top) - 104rpx);
display: flex;
flex-direction: column;
padding: 10rpx 14rpx calc(env(safe-area-inset-bottom) + 36rpx);
}
.hero-card,
.pending-card {
border-radius: 8rpx;
box-shadow: 0 12rpx 24rpx rgba(8, 13, 30, 0.12);
}
.hero-card {
position: relative;
min-height: 240rpx;
padding: 24rpx 28rpx;
overflow: hidden;
background: #242944 url("https://imgs.agrimedia.cn/bm-bmt/jifen-header.png")
no-repeat center top / 100% 240rpx;
}
.hero-card__content {
position: relative;
z-index: 1;
display: flex;
flex-direction: column;
}
.hero-card__coin-row {
display: flex;
align-items: center;
}
.hero-card__coin {
display: flex;
align-items: center;
justify-content: center;
width: 56rpx;
height: 56rpx;
border-radius: 50%;
background: linear-gradient(135deg, #f85ca9 0%, #de4d95 100%);
box-shadow: 0 12rpx 20rpx rgba(230, 90, 156, 0.2);
}
.hero-card__coin-image {
width: 30rpx;
height: 30rpx;
}
.hero-card__coin-text {
margin-left: 16rpx;
font-size: 32rpx;
font-weight: 500;
color: #ffffff;
}
.hero-card__label {
margin-top: 38rpx;
font-size: 28rpx;
color: #9ba7ce;
}
.hero-card__value {
margin-top: 8rpx;
font-size: 48rpx;
font-weight: 800;
line-height: 1.08;
color: #ffffff;
}
.pending-card {
display: flex;
align-items: center;
justify-content: space-between;
margin-top: 20rpx;
padding: 30rpx 26rpx;
background: rgba(59, 49, 67, 0.92);
}
.pending-card__label,
.pending-card__value {
font-size: 26rpx;
font-weight: 600;
color: #ff885d;
}
.pending-card__value {
font-size: 28rpx;
}
.tips-block {
margin-top: 20rpx;
padding: 0 2rpx;
}
.tips-block__item {
display: flex;
align-items: flex-start;
margin-top: 10rpx;
}
.tips-block__item:first-child {
margin-top: 0;
}
.tips-block__index,
.tips-block__text {
font-size: 24rpx;
font-weight: 400;
line-height: 1.75;
color: rgba(173, 184, 216, 0.82);
}
.tips-block__index {
flex-shrink: 0;
margin-right: 6rpx;
}
.action-wrap {
margin-top: auto;
padding: 120rpx 24rpx 0;
}
.action-button {
display: flex;
align-items: center;
justify-content: center;
height: 90rpx;
border-radius: 999rpx;
background: linear-gradient(135deg, #22c2ff 0%, #159de6 100%);
box-shadow: 0 16rpx 30rpx rgba(31, 169, 243, 0.2);
font-size: 32rpx;
font-weight: 700;
color: #ffffff;
}
.action-button--disabled {
opacity: 0.56;
}
</style>