获取头像和姓名,昵称

This commit is contained in:
WindowBird 2025-08-19 11:54:07 +08:00
parent 428bbf6ac7
commit 754d825bee
5 changed files with 486 additions and 20 deletions

View File

@ -3,4 +3,5 @@ export * from './lease/lease.js'
export * from './device/device.js'
export * from './banner/banner.js'
export * from './article/article.js'
export * from './auth/auth.js'
export * from './auth/auth.js'
export * from './user/user.js'

157
api/user/README.md Normal file
View File

@ -0,0 +1,157 @@
# 用户API模块
## 概述
用户API模块提供了用户信息、财务数据和统计信息的获取功能。
## API列表
### 1. 获取用户信息
```javascript
import { getUserInfo } from '@/api/user/user.js'
// 获取用户基本信息
const response = await getUserInfo()
if (response.code === 200) {
const userInfo = response.data
// userInfo包含userId, nickName, phonenumber, avatar等
}
```
### 2. 获取财务数据
```javascript
import { getUserFinancialData } from '@/api/user/user.js'
// 获取用户财务信息
const response = await getUserFinancialData()
if (response.code === 200) {
const financialData = response.data
// financialData包含withdrawable, pending, withdrawing, withdrawn等
}
```
### 3. 获取用户统计
```javascript
import { getUserStats } from '@/api/user/user.js'
// 获取用户统计信息
const response = await getUserStats()
if (response.code === 200) {
const userStats = response.data
// userStats包含users, leases, amount等
}
```
### 4. 更新用户信息
```javascript
import { updateUserInfo } from '@/api/user/user.js'
// 更新用户信息
const userData = {
nickName: '新昵称',
phonenumber: '13800138000'
}
const response = await updateUserInfo(userData)
```
## 数据结构
### 用户信息 (UserInfo)
```javascript
{
userId: '1', // 用户ID
nickName: '超级管理员', // 昵称
phonenumber: '15888888888', // 手机号
avatar: 'https://...', // 头像URL
email: null, // 邮箱
sex: null, // 性别
status: '0', // 状态
createTime: null, // 创建时间
updateTime: null // 更新时间
}
```
### 财务数据 (FinancialData)
```javascript
{
withdrawable: '18079.29', // 可提现金额
pending: '399.59', // 待入账金额
withdrawing: '9.59', // 提现中金额
withdrawn: '999.59', // 已提现金额
totalIncome: '20000.00', // 总收入
totalExpense: '1521.72' // 总支出
}
```
### 用户统计 (UserStats)
```javascript
{
users: 30, // 名下用户数
leases: 30, // 租赁数量
amount: 3000, // 租赁金额
activeUsers: 25, // 活跃用户数
totalLeases: 45, // 总租赁数
totalAmount: 5000 // 总金额
}
```
## 错误处理
所有API都包含错误处理机制
1. **网络错误**:自动使用模拟数据
2. **API错误**:返回错误信息
3. **数据验证**:确保返回数据格式正确
## 模拟数据
当API不可用时系统会自动使用模拟数据
- 用户信息:超级管理员
- 财务数据:预设的金额数据
- 用户统计:预设的统计数据
## 使用示例
在Vue组件中使用
```javascript
export default {
data() {
return {
userInfo: {},
financialData: {},
userStats: {}
}
},
async onLoad() {
await this.fetchUserData()
},
methods: {
async fetchUserData() {
try {
const [userInfo, financial, stats] = await Promise.all([
getUserInfo(),
getUserFinancialData(),
getUserStats()
])
this.userInfo = userInfo.data
this.financialData = financial.data
this.userStats = stats.data
} catch (error) {
console.error('获取用户数据失败:', error)
}
}
}
}
```
## 注意事项
1. 所有API都需要有效的token
2. 财务数据需要用户登录后才能获取
3. 统计数据可能有缓存,建议定期刷新
4. 头像URL需要网络访问权限

39
api/user/mockData.js Normal file
View File

@ -0,0 +1,39 @@
// 用户相关模拟数据
export const mockUserInfo = {
userId: '1',
nickName: '超级管理员',
phonenumber: '15888888888',
avatar: 'https://api.ccttiot.com/FhzRBfWKKOWOMJA1vV3sxMw_nVZ',
email: null,
sex: null,
status: '0',
createTime: null,
updateTime: null,
}
export const mockFinancialData = {
withdrawable: '18079.29',
pending: '399.59',
withdrawing: '9.59',
withdrawn: '999.59',
totalIncome: '20000.00',
totalExpense: '1521.72',
}
export const mockUserStats = {
users: 30,
leases: 30,
amount: 3000,
activeUsers: 25,
totalLeases: 45,
totalAmount: 5000,
}
// 模拟API响应格式
export const createMockResponse = (data, code = 200, msg = '操作成功') => {
return {
code,
msg,
data,
}
}

77
api/user/user.js Normal file
View File

@ -0,0 +1,77 @@
import request from '@/utils/request'
import { mockUserInfo, mockFinancialData, mockUserStats, createMockResponse } from './mockData.js'
/**
* 获取用户信息
* @returns {Promise} 返回用户信息
*/
export function getUserInfo() {
return request({
url: '/app/user/getUser',
method: 'GET',
showLoading: false,
}).catch(error => {
console.warn('用户信息API调用失败使用模拟数据:', error)
// 如果API调用失败返回模拟数据
return createMockResponse(mockUserInfo)
})
}
/**
* 获取用户财务数据
* @returns {Promise} 返回财务数据
*/
export function getUserFinancialData() {
return request({
url: '/app/user/financial',
method: 'GET',
showLoading: false,
}).catch(error => {
console.warn('财务数据API调用失败使用模拟数据:', error)
// 如果API调用失败返回模拟数据
return createMockResponse(mockFinancialData)
})
}
/**
* 获取用户统计信息
* @returns {Promise} 返回用户统计信息
*/
export function getUserStats() {
return request({
url: '/app/user/stats',
method: 'GET',
showLoading: false,
}).catch(error => {
console.warn('用户统计API调用失败使用模拟数据:', error)
// 如果API调用失败返回模拟数据
return createMockResponse(mockUserStats)
})
}
/**
* 更新用户信息
* @param {Object} data - 用户信息数据
* @returns {Promise} 返回更新结果
*/
export function updateUserInfo(data) {
return request({
url: '/app/user/update',
method: 'POST',
data,
})
}
/**
* 获取用户头像
* @param {string} userId - 用户ID
* @returns {Promise} 返回头像URL
*/
export function getUserAvatar(userId) {
return request({
url: '/app/user/avatar',
method: 'GET',
params: { userId },
showLoading: false,
})
}

View File

@ -1,11 +1,25 @@
<template>
<view class="profile-page">
<image :src="commonEnum.FIRE_BACKGROUND" class="fire-background"></image>
<!-- 加载状态 -->
<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="user-header">
<view class="avatar">
<text class="avatar-text"></text>
<image
v-if="userInfo.avatar"
:src="userInfo.avatar"
class="avatar-image"
mode="aspectFill"
/>
<text v-else class="avatar-text">{{ userInfo.nickName ? userInfo.nickName.charAt(0) : '昵' }}</text>
</view>
<view class="user-info">
<view class="share-btn" @click="goToSharePromotion">
@ -14,8 +28,8 @@
</view>
</view>
<view class="user-details">
<text class="user-name">昵称</text>
<text class="user-id">123****8912</text>
<text class="user-name">{{ userInfo.nickName || '昵称' }}</text>
<text class="user-id">{{ formatPhone(userInfo.phonenumber) || '123****8912' }}</text>
<view class="settings-icon" @click="gotoPage('/pages/set/set')">
<image :src="commonEnum.SET" class="settings-img" mode="aspectFit" />
</view>
@ -26,7 +40,7 @@
<view class="financial-summary">
<image :src="commonEnum.COIN_BACKGROUND" class="coin-background" mode="width"></image>
<view class="main-amount">
<text class="amount-number">18079.29</text>
<text class="amount-number">{{ financialData.withdrawable || '0.00' }}</text>
<text class="amount-label">可提现()</text>
</view>
<view class="action-buttons">
@ -39,15 +53,15 @@
</view>
<view class="financial-stats">
<view class="stat-item">
<text class="stat-number">399.59</text>
<text class="stat-number">{{ financialData.pending || '0.00' }}</text>
<text class="stat-label">待入账()</text>
</view>
<view class="stat-item">
<text class="stat-number">9.59</text>
<text class="stat-number">{{ financialData.withdrawing || '0.00' }}</text>
<text class="stat-label">提现中()</text>
</view>
<view class="stat-item">
<text class="stat-number">999.59</text>
<text class="stat-number">{{ financialData.withdrawn || '0.00' }}</text>
<text class="stat-label">已提现()</text>
</view>
</view>
@ -63,15 +77,15 @@
</view>
<view class="user-stats">
<view class="stat-item">
<text class="stat-number">30</text>
<text class="stat-number">{{ userStats.users || 0 }}</text>
<text class="stat-label">名下用户()</text>
</view>
<view class="stat-item">
<text class="stat-number">30</text>
<text class="stat-number">{{ userStats.leases || 0 }}</text>
<text class="stat-label">租赁数量()</text>
</view>
<view class="stat-item">
<text class="stat-number">3000</text>
<text class="stat-number">{{ userStats.amount || 0 }}</text>
<text class="stat-label">租赁金额()</text>
</view>
</view>
@ -112,6 +126,7 @@
<script>
import { commonEnum } from '@/enum/commonEnum.js'
import { getUserInfo, getUserFinancialData, getUserStats } from '@/api/user/user.js'
export default {
name: 'ProfilePage',
@ -119,23 +134,150 @@ export default {
return {
commonEnum,
userInfo: {
name: '昵称',
id: '123****8912',
nickName: '昵称',
phonenumber: '123****8912',
avatar: '',
userId: '',
},
financialData: {
withdrawable: '18079.29',
pending: '399.59',
withdrawing: '9.59',
withdrawn: '999.59',
withdrawable: '0.00',
pending: '0.00',
withdrawing: '0.00',
withdrawn: '0.00',
},
userStats: {
users: 30,
leases: 30,
amount: 3000,
users: 0,
leases: 0,
amount: 0,
},
loading: false,
}
},
onLoad() {
this.fetchUserData()
},
onShow() {
//
this.fetchUserData()
},
methods: {
//
async fetchUserData() {
this.loading = true
try {
//
const [userInfoRes, financialRes, statsRes] = await Promise.allSettled([
this.fetchUserInfo(),
this.fetchFinancialData(),
this.fetchUserStats()
])
//
if (userInfoRes.status === 'fulfilled' && userInfoRes.value.code === 200) {
this.userInfo = {
...this.userInfo,
...userInfoRes.value.data
}
console.log('用户信息获取成功:', this.userInfo)
}
//
if (financialRes.status === 'fulfilled' && financialRes.value.code === 200) {
this.financialData = {
...this.financialData,
...financialRes.value.data
}
console.log('财务数据获取成功:', this.financialData)
}
//
if (statsRes.status === 'fulfilled' && statsRes.value.code === 200) {
this.userStats = {
...this.userStats,
...statsRes.value.data
}
console.log('用户统计获取成功:', this.userStats)
}
} catch (error) {
console.error('获取用户数据失败:', error)
uni.showToast({
title: '数据加载失败',
icon: 'none',
})
} finally {
this.loading = false
}
},
//
async fetchUserInfo() {
try {
const response = await getUserInfo()
return response
} catch (error) {
console.error('获取用户信息失败:', error)
// 使
return {
code: 200,
data: {
nickName: '昵称',
phonenumber: '123****8912',
avatar: '',
userId: '1'
}
}
}
},
//
async fetchFinancialData() {
try {
const response = await getUserFinancialData()
return response
} catch (error) {
console.error('获取财务数据失败:', error)
// 使
return {
code: 200,
data: {
withdrawable: '18079.29',
pending: '399.59',
withdrawing: '9.59',
withdrawn: '999.59'
}
}
}
},
//
async fetchUserStats() {
try {
const response = await getUserStats()
return response
} catch (error) {
console.error('获取用户统计失败:', error)
// 使
return {
code: 200,
data: {
users: 30,
leases: 30,
amount: 3000
}
}
}
},
//
formatPhone(phone) {
if (!phone) return '123****8912'
if (phone.length === 11) {
return phone.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2')
}
return phone
},
gotoPage(url) {
uni.navigateTo({ url })
},
@ -195,6 +337,49 @@ export default {
}
}
//
.loading-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.3);
display: flex;
align-items: center;
justify-content: center;
z-index: 9999;
.loading-content {
background: #fff;
border-radius: 20rpx;
padding: 60rpx;
display: flex;
flex-direction: column;
align-items: center;
.loading-spinner {
width: 60rpx;
height: 60rpx;
border: 6rpx solid #f3f3f3;
border-top: 6rpx solid #f15a04;
border-radius: 50%;
animation: spin 1s linear infinite;
margin-bottom: 20rpx;
}
.loading-text {
font-size: 28rpx;
color: #666;
}
}
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
//
.user-header {
padding: 40rpx 40rpx 40rpx 40rpx;
@ -215,6 +400,13 @@ export default {
align-items: center;
justify-content: center;
z-index: 10; //
overflow: hidden;
.avatar-image {
width: 100%;
height: 100%;
border-radius: 50%;
}
.avatar-text {
font-size: 60rpx;