# 用户信息管理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. **数据更新**
   - 只需要传递需要更新的字段
   - 未传递的字段不会被更新
   - 建议每次都传递完整的可编辑字段数据
