我的页面

This commit is contained in:
haomingming
2025-09-01 16:20:16 +08:00
parent c9dcab1e36
commit 1f4c0834fa
21 changed files with 3904 additions and 327 deletions
+39
View File
@@ -0,0 +1,39 @@
# 我的账户页面
## 页面描述
这是一个100%还原的"我的账户"页面,包含以下功能:
### 主要功能
1. **状态栏显示** - 显示时间、网络状态、电池等信息
2. **头部导航** - 包含返回按钮和页面标题
3. **账户余额展示** - 显示用户头像和账户余额
4. **操作选项** - 提现和账单明细功能
### 页面结构
- `status-bar` - 状态栏区域
- `header` - 头部导航区域
- `account-summary` - 账户余额展示区域
- `action-items` - 操作选项列表
- `bottom-indicator` - 底部指示器
### 样式特点
- 使用深红色/棕色渐变背景 (#8B2316 到 #A0522D)
- 圆形头像设计
- 白色操作卡片
- 响应式交互效果
### 使用方法
1. 在 `pages.json` 中已配置路由
2. 从其他页面通过 `uni.navigateTo` 跳转
3. 支持返回上一页功能
### 技术实现
- 使用 Vue 3 Composition API
- SCSS 样式预处理器
- uni-app 框架
- 响应式设计
### 注意事项
- 头像图片路径:`/static/new_man_big.png`
- 页面标题:我的账户
- 导航样式:自定义导航栏
+278
View File
@@ -0,0 +1,278 @@
<template>
<view class="bill-details-page">
<!-- 顶部导航栏 -->
<uni-nav-bar
left-icon="left"
title="账单明细"
@clickLeft="goBack"
fixed
color="#8B2316"
height="140rpx"
:border="false"
backgroundColor="#eeeeee"
></uni-nav-bar>
<!-- 表格头部 -->
<view class="table-header">
<view class="header-cell business-type">业务类型</view>
<view class="header-cell user">用户</view>
<view class="header-cell date-amount">
<text class="date-label">日期</text>
<text class="amount-label">金额</text>
</view>
</view>
<!-- 交易记录列表 -->
<scroll-view
class="transaction-list"
scroll-y
refresher-enabled
@refresherrefresh="onRefresh"
:refresher-triggered="refreshing"
@scrolltolower="onLoadMore"
:lower-threshold="100"
>
<view class="transaction-item" v-for="(item, index) in orderList" :key="item.id">
<view class="cell business-type">{{ item.typeName }}</view>
<view class="cell user">{{ item.userName }}</view>
<view class="cell date-amount">
<text class="date">{{ formatDate(item.createTime) }}</text>
<text class="amount" :class="item.accountStr < 0 ? 'negative' : 'positive'">{{ item.accountStr }}</text>
</view>
</view>
<!-- 加载更多提示 -->
<view v-if="loading" class="loading-more">
<text>加载中...</text>
</view>
<!-- 空数据状态 -->
<view v-if="!loading && orderList.length === 0" class="empty-state">
<text>暂无交易记录</text>
</view>
<!-- 没有更多数据提示 -->
<view v-if="isLastPage && orderList.length > 0" class="no-more">
<text>没有更多数据了</text>
</view>
</scroll-view>
</view>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import api from '@/api/api.js'
// 响应式数据
const orderList = ref([])
const loading = ref(false)
const refreshing = ref(false)
const page = ref(1)
const total = ref(0)
const isFirstPage = ref(true)
const isLastPage = ref(false)
// 获取订单列表
const getOrderList = async (isRefresh = false) => {
if (loading.value) return
loading.value = true
try {
const res = await api.getOrderList({
page: page.value,
})
console.log('订单列表:', res)
if (res && res.code === 200 && res.data) {
const { list, total: totalCount, isFirstPage: firstPage, isLastPage: lastPage } = res.data
if (isRefresh) {
orderList.value = []
}
// 处理订单数据
const processedList = list.map(item => ({
id: item.trade_no,
typeName: item.type_name,
userName: item.user_name,
createTime: item.create_time,
accountStr: item.accountstr,
payChannel: item.pay_channel,
orderType: item.order_type,
status: item.status
}))
orderList.value.push(...processedList)
total.value = totalCount
isFirstPage.value = firstPage
isLastPage.value = lastPage
}
} catch (error) {
console.error('获取订单列表失败:', error)
uni.showToast({
title: '获取数据失败',
icon: 'none'
})
} finally {
loading.value = false
refreshing.value = false
}
}
// 刷新数据
const onRefresh = () => {
refreshing.value = true
page.value = 1
isLastPage.value = false
getOrderList(true)
}
// 加载更多
const onLoadMore = () => {
if (loading.value || isLastPage.value) return
page.value++
getOrderList()
}
// 格式化日期
const formatDate = (dateStr) => {
if (!dateStr) return ''
const date = new Date(dateStr)
const year = date.getFullYear()
const month = String(date.getMonth() + 1).padStart(2, '0')
const day = String(date.getDate()).padStart(2, '0')
return `${year}-${month}-${day}`
}
// 返回上一页
const goBack = () => {
uni.navigateBack()
}
onMounted(() => {
getOrderList()
})
</script>
<style lang="scss" scoped>
.bill-details-page {
background-color: #f5f5f5;
min-height: 100vh;
}
// 加载状态和空数据状态样式
.loading-more, .no-more, .empty-state {
text-align: center;
padding: 30rpx;
color: #999999;
font-size: 26rpx;
}
.empty-state {
padding: 100rpx 30rpx;
color: #999999;
}
// 表格头部样式
.table-header {
background-color: #e0e0e0;
display: flex;
padding: 20rpx 30rpx;
margin-top: 170rpx; /* 为固定导航栏留出空间 */
border-bottom: 1rpx solid #ccc;
.header-cell {
font-size: 28rpx;
color: #333;
font-weight: 500;
&.business-type {
flex: 1;
text-align: left;
}
&.user {
flex: 1;
text-align: center;
}
&.date-amount {
flex: 1;
text-align: right;
display: flex;
flex-direction: column;
align-items: flex-end;
.date-label {
font-size: 24rpx;
margin-bottom: 4rpx;
}
.amount-label {
font-size: 24rpx;
}
}
}
}
// 交易记录列表样式
.transaction-list {
background-color: #f5f5f5;
}
.transaction-item {
background-color: #f8f8f8;
display: flex;
padding: 20rpx 30rpx;
border-bottom: 1rpx solid #e5e5e5;
.cell {
font-size: 26rpx;
&.business-type {
flex: 1;
text-align: left;
color: #666;
}
&.user {
flex: 1;
text-align: center;
color: #ff0000;
}
&.date-amount {
flex: 1;
text-align: right;
display: flex;
flex-direction: column;
align-items: flex-end;
.date {
font-size: 24rpx;
color: #666;
margin-bottom: 4rpx;
}
.amount {
font-size: 24rpx;
&.positive {
color: #ff0000;
}
&.negative {
color: #666;
}
}
}
}
}
</style>
+284
View File
@@ -0,0 +1,284 @@
<template>
<view class="my-account-page">
<!-- 顶部导航栏 -->
<uni-nav-bar
left-icon="left"
title="我的账户"
@clickLeft="goBack"
fixed
color="#8B2316"
height="140rpx"
:border="false"
backgroundColor="#eeeeee"
></uni-nav-bar>
<!-- 账户余额区域 -->
<view class="account-summary">
<view class="profile-section">
<image class="profile-avatar" :src="avatar" mode="aspectFill"></image>
</view>
<text class="balance-label">账户余额(元)</text>
<text class="balance-amount">{{ (accountBalance/100).toFixed(2) }}</text>
<!-- 账户信息详情 -->
<view class="account-details">
<view class="detail-item">
<text class="detail-label">单次提现限额</text>
<text class="detail-value">{{ (withdrawalBalanceMaxOnce/100).toFixed(2) }}元</text>
</view>
<view class="detail-item">
<text class="detail-label">提现手续费</text>
<text class="detail-value">{{ (withdrawalBalanceFee/100).toFixed(2) }}元</text>
</view>
<view class="detail-item">
<text class="detail-label">最低提现金额</text>
<text class="detail-value">{{ (lessWithdrawalBalance/100).toFixed(2) }}元</text>
</view>
</view>
</view>
<!-- 操作选项 -->
<view class="action-items">
<view class="action-item" @click="handleWithdrawal">
<view class="action-icon withdrawal-icon">
<text class="icon-text">💰</text>
</view>
<view class="action-content">
<text class="action-title">提现</text>
<text class="action-subtitle">提现金额不得少于{{ (lessWithdrawalBalance/100).toFixed(2) }}元</text>
</view>
<text class="action-arrow">></text>
</view>
<view class="action-item" @click="handleBillDetails">
<view class="action-icon bill-icon">
<text class="icon-text">📋</text>
</view>
<view class="action-content">
<text class="action-title">账单明细</text>
</view>
<text class="action-arrow">></text>
</view>
</view>
<!-- 底部指示器 -->
<view class="bottom-indicator"></view>
</view>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import api from '@/api/api.js'
import docUrl from '@/utils/docUrl'
// 响应式数据
const accountBalance = ref(0)
const withdrawalBalanceMaxOnce = ref(0)
const withdrawalBalanceFee = ref(0)
const lessWithdrawalBalance = ref(0)
const avatar = ref('')
onMounted(() => {
getMyAccount()
let userInfo= uni.getStorageSync('userInfo')
avatar.value = docUrl+userInfo.photo
})
// 方法
const goBack = () => {
uni.navigateBack()
}
const handleWithdrawal = () => {
uni.showToast({
title: '提现功能开发中',
icon: 'none'
})
}
const handleBillDetails = () => {
uni.navigateTo({
url: '/pages_app/myAccount/billDetails'
})
}
const getMyAccount = async () => {
const res = await api.getMyAccount({})
console.log(res)
if (res && res.code === 200 && res.data) {
accountBalance.value = res.data.balance
withdrawalBalanceMaxOnce.value = res.data.withdrawalBalanceMaxOnce
withdrawalBalanceFee.value = res.data.withdrawalBalanceFee
lessWithdrawalBalance.value = res.data.lessWithdrawalBalance
}
}
</script>
<style lang="scss" scoped>
.my-account-page {
background-color: #f5f5f5;
min-height: 100vh;
position: relative;
}
// 账户余额区域样式
.account-summary {
background: linear-gradient(135deg, #8B2316, #A0522D);
margin: 30rpx;
border-radius: 20rpx;
padding: 60rpx 40rpx;
text-align: center;
box-shadow: 0 8rpx 24rpx rgba(139, 35, 22, 0.3);
position: relative;
.profile-section {
margin-bottom: 40rpx;
.profile-avatar {
width: 120rpx;
height: 120rpx;
border-radius: 60rpx;
border: 4rpx solid rgba(255, 255, 255, 0.3);
object-fit: cover;
}
}
.balance-label {
display: block;
color: rgba(255, 255, 255, 0.9);
font-size: 28rpx;
margin-bottom: 20rpx;
font-weight: 500;
}
.balance-amount {
display: block;
color: #ffffff;
font-size: 72rpx;
font-weight: bold;
text-shadow: 0 2rpx 4rpx rgba(0, 0, 0, 0.2);
letter-spacing: 2rpx;
margin-bottom: 40rpx;
}
// 账户信息详情样式
.account-details {
background: rgba(255, 255, 255, 0.1);
border-radius: 16rpx;
padding: 30rpx;
margin-top: 20rpx;
.detail-item {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20rpx;
&:last-child {
margin-bottom: 0;
}
.detail-label {
color: rgba(255, 255, 255, 0.8);
font-size: 24rpx;
font-weight: 400;
}
.detail-value {
color: #ffffff;
font-size: 26rpx;
font-weight: 500;
}
}
}
}
// 操作选项样式
.action-items {
background-color: #ffffff;
margin: 0 30rpx;
border-radius: 20rpx;
overflow: hidden;
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.08);
.action-item {
display: flex;
align-items: center;
padding: 40rpx 30rpx;
border-bottom: 1rpx solid #f0f0f0;
transition: background-color 0.2s ease;
&:last-child {
border-bottom: none;
}
&:active {
background-color: #f8f8f8;
}
.action-icon {
width: 60rpx;
height: 60rpx;
border-radius: 30rpx;
display: flex;
align-items: center;
justify-content: center;
margin-right: 30rpx;
background-color: #f8f8f8;
.icon-text {
font-size: 32rpx;
}
}
.withdrawal-icon {
background-color: #f5f5f5;
}
.bill-icon {
background-color: #fff8e1;
}
.action-content {
flex: 1;
.action-title {
display: block;
font-size: 32rpx;
color: #333;
font-weight: 500;
margin-bottom: 8rpx;
}
.action-subtitle {
display: block;
font-size: 24rpx;
color: #999;
line-height: 1.4;
font-weight: 400;
}
}
.action-arrow {
font-size: 32rpx;
color: #ccc;
font-weight: bold;
margin-left: 20rpx;
}
}
}
// 底部指示器
.bottom-indicator {
position: fixed;
bottom: 20rpx;
left: 50%;
transform: translateX(-50%);
width: 120rpx;
height: 6rpx;
background-color: #e0e0e0;
border-radius: 3rpx;
opacity: 0.6;
}
</style>