no message
This commit is contained in:
@@ -0,0 +1,24 @@
|
||||
<template>
|
||||
<page-meta :page-style="$theme.pageStyle">
|
||||
<!-- #ifndef H5 -->
|
||||
<navigation-bar
|
||||
:front-color="$theme.navColor"
|
||||
:background-color="$theme.navBgColor"
|
||||
/>
|
||||
<!-- #endif -->
|
||||
</page-meta>
|
||||
<view class="h-screen flex flex-col justify-center items-center">
|
||||
<view>
|
||||
<u-empty text="对不起,您访问的页面不存在" mode="data"></u-empty>
|
||||
</view>
|
||||
<view class="w-full px-[100rpx] mt-[40rpx]">
|
||||
<router-navigate
|
||||
class="bg-primary rounded-full text-btn-text leading-[80rpx] text-center"
|
||||
to="/"
|
||||
nav-type="reLaunch"
|
||||
>
|
||||
返回首页
|
||||
</router-navigate>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
@@ -0,0 +1,108 @@
|
||||
<template>
|
||||
<page-meta :page-style="$theme.pageStyle">
|
||||
<!-- #ifndef H5 -->
|
||||
<navigation-bar :front-color="$theme.navColor" :background-color="$theme.navBgColor" />
|
||||
<!-- #endif -->
|
||||
</page-meta>
|
||||
<z-paging ref="paging" v-model="dataList" @query="queryList" :show-loading-more-when-reload="true">
|
||||
<view class="points-log">
|
||||
<view class="p-[20rpx]">
|
||||
<view
|
||||
class="bg-primary rounded-[14rpx] flex items-center justify-between pl-[44rpx] py-[54rpx] text-white">
|
||||
<view>
|
||||
<view class="text-sm">当前积分</view>
|
||||
<view class="text-[60rpx]">{{ userPoints }}</view>
|
||||
</view>
|
||||
<navigator url="/packages/pages/points_products/points_products" hover-class="none">
|
||||
<view class="text-primary px-[30rpx] py-[15rpx] bg-white rounded-l-full">
|
||||
去购买
|
||||
</view>
|
||||
</navigator>
|
||||
</view>
|
||||
</view>
|
||||
<u-tabs :list="tabList" :is-scroll="false" v-model="current" activeColor="var(--color-primary)"
|
||||
@change="changeType"></u-tabs>
|
||||
|
||||
<view class="pt-2.5">
|
||||
<view v-for="item in dataList" :key="item.id"
|
||||
class="bg-white border-solid border-b border-0 border-light px-[26rpx] py-[24rpx]">
|
||||
<view class="flex justify-between">
|
||||
<view class="mr-2">{{ item.type_desc }}</view>
|
||||
<view class="text-lg" :class="{
|
||||
'text-primary': item.action == 1
|
||||
}">
|
||||
{{ item.change_amount_desc }}
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="item.remark" class="text-sm text-muted mt-1">{{ item.remark }}</view>
|
||||
<view class="text-sm text-muted mr-1">{{ item.create_time }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</z-paging>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, shallowRef } from 'vue'
|
||||
import { accountLog } from '@/api/user'
|
||||
import { onShow } from '@dcloudio/uni-app'
|
||||
import request from '@/utils/request'
|
||||
|
||||
const tabList = ref([
|
||||
{
|
||||
name: '全部',
|
||||
type: ''
|
||||
},
|
||||
{
|
||||
name: '收入',
|
||||
type: 1
|
||||
},
|
||||
{
|
||||
name: '支出',
|
||||
type: 2
|
||||
}
|
||||
])
|
||||
const paging = shallowRef()
|
||||
const dataList = ref<any[]>([])
|
||||
const current = ref(0)
|
||||
|
||||
const changeType = (index: number) => {
|
||||
current.value = index
|
||||
paging.value.reload()
|
||||
}
|
||||
|
||||
const queryList = async (pageNo: number, pageSize: number) => {
|
||||
try {
|
||||
const action = tabList.value[current.value].type
|
||||
const data = await accountLog({
|
||||
action,
|
||||
type: 'up',
|
||||
page_no: pageNo,
|
||||
page_size: pageSize
|
||||
})
|
||||
paging.value.complete(data.lists)
|
||||
} catch (error) {
|
||||
paging.value.complete(false)
|
||||
}
|
||||
}
|
||||
|
||||
const userPoints = ref(0)
|
||||
const fetchUserPoints = async () => {
|
||||
try {
|
||||
const res: any = await request.get(
|
||||
{ url: '/community/userStats' },
|
||||
{ isTransformResponse: false }
|
||||
)
|
||||
if (res?.code === 1 && res.data) {
|
||||
userPoints.value = res.data.user_points || 0
|
||||
}
|
||||
} catch (e) {
|
||||
// 静默
|
||||
}
|
||||
}
|
||||
onShow(() => {
|
||||
fetchUserPoints()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
@@ -0,0 +1,96 @@
|
||||
<template>
|
||||
<view class="points-order">
|
||||
<view class="card">
|
||||
<view class="title">确认订单</view>
|
||||
<view class="product">
|
||||
<view>
|
||||
<view class="name">{{ orderInfo.name }}</view>
|
||||
<view class="desc">到账积分:{{ orderInfo.points }}</view>
|
||||
</view>
|
||||
<view class="amount">¥{{ orderInfo.amount }}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="submit">
|
||||
<u-button :loading="loading" type="primary" shape="circle" @click="submitOrder">提交订单</u-button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import { reactive, ref } from 'vue'
|
||||
import { pointsPreOrder, pointsCreateOrder } from '@/api/points'
|
||||
|
||||
const productId = ref(0)
|
||||
const loading = ref(false)
|
||||
const orderInfo = reactive({
|
||||
product_id: 0,
|
||||
name: '',
|
||||
points: 0,
|
||||
amount: '0.00'
|
||||
})
|
||||
|
||||
const getPreOrder = async () => {
|
||||
const data = await pointsPreOrder({ product_id: productId.value })
|
||||
Object.assign(orderInfo, data)
|
||||
}
|
||||
|
||||
const submitOrder = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const data = await pointsCreateOrder({ product_id: productId.value })
|
||||
uni.redirectTo({
|
||||
url: `/packages/pages/points_order_detail/points_order_detail?order_id=${data.order_id}`
|
||||
})
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
onLoad((options: any) => {
|
||||
productId.value = Number(options.product_id || 0)
|
||||
getPreOrder()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.points-order {
|
||||
min-height: 100vh;
|
||||
padding: 24rpx;
|
||||
background: #f5f5f5;
|
||||
}
|
||||
.card {
|
||||
padding: 32rpx;
|
||||
background: #fff;
|
||||
border-radius: 18rpx;
|
||||
}
|
||||
.title {
|
||||
font-size: 34rpx;
|
||||
font-weight: 700;
|
||||
color: #222;
|
||||
}
|
||||
.product {
|
||||
margin-top: 30rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.name {
|
||||
font-size: 32rpx;
|
||||
color: #222;
|
||||
font-weight: 600;
|
||||
}
|
||||
.desc {
|
||||
margin-top: 10rpx;
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
}
|
||||
.amount {
|
||||
font-size: 36rpx;
|
||||
color: #185dff;
|
||||
font-weight: 700;
|
||||
}
|
||||
.submit {
|
||||
margin-top: 40rpx;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,124 @@
|
||||
<template>
|
||||
<view class="points-detail">
|
||||
<view class="card">
|
||||
<view class="status">{{ order.pay_status_text }}</view>
|
||||
<view class="row">
|
||||
<text>订单编号</text>
|
||||
<text>{{ order.sn }}</text>
|
||||
</view>
|
||||
<view class="row">
|
||||
<text>积分套餐</text>
|
||||
<text>{{ order.product_name }}</text>
|
||||
</view>
|
||||
<view class="row">
|
||||
<text>到账积分</text>
|
||||
<text>{{ order.points }}</text>
|
||||
</view>
|
||||
<view class="row">
|
||||
<text>支付金额</text>
|
||||
<text class="amount">¥{{ order.order_amount }}</text>
|
||||
</view>
|
||||
<view v-if="order.pay_time" class="row">
|
||||
<text>支付时间</text>
|
||||
<text>{{ order.pay_time }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-if="order.pay_status === 0" class="pay-card">
|
||||
<view class="pay-title">请选择支付方式</view>
|
||||
<view class="pay-tips">支持支付宝、微信支付;使用币支付入口预留中</view>
|
||||
<u-button type="primary" shape="circle" @click="payState.showPay = true">立即支付</u-button>
|
||||
</view>
|
||||
|
||||
<payment v-model:show="payState.showPay" v-model:show-check="payState.showCheck" :order-id="orderId"
|
||||
from="points_order" :redirect="payState.redirect" @success="handlePaySuccess" @fail="handlePayFail" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onLoad, onShow } from '@dcloudio/uni-app'
|
||||
import { reactive, ref } from 'vue'
|
||||
import { pointsOrderDetail } from '@/api/points'
|
||||
|
||||
const orderId = ref(0)
|
||||
const order = reactive<any>({})
|
||||
const payState = reactive({
|
||||
showPay: false,
|
||||
showCheck: false,
|
||||
redirect: '/packages/pages/points_order_detail/points_order_detail'
|
||||
})
|
||||
|
||||
const getDetail = async () => {
|
||||
const data = await pointsOrderDetail({ order_id: orderId.value })
|
||||
Object.assign(order, data)
|
||||
}
|
||||
|
||||
const handlePaySuccess = async () => {
|
||||
payState.showPay = false
|
||||
payState.showCheck = false
|
||||
await getDetail()
|
||||
uni.$u.toast('支付成功')
|
||||
}
|
||||
|
||||
const handlePayFail = () => {
|
||||
uni.$u.toast('支付失败')
|
||||
}
|
||||
|
||||
onLoad((options: any) => {
|
||||
orderId.value = Number(options.order_id || 0)
|
||||
payState.redirect = `/packages/pages/points_order_detail/points_order_detail?order_id=${orderId.value}`
|
||||
})
|
||||
|
||||
onShow(() => {
|
||||
if (orderId.value) getDetail()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.points-detail {
|
||||
min-height: 100vh;
|
||||
padding: 24rpx;
|
||||
background: #f5f5f5;
|
||||
}
|
||||
.card,
|
||||
.pay-card {
|
||||
padding: 32rpx;
|
||||
background: #fff;
|
||||
border-radius: 18rpx;
|
||||
}
|
||||
.status {
|
||||
margin-bottom: 24rpx;
|
||||
font-size: 36rpx;
|
||||
font-weight: 700;
|
||||
color: #185dff;
|
||||
}
|
||||
.row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 20rpx 0;
|
||||
font-size: 26rpx;
|
||||
color: #666;
|
||||
border-bottom: 1rpx solid #f2f2f2;
|
||||
}
|
||||
.row:last-child {
|
||||
border-bottom: 0;
|
||||
}
|
||||
.amount {
|
||||
color: #185dff;
|
||||
font-weight: 700;
|
||||
}
|
||||
.pay-card {
|
||||
margin-top: 24rpx;
|
||||
}
|
||||
.pay-title {
|
||||
font-size: 30rpx;
|
||||
font-weight: 700;
|
||||
color: #222;
|
||||
}
|
||||
.pay-tips {
|
||||
margin: 12rpx 0 28rpx;
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,352 @@
|
||||
<template>
|
||||
<view class="pp">
|
||||
<!-- 顶部积分 -->
|
||||
<view class="pp-header">
|
||||
<view class="pp-header__row">
|
||||
<text class="pp-header__label">当前积分</text>
|
||||
<text class="pp-header__value">{{ userPoints }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 步骤1: 选择积分套餐 (两列网格) -->
|
||||
<view class="pp-section">
|
||||
<view class="pp-section__title">选择积分套餐</view>
|
||||
<view class="pp-grid">
|
||||
<view v-for="item in products" :key="item.id" class="pp-grid__item"
|
||||
:class="{ 'pp-grid__item--active': selectedId === item.id }" @tap="selectProduct(item)">
|
||||
<text class="pp-grid__points">{{ item.points }}</text>
|
||||
<text class="pp-grid__unit">积分</text>
|
||||
<text class="pp-grid__price">¥{{ item.amount }}</text>
|
||||
<view v-if="selectedId === item.id" class="pp-grid__check">
|
||||
<u-icon name="checkbox-mark" color="#fff" size="20" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 步骤2: 订单确认信息(选择商品后显示) -->
|
||||
<view v-if="selectedProduct" class="pp-section">
|
||||
<view class="pp-section__title">订单确认</view>
|
||||
<view class="pp-confirm">
|
||||
<view class="pp-confirm__row">
|
||||
<text class="pp-confirm__label">商品名称</text>
|
||||
<text class="pp-confirm__value">{{ selectedProduct.name }}</text>
|
||||
</view>
|
||||
<view class="pp-confirm__row">
|
||||
<text class="pp-confirm__label">积分数量</text>
|
||||
<text class="pp-confirm__value">{{ selectedProduct.points }} 积分</text>
|
||||
</view>
|
||||
<view class="pp-confirm__row">
|
||||
<text class="pp-confirm__label">支付金额</text>
|
||||
<text class="pp-confirm__value pp-confirm__value--price">¥{{ selectedProduct.amount }}</text>
|
||||
</view>
|
||||
<view class="pp-confirm__row">
|
||||
<text class="pp-confirm__label">充值账号</text>
|
||||
<text class="pp-confirm__value">{{ userInfo.nickname }} (ID: {{ userInfo.sn }})</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-if="!products.length && !loading" class="pp-empty">
|
||||
<text>暂无积分套餐</text>
|
||||
</view>
|
||||
|
||||
<!-- 底部按钮 -->
|
||||
<view v-if="selectedId" class="pp-bottom">
|
||||
<view class="pp-bottom__left">
|
||||
<text class="pp-bottom__total">¥{{ selectedProduct?.amount || '0.00' }}</text>
|
||||
</view>
|
||||
<view class="pp-bottom__btn" :class="{ 'pp-bottom__btn--disabled': submitting }" @tap="handleSubmit">
|
||||
<text v-if="!submitting">确认支付</text>
|
||||
<u-loading v-else color="#fff" size="36" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 支付组件 -->
|
||||
<payment v-model:show="payState.show" v-model:showCheck="payState.showCheck" :orderId="payState.orderId"
|
||||
:from="payState.from" redirect="/packages/pages/points_order_detail/points_order_detail"
|
||||
@success="onPaySuccess" @close="onPayClose" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onShow } from '@dcloudio/uni-app'
|
||||
import { ref, reactive, computed } from 'vue'
|
||||
import { useUserStore } from '@/stores/user'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { pointsProducts, pointsCreateOrder } from '@/api/points'
|
||||
import request from '@/utils/request'
|
||||
|
||||
const userStore = useUserStore()
|
||||
const { userInfo } = storeToRefs(userStore)
|
||||
|
||||
const products = ref<any[]>([])
|
||||
const userPoints = ref(0)
|
||||
const loading = ref(false)
|
||||
const selectedId = ref(0)
|
||||
const submitting = ref(false)
|
||||
|
||||
const payState = reactive({
|
||||
show: false,
|
||||
showCheck: false,
|
||||
orderId: 0,
|
||||
from: 'points_order'
|
||||
})
|
||||
|
||||
const selectedProduct = computed(() => {
|
||||
return products.value.find((p: any) => p.id === selectedId.value) || null
|
||||
})
|
||||
|
||||
const fetchProducts = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const data = await pointsProducts()
|
||||
products.value = data || []
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const fetchUserPoints = async () => {
|
||||
try {
|
||||
const res: any = await request.get(
|
||||
{ url: '/community/userStats' },
|
||||
{ isTransformResponse: false }
|
||||
)
|
||||
if (res?.code === 1 && res.data) {
|
||||
userPoints.value = res.data.user_points || 0
|
||||
}
|
||||
} catch (e) {
|
||||
// 静默
|
||||
}
|
||||
}
|
||||
|
||||
const selectProduct = (item: any) => {
|
||||
if (selectedId.value === item.id) return
|
||||
selectedId.value = item.id
|
||||
}
|
||||
|
||||
const handleSubmit = async () => {
|
||||
if (!selectedProduct.value || submitting.value) return
|
||||
submitting.value = true
|
||||
try {
|
||||
const orderRes = await pointsCreateOrder({
|
||||
product_id: selectedProduct.value.id
|
||||
})
|
||||
payState.orderId = orderRes.order_id
|
||||
payState.from = orderRes.from
|
||||
payState.show = true
|
||||
} catch (e: any) {
|
||||
uni.$u.toast(e?.msg || '下单失败')
|
||||
} finally {
|
||||
submitting.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const onPaySuccess = () => {
|
||||
uni.$u.toast('支付成功')
|
||||
fetchUserPoints()
|
||||
uni.redirectTo({
|
||||
url: `/packages/pages/points_order_detail/points_order_detail?order_id=${payState.orderId}`
|
||||
})
|
||||
}
|
||||
|
||||
const onPayClose = () => {
|
||||
if (payState.orderId) {
|
||||
uni.navigateTo({
|
||||
url: `/packages/pages/points_order_detail/points_order_detail?order_id=${payState.orderId}`
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
onShow(() => {
|
||||
fetchProducts()
|
||||
fetchUserPoints()
|
||||
userStore.getUser()
|
||||
selectedId.value = 0
|
||||
payState.show = false
|
||||
payState.orderId = 0
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.pp {
|
||||
min-height: 100vh;
|
||||
background: #f5f5f5;
|
||||
padding-bottom: calc(120rpx + env(safe-area-inset-bottom));
|
||||
}
|
||||
|
||||
.pp-header {
|
||||
background: linear-gradient(170deg, #185dff, #4d82ff);
|
||||
padding: 40rpx 32rpx 48rpx;
|
||||
|
||||
&__row {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: 12rpx;
|
||||
}
|
||||
|
||||
&__label {
|
||||
font-size: 28rpx;
|
||||
color: rgba(255, 255, 255, 0.8);
|
||||
}
|
||||
|
||||
&__value {
|
||||
font-size: 56rpx;
|
||||
font-weight: 700;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
.pp-section {
|
||||
margin: 24rpx;
|
||||
background: #fff;
|
||||
border-radius: 20rpx;
|
||||
padding: 28rpx;
|
||||
|
||||
&__title {
|
||||
font-size: 30rpx;
|
||||
font-weight: 600;
|
||||
color: #222;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
}
|
||||
|
||||
/* 两列网格 */
|
||||
.pp-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 20rpx;
|
||||
}
|
||||
|
||||
.pp-grid__item {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: #f7f8fa;
|
||||
border-radius: 16rpx;
|
||||
padding: 32rpx 16rpx;
|
||||
border: 3rpx solid transparent;
|
||||
transition: all 0.2s;
|
||||
|
||||
&--active {
|
||||
border-color: #185dff;
|
||||
background: #eef3ff;
|
||||
}
|
||||
}
|
||||
|
||||
.pp-grid__points {
|
||||
font-size: 42rpx;
|
||||
font-weight: 700;
|
||||
color: #222;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.pp-grid__unit {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
margin-top: 8rpx;
|
||||
}
|
||||
|
||||
.pp-grid__price {
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
color: #185dff;
|
||||
margin-top: 12rpx;
|
||||
}
|
||||
|
||||
.pp-grid__check {
|
||||
position: absolute;
|
||||
top: -2rpx;
|
||||
right: -2rpx;
|
||||
width: 48rpx;
|
||||
height: 48rpx;
|
||||
background: #185dff;
|
||||
border-radius: 0 16rpx 0 16rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
/* 订单确认 */
|
||||
.pp-confirm {
|
||||
background: #f7f8fa;
|
||||
border-radius: 12rpx;
|
||||
padding: 20rpx 24rpx;
|
||||
|
||||
&__row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 14rpx 0;
|
||||
}
|
||||
|
||||
&__label {
|
||||
font-size: 26rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
&__value {
|
||||
font-size: 26rpx;
|
||||
color: #333;
|
||||
|
||||
&--price {
|
||||
font-size: 32rpx;
|
||||
font-weight: 700;
|
||||
color: #185dff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.pp-empty {
|
||||
text-align: center;
|
||||
padding: 120rpx 0;
|
||||
color: #999;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
/* 底部栏 */
|
||||
.pp-bottom {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 16rpx 32rpx;
|
||||
padding-bottom: calc(16rpx + env(safe-area-inset-bottom));
|
||||
box-shadow: 0 -2rpx 16rpx rgba(0, 0, 0, 0.06);
|
||||
|
||||
&__left {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
&__total {
|
||||
font-size: 40rpx;
|
||||
font-weight: 700;
|
||||
color: #185dff;
|
||||
}
|
||||
|
||||
&__btn {
|
||||
background: #185dff;
|
||||
color: #fff;
|
||||
font-size: 30rpx;
|
||||
font-weight: 500;
|
||||
padding: 20rpx 64rpx;
|
||||
border-radius: 44rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-width: 220rpx;
|
||||
|
||||
&--disabled {
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,109 @@
|
||||
<template>
|
||||
<page-meta :page-style="$theme.pageStyle">
|
||||
<!-- #ifndef H5 -->
|
||||
<navigation-bar
|
||||
:front-color="$theme.navColor"
|
||||
:background-color="$theme.navBgColor"
|
||||
/>
|
||||
<!-- #endif -->
|
||||
</page-meta>
|
||||
<view class="recharge p-[20rpx]">
|
||||
<view class="bg-white rounded-[14rpx] p-[40rpx]">
|
||||
<view class="text-content">充值金额</view>
|
||||
<view class="border-0 border-b border-solid border-light">
|
||||
<input
|
||||
v-model="money"
|
||||
class="text-[60rpx] h-[60rpx] py-[24rpx]"
|
||||
placeholder="0.00"
|
||||
type="digit"
|
||||
/>
|
||||
</view>
|
||||
<view class="mt-[20rpx] text-xs text-muted">
|
||||
当前可用余额
|
||||
<text class="text-primary"> {{ wallet.user_money }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="mt-[40rpx]">
|
||||
<u-button :loading="isLock" type="primary" shape="circle" @click="rechargeLock">
|
||||
立即充值
|
||||
</u-button>
|
||||
</view>
|
||||
<view class="flex justify-center m-[60rpx]">
|
||||
<navigator url="/packages/pages/recharge_record/recharge_record" hover-class="none">
|
||||
<text class="text-content text-sm">充值记录</text>
|
||||
</navigator>
|
||||
</view>
|
||||
<payment
|
||||
v-model:show="payState.showPay"
|
||||
v-model:show-check="payState.showCheck"
|
||||
:order-id="payState.orderId"
|
||||
:from="payState.from"
|
||||
:redirect="payState.redirect"
|
||||
@success="handlePaySuccess"
|
||||
@fail="handlePayFail"
|
||||
/>
|
||||
</view>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { recharge, rechargeConfig } from '@/api/recharge'
|
||||
import { useLockFn } from '@/hooks/useLockFn'
|
||||
import { onLoad, onShow } from '@dcloudio/uni-app'
|
||||
import { reactive, ref } from 'vue'
|
||||
const money = ref('')
|
||||
|
||||
const payState = reactive({
|
||||
orderId: '',
|
||||
from: '',
|
||||
showPay: false,
|
||||
showCheck: false,
|
||||
redirect: '/packages/pages/recharge/recharge'
|
||||
})
|
||||
const wallet = reactive({
|
||||
user_money: '',
|
||||
min_amount: 0
|
||||
})
|
||||
|
||||
const { isLock, lockFn: rechargeLock } = useLockFn(async () => {
|
||||
const minNum = wallet.min_amount
|
||||
if (!money.value) return uni.$u.toast('请输入充值金额')
|
||||
if (minNum == 0 && Number(money.value) == minNum) {
|
||||
return uni.$u.toast(`充值金额必须大于0`)
|
||||
}
|
||||
if (Number(money.value) < minNum) return uni.$u.toast(`最低充值金额${minNum}`)
|
||||
const data = await recharge({
|
||||
money: money.value
|
||||
})
|
||||
payState.orderId = data.order_id
|
||||
payState.from = data.from
|
||||
payState.showPay = true
|
||||
})
|
||||
|
||||
const handlePaySuccess = async () => {
|
||||
payState.showPay = false
|
||||
payState.showCheck = false
|
||||
uni.navigateTo({
|
||||
url: `/pages/payment_result/payment_result?id=${payState.orderId}&from=${payState.from}`
|
||||
})
|
||||
}
|
||||
|
||||
const handlePayFail = async () => {
|
||||
uni.$u.toast('支付失败')
|
||||
}
|
||||
|
||||
const getWallet = async () => {
|
||||
const data = await rechargeConfig()
|
||||
Object.assign(wallet, data)
|
||||
}
|
||||
|
||||
onLoad((options: any) => {
|
||||
// h5支付用于弹起手动确认支付弹窗
|
||||
if (options?.checkPay) {
|
||||
payState.orderId = options.id
|
||||
payState.from = options.from
|
||||
payState.showCheck = true
|
||||
}
|
||||
})
|
||||
onShow(() => {
|
||||
getWallet()
|
||||
})
|
||||
</script>
|
||||
@@ -0,0 +1,52 @@
|
||||
<template>
|
||||
<page-meta :page-style="$theme.pageStyle">
|
||||
<!-- #ifndef H5 -->
|
||||
<navigation-bar
|
||||
:front-color="$theme.navColor"
|
||||
:background-color="$theme.navBgColor"
|
||||
/>
|
||||
<!-- #endif -->
|
||||
</page-meta>
|
||||
<z-paging
|
||||
ref="paging"
|
||||
v-model="dataList"
|
||||
@query="queryList"
|
||||
:show-loading-more-when-reload="true"
|
||||
>
|
||||
<view class="pt-2.5">
|
||||
<view
|
||||
v-for="item in dataList"
|
||||
:key="item.id"
|
||||
class="bg-white border-solid border-b border-0 border-light px-[26rpx] py-[24rpx]"
|
||||
>
|
||||
<view class="flex justify-between">
|
||||
<view class="mr-2">{{ item.tips }}</view>
|
||||
<view class="text-lg text-primary"> +{{ item.order_amount }} </view>
|
||||
</view>
|
||||
<view class="text-sm text-muted mr-1">{{ item.create_time }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</z-paging>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, shallowRef } from 'vue'
|
||||
import { rechargeRecord } from '@/api/recharge'
|
||||
|
||||
const paging = shallowRef()
|
||||
const dataList = ref<any[]>([])
|
||||
|
||||
const queryList = async (pageNo: number, pageSize: number) => {
|
||||
try {
|
||||
const data = await rechargeRecord({
|
||||
page_no: pageNo,
|
||||
page_size: pageSize
|
||||
})
|
||||
paging.value.complete(data.lists)
|
||||
} catch (error) {
|
||||
paging.value.complete(false)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
@@ -0,0 +1,199 @@
|
||||
<template>
|
||||
<page-meta page-style="background-color: #005fff">
|
||||
<!-- #ifndef H5 -->
|
||||
<navigation-bar front-color="#ffffff" background-color="#005fff" />
|
||||
<!-- #endif -->
|
||||
</page-meta>
|
||||
<z-paging ref="paging" v-model="dataList" @query="queryList" :show-loading-more-when-reload="true">
|
||||
<view class="user-wallet">
|
||||
<view class="wallet-header">
|
||||
<view class="wallet-header__card">
|
||||
<view class="wallet-header__label">钱包余额</view>
|
||||
<view class="wallet-header__amount">{{ wallet.user_money || '0.00' }}</view>
|
||||
<view class="wallet-header__row">
|
||||
<view class="wallet-header__item">
|
||||
<text class="wallet-header__item-label">总收益</text>
|
||||
<text class="wallet-header__item-value">{{ wallet.total_income || '0.00' }}</text>
|
||||
</view>
|
||||
<view class="wallet-header__item">
|
||||
<text class="wallet-header__item-label">佣金比例</text>
|
||||
<text class="wallet-header__item-value">{{ wallet.commission_rate || '0' }}%</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="wallet-card">
|
||||
<view class="wallet-tabs">
|
||||
<view v-for="(tab, idx) in tabList" :key="idx" class="wallet-tabs__item"
|
||||
:class="{ 'wallet-tabs__item--active': current === idx }" @tap="changeType(idx)">
|
||||
<text>{{ tab.name }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-for="item in dataList" :key="item.id"
|
||||
class="border-solid border-b border-0 border-light px-[26rpx] py-[24rpx]">
|
||||
<view class="flex justify-between items-start">
|
||||
<view>
|
||||
<view class="text-[28rpx] font-medium">{{ item.type_desc }}</view>
|
||||
<view class="text-[24rpx] text-muted mt-[6rpx]">{{ item.create_time }}</view>
|
||||
</view>
|
||||
<view class="text-right">
|
||||
<view class="text-[32rpx] font-bold"
|
||||
:class="item.action == 1 ? 'text-primary' : 'text-[#333]'">
|
||||
{{ item.change_amount_desc }}
|
||||
</view>
|
||||
<view v-if="item.left_amount !== undefined" class="text-[22rpx] text-muted mt-[4rpx]">
|
||||
剩余 {{ item.left_amount }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</z-paging>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, shallowRef } from 'vue'
|
||||
import { accountLog } from '@/api/user'
|
||||
import { rechargeConfig } from '@/api/recharge'
|
||||
import { onShow } from '@dcloudio/uni-app'
|
||||
const tabList = ref([
|
||||
{
|
||||
name: '全部',
|
||||
type: ''
|
||||
},
|
||||
{
|
||||
name: '收入',
|
||||
type: 1
|
||||
},
|
||||
{
|
||||
name: '支出',
|
||||
type: 2
|
||||
}
|
||||
])
|
||||
const paging = shallowRef()
|
||||
const dataList = ref<any[]>([])
|
||||
const current = ref(0)
|
||||
|
||||
const changeType = (index: number) => {
|
||||
current.value = index
|
||||
paging.value.reload()
|
||||
}
|
||||
|
||||
const queryList = async (pageNo: number, pageSize: number) => {
|
||||
try {
|
||||
const action = tabList.value[current.value].type
|
||||
const data = await accountLog({
|
||||
action,
|
||||
type: 'um',
|
||||
page_no: pageNo,
|
||||
page_size: pageSize
|
||||
})
|
||||
paging.value.complete(data.lists)
|
||||
} catch (error) {
|
||||
paging.value.complete(false)
|
||||
}
|
||||
}
|
||||
|
||||
const wallet = ref<any>({})
|
||||
const getWallet = async () => {
|
||||
wallet.value = await rechargeConfig()
|
||||
}
|
||||
onShow(() => {
|
||||
getWallet()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.user-wallet {
|
||||
background: #f5f5f5;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.wallet-header {
|
||||
background: linear-gradient(to bottom, #005fff 60%, #f5f5f5 60%);
|
||||
padding: 20rpx 40rpx 0rpx;
|
||||
|
||||
&__card {
|
||||
background: #fff;
|
||||
border-radius: 20rpx;
|
||||
padding: 10rpx 32rpx 0;
|
||||
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
|
||||
&__label {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
&__amount {
|
||||
font-size: 64rpx;
|
||||
font-weight: 700;
|
||||
color: #222;
|
||||
margin-top: 8rpx;
|
||||
}
|
||||
|
||||
&__row {
|
||||
display: flex;
|
||||
gap: 48rpx;
|
||||
margin-top: 28rpx;
|
||||
padding: 28rpx 0;
|
||||
border-top: 1rpx solid #f0f0f0;
|
||||
}
|
||||
|
||||
&__item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
&__item-label {
|
||||
font-size: 22rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
&__item-value {
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: #222;
|
||||
margin-top: 4rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.wallet-card {
|
||||
margin: 20rpx 40rpx 0;
|
||||
background: #fff;
|
||||
border-radius: 20rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.wallet-tabs {
|
||||
display: flex;
|
||||
border-bottom: 1rpx solid #f0f0f0;
|
||||
|
||||
&__item {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
padding: 24rpx 0;
|
||||
font-size: 28rpx;
|
||||
color: #999;
|
||||
position: relative;
|
||||
transition: all 0.2s;
|
||||
|
||||
&--active {
|
||||
color: #0053d8;
|
||||
font-weight: 600;
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 4rpx;
|
||||
background: #0053d8;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 3.0 KiB |
Reference in New Issue
Block a user