338 lines
7.2 KiB
Vue
338 lines
7.2 KiB
Vue
<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>
|