个人中心页面数据渲染

This commit is contained in:
WindowBird 2025-08-19 12:01:17 +08:00
parent d006184496
commit 1942e317bc
5 changed files with 240 additions and 111 deletions

View File

@ -30,19 +30,31 @@ if (response.code === 200) {
} }
``` ```
### 3. 获取用户统计 ### 3. 获取代理统计
```javascript ```javascript
import { getUserStats } from '@/api/user/user.js' import { getAgentCount } from '@/api/user/user.js'
// 获取用户统计信息 // 获取代理统计信息
const response = await getUserStats() const response = await getAgentCount()
if (response.code === 200) { if (response.code === 200) {
const userStats = response.data const agentStats = response.data
// userStats包含users, leases, amount等 // agentStats包含userNum, deviceNum, rentAmount等
} }
``` ```
### 4. 更新用户信息 ### 4. 获取用户列表
```javascript
import { getUserList } from '@/api/user/user.js'
// 获取用户列表
const response = await getUserList()
if (response.code === 200) {
const userList = response.data
// userList包含用户列表数据
}
```
### 5. 更新用户信息
```javascript ```javascript
import { updateUserInfo } from '@/api/user/user.js' import { updateUserInfo } from '@/api/user/user.js'
@ -81,18 +93,36 @@ const response = await updateUserInfo(userData)
} }
``` ```
### 用户统计 (UserStats) ### 代理统计 (AgentStats)
```javascript ```javascript
{ {
users: 30, // 名下用户数 userNum: 4, // 名下用户数
leases: 30, // 租赁数量 deviceNum: 1, // 设备数量
amount: 3000, // 租赁金额 rentAmount: 2 // 租赁数量
activeUsers: 25, // 活跃用户数
totalLeases: 45, // 总租赁数
totalAmount: 5000 // 总金额
} }
``` ```
### 用户列表 (UserList)
```javascript
[
{
id: 1, // 用户ID
username: '张三', // 用户名
totalAmount: '5000', // 总金额
deviceCount: 2, // 设备数量
devices: [ // 设备列表
{
type: '智能门锁', // 设备类型
amount: '1000', // 金额
rentDate: '2025.01.15', // 租赁日期
period: '1年', // 租赁周期
expiryDate: '2026.01.15' // 到期日期
}
]
}
]
```
## 错误处理 ## 错误处理
所有API都包含错误处理机制 所有API都包含错误处理机制
@ -133,7 +163,7 @@ export default {
const [userInfo, financial, stats] = await Promise.all([ const [userInfo, financial, stats] = await Promise.all([
getUserInfo(), getUserInfo(),
getUserFinancialData(), getUserFinancialData(),
getUserStats() getAgentCount()
]) ])
this.userInfo = userInfo.data this.userInfo = userInfo.data

View File

@ -18,13 +18,10 @@ export const mockFinancialData = {
withdrawedBalance: 0, withdrawedBalance: 0,
} }
export const mockUserStats = { export const mockAgentStats = {
users: 30, userNum: 4,
leases: 30, deviceNum: 1,
amount: 3000, rentAmount: 2,
activeUsers: 25,
totalLeases: 45,
totalAmount: 5000,
} }
// 模拟API响应格式 // 模拟API响应格式

View File

@ -1,5 +1,5 @@
import request from '@/utils/request' import request from '@/utils/request'
import { mockUserInfo, mockFinancialData, mockUserStats, createMockResponse } from './mockData.js' import { mockUserInfo, mockFinancialData, mockAgentStats, createMockResponse } from './mockData.js'
/** /**
* 获取用户信息 * 获取用户信息
@ -45,7 +45,97 @@ export function getUserStats() {
}).catch(error => { }).catch(error => {
console.warn('用户统计API调用失败使用模拟数据:', error) console.warn('用户统计API调用失败使用模拟数据:', error)
// 如果API调用失败返回模拟数据 // 如果API调用失败返回模拟数据
return createMockResponse(mockUserStats) return createMockResponse(mockAgentStats)
})
}
/**
* 获取代理统计数据
* @returns {Promise} 返回代理统计信息
*/
export function getAgentCount() {
return request({
url: '/app/order/agentCount',
method: 'GET',
showLoading: false,
}).catch(error => {
console.warn('代理统计API调用失败使用模拟数据:', error)
// 如果API调用失败返回模拟数据
return createMockResponse({
userNum: 4,
deviceNum: 1,
rentAmount: 2
})
})
}
/**
* 获取用户列表
* @param {Object} params - 查询参数
* @returns {Promise} 返回用户列表数据
*/
export function getUserList(params = {}) {
return request({
url: '/app/user/list',
method: 'GET',
params,
showLoading: false,
}).catch(error => {
console.warn('用户列表API调用失败使用模拟数据:', error)
// 如果API调用失败返回模拟数据
return createMockResponse([
{
id: 1,
username: '张三',
totalAmount: '5000',
deviceCount: 2,
devices: [
{
type: '智能门锁',
amount: '1000',
rentDate: '2025.01.15 12:56:08',
period: '1年',
expiryDate: '2026.01.15 12:56:08',
},
{
type: '智能摄像头',
amount: '800',
rentDate: '2025.02.20 10:30:00',
period: '6个月',
expiryDate: '2025.08.20 10:30:00',
},
],
},
{
id: 2,
username: '李四',
totalAmount: '3200',
deviceCount: 3,
devices: [
{
type: '智能门锁',
amount: '1200',
rentDate: '2025.03.10 14:20:00',
period: '1年',
expiryDate: '2026.03.10 14:20:00',
},
{
type: '智能摄像头',
amount: '600',
rentDate: '2025.04.05 09:15:00',
period: '3个月',
expiryDate: '2025.07.05 09:15:00',
},
{
type: '智能音箱',
amount: '400',
rentDate: '2025.05.12 16:45:00',
period: '6个月',
expiryDate: '2025.11.12 16:45:00',
},
],
},
])
}) })
} }

View File

@ -77,16 +77,16 @@
</view> </view>
<view class="user-stats"> <view class="user-stats">
<view class="stat-item"> <view class="stat-item">
<text class="stat-number">{{ userStats.users || 0 }}</text> <text class="stat-number">{{ userStats.userNum || 0 }}</text>
<text class="stat-label">名下用户()</text> <text class="stat-label">名下用户()</text>
</view> </view>
<view class="stat-item"> <view class="stat-item">
<text class="stat-number">{{ userStats.leases || 0 }}</text> <text class="stat-number">{{ userStats.deviceNum || 0 }}</text>
<text class="stat-label">租赁数量()</text> <text class="stat-label">设备数量()</text>
</view> </view>
<view class="stat-item"> <view class="stat-item">
<text class="stat-number">{{ userStats.amount || 0 }}</text> <text class="stat-number">{{ userStats.rentAmount || 0 }}</text>
<text class="stat-label">租赁金额()</text> <text class="stat-label">租赁数量()</text>
</view> </view>
</view> </view>
</view> </view>
@ -126,7 +126,7 @@
<script> <script>
import { commonEnum } from '@/enum/commonEnum.js' import { commonEnum } from '@/enum/commonEnum.js'
import { getUserInfo, getUserFinancialData, getUserStats } from '@/api/user/user.js' import { getUserInfo, getUserFinancialData, getAgentCount } from '@/api/user/user.js'
export default { export default {
name: 'ProfilePage', name: 'ProfilePage',
@ -146,9 +146,9 @@ export default {
withdrawedBalance: 0, withdrawedBalance: 0,
}, },
userStats: { userStats: {
users: 0, userNum: 0,
leases: 0, deviceNum: 0,
amount: 0, rentAmount: 0,
}, },
loading: false, loading: false,
} }
@ -190,13 +190,13 @@ export default {
console.log('财务数据获取成功:', this.financialData) console.log('财务数据获取成功:', this.financialData)
} }
// //
if (statsRes.status === 'fulfilled' && statsRes.value.code === 200) { if (statsRes.status === 'fulfilled' && statsRes.value.code === 200) {
this.userStats = { this.userStats = {
...this.userStats, ...this.userStats,
...statsRes.value.data ...statsRes.value.data
} }
console.log('用户统计获取成功:', this.userStats) console.log('代理统计获取成功:', this.userStats)
} }
} catch (error) { } catch (error) {
@ -250,20 +250,20 @@ export default {
} }
}, },
// //
async fetchUserStats() { async fetchUserStats() {
try { try {
const response = await getUserStats() const response = await getAgentCount()
return response return response
} catch (error) { } catch (error) {
console.error('获取用户统计失败:', error) console.error('获取代理统计失败:', error)
// 使 // 使
return { return {
code: 200, code: 200,
data: { data: {
users: 30, userNum: 4,
leases: 30, deviceNum: 1,
amount: 3000 rentAmount: 2
} }
} }
} }

View File

@ -1,5 +1,13 @@
<template> <template>
<view class="page"> <view class="page">
<!-- 加载状态 -->
<view v-if="loading" class="loading-overlay">
<view class="loading-content">
<view class="loading-spinner"></view>
<text class="loading-text">加载中...</text>
</view>
</view>
<!-- 搜索和筛选区域 --> <!-- 搜索和筛选区域 -->
<view class="search-filter-section"> <view class="search-filter-section">
<view class="search-box"> <view class="search-box">
@ -69,6 +77,7 @@
<script> <script>
import { commonEnum } from '@/enum/commonEnum.js' import { commonEnum } from '@/enum/commonEnum.js'
import { getUserList } from '@/api/user/user.js'
import UniIcons from '../../uni_modules/uni-icons/components/uni-icons/uni-icons.vue' import UniIcons from '../../uni_modules/uni-icons/components/uni-icons/uni-icons.vue'
export default { export default {
@ -76,77 +85,17 @@ export default {
data() { data() {
return { return {
searchKeyword: '', searchKeyword: '',
users: [ users: [],
{ loading: false,
id: 1,
username: '用户名',
totalAmount: '5000',
deviceCount: 2,
isExpanded: true,
devices: [
{
type: '密密麻麻',
amount: '1000',
rentDate: '2025.07.15 12:56:08',
period: '1年',
expiryDate: '2025.07.15 12:56:08',
},
{
type: '密密麻麻',
amount: '1000',
rentDate: '2025.07.15 12:56:08',
period: '1年',
expiryDate: '2025.07.15 12:56:08',
},
],
},
{
id: 2,
username: '用户名',
totalAmount: '5000',
deviceCount: 5,
isExpanded: false,
devices: [
{
type: '密密麻麻',
amount: '1000',
rentDate: '2025.07.15 12:56:08',
period: '1年',
expiryDate: '2025.07.15 12:56:08',
},
{
type: '密密麻麻',
amount: '1000',
rentDate: '2025.07.15 12:56:08',
period: '1年',
expiryDate: '2025.07.15 12:56:08',
},
{
type: '密密麻麻',
amount: '1000',
rentDate: '2025.07.15 12:56:08',
period: '1年',
expiryDate: '2025.07.15 12:56:08',
},
{
type: '密密麻麻',
amount: '1000',
rentDate: '2025.07.15 12:56:08',
period: '1年',
expiryDate: '2025.07.15 12:56:08',
},
{
type: '密密麻麻',
amount: '1000',
rentDate: '2025.07.15 12:56:08',
period: '1年',
expiryDate: '2025.07.15 12:56:08',
},
],
},
],
} }
}, },
onLoad() {
this.fetchUserList()
},
onShow() {
//
this.fetchUserList()
},
computed: { computed: {
filteredUsers() { filteredUsers() {
if (!this.searchKeyword) { if (!this.searchKeyword) {
@ -158,6 +107,30 @@ export default {
}, },
}, },
methods: { methods: {
//
async fetchUserList() {
this.loading = true
try {
const response = await getUserList()
if (response.code === 200 && response.data && Array.isArray(response.data)) {
//
this.users = response.data.map(user => ({
...user,
isExpanded: false //
}))
console.log('用户列表获取成功:', this.users)
}
} catch (error) {
console.error('获取用户列表失败:', error)
uni.showToast({
title: '数据加载失败',
icon: 'none',
})
} finally {
this.loading = false
}
},
onSearch() { onSearch() {
// computed // computed
}, },
@ -179,8 +152,47 @@ export default {
.page { .page {
min-height: 90vh; min-height: 90vh;
background: #f7f7f7; background: #f7f7f7;
padding-bottom: 40rpx; padding-bottom: 40rpx;
position: relative;
}
.loading-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(255, 255, 255, 0.8);
display: flex;
align-items: center;
justify-content: center;
z-index: 9999;
}
.loading-content {
display: flex;
flex-direction: column;
align-items: center;
gap: 20rpx;
}
.loading-spinner {
width: 60rpx;
height: 60rpx;
border: 4rpx solid #f3f3f3;
border-top: 4rpx solid #007aff;
border-radius: 50%;
animation: spin 1s linear infinite;
}
.loading-text {
font-size: 28rpx;
color: #666;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
} }
.search-filter-section { .search-filter-section {