686 lines
18 KiB
Markdown
686 lines
18 KiB
Markdown
|
|
# 用户信息管理API使用说明
|
|||
|
|
|
|||
|
|
## 接口概述
|
|||
|
|
|
|||
|
|
本文档提供用户信息获取和编辑的接口说明,包括会员个人信息的查询和更新功能。
|
|||
|
|
|
|||
|
|
## 基础信息
|
|||
|
|
|
|||
|
|
- **Base URL**: `http://localhost:8123/api`
|
|||
|
|
- **Content-Type**: `application/json`
|
|||
|
|
- **认证方式**: Session(需要先登录)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 1. 获取当前登录用户信息
|
|||
|
|
|
|||
|
|
### 接口地址
|
|||
|
|
```
|
|||
|
|
GET /user/get/login
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 接口说明
|
|||
|
|
获取当前登录用户的详细信息,包括会员ID、等级、昵称、手机号码、注册日期、套餐类别、费用到期时间、性别、所在省市、彩票偏好、获客渠道等。
|
|||
|
|
|
|||
|
|
### 请求参数
|
|||
|
|
无需参数(通过Session获取当前登录用户)
|
|||
|
|
|
|||
|
|
### 请求示例(使用 curl)
|
|||
|
|
```bash
|
|||
|
|
curl -X GET "http://localhost:8123/api/user/get/login" \
|
|||
|
|
-H "Content-Type: application/json" \
|
|||
|
|
-b "JSESSIONID=your_session_id"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 请求示例(使用 JavaScript)
|
|||
|
|
```javascript
|
|||
|
|
fetch('http://localhost:8123/api/user/get/login', {
|
|||
|
|
method: 'GET',
|
|||
|
|
credentials: 'include', // 携带cookie
|
|||
|
|
headers: {
|
|||
|
|
'Content-Type': 'application/json'
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
.then(response => response.json())
|
|||
|
|
.then(data => {
|
|||
|
|
console.log('用户信息:', data);
|
|||
|
|
})
|
|||
|
|
.catch(error => {
|
|||
|
|
console.error('获取失败:', error);
|
|||
|
|
});
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 响应示例(成功)
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"code": 0,
|
|||
|
|
"data": {
|
|||
|
|
"id": "1234567890123456789",
|
|||
|
|
"userName": "张三",
|
|||
|
|
"userAccount": "zhangsan",
|
|||
|
|
"phone": "13800138000",
|
|||
|
|
"userAvatar": "https://example.com/avatar.jpg",
|
|||
|
|
"gender": 1,
|
|||
|
|
"userRole": "user",
|
|||
|
|
"isVip": 1,
|
|||
|
|
"vipExpire": "2026-12-31T23:59:59",
|
|||
|
|
"vipType": "年度会员",
|
|||
|
|
"location": "北京市",
|
|||
|
|
"preference": "双色球",
|
|||
|
|
"channel": "微信推广",
|
|||
|
|
"status": 0,
|
|||
|
|
"createTime": "2025-01-01T10:00:00",
|
|||
|
|
"updateTime": "2026-01-26T15:30:00"
|
|||
|
|
},
|
|||
|
|
"message": "ok"
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 响应字段说明
|
|||
|
|
|
|||
|
|
| 字段名 | 类型 | 说明 | 备注 |
|
|||
|
|
|--------|------|------|------|
|
|||
|
|
| code | Integer | 状态码 | 0表示成功 |
|
|||
|
|
| data | Object | 用户信息对象 | |
|
|||
|
|
| data.id | String | 会员ID | 系统自动生成,不可修改 |
|
|||
|
|
| data.userName | String | 昵称 | 可修改 |
|
|||
|
|
| data.userAccount | String | 账号 | 系统收集,不可修改 |
|
|||
|
|
| data.phone | String | 手机号码 | 可修改 |
|
|||
|
|
| data.userAvatar | String | 头像URL | 可修改 |
|
|||
|
|
| data.gender | Integer | 性别 | 0-女,1-男,2-未知,可修改 |
|
|||
|
|
| data.userRole | String | 用户角色 | user/admin,系统收集 |
|
|||
|
|
| data.isVip | Integer | 是否会员 | 0-非会员,1-会员,系统收集 |
|
|||
|
|
| data.vipExpire | String | 费用到期时间 | ISO 8601格式,系统收集 |
|
|||
|
|
| data.vipType | String | 套餐类别 | 体验会员/月度会员/年度会员,系统收集 |
|
|||
|
|
| data.location | String | 所在省市 | 可由用户填写或客服填写 |
|
|||
|
|
| data.preference | String | 彩票偏好 | 双色球/大乐透等,可由用户填写或客服填写 |
|
|||
|
|
| data.channel | String | 获客渠道 | 可由用户填写或客服填写 |
|
|||
|
|
| data.status | Integer | 状态 | 0-正常,1-封禁,系统收集 |
|
|||
|
|
| data.createTime | String | 注册日期 | ISO 8601格式,系统收集 |
|
|||
|
|
| data.updateTime | String | 更新时间 | ISO 8601格式 |
|
|||
|
|
| message | String | 响应消息 | |
|
|||
|
|
|
|||
|
|
### 字段权限说明
|
|||
|
|
|
|||
|
|
**系统收集字段(黄色标记,会员可查看但不可修改):**
|
|||
|
|
- 会员ID (id)
|
|||
|
|
- 等级 (userRole)
|
|||
|
|
- 注册日期 (createTime)
|
|||
|
|
- 套餐类别 (vipType)
|
|||
|
|
- 费用到期时间 (vipExpire)
|
|||
|
|
|
|||
|
|
**用户可填写或客服可填写字段(其它四项):**
|
|||
|
|
- 性别 (gender)
|
|||
|
|
- 所在省市 (location)
|
|||
|
|
- 彩票偏好 (preference)
|
|||
|
|
- 获客渠道 (channel)
|
|||
|
|
|
|||
|
|
### 错误响应示例
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"code": 40100,
|
|||
|
|
"data": null,
|
|||
|
|
"message": "未登录"
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 2. 编辑用户信息
|
|||
|
|
|
|||
|
|
### 接口地址
|
|||
|
|
```
|
|||
|
|
POST /user/update
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 接口说明
|
|||
|
|
更新当前登录用户的个人信息。用户只能修改自己的信息,管理员可以修改任何用户的信息。
|
|||
|
|
|
|||
|
|
**注意:**
|
|||
|
|
- 系统收集的字段(会员ID、等级、注册日期、套餐类别、费用到期时间)不可通过此接口修改
|
|||
|
|
- 用户可以修改:昵称、手机号码、头像、性别、所在省市、彩票偏好、获客渠道
|
|||
|
|
|
|||
|
|
### 请求参数
|
|||
|
|
|
|||
|
|
| 参数名 | 类型 | 必填 | 说明 |
|
|||
|
|
|--------|------|------|------|
|
|||
|
|
| id | Long | 是 | 用户ID(当前登录用户的ID) |
|
|||
|
|
| userName | String | 否 | 昵称 |
|
|||
|
|
| phone | String | 否 | 手机号码(11位) |
|
|||
|
|
| userAvatar | String | 否 | 头像URL |
|
|||
|
|
| gender | Integer | 否 | 性别(0-女,1-男,2-未知) |
|
|||
|
|
| location | String | 否 | 所在省市 |
|
|||
|
|
| preference | String | 否 | 彩票偏好(如:双色球、大乐透) |
|
|||
|
|
| channel | String | 否 | 获客渠道 |
|
|||
|
|
|
|||
|
|
### 请求示例(使用 curl)
|
|||
|
|
```bash
|
|||
|
|
curl -X POST "http://localhost:8123/api/user/update" \
|
|||
|
|
-H "Content-Type: application/json" \
|
|||
|
|
-b "JSESSIONID=your_session_id" \
|
|||
|
|
-d '{
|
|||
|
|
"id": 1234567890123456789,
|
|||
|
|
"userName": "李四",
|
|||
|
|
"phone": "13900139000",
|
|||
|
|
"gender": 1,
|
|||
|
|
"location": "上海市",
|
|||
|
|
"preference": "大乐透",
|
|||
|
|
"channel": "朋友推荐"
|
|||
|
|
}'
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 请求示例(使用 JavaScript)
|
|||
|
|
```javascript
|
|||
|
|
const updateUserInfo = async (userInfo) => {
|
|||
|
|
const response = await fetch('http://localhost:8123/api/user/update', {
|
|||
|
|
method: 'POST',
|
|||
|
|
credentials: 'include',
|
|||
|
|
headers: {
|
|||
|
|
'Content-Type': 'application/json'
|
|||
|
|
},
|
|||
|
|
body: JSON.stringify(userInfo)
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
const result = await response.json();
|
|||
|
|
return result;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 使用示例
|
|||
|
|
updateUserInfo({
|
|||
|
|
id: 1234567890123456789,
|
|||
|
|
userName: "李四",
|
|||
|
|
phone: "13900139000",
|
|||
|
|
gender: 1,
|
|||
|
|
location: "上海市",
|
|||
|
|
preference: "大乐透",
|
|||
|
|
channel: "朋友推荐"
|
|||
|
|
}).then(data => {
|
|||
|
|
console.log('更新成功:', data);
|
|||
|
|
}).catch(error => {
|
|||
|
|
console.error('更新失败:', error);
|
|||
|
|
});
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 请求示例(使用 Vue 3)
|
|||
|
|
```vue
|
|||
|
|
<template>
|
|||
|
|
<div class="user-profile">
|
|||
|
|
<form @submit.prevent="handleSubmit">
|
|||
|
|
<div class="form-item">
|
|||
|
|
<label>昵称:</label>
|
|||
|
|
<input v-model="userForm.userName" type="text" />
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="form-item">
|
|||
|
|
<label>手机号码:</label>
|
|||
|
|
<input v-model="userForm.phone" type="tel" maxlength="11" />
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="form-item">
|
|||
|
|
<label>性别:</label>
|
|||
|
|
<select v-model="userForm.gender">
|
|||
|
|
<option :value="0">女</option>
|
|||
|
|
<option :value="1">男</option>
|
|||
|
|
<option :value="2">未知</option>
|
|||
|
|
</select>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="form-item">
|
|||
|
|
<label>所在省市:</label>
|
|||
|
|
<input v-model="userForm.location" type="text" placeholder="如:北京市" />
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="form-item">
|
|||
|
|
<label>彩票偏好:</label>
|
|||
|
|
<select v-model="userForm.preference">
|
|||
|
|
<option value="">请选择</option>
|
|||
|
|
<option value="双色球">双色球</option>
|
|||
|
|
<option value="大乐透">大乐透</option>
|
|||
|
|
<option value="双色球和大乐透">双色球和大乐透</option>
|
|||
|
|
</select>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="form-item">
|
|||
|
|
<label>获客渠道:</label>
|
|||
|
|
<input v-model="userForm.channel" type="text" placeholder="如:微信推广" />
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<button type="submit">保存</button>
|
|||
|
|
</form>
|
|||
|
|
</div>
|
|||
|
|
</template>
|
|||
|
|
|
|||
|
|
<script setup>
|
|||
|
|
import { ref, onMounted } from 'vue';
|
|||
|
|
import axios from 'axios';
|
|||
|
|
|
|||
|
|
const userForm = ref({
|
|||
|
|
id: null,
|
|||
|
|
userName: '',
|
|||
|
|
phone: '',
|
|||
|
|
gender: 2,
|
|||
|
|
location: '',
|
|||
|
|
preference: '',
|
|||
|
|
channel: ''
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 获取用户信息
|
|||
|
|
const getUserInfo = async () => {
|
|||
|
|
try {
|
|||
|
|
const response = await axios.get('/api/user/get/login');
|
|||
|
|
if (response.data.code === 0) {
|
|||
|
|
const user = response.data.data;
|
|||
|
|
userForm.value = {
|
|||
|
|
id: user.id,
|
|||
|
|
userName: user.userName,
|
|||
|
|
phone: user.phone,
|
|||
|
|
gender: user.gender,
|
|||
|
|
location: user.location || '',
|
|||
|
|
preference: user.preference || '',
|
|||
|
|
channel: user.channel || ''
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('获取用户信息失败:', error);
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 提交表单
|
|||
|
|
const handleSubmit = async () => {
|
|||
|
|
try {
|
|||
|
|
const response = await axios.post('/api/user/update', userForm.value);
|
|||
|
|
if (response.data.code === 0) {
|
|||
|
|
alert('保存成功!');
|
|||
|
|
} else {
|
|||
|
|
alert('保存失败:' + response.data.message);
|
|||
|
|
}
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('保存失败:', error);
|
|||
|
|
alert('保存失败,请稍后重试');
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
onMounted(() => {
|
|||
|
|
getUserInfo();
|
|||
|
|
});
|
|||
|
|
</script>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 响应示例(成功)
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"code": 0,
|
|||
|
|
"data": true,
|
|||
|
|
"message": "ok"
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 响应字段说明
|
|||
|
|
|
|||
|
|
| 字段名 | 类型 | 说明 |
|
|||
|
|
|--------|------|------|
|
|||
|
|
| code | Integer | 状态码,0表示成功 |
|
|||
|
|
| data | Boolean | 是否更新成功 |
|
|||
|
|
| message | String | 响应消息 |
|
|||
|
|
|
|||
|
|
### 错误响应示例
|
|||
|
|
|
|||
|
|
#### 1. 未登录
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"code": 40100,
|
|||
|
|
"data": null,
|
|||
|
|
"message": "未登录"
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 2. 参数错误
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"code": 40000,
|
|||
|
|
"data": null,
|
|||
|
|
"message": "手机号格式不正确"
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 3. 无权限
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"code": 40101,
|
|||
|
|
"data": null,
|
|||
|
|
"message": "无权限修改其他用户信息"
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 3. 根据ID获取用户信息(管理员)
|
|||
|
|
|
|||
|
|
### 接口地址
|
|||
|
|
```
|
|||
|
|
GET /user/get?id={userId}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 接口说明
|
|||
|
|
管理员根据用户ID获取指定用户的详细信息。
|
|||
|
|
|
|||
|
|
### 请求参数
|
|||
|
|
|
|||
|
|
| 参数名 | 类型 | 必填 | 说明 |
|
|||
|
|
|--------|------|------|------|
|
|||
|
|
| id | Long | 是 | 用户ID |
|
|||
|
|
|
|||
|
|
### 请求示例
|
|||
|
|
```bash
|
|||
|
|
curl -X GET "http://localhost:8123/api/user/get?id=1234567890123456789" \
|
|||
|
|
-H "Content-Type: application/json" \
|
|||
|
|
-b "JSESSIONID=your_session_id"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 响应示例
|
|||
|
|
与"获取当前登录用户信息"接口响应格式相同。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 错误码说明
|
|||
|
|
|
|||
|
|
| 错误码 | 说明 |
|
|||
|
|
|--------|------|
|
|||
|
|
| 0 | 成功 |
|
|||
|
|
| 40000 | 参数错误 |
|
|||
|
|
| 40100 | 未登录 |
|
|||
|
|
| 40101 | 无权限 |
|
|||
|
|
| 40400 | 用户不存在 |
|
|||
|
|
| 50000 | 系统错误 |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 字段约束说明
|
|||
|
|
|
|||
|
|
### 1. 手机号码 (phone)
|
|||
|
|
- 长度:11位
|
|||
|
|
- 格式:纯数字
|
|||
|
|
- 示例:13800138000
|
|||
|
|
|
|||
|
|
### 2. 性别 (gender)
|
|||
|
|
- 0:女
|
|||
|
|
- 1:男
|
|||
|
|
- 2:未知
|
|||
|
|
|
|||
|
|
### 3. 所在省市 (location)
|
|||
|
|
- 最大长度:100字符
|
|||
|
|
- 格式:省份+城市,如"北京市"、"广东省广州市"
|
|||
|
|
- 可为空
|
|||
|
|
|
|||
|
|
### 4. 彩票偏好 (preference)
|
|||
|
|
- 最大长度:100字符
|
|||
|
|
- 常见值:双色球、大乐透、双色球和大乐透
|
|||
|
|
- 可为空
|
|||
|
|
|
|||
|
|
### 5. 获客渠道 (channel)
|
|||
|
|
- 最大长度:100字符
|
|||
|
|
- 常见值:微信推广、朋友推荐、搜索引擎、广告投放等
|
|||
|
|
- 可为空
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 完整的前端表单示例(HTML + JavaScript)
|
|||
|
|
|
|||
|
|
```html
|
|||
|
|
<!DOCTYPE html>
|
|||
|
|
<html lang="zh-CN">
|
|||
|
|
<head>
|
|||
|
|
<meta charset="UTF-8">
|
|||
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|||
|
|
<title>用户信息编辑</title>
|
|||
|
|
<style>
|
|||
|
|
.user-profile {
|
|||
|
|
max-width: 600px;
|
|||
|
|
margin: 50px auto;
|
|||
|
|
padding: 20px;
|
|||
|
|
border: 1px solid #ddd;
|
|||
|
|
border-radius: 8px;
|
|||
|
|
}
|
|||
|
|
.form-item {
|
|||
|
|
margin-bottom: 15px;
|
|||
|
|
}
|
|||
|
|
.form-item label {
|
|||
|
|
display: inline-block;
|
|||
|
|
width: 120px;
|
|||
|
|
font-weight: bold;
|
|||
|
|
}
|
|||
|
|
.form-item input,
|
|||
|
|
.form-item select {
|
|||
|
|
width: 300px;
|
|||
|
|
padding: 8px;
|
|||
|
|
border: 1px solid #ddd;
|
|||
|
|
border-radius: 4px;
|
|||
|
|
}
|
|||
|
|
.form-item.readonly input {
|
|||
|
|
background-color: #f5f5f5;
|
|||
|
|
cursor: not-allowed;
|
|||
|
|
}
|
|||
|
|
.readonly-note {
|
|||
|
|
color: #999;
|
|||
|
|
font-size: 12px;
|
|||
|
|
margin-left: 120px;
|
|||
|
|
}
|
|||
|
|
button {
|
|||
|
|
margin-left: 120px;
|
|||
|
|
padding: 10px 30px;
|
|||
|
|
background-color: #4CAF50;
|
|||
|
|
color: white;
|
|||
|
|
border: none;
|
|||
|
|
border-radius: 4px;
|
|||
|
|
cursor: pointer;
|
|||
|
|
}
|
|||
|
|
button:hover {
|
|||
|
|
background-color: #45a049;
|
|||
|
|
}
|
|||
|
|
</style>
|
|||
|
|
</head>
|
|||
|
|
<body>
|
|||
|
|
<div class="user-profile">
|
|||
|
|
<h2>会员个人信息</h2>
|
|||
|
|
<form id="userForm">
|
|||
|
|
<!-- 系统收集字段(只读) -->
|
|||
|
|
<div class="form-item readonly">
|
|||
|
|
<label>会员ID:</label>
|
|||
|
|
<input type="text" id="userId" readonly />
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="form-item readonly">
|
|||
|
|
<label>等级:</label>
|
|||
|
|
<input type="text" id="userRole" readonly />
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="form-item readonly">
|
|||
|
|
<label>注册日期:</label>
|
|||
|
|
<input type="text" id="createTime" readonly />
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="form-item readonly">
|
|||
|
|
<label>套餐类别:</label>
|
|||
|
|
<input type="text" id="vipType" readonly />
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="form-item readonly">
|
|||
|
|
<label>费用到期时间:</label>
|
|||
|
|
<input type="text" id="vipExpire" readonly />
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<p class="readonly-note">注:黄色标记为系统收集,会员可查看但不可修改</p>
|
|||
|
|
|
|||
|
|
<hr style="margin: 20px 0;">
|
|||
|
|
|
|||
|
|
<!-- 可编辑字段 -->
|
|||
|
|
<div class="form-item">
|
|||
|
|
<label>昵称:</label>
|
|||
|
|
<input type="text" id="userName" />
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="form-item">
|
|||
|
|
<label>手机号码:</label>
|
|||
|
|
<input type="tel" id="phone" maxlength="11" />
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="form-item">
|
|||
|
|
<label>性别:</label>
|
|||
|
|
<select id="gender">
|
|||
|
|
<option value="0">女</option>
|
|||
|
|
<option value="1">男</option>
|
|||
|
|
<option value="2">未知</option>
|
|||
|
|
</select>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="form-item">
|
|||
|
|
<label>所在省市:</label>
|
|||
|
|
<input type="text" id="location" placeholder="如:北京市" />
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="form-item">
|
|||
|
|
<label>彩票偏好:</label>
|
|||
|
|
<select id="preference">
|
|||
|
|
<option value="">请选择</option>
|
|||
|
|
<option value="双色球">双色球</option>
|
|||
|
|
<option value="大乐透">大乐透</option>
|
|||
|
|
<option value="双色球和大乐透">双色球和大乐透</option>
|
|||
|
|
</select>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="form-item">
|
|||
|
|
<label>获客渠道:</label>
|
|||
|
|
<input type="text" id="channel" placeholder="如:微信推广" />
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<p class="readonly-note">注:其它四项可由用户填写或客服填写</p>
|
|||
|
|
|
|||
|
|
<button type="submit">保存</button>
|
|||
|
|
</form>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<script>
|
|||
|
|
// 获取用户信息
|
|||
|
|
async function loadUserInfo() {
|
|||
|
|
try {
|
|||
|
|
const response = await fetch('/api/user/get/login', {
|
|||
|
|
method: 'GET',
|
|||
|
|
credentials: 'include'
|
|||
|
|
});
|
|||
|
|
const result = await response.json();
|
|||
|
|
|
|||
|
|
if (result.code === 0) {
|
|||
|
|
const user = result.data;
|
|||
|
|
|
|||
|
|
// 填充只读字段
|
|||
|
|
document.getElementById('userId').value = user.id;
|
|||
|
|
document.getElementById('userRole').value = user.userRole === 'admin' ? '管理员' : '普通用户';
|
|||
|
|
document.getElementById('createTime').value = formatDate(user.createTime);
|
|||
|
|
document.getElementById('vipType').value = user.vipType || '体验会员';
|
|||
|
|
document.getElementById('vipExpire').value = user.vipExpire ? formatDate(user.vipExpire) : '未开通';
|
|||
|
|
|
|||
|
|
// 填充可编辑字段
|
|||
|
|
document.getElementById('userName').value = user.userName || '';
|
|||
|
|
document.getElementById('phone').value = user.phone || '';
|
|||
|
|
document.getElementById('gender').value = user.gender !== null ? user.gender : 2;
|
|||
|
|
document.getElementById('location').value = user.location || '';
|
|||
|
|
document.getElementById('preference').value = user.preference || '';
|
|||
|
|
document.getElementById('channel').value = user.channel || '';
|
|||
|
|
} else {
|
|||
|
|
alert('获取用户信息失败:' + result.message);
|
|||
|
|
}
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('获取用户信息失败:', error);
|
|||
|
|
alert('获取用户信息失败,请稍后重试');
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 格式化日期
|
|||
|
|
function formatDate(dateString) {
|
|||
|
|
if (!dateString) return '';
|
|||
|
|
const date = new Date(dateString);
|
|||
|
|
return date.toLocaleString('zh-CN');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 提交表单
|
|||
|
|
document.getElementById('userForm').addEventListener('submit', async (e) => {
|
|||
|
|
e.preventDefault();
|
|||
|
|
|
|||
|
|
const userId = document.getElementById('userId').value;
|
|||
|
|
const phone = document.getElementById('phone').value;
|
|||
|
|
|
|||
|
|
// 验证手机号
|
|||
|
|
if (phone && phone.length !== 11) {
|
|||
|
|
alert('手机号格式不正确,请输入11位手机号');
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const formData = {
|
|||
|
|
id: userId,
|
|||
|
|
userName: document.getElementById('userName').value,
|
|||
|
|
phone: phone,
|
|||
|
|
gender: parseInt(document.getElementById('gender').value),
|
|||
|
|
location: document.getElementById('location').value,
|
|||
|
|
preference: document.getElementById('preference').value,
|
|||
|
|
channel: document.getElementById('channel').value
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
const response = await fetch('/api/user/update', {
|
|||
|
|
method: 'POST',
|
|||
|
|
credentials: 'include',
|
|||
|
|
headers: {
|
|||
|
|
'Content-Type': 'application/json'
|
|||
|
|
},
|
|||
|
|
body: JSON.stringify(formData)
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
const result = await response.json();
|
|||
|
|
|
|||
|
|
if (result.code === 0) {
|
|||
|
|
alert('保存成功!');
|
|||
|
|
loadUserInfo(); // 重新加载用户信息
|
|||
|
|
} else {
|
|||
|
|
alert('保存失败:' + result.message);
|
|||
|
|
}
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('保存失败:', error);
|
|||
|
|
alert('保存失败,请稍后重试');
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 页面加载时获取用户信息
|
|||
|
|
loadUserInfo();
|
|||
|
|
</script>
|
|||
|
|
</body>
|
|||
|
|
</html>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 注意事项
|
|||
|
|
|
|||
|
|
1. **权限控制**
|
|||
|
|
- 用户只能查看和修改自己的信息
|
|||
|
|
- 管理员可以查看和修改任何用户的信息
|
|||
|
|
- 系统收集的字段(会员ID、等级、注册日期、套餐类别、费用到期时间)任何人都不能通过此接口修改
|
|||
|
|
|
|||
|
|
2. **数据验证**
|
|||
|
|
- 手机号必须是11位数字
|
|||
|
|
- 性别只能是0、1、2
|
|||
|
|
- 所有字符串字段都有长度限制
|
|||
|
|
|
|||
|
|
3. **Session管理**
|
|||
|
|
- 所有接口都需要先登录
|
|||
|
|
- 请求时需要携带Session Cookie
|
|||
|
|
- 前端使用`credentials: 'include'`来携带Cookie
|
|||
|
|
|
|||
|
|
4. **错误处理**
|
|||
|
|
- 前端应该处理所有可能的错误情况
|
|||
|
|
- 显示友好的错误提示给用户
|
|||
|
|
|
|||
|
|
5. **数据更新**
|
|||
|
|
- 只需要传递需要更新的字段
|
|||
|
|
- 未传递的字段不会被更新
|
|||
|
|
- 建议每次都传递完整的可编辑字段数据
|