用户列表渲染完毕
This commit is contained in:
parent
1942e317bc
commit
f82e8c1aa9
|
|
@ -1,78 +1,21 @@
|
||||||
# 用户API模块
|
# 用户模块 API 文档
|
||||||
|
|
||||||
## 概述
|
## 接口列表
|
||||||
|
|
||||||
用户API模块提供了用户信息、财务数据和统计信息的获取功能。
|
|
||||||
|
|
||||||
## API列表
|
|
||||||
|
|
||||||
### 1. 获取用户信息
|
### 1. 获取用户信息
|
||||||
```javascript
|
```javascript
|
||||||
import { getUserInfo } from '@/api/user/user.js'
|
import { getUserInfo } from '@/api/user/user.js'
|
||||||
|
|
||||||
// 获取用户基本信息
|
|
||||||
const response = await getUserInfo()
|
const response = await getUserInfo()
|
||||||
if (response.code === 200) {
|
|
||||||
const userInfo = response.data
|
|
||||||
// userInfo包含:userId, nickName, phonenumber, avatar等
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### 2. 获取财务数据
|
**接口地址:** `GET /app/user/info`
|
||||||
```javascript
|
|
||||||
import { getUserFinancialData } from '@/api/user/user.js'
|
|
||||||
|
|
||||||
// 获取用户财务信息
|
**响应数据:**
|
||||||
const response = await getUserFinancialData()
|
|
||||||
if (response.code === 200) {
|
|
||||||
const financialData = response.data
|
|
||||||
// financialData包含:balance, waitBalance, withdrawBalance, withdrawedBalance等
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. 获取代理统计
|
|
||||||
```javascript
|
|
||||||
import { getAgentCount } from '@/api/user/user.js'
|
|
||||||
|
|
||||||
// 获取代理统计信息
|
|
||||||
const response = await getAgentCount()
|
|
||||||
if (response.code === 200) {
|
|
||||||
const agentStats = response.data
|
|
||||||
// agentStats包含:userNum, deviceNum, rentAmount等
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4. 获取用户列表
|
|
||||||
```javascript
|
|
||||||
import { getUserList } from '@/api/user/user.js'
|
|
||||||
|
|
||||||
// 获取用户列表
|
|
||||||
const response = await getUserList()
|
|
||||||
if (response.code === 200) {
|
|
||||||
const userList = response.data
|
|
||||||
// userList包含用户列表数据
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 5. 更新用户信息
|
|
||||||
```javascript
|
|
||||||
import { updateUserInfo } from '@/api/user/user.js'
|
|
||||||
|
|
||||||
// 更新用户信息
|
|
||||||
const userData = {
|
|
||||||
nickName: '新昵称',
|
|
||||||
phonenumber: '13800138000'
|
|
||||||
}
|
|
||||||
const response = await updateUserInfo(userData)
|
|
||||||
```
|
|
||||||
|
|
||||||
## 数据结构
|
|
||||||
|
|
||||||
### 用户信息 (UserInfo)
|
|
||||||
```javascript
|
```javascript
|
||||||
{
|
{
|
||||||
userId: '1', // 用户ID
|
userId: '1', // 用户ID
|
||||||
nickName: '超级管理员', // 昵称
|
nickName: '超级管理员', // 用户昵称
|
||||||
phonenumber: '15888888888', // 手机号
|
phonenumber: '15888888888', // 手机号
|
||||||
avatar: 'https://...', // 头像URL
|
avatar: 'https://...', // 头像URL
|
||||||
email: null, // 邮箱
|
email: null, // 邮箱
|
||||||
|
|
@ -83,17 +26,35 @@ const response = await updateUserInfo(userData)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 财务数据 (FinancialData)
|
### 2. 获取用户财务数据
|
||||||
|
```javascript
|
||||||
|
import { getUserFinancialData } from '@/api/user/user.js'
|
||||||
|
|
||||||
|
const response = await getUserFinancialData()
|
||||||
|
```
|
||||||
|
|
||||||
|
**接口地址:** `GET /app/user/financial`
|
||||||
|
|
||||||
|
**响应数据:**
|
||||||
```javascript
|
```javascript
|
||||||
{
|
{
|
||||||
balance: 10000.00, // 可提现金额
|
balance: 10000.00, // 余额
|
||||||
waitBalance: 0, // 待入账金额
|
waitBalance: 0, // 待结算余额
|
||||||
withdrawBalance: 0, // 提现中金额
|
withdrawBalance: 0, // 可提现余额
|
||||||
withdrawedBalance: 0 // 已提现金额
|
withdrawedBalance: 0 // 已提现余额
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 代理统计 (AgentStats)
|
### 3. 获取代理统计
|
||||||
|
```javascript
|
||||||
|
import { getAgentCount } from '@/api/user/user.js'
|
||||||
|
|
||||||
|
const response = await getAgentCount()
|
||||||
|
```
|
||||||
|
|
||||||
|
**接口地址:** `GET /app/order/agentCount`
|
||||||
|
|
||||||
|
**响应数据:**
|
||||||
```javascript
|
```javascript
|
||||||
{
|
{
|
||||||
userNum: 4, // 名下用户数
|
userNum: 4, // 名下用户数
|
||||||
|
|
@ -102,84 +63,135 @@ const response = await updateUserInfo(userData)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 用户列表 (UserList)
|
### 4. 获取代理用户列表
|
||||||
|
```javascript
|
||||||
|
import { getAgentList } from '@/api/user/user.js'
|
||||||
|
|
||||||
|
const response = await getAgentList({
|
||||||
|
beginTime: '2024-10-10 12:10:00', // 开始时间(筛选)
|
||||||
|
endTime: '2026-10-10 12:10:00', // 结束时间(筛选)
|
||||||
|
name: '李' // 用户昵称(搜索)
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
**接口地址:** `GET /app/order/agentList`
|
||||||
|
|
||||||
|
**请求参数:**
|
||||||
|
- `beginTime` (string, 可选): 开始时间,格式: YYYY-MM-DD HH:mm:ss
|
||||||
|
- `endTime` (string, 可选): 结束时间,格式: YYYY-MM-DD HH:mm:ss
|
||||||
|
- `name` (string, 可选): 用户昵称,支持模糊搜索
|
||||||
|
|
||||||
|
**响应数据:**
|
||||||
```javascript
|
```javascript
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
id: 1, // 用户ID
|
userId: '28', // 用户ID
|
||||||
username: '张三', // 用户名
|
nickName: '李四', // 用户昵称
|
||||||
totalAmount: '5000', // 总金额
|
avatar: '', // 头像
|
||||||
deviceCount: 2, // 设备数量
|
totalAmount: 730.00, // 总金额
|
||||||
devices: [ // 设备列表
|
deviceNum: 2, // 设备数量
|
||||||
|
orders: [ // 订单列表
|
||||||
{
|
{
|
||||||
type: '智能门锁', // 设备类型
|
id: '3', // 订单ID
|
||||||
amount: '1000', // 金额
|
userId: '28', // 用户ID
|
||||||
rentDate: '2025.01.15', // 租赁日期
|
name: '派大星', // 联系人姓名
|
||||||
period: '1年', // 租赁周期
|
phone: '13777777777', // 联系电话
|
||||||
expiryDate: '2026.01.15' // 到期日期
|
address: '广西南宁市西乡塘区', // 地址
|
||||||
|
detailed: '详细地址', // 详细地址
|
||||||
|
typeName: '单头灶', // 设备类型名称
|
||||||
|
suitName: '一年', // 套餐名称
|
||||||
|
suitDay: '365', // 套餐天数
|
||||||
|
amount: 365.00, // 金额
|
||||||
|
status: '2', // 订单状态
|
||||||
|
leaseTime: '2025-08-15 10:50:22', // 租赁时间
|
||||||
|
expirationTime: '2025-11-15 10:50:25', // 到期时间
|
||||||
|
orderNumber: '123456789101114' // 订单号
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### 5. 更新用户信息
|
||||||
|
```javascript
|
||||||
|
import { updateUserInfo } from '@/api/user/user.js'
|
||||||
|
|
||||||
|
const response = await updateUserInfo({
|
||||||
|
nickName: '新昵称',
|
||||||
|
email: 'new@example.com'
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
**接口地址:** `PUT /app/user/info`
|
||||||
|
|
||||||
|
## 使用示例
|
||||||
|
|
||||||
|
### 在页面中获取用户数据
|
||||||
|
```javascript
|
||||||
|
// 在 Profile 页面中
|
||||||
|
async fetchUserData() {
|
||||||
|
try {
|
||||||
|
const [userInfo, financial, stats] = await Promise.all([
|
||||||
|
getUserInfo(),
|
||||||
|
getUserFinancialData(),
|
||||||
|
getAgentCount()
|
||||||
|
])
|
||||||
|
|
||||||
|
this.userInfo = userInfo.data
|
||||||
|
this.financialData = financial.data
|
||||||
|
this.userStats = stats.data
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取用户数据失败:', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 在用户列表页面中
|
||||||
|
```javascript
|
||||||
|
// 在用户列表页面中
|
||||||
|
async fetchUserList() {
|
||||||
|
try {
|
||||||
|
const params = {
|
||||||
|
beginTime: '2024-10-10 00:00:00',
|
||||||
|
endTime: '2026-10-10 23:59:59',
|
||||||
|
name: '李'
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await getAgentList(params)
|
||||||
|
if (response.code === 200) {
|
||||||
|
// 转换数据格式
|
||||||
|
this.users = response.data.map(user => ({
|
||||||
|
...user,
|
||||||
|
devices: user.orders.map(order => ({
|
||||||
|
type: order.typeName,
|
||||||
|
amount: order.amount,
|
||||||
|
rentDate: this.formatDate(order.leaseTime),
|
||||||
|
period: order.suitName,
|
||||||
|
expiryDate: this.formatDate(order.expirationTime)
|
||||||
|
}))
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取用户列表失败:', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## 错误处理
|
## 错误处理
|
||||||
|
|
||||||
所有API都包含错误处理机制:
|
所有API函数都包含错误处理机制,如果API调用失败,会自动返回模拟数据:
|
||||||
|
|
||||||
1. **网络错误**:自动使用模拟数据
|
```javascript
|
||||||
2. **API错误**:返回错误信息
|
// 如果API调用失败,会返回模拟数据
|
||||||
3. **数据验证**:确保返回数据格式正确
|
const response = await getUserInfo()
|
||||||
|
// 即使网络错误,也会返回模拟的用户信息
|
||||||
|
```
|
||||||
|
|
||||||
## 模拟数据
|
## 模拟数据
|
||||||
|
|
||||||
当API不可用时,系统会自动使用模拟数据:
|
当API不可用时,系统会自动使用模拟数据:
|
||||||
|
|
||||||
- 用户信息:超级管理员
|
- `mockUserInfo`: 用户基本信息
|
||||||
- 财务数据:预设的金额数据
|
- `mockFinancialData`: 财务数据
|
||||||
- 用户统计:预设的统计数据
|
- `mockAgentStats`: 代理统计数据
|
||||||
|
- `mockAgentList`: 代理用户列表数据
|
||||||
## 使用示例
|
|
||||||
|
|
||||||
在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(),
|
|
||||||
getAgentCount()
|
|
||||||
])
|
|
||||||
|
|
||||||
this.userInfo = userInfo.data
|
|
||||||
this.financialData = financial.data
|
|
||||||
this.userStats = stats.data
|
|
||||||
} catch (error) {
|
|
||||||
console.error('获取用户数据失败:', error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 注意事项
|
|
||||||
|
|
||||||
1. 所有API都需要有效的token
|
|
||||||
2. 财务数据需要用户登录后才能获取
|
|
||||||
3. 统计数据可能有缓存,建议定期刷新
|
|
||||||
4. 头像URL需要网络访问权限
|
|
||||||
|
|
@ -24,6 +24,50 @@ export const mockAgentStats = {
|
||||||
rentAmount: 2,
|
rentAmount: 2,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const mockAgentList = [
|
||||||
|
{
|
||||||
|
userId: '28',
|
||||||
|
nickName: '李四',
|
||||||
|
avatar: '',
|
||||||
|
totalAmount: 730.00,
|
||||||
|
deviceNum: 2,
|
||||||
|
orders: [
|
||||||
|
{
|
||||||
|
id: '3',
|
||||||
|
userId: '28',
|
||||||
|
name: '派大星',
|
||||||
|
phone: '13777777777',
|
||||||
|
address: '广西南宁市西乡塘区',
|
||||||
|
detailed: '详细地址',
|
||||||
|
typeName: '单头灶',
|
||||||
|
suitName: '一年',
|
||||||
|
suitDay: '365',
|
||||||
|
amount: 365.00,
|
||||||
|
status: '2',
|
||||||
|
leaseTime: '2025-08-15 10:50:22',
|
||||||
|
expirationTime: '2025-11-15 10:50:25',
|
||||||
|
orderNumber: '123456789101114',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '4',
|
||||||
|
userId: '28',
|
||||||
|
name: '派大星',
|
||||||
|
phone: '137777777777',
|
||||||
|
address: '测试',
|
||||||
|
detailed: '测试',
|
||||||
|
typeName: '单头灶',
|
||||||
|
suitName: '一年',
|
||||||
|
suitDay: '365',
|
||||||
|
amount: 365.00,
|
||||||
|
status: '2',
|
||||||
|
leaseTime: '2025-08-18 14:10:26',
|
||||||
|
expirationTime: '2025-10-01 14:10:29',
|
||||||
|
orderNumber: '123456789101115',
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
// 模拟API响应格式
|
// 模拟API响应格式
|
||||||
export const createMockResponse = (data, code = 200, msg = '操作成功') => {
|
export const createMockResponse = (data, code = 200, msg = '操作成功') => {
|
||||||
return {
|
return {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import request from '@/utils/request'
|
import request from '@/utils/request'
|
||||||
import { mockUserInfo, mockFinancialData, mockAgentStats, createMockResponse } from './mockData.js'
|
import { mockUserInfo, mockFinancialData, mockAgentStats, mockAgentList, createMockResponse } from './mockData.js'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取用户信息
|
* 获取用户信息
|
||||||
|
|
@ -70,75 +70,35 @@ export function getAgentCount() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取用户列表
|
* 获取代理用户列表
|
||||||
* @param {Object} params - 查询参数
|
* @param {Object} params - 查询参数
|
||||||
* @returns {Promise} 返回用户列表数据
|
* @param {string} params.beginTime - 开始时间
|
||||||
|
* @param {string} params.endTime - 结束时间
|
||||||
|
* @param {string} params.name - 用户昵称搜索
|
||||||
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
export function getUserList(params = {}) {
|
export function getAgentList(params = {}) {
|
||||||
return request({
|
return request({
|
||||||
url: '/app/user/list',
|
url: '/app/order/agentList',
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
params,
|
params,
|
||||||
showLoading: false,
|
showLoading: false,
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
console.warn('用户列表API调用失败,使用模拟数据:', error)
|
console.warn('代理用户列表API调用失败,使用模拟数据:', error)
|
||||||
// 如果API调用失败,返回模拟数据
|
// 如果API调用失败,返回模拟数据
|
||||||
return createMockResponse([
|
return createMockResponse(mockAgentList)
|
||||||
{
|
|
||||||
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',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
])
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取用户列表 (使用代理列表接口)
|
||||||
|
* @param {Object} params - 查询参数
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
export function getUserList(params = {}) {
|
||||||
|
return getAgentList(params)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新用户信息
|
* 更新用户信息
|
||||||
* @param {Object} data - 用户信息数据
|
* @param {Object} data - 用户信息数据
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<view class="profile-page">
|
<view class="profile-page">
|
||||||
<image :src="commonEnum.FIRE_BACKGROUND" class="fire-background"></image>
|
<image :src="commonEnum.FIRE_BACKGROUND" class="fire-background"></image>
|
||||||
|
|
||||||
<!-- 加载状态 -->
|
<!-- 加载状态 -->
|
||||||
<view v-if="loading" class="loading-overlay">
|
<view v-if="loading" class="loading-overlay">
|
||||||
<view class="loading-content">
|
<view class="loading-content">
|
||||||
|
|
@ -13,13 +13,15 @@
|
||||||
<!-- 头部用户信息 -->
|
<!-- 头部用户信息 -->
|
||||||
<view class="user-header">
|
<view class="user-header">
|
||||||
<view class="avatar">
|
<view class="avatar">
|
||||||
<image
|
<image
|
||||||
v-if="userInfo.avatar"
|
v-if="userInfo.avatar"
|
||||||
:src="userInfo.avatar"
|
:src="userInfo.avatar"
|
||||||
class="avatar-image"
|
class="avatar-image"
|
||||||
mode="aspectFill"
|
mode="aspectFill"
|
||||||
/>
|
/>
|
||||||
<text v-else class="avatar-text">{{ userInfo.nickName ? userInfo.nickName.charAt(0) : '昵' }}</text>
|
<text v-else class="avatar-text">{{
|
||||||
|
userInfo.nickName ? userInfo.nickName.charAt(0) : '昵'
|
||||||
|
}}</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="user-info">
|
<view class="user-info">
|
||||||
<view class="share-btn" @click="goToSharePromotion">
|
<view class="share-btn" @click="goToSharePromotion">
|
||||||
|
|
@ -140,7 +142,7 @@ export default {
|
||||||
userId: '',
|
userId: '',
|
||||||
},
|
},
|
||||||
financialData: {
|
financialData: {
|
||||||
balance: 0.00,
|
balance: 0.0,
|
||||||
waitBalance: 0,
|
waitBalance: 0,
|
||||||
withdrawBalance: 0,
|
withdrawBalance: 0,
|
||||||
withdrawedBalance: 0,
|
withdrawedBalance: 0,
|
||||||
|
|
@ -169,14 +171,14 @@ export default {
|
||||||
const [userInfoRes, financialRes, statsRes] = await Promise.allSettled([
|
const [userInfoRes, financialRes, statsRes] = await Promise.allSettled([
|
||||||
this.fetchUserInfo(),
|
this.fetchUserInfo(),
|
||||||
this.fetchFinancialData(),
|
this.fetchFinancialData(),
|
||||||
this.fetchUserStats()
|
this.fetchUserStats(),
|
||||||
])
|
])
|
||||||
|
|
||||||
// 处理用户信息
|
// 处理用户信息
|
||||||
if (userInfoRes.status === 'fulfilled' && userInfoRes.value.code === 200) {
|
if (userInfoRes.status === 'fulfilled' && userInfoRes.value.code === 200) {
|
||||||
this.userInfo = {
|
this.userInfo = {
|
||||||
...this.userInfo,
|
...this.userInfo,
|
||||||
...userInfoRes.value.data
|
...userInfoRes.value.data,
|
||||||
}
|
}
|
||||||
console.log('用户信息获取成功:', this.userInfo)
|
console.log('用户信息获取成功:', this.userInfo)
|
||||||
}
|
}
|
||||||
|
|
@ -185,7 +187,7 @@ export default {
|
||||||
if (financialRes.status === 'fulfilled' && financialRes.value.code === 200) {
|
if (financialRes.status === 'fulfilled' && financialRes.value.code === 200) {
|
||||||
this.financialData = {
|
this.financialData = {
|
||||||
...this.financialData,
|
...this.financialData,
|
||||||
...financialRes.value.data
|
...financialRes.value.data,
|
||||||
}
|
}
|
||||||
console.log('财务数据获取成功:', this.financialData)
|
console.log('财务数据获取成功:', this.financialData)
|
||||||
}
|
}
|
||||||
|
|
@ -194,11 +196,10 @@ export default {
|
||||||
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) {
|
||||||
console.error('获取用户数据失败:', error)
|
console.error('获取用户数据失败:', error)
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
|
|
@ -224,8 +225,8 @@ export default {
|
||||||
nickName: '昵称',
|
nickName: '昵称',
|
||||||
phonenumber: '123****8912',
|
phonenumber: '123****8912',
|
||||||
avatar: '',
|
avatar: '',
|
||||||
userId: '1'
|
userId: '1',
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -241,11 +242,11 @@ export default {
|
||||||
return {
|
return {
|
||||||
code: 200,
|
code: 200,
|
||||||
data: {
|
data: {
|
||||||
balance: 10000.00,
|
balance: 10000.0,
|
||||||
waitBalance: 0,
|
waitBalance: 0,
|
||||||
withdrawBalance: 0,
|
withdrawBalance: 0,
|
||||||
withdrawedBalance: 0
|
withdrawedBalance: 0,
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -263,8 +264,8 @@ export default {
|
||||||
data: {
|
data: {
|
||||||
userNum: 4,
|
userNum: 4,
|
||||||
deviceNum: 1,
|
deviceNum: 1,
|
||||||
rentAmount: 2
|
rentAmount: 2,
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -376,8 +377,12 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes spin {
|
@keyframes spin {
|
||||||
0% { transform: rotate(0deg); }
|
0% {
|
||||||
100% { transform: rotate(360deg); }
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 用户头部
|
// 用户头部
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,12 @@
|
||||||
<view class="search-filter-section">
|
<view class="search-filter-section">
|
||||||
<view class="search-box">
|
<view class="search-box">
|
||||||
<uni-icons color="#7F7F7F" size="20" type="search"></uni-icons>
|
<uni-icons color="#7F7F7F" size="20" type="search"></uni-icons>
|
||||||
<input v-model="searchKeyword" class="search-input" placeholder="搜索" @input="onSearch" />
|
<input
|
||||||
|
v-model="searchKeyword"
|
||||||
|
class="search-input"
|
||||||
|
placeholder="搜索用户昵称"
|
||||||
|
@input="onSearch"
|
||||||
|
/>
|
||||||
</view>
|
</view>
|
||||||
<view class="filter-btn" @click="showFilter">
|
<view class="filter-btn" @click="showFilter">
|
||||||
<text class="filter-text">筛选</text>
|
<text class="filter-text">筛选</text>
|
||||||
|
|
@ -20,17 +25,37 @@
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
|
<!-- 筛选面板 -->
|
||||||
|
<view v-if="showFilterPanel" class="filter-panel">
|
||||||
|
<view class="filter-item">
|
||||||
|
<text class="filter-label">开始时间</text>
|
||||||
|
<picker :value="filterParams.beginTime" mode="date" @change="onBeginTimeChange">
|
||||||
|
<view class="picker-input">{{ filterParams.beginTime || '请选择' }}</view>
|
||||||
|
</picker>
|
||||||
|
</view>
|
||||||
|
<view class="filter-item">
|
||||||
|
<text class="filter-label">结束时间</text>
|
||||||
|
<picker :value="filterParams.endTime" mode="date" @change="onEndTimeChange">
|
||||||
|
<view class="picker-input">{{ filterParams.endTime || '请选择' }}</view>
|
||||||
|
</picker>
|
||||||
|
</view>
|
||||||
|
<view class="filter-actions">
|
||||||
|
<button class="filter-reset" @click="resetFilter">重置</button>
|
||||||
|
<button class="filter-confirm" @click="applyFilter">确定</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
<!-- 用户列表 -->
|
<!-- 用户列表 -->
|
||||||
<view class="user-list">
|
<view class="user-list">
|
||||||
<view v-for="(user, index) in filteredUsers" :key="user.id" class="user-card">
|
<view v-for="(user, index) in filteredUsers" :key="user.userId" class="user-card">
|
||||||
<!-- 用户基本信息 -->
|
<!-- 用户基本信息 -->
|
||||||
<view class="user-info">
|
<view class="user-info">
|
||||||
<view class="avatar-placeholder"></view>
|
<view class="avatar-placeholder"></view>
|
||||||
<view class="user-details">
|
<view class="user-details">
|
||||||
<text class="username">{{ user.username }}</text>
|
<text class="username">{{ user.nickName }}</text>
|
||||||
<view class="user-stats">
|
<view class="user-stats">
|
||||||
<text class="amount">¥ {{ user.totalAmount }}</text>
|
<text class="amount">¥ {{ user.totalAmount }}</text>
|
||||||
<text class="device-count">{{ user.deviceCount }}台</text>
|
<text class="device-count">{{ user.deviceNum }}台</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
@ -87,6 +112,12 @@ export default {
|
||||||
searchKeyword: '',
|
searchKeyword: '',
|
||||||
users: [],
|
users: [],
|
||||||
loading: false,
|
loading: false,
|
||||||
|
showFilterPanel: false,
|
||||||
|
filterParams: {
|
||||||
|
beginTime: '',
|
||||||
|
endTime: '',
|
||||||
|
name: '',
|
||||||
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onLoad() {
|
onLoad() {
|
||||||
|
|
@ -102,7 +133,7 @@ export default {
|
||||||
return this.users
|
return this.users
|
||||||
}
|
}
|
||||||
return this.users.filter(user =>
|
return this.users.filter(user =>
|
||||||
user.username.toLowerCase().includes(this.searchKeyword.toLowerCase())
|
user.nickName.toLowerCase().includes(this.searchKeyword.toLowerCase())
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -111,12 +142,34 @@ export default {
|
||||||
async fetchUserList() {
|
async fetchUserList() {
|
||||||
this.loading = true
|
this.loading = true
|
||||||
try {
|
try {
|
||||||
const response = await getUserList()
|
// 构建查询参数
|
||||||
|
const params = {}
|
||||||
|
if (this.filterParams.beginTime) {
|
||||||
|
params.beginTime = this.filterParams.beginTime + ' 00:00:00'
|
||||||
|
}
|
||||||
|
if (this.filterParams.endTime) {
|
||||||
|
params.endTime = this.filterParams.endTime + ' 23:59:59'
|
||||||
|
}
|
||||||
|
if (this.filterParams.name) {
|
||||||
|
params.name = this.filterParams.name
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await getUserList(params)
|
||||||
if (response.code === 200 && response.data && Array.isArray(response.data)) {
|
if (response.code === 200 && response.data && Array.isArray(response.data)) {
|
||||||
// 为每个用户添加展开状态
|
// 转换API数据格式为页面需要的格式
|
||||||
this.users = response.data.map(user => ({
|
this.users = response.data.map(user => ({
|
||||||
...user,
|
...user,
|
||||||
isExpanded: false // 默认收起
|
isExpanded: false, // 默认收起
|
||||||
|
// 将orders转换为devices格式
|
||||||
|
devices: user.orders
|
||||||
|
? user.orders.map(order => ({
|
||||||
|
type: order.typeName || '未知设备',
|
||||||
|
amount: order.amount || 0,
|
||||||
|
rentDate: this.formatDate(order.leaseTime),
|
||||||
|
period: order.suitName || '未知周期',
|
||||||
|
expiryDate: this.formatDate(order.expirationTime),
|
||||||
|
}))
|
||||||
|
: [],
|
||||||
}))
|
}))
|
||||||
console.log('用户列表获取成功:', this.users)
|
console.log('用户列表获取成功:', this.users)
|
||||||
}
|
}
|
||||||
|
|
@ -131,16 +184,44 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// 格式化日期
|
||||||
|
formatDate(dateString) {
|
||||||
|
if (!dateString) return '未知'
|
||||||
|
const date = new Date(dateString)
|
||||||
|
return `${date.getFullYear()}.${String(date.getMonth() + 1).padStart(2, '0')}.${String(date.getDate()).padStart(2, '0')}`
|
||||||
|
},
|
||||||
|
|
||||||
onSearch() {
|
onSearch() {
|
||||||
// 搜索逻辑已在computed中处理
|
// 搜索逻辑已在computed中处理
|
||||||
},
|
},
|
||||||
|
|
||||||
showFilter() {
|
showFilter() {
|
||||||
// 显示筛选选项
|
this.showFilterPanel = !this.showFilterPanel
|
||||||
uni.showToast({
|
|
||||||
title: '筛选功能开发中',
|
|
||||||
icon: 'none',
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
onBeginTimeChange(e) {
|
||||||
|
this.filterParams.beginTime = e.detail.value
|
||||||
|
},
|
||||||
|
|
||||||
|
onEndTimeChange(e) {
|
||||||
|
this.filterParams.endTime = e.detail.value
|
||||||
|
},
|
||||||
|
|
||||||
|
resetFilter() {
|
||||||
|
this.filterParams = {
|
||||||
|
beginTime: '',
|
||||||
|
endTime: '',
|
||||||
|
name: '',
|
||||||
|
}
|
||||||
|
this.searchKeyword = ''
|
||||||
|
},
|
||||||
|
|
||||||
|
applyFilter() {
|
||||||
|
this.filterParams.name = this.searchKeyword
|
||||||
|
this.showFilterPanel = false
|
||||||
|
this.fetchUserList()
|
||||||
|
},
|
||||||
|
|
||||||
toggleExpand(index) {
|
toggleExpand(index) {
|
||||||
this.users[index].isExpanded = !this.users[index].isExpanded
|
this.users[index].isExpanded = !this.users[index].isExpanded
|
||||||
},
|
},
|
||||||
|
|
@ -191,8 +272,12 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes spin {
|
@keyframes spin {
|
||||||
0% { transform: rotate(0deg); }
|
0% {
|
||||||
100% { transform: rotate(360deg); }
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-filter-section {
|
.search-filter-section {
|
||||||
|
|
@ -236,6 +321,122 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.filter-panel {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
background: white;
|
||||||
|
padding: 20rpx;
|
||||||
|
box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.1);
|
||||||
|
z-index: 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 15rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-label {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #333;
|
||||||
|
margin-right: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.picker-input {
|
||||||
|
flex: 1;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #333;
|
||||||
|
border: 1rpx solid #eee;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
padding: 10rpx 20rpx;
|
||||||
|
background: #f8f8f8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-actions {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-around;
|
||||||
|
margin-top: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-reset,
|
||||||
|
.filter-confirm {
|
||||||
|
flex: 1;
|
||||||
|
margin: 0 10rpx;
|
||||||
|
padding: 15rpx 20rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
border: none;
|
||||||
|
background: #ff6b35;
|
||||||
|
color: white;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-reset {
|
||||||
|
background: #f0f0f0;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-confirm {
|
||||||
|
background: #ff6b35;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-panel {
|
||||||
|
background: white;
|
||||||
|
padding: 20rpx;
|
||||||
|
border-top: 1rpx solid #eee;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-label {
|
||||||
|
width: 120rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.picker-input {
|
||||||
|
flex: 1;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #333;
|
||||||
|
border: 1rpx solid #ddd;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
padding: 15rpx 20rpx;
|
||||||
|
background: #f8f8f8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-actions {
|
||||||
|
display: flex;
|
||||||
|
gap: 20rpx;
|
||||||
|
margin-top: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-reset,
|
||||||
|
.filter-confirm {
|
||||||
|
flex: 1;
|
||||||
|
padding: 20rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
border: none;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-reset {
|
||||||
|
background: #f0f0f0;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-confirm {
|
||||||
|
background: #ff6b35;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
.user-list {
|
.user-list {
|
||||||
padding: 0 20rpx;
|
padding: 0 20rpx;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user