feat(user): 实现用户注册、登录和信息更新功能

- 新增用户注册和登录接口
- 实现用户信息获取和更新接口
- 修改用户服务和 mapper接口,支持新的功能
- 优化 JWT 工具类,增加从 token 中获取用户 ID 的方法
- 重命名 ExampleController 为 ProductController,准备实现商品相关功能
main
孙贺贺 3 days ago
parent c7fd81b72f
commit 991cf6eb8e

@ -56,6 +56,16 @@
- [3.4.2请求参数](#342请求参数)
- [3.4.3响应数据](#343响应数据)
- [3.5、搜索商品](#35搜索商品)
- [3.5.1基本信息](#351基本信息)
- [3.5.2请求参数](#352请求参数)
- [3.5.3响应数据](#353响应数据)
- [3.6、更新商品](#36更新商品)
- [3.6.1基本信息](#361基本信息)
- [3.6.2请求参数](#362请求参数)
- [3.6.3响应数据](#363响应数据)
- [4、交易管理](#4交易管理)
- [4.1、创建订单](#41创建订单)
- [4.1.1基本信息](#411基本信息)
@ -93,17 +103,12 @@
- [5.4、订单管理](#54订单管理)
- [5.4.1基本信息](#541基本信息)
- [5.4.2请求参数](#542请求参数)
- [5.4.3响应数据](#543响应数据)
- [5.4.3响应数据](#543响应数据)
- [5.5、退出模块](#55退出模块)
- [5.5.1基本信息](#551基本信息)
- [5.5.2请求参数](#552请求参数)
- [5.5.3响应数据](#553响应数据)
- [6、其他接口](#6其他接口)
- [6.1、搜索商品](#61搜索商品)
- [6.1.1基本信息](#611基本信息)
- [6.1.2请求参数](#612请求参数)
- [6.1.3响应数据](#613响应数据)
- [6.2、用户反馈](#62用户反馈)
- [6.2.1基本信息](#621基本信息)
- [6.2.2请求参数](#622请求参数)
@ -119,7 +124,7 @@
#### 2.1.1基本信息
- 请求路径URL`user/register`
- 请求路径URL`users/register`
- 请求方式:`POST`
- 接口描述:该接口用于注册新用户
@ -165,7 +170,7 @@ username=sunhehe&password=123456
#### 2.2.1基本信息
- 请求路径URL`user/login`
- 请求路径URL`users/login`
- 请求方式:`POST`
- 接口描述:该接口用于用户登录
@ -194,7 +199,7 @@ username=sunhehe&password=123456
|:------------|:-------|:---------|:----------------|
| **code** | number | 必须 | 响应码0 -成功1 -失败 |
| **message** | string | 非必须 | 提示信息 |
| **data** | string | 必须 | 返回的数据 jwt 令牌 |
| **data** | string | 必须 | 返回的数据 jwt 令牌 |
- 响应数据样例:
@ -217,7 +222,7 @@ username=sunhehe&password=123456
#### 2.3.1基本信息
- 请求路径URL`user/userinfo`
- 请求路径URL`users/info`
- 请求方式:`GET`
- 接口描述:该接口用于获取当前已登陆用户的详细信息
@ -230,18 +235,18 @@ username=sunhehe&password=123456
- 响应数据类型:`application/json`
- 响应参数说明:
| **名称** | **类型** | **是否必须** | **备注** |
|:-------------|:----------|:------------|:----------------|
| **code** | number | 必须 | 响应码0 -成功1 -失败 |
| **message** | string | 非必须 | 提示信息 |
| **data** | string | 必须 | 返回的数据 |
| --id | number | 非必须 | 主键ID |
| --userna | string | 非必须 | 用户名 |
| --nickname | string | 非必须 | 昵称 |
| --email | string | 非必须 | 邮箱 |
| --userPic | string | 非必须 | 头像地址 |
| --createTime | string | 非必须 | 创建时间 |
| --updateTime | string | 非必须 | 更新时间 |
| **名称** | **类型** | **是否必须** | **备注** |
|:-------------|:-------|:---------|:----------------|
| **code** | number | 必须 | 响应码0 -成功1 -失败 |
| **message** | string | 非必须 | 提示信息 |
| **data** | string | 必须 | 返回的数据 |
| --id | number | 非必须 | 主键ID |
| --userna | string | 非必须 | 用户名 |
| --nickname | string | 非必须 | 昵称 |
| --email | string | 非必须 | 邮箱 |
| --userPic | string | 非必须 | 头像地址 |
| --createTime | string | 非必须 | 创建时间 |
| --updateTime | string | 非必须 | 更新时间 |
- 响应数据样例:
@ -334,7 +339,8 @@ username=sunhehe&password=123456
```js
{
avatarur1 = https://haowallpaper.com/link/common/file/previewFileImg/15690537886650688
avatarur1 = https
://haowallpaper.com/link/common/file/previewFileImg/15690537886650688
}
```
@ -347,7 +353,7 @@ username=sunhehe&password=123456
|:------------|:-------|:---------|:----------------|
| **code** | number | 必须 | 响应码0 -成功1 -失败 |
| **message** | string | 非必须 | 提示信息 |
| **data** | object | 非必须 | 返回的数据 |
| **data** | object | 非必须 | 返回的数据 |
- 响应数据样例:
@ -397,7 +403,7 @@ username=sunhehe&password=123456
|:------------|:-------|:---------|:----------------|
| **code** | number | 必须 | 响应码0 -成功1 -失败 |
| **message** | string | 非必须 | 提示信息 |
| **data** | object | 非必须 | 返回的数据 |
| **data** | object | 非必须 | 返回的数据 |
- 响应数据样例:
@ -453,7 +459,7 @@ username=sunhehe&password=123456
|:------------|:-------|:---------|:----------------|
| **code** | number | 必须 | 响应码0 -成功1 -失败 |
| **message** | string | 非必须 | 提示信息 |
| **data** | object | 非必须 | 返回的数据 |
| **data** | object | 非必须 | 返回的数据 |
- 响应数据样例:
@ -555,7 +561,7 @@ username=sunhehe&password=123456
|:------------|:-------|:---------|:----------------|
| **code** | number | 必须 | 响应码0 -成功1 -失败 |
| **message** | string | 非必须 | 提示信息 |
| **data** | object | 非必须 | 商品详细信息 |
| **data** | object | 非必须 | 商品详细信息 |
- 响应数据样例:
@ -608,7 +614,7 @@ username=sunhehe&password=123456
|:------------|:-------|:---------|:----------------|
| **code** | number | 必须 | 响应码0 -成功1 -失败 |
| **message** | string | 非必须 | 提示信息 |
| **data** | object | 非必须 | 返回的数据 |
| **data** | object | 非必须 | 返回的数据 |
- 响应数据样例:
@ -620,6 +626,150 @@ username=sunhehe&password=123456
}
```
### 3.5、搜索商品
#### 3.5.1基本信息
- 请求路径URL`/product/search`
- 请求方式:`GET`
- 接口描述:该接口用于根据关键词搜索商品。可以根据商品名称、分类、描述等信息进行模糊查询。
#### 3.5.2请求参数
- 请求参数格式:`application/json`
- 请求参数说明:
| **参数名称** | **说明** | **类型** | **是否必须** | **备注** |
|:-------------|:----------------|:-------|:--------:|:---------------------------|
| **keyword** | 搜索关键词(商品名称、描述等) | string | 是 | 用于搜索商品的关键词,支持模糊查询。 |
| **category** | 商品分类 | string | 否 | 可选,指定商品类别进行筛选,若不提供则不筛选类别。 |
| **page** | 页码(分页查询) | number | 否 | 默认值为1表示第一页。 |
| **pageSize** | 每页显示的商品数量 | number | 否 | 默认值为20最大值为100表示每页显示的商品数。 |
- 请求数据样例:
```json
{
"keyword": "手机",
"category": "电子产品",
"page": 1,
"pageSize": 20
}
```
#### 3.5.3响应数据
- 响应数据类型:`application/json`
- 响应参数说明:
| **名称** | **类型** | **是否必须** | **备注** |
|:-------------|:-------|:--------:|:------------------|
| **code** | number | 必须 | 响应码0 - 成功1 - 失败 |
| **message** | string | 非必须 | 提示信息 |
| **data** | object | 必须 | 返回的数据,包含商品列表信息 |
| **total** | number | 必须 | 符合条件的商品总数 |
| **page** | number | 必须 | 当前页码 |
| **pageSize** | number | 必须 | 每页商品数 |
- 响应数据样例:
```json
{
"code": 0,
"message": "操作成功",
"data": [
{
"productId": 12345,
"name": "二手iPhone 12",
"category": "电子产品",
"price": 3000,
"description": "几乎全新,屏幕完好,原装配件",
"imageUrl": "http://example.com/iphone12.jpg",
"sellerId": 67890,
"sellerName": "张三"
},
{
"productId": 67890,
"name": "二手MacBook Pro",
"category": "电子产品",
"price": 4500,
"description": "配置高,性能稳定,电池寿命长",
"imageUrl": "http://example.com/macbookpro.jpg",
"sellerId": 12345,
"sellerName": "李四"
}
],
"total": 50,
"page": 1,
"pageSize": 20
}
```
### 3.6、更新商品
#### 3.6.1基本信息
- 请求路径URL`/product/update/{id}`
- 请求方式:`POST`
- 接口描述:该接口用于根据关键词更新商品。
#### 3.6.2请求参数
- 请求参数格式:`application/json`
- 请求参数说明:
| **参数名称** | **说明** | **类型** | **是否必须** | **备注** |
|:----------------|:--------|:-------|:--------:|:-----------|
| **id** | 商品ID | number | 是 | 要更新的商品ID。 |
| **name** | 商品名称 | string | 否 | 商品的名称。 |
| **category** | 商品分类 | string | 否 | 商品的分类(可选)。 |
| **price** | 商品价格 | number | 否 | 商品的价格。 |
| **description** | 商品描述 | string | 否 | 商品的描述信息。 |
| **imageUrl** | 商品图片URL | string | 否 | 商品图片的URL。 |
- 请求数据样例:
```json
{
"id": 12345,
"name": "二手iPhone 12 Pro",
"category": "电子产品",
"price": 3500,
"description": "几乎全新,屏幕无划痕,配件齐全",
"imageUrl": "http://example.com/iphone12pro.jpg"
}
```
#### 3.6.3响应数据
- 响应数据类型:`application/json`
- 响应参数说明:
| **名称** | **类型** | **是否必须** | **备注** |
|:------------|:-------|:--------:|:------------------|
| **code** | number | 必须 | 响应码0 - 成功1 - 失败 |
| **message** | string | 非必须 | 提示信息 |
| **data** | object | 必须 | 返回的数据,包含商品列表信息 |
- 响应数据样例:
```json
{
"code": 0,
"message": "商品更新成功",
"data": {
"productId": 12345,
"name": "二手iPhone 12 Pro",
"category": "电子产品",
"price": 3500,
"description": "几乎全新,屏幕无划痕,配件齐全",
"imageUrl": "http://example.com/iphone12pro.jpg",
"sellerId": 67890,
"sellerName": "张三"
}
}
```
## 4、交易管理
### 4.1、创建订单
@ -654,7 +804,7 @@ username=sunhehe&password=123456
|:------------|:-------|:---------|:----------------|
| **code** | number | 必须 | 响应码0 -成功1 -失败 |
| **message** | string | 非必须 | 提示信息 |
| **data** | object | 非必须 | 返回的数据 |
| **data** | object | 非必须 | 返回的数据 |
- 响应数据样例:
@ -675,6 +825,7 @@ username=sunhehe&password=123456
- 接口描述:该接口用于获取用户的订单列表
#### 4.2.2请求参数
#### 4.2.3响应数据
@ -686,7 +837,7 @@ username=sunhehe&password=123456
|:------------|:-------|:---------|:----------------|
| **code** | number | 必须 | 响应码0 -成功1 -失败 |
| **message** | string | 非必须 | 提示信息 |
| **data** | object | 非必须 | 返回的数据 |
| **data** | object | 非必须 | 返回的数据 |
- 响应数据样例:
@ -710,9 +861,9 @@ username=sunhehe&password=123456
- 请求参数格式:`application/json`
- 请求参数说明:
- 请求数据样例:
#### 4.3.3响应数据
@ -723,7 +874,7 @@ username=sunhehe&password=123456
|:------------|:-------|:---------|:----------------|
| **code** | number | 必须 | 响应码0 -成功1 -失败 |
| **message** | string | 非必须 | 提示信息 |
| **data** | object | 非必须 | 返回的数据 |
| **data** | object | 非必须 | 返回的数据 |
- 响应数据样例:
@ -748,27 +899,28 @@ username=sunhehe&password=123456
- 请求参数格式:`application/json`
- 请求参数说明:
| **参数名称** | **说明** | **类型** | **是否必须** | **备注** |
|:------------|:------------|:--------|:-----------:|:------------|
| **id** | 订单ID | number | | 订单的唯一标识符,用于指定需要取消的订单。 |
| **参数名称** | **说明** | **类型** | **是否必须** | **备注** |
|:---------|:-------|:-------|:--------:|:----------------------|
| **id** | 订单ID | number | | 订单的唯一标识符,用于指定需要取消的订单。 |
> 注:`id`是URL路径的一部分不是请求体中的参数。
- 请求数据样例:
#### 4.4.3响应数据
- 响应数据类型:`application/json`
- 响应参数说明:
| **名称** | **类型** | **是否必须** | **备注** |
|:-------------|:---------|:-----------:|:----------------------------|
| **code** | number | 必须 | 响应码0 - 成功1 - 失败 |
| **message** | string | 必须 | 提示信息 |
| **data** | object | 非必须 | 返回的数据,通常为空 |
| **名称** | **类型** | **是否必须** | **备注** |
|:------------|:-------|:--------:|:------------------|
| **code** | number | 必须 | 响应码0 - 成功1 - 失败 |
| **message** | string | 必须 | 提示信息 |
| **data** | object | 非必须 | 返回的数据,通常为空 |
- 响应数据样例:
```json
//取消订单成功
{
@ -802,12 +954,13 @@ username=sunhehe&password=123456
- 请求参数格式:`application/x-www-form-urlencoded`
- 请求参数说明:
| **参数名称** | **说明** | **类型** | **是否必须** | **备注** |
|:-------------|:----------|:--------:|:-----------:|:------------------|
| **username** | 用户名 | string | 是 | 管理员的用户名5-16位 |
| **password** | 密码 | string | 是 | 管理员的密码5-16位 |
| **参数名称** | **说明** | **类型** | **是否必须** | **备注** |
|:-------------|:-------|:------:|:--------:|:--------------|
| **username** | 用户名 | string | 是 | 管理员的用户名5-16位 |
| **password** | 密码 | string | 是 | 管理员的密码5-16位 |
- 请求数据样例:
```json
username=sunhehe&password=123456
```
@ -817,13 +970,14 @@ username=sunhehe&password=123456
- 响应数据类型:`application/json`
- 响应参数说明:
| **名称** | **类型** | **是否必须** | **备注** |
|:-------------|:--------|:-----------:|:------------------------------|
| **code** | number | 必须 | 响应码0 - 成功1 - 失败 |
| **message** | string | 非必须 | 提示信息,登录成功或失败的描述 |
| **data** | object | 非必须 | 包含管理员的登录令牌等信息 |
| **名称** | **类型** | **是否必须** | **备注** |
|:------------|:-------|:--------:|:------------------|
| **code** | number | 必须 | 响应码0 - 成功1 - 失败 |
| **message** | string | 非必须 | 提示信息,登录成功或失败的描述 |
| **data** | object | 非必须 | 包含管理员的登录令牌等信息 |
- 响应数据样例:
```json
{
"code": 0,
@ -849,10 +1003,10 @@ username=sunhehe&password=123456
- 请求参数格式:`application/x-www-form-urlencoded`
- 请求参数说明:
| **参数名称** | **说明** | **类型** | **是否必须** | **备注** |
|:-------------|:----------|:--------:|:-----------:|:-------------|
| **page** | 页码 | number | 否 | 默认为1分页 |
| **size** | 每页数量 | number | 否 | 默认为10分页 |
| **参数名称** | **说明** | **类型** | **是否必须** | **备注** |
|:---------|:-------|:------:|:--------:|:---------|
| **page** | 页码 | number | 否 | 默认为1分页 |
| **size** | 每页数量 | number | 否 | 默认为10分页 |
- 请求数据样例:
@ -861,18 +1015,19 @@ username=sunhehe&password=123456
- 响应数据类型:`application/json`
- 响应参数说明:
| **名称** | **类型** | **是否必须** | **备注** |
|:-------------|:----------|:-----------:|:----------------------|
| **code** | number | 必须 | 响应码0 - 成功1 - 失败 |
| **message** | string | 非必须 | 提示信息 |
| **data** | object[] | 必须 | 用户列表数据 |
| **data[]** | object | 必须 | 每个用户的详细信息 |
| **data[].id**| string | 必须 | 用户ID |
| **data[].username** | string | 必须 | 用户名 |
| **data[].email** | string | 非必须 | 用户邮箱 |
| **data[].status** | string | 非必须 | 用户状态 (active/inactive) |
| **名称** | **类型** | **是否必须** | **备注** |
|:--------------------|:---------|:--------:|:-----------------------|
| **code** | number | 必须 | 响应码0 - 成功1 - 失败 |
| **message** | string | 非必须 | 提示信息 |
| **data** | object[] | 必须 | 用户列表数据 |
| **data[]** | object | 必须 | 每个用户的详细信息 |
| **data[].id** | string | 必须 | 用户ID |
| **data[].username** | string | 必须 | 用户名 |
| **data[].email** | string | 非必须 | 用户邮箱 |
| **data[].status** | string | 非必须 | 用户状态 (active/inactive) |
- 响应数据样例:
```json
{
"code": 0,
@ -894,7 +1049,6 @@ username=sunhehe&password=123456
}
```
### 5.3、商品管理
#### 5.3.1基本信息
@ -908,10 +1062,11 @@ username=sunhehe&password=123456
- 请求参数格式:`application/x-www-form-urlencoded`
- 请求参数说明:
| **参数名称** | **说明** | **类型** | **是否必须** | **备注** |
|:-------------|:----------|:--------:|:-----------:|:--------------|
| **page** | 页码 | number | 否 | 默认为1分页 |
| **size** | 每页数量 | number | 否 | 默认为10分页 |
| **参数名称** | **说明** | **类型** | **是否必须** | **备注** |
|:---------|:-------|:------:|:--------:|:---------|
| **page** | 页码 | number | 否 | 默认为1分页 |
| **size** | 每页数量 | number | 否 | 默认为10分页 |
- 请求数据样例:
#### 5.3.3响应数据
@ -919,18 +1074,19 @@ username=sunhehe&password=123456
- 响应数据类型:`application/json`
- 响应参数说明:
| **名称** | **类型** | **是否必须** | **备注** |
|:-------------|:----------|:-----------:|:----------------------|
| **code** | number | 必须 | 响应码0 - 成功1 - 失败 |
| **message** | string | 非必须 | 提示信息 |
| **data** | object[] | 必须 | 商品列表数据 |
| **data[]** | object | 必须 | 每个商品的详细信息 |
| **data[].id**| string | 必须 | 商品ID |
| **data[].name** | string | 必须 | 商品名称 |
| **data[].price** | number | 必须 | 商品价格 |
| **data[].quantity** | number | 必须 | 商品库存数量 |
| **名称** | **类型** | **是否必须** | **备注** |
|:--------------------|:---------|:--------:|:------------------|
| **code** | number | 必须 | 响应码0 - 成功1 - 失败 |
| **message** | string | 非必须 | 提示信息 |
| **data** | object[] | 必须 | 商品列表数据 |
| **data[]** | object | 必须 | 每个商品的详细信息 |
| **data[].id** | string | 必须 | 商品ID |
| **data[].name** | string | 必须 | 商品名称 |
| **data[].price** | number | 必须 | 商品价格 |
| **data[].quantity** | number | 必须 | 商品库存数量 |
- 响应数据样例:
```json
{
"code": 0,
@ -965,10 +1121,10 @@ username=sunhehe&password=123456
- 请求参数格式:`application/x-www-form-urlencoded`
- 请求参数说明:
| **参数名称** | **说明** | **类型** | **是否必须** | **备注** |
|:-------------|:----------|:--------:|:-----------:|:--------------|
| **page** | 页码 | number | 否 | 默认为1分页 |
| **size** | 每页数量 | number | 否 | 默认为10分页 |
| **参数名称** | **说明** | **类型** | **是否必须** | **备注** |
|:---------|:-------|:------:|:--------:|:---------|
| **page** | 页码 | number | 否 | 默认为1分页 |
| **size** | 每页数量 | number | 否 | 默认为10分页 |
- 请求数据样例:
@ -977,19 +1133,20 @@ username=sunhehe&password=123456
- 响应数据类型:`application/json`
- 响应参数说明:
| **名称** | **类型** | **是否必须** | **备注** |
|:-------------|:----------|:-----------:|:----------------------|
| **code** | number | 必须 | 响应码0 - 成功1 - 失败 |
| **message** | string | 非必须 | 提示信息 |
| **data** | object[] | 必须 | 订单列表数据 |
| **data[]** | object | 必须 | 每个订单的详细信息 |
| **data[].orderId** | string | 必须 | 订单ID |
| **data[].userId** | string | 必须 | 用户ID |
| **data[].productId** | string | 必须 | 商品ID |
| **data[].quantity** | number | 必须 | 商品数量 |
| **data[].status** | string | 必须 | 订单状态 (pending/paid/shipped) |
| **名称** | **类型** | **是否必须** | **备注** |
|:---------------------|:---------|:--------:|:----------------------------|
| **code** | number | 必须 | 响应码0 - 成功1 - 失败 |
| **message** | string | 非必须 | 提示信息 |
| **data** | object[] | 必须 | 订单列表数据 |
| **data[]** | object | 必须 | 每个订单的详细信息 |
| **data[].orderId** | string | 必须 | 订单ID |
| **data[].userId** | string | 必须 | 用户ID |
| **data[].productId** | string | 必须 | 商品ID |
| **data[].quantity** | number | 必须 | 商品数量 |
| **data[].status** | string | 必须 | 订单状态 (pending/paid/shipped) |
- 响应数据样例:
```json
{
"code": 0,
@ -1026,24 +1183,25 @@ username=sunhehe&password=123456
- 请求参数格式:`application/json`
- 请求参数说明:
| **参数名称** | **说明** | **类型** | **是否必须** | **备注** |
|:-------------|:----------|:--------:|:-----------:|:--------------|
| **token** | 登录令牌 | string | 是 | 管理员登录时获取的token用于身份验证 |
| **参数名称** | **说明** | **类型** | **是否必须** | **备注** |
|:----------|:-------|:------:|:--------:|:----------------------|
| **token** | 登录令牌 | string | 是 | 管理员登录时获取的token用于身份验证 |
- 请求数据样例:
#### 5.5.3响应数据
- 响应数据类型:`application/json`
- 响应参数说明:
| **名称** | **类型** | **是否必须** | **备注** |
|:-------------|:---------|:-----------:|:------------------------------|
| **code** | number | 必须 | 响应码0 - 成功1 - 失败 |
| **message** | string | 非必须 | 提示信息 |
| **名称** | **类型** | **是否必须** | **备注** |
|:------------|:-------|:--------:|:------------------|
| **code** | number | 必须 | 响应码0 - 成功1 - 失败 |
| **message** | string | 非必须 | 提示信息 |
- 响应数据样例:
```json
{
"code": 0,
@ -1053,83 +1211,6 @@ username=sunhehe&password=123456
## 6、其他接口
### 6.1、搜索商品
#### 6.1.1基本信息
- 请求路径URL`/product/search`
- 请求方式:`GET`
- 接口描述:该接口用于根据关键词搜索商品。可以根据商品名称、分类、描述等信息进行模糊查询。
#### 6.1.2请求参数
- 请求参数格式:`application/json`
- 请求参数说明:
| **参数名称** | **说明** | **类型** | **是否必须** | **备注** |
|:--------------|:-------------------------|:---------|:-----------:|:-----------------------------------------|
| **keyword** | 搜索关键词(商品名称、描述等) | string | 是 | 用于搜索商品的关键词,支持模糊查询。 |
| **category** | 商品分类 | string | 否 | 可选,指定商品类别进行筛选,若不提供则不筛选类别。 |
| **page** | 页码(分页查询) | number | 否 | 默认值为1表示第一页。 |
| **pageSize** | 每页显示的商品数量 | number | 否 | 默认值为20最大值为100表示每页显示的商品数。 |
- 请求数据样例:
```json
{
"keyword": "手机",
"category": "电子产品",
"page": 1,
"pageSize": 20
}
```
#### 6.1.3响应数据
- 响应数据类型:`application/json`
- 响应参数说明:
| **名称** | **类型** | **是否必须** | **备注** |
|:-------------|:---------|:-----------:|:----------------------------|
| **code** | number | 必须 | 响应码0 - 成功1 - 失败 |
| **message** | string | 非必须 | 提示信息 |
| **data** | object | 必须 | 返回的数据,包含商品列表信息 |
| **total** | number | 必须 | 符合条件的商品总数 |
| **page** | number | 必须 | 当前页码 |
| **pageSize** | number | 必须 | 每页商品数 |
- 响应数据样例:
```json
{
"code": 0,
"message": "操作成功",
"data": [
{
"productId": 12345,
"name": "二手iPhone 12",
"category": "电子产品",
"price": 3000,
"description": "几乎全新,屏幕完好,原装配件",
"imageUrl": "http://example.com/iphone12.jpg",
"sellerId": 67890,
"sellerName": "张三"
},
{
"productId": 67890,
"name": "二手MacBook Pro",
"category": "电子产品",
"price": 4500,
"description": "配置高,性能稳定,电池寿命长",
"imageUrl": "http://example.com/macbookpro.jpg",
"sellerId": 12345,
"sellerName": "李四"
}
],
"total": 50,
"page": 1,
"pageSize": 20
}
```
### 6.2、用户反馈
#### 6.2.1基本信息
@ -1142,11 +1223,12 @@ username=sunhehe&password=123456
- 请求参数格式:`application/json`
- 请求参数说明:
| **参数名称** | **说明** | **类型** | **是否必须** | **备注** |
|:--------------|:----------------------------|:---------|:-----------:|:--------------------------------------|
| **userId** | 用户ID | number | 是 | 提交反馈的用户的ID用于标识反馈来源。 |
| **content** | 反馈内容 | string | 是 | 用户提交的反馈内容字数限制为500个字符。 |
| **contactInfo**| 联系方式(可选) | string | 否 | 可选,用户希望被平台联系的方式(如电话、邮箱等)。 |
| **参数名称** | **说明** | **类型** | **是否必须** | **备注
** |
|:--------------|:----------------------------|:---------|:-----------:|:--------------------------------------|
| **userId** | 用户ID | number | 是 | 提交反馈的用户的ID用于标识反馈来源。 |
| **content** | 反馈内容 | string | 是 | 用户提交的反馈内容字数限制为500个字符。 |
| **contactInfo**| 联系方式(可选) | string | 否 | 可选,用户希望被平台联系的方式(如电话、邮箱等)。 |
- 请求数据样例:
@ -1163,13 +1245,14 @@ username=sunhehe&password=123456
- 响应数据类型:`application/json`
- 响应参数说明:
| **名称** | **类型** | **是否必须** | **备注** |
|:-------------|:---------|:-----------:|:----------------------------|
| **code** | number | 必须 | 响应码0 - 成功1 - 失败 |
| **message** | string | 非必须 | 提示信息 |
| **data** | object | 非必须 | 返回的数据,通常为空 |
| **名称** | **类型** | **是否必须** | **备注** |
|:------------|:-------|:--------:|:------------------|
| **code** | number | 必须 | 响应码0 - 成功1 - 失败 |
| **message** | string | 非必须 | 提示信息 |
| **data** | object | 非必须 | 返回的数据,通常为空 |
- 响应数据样例:
```json
{
"code": 0,
@ -1177,59 +1260,3 @@ username=sunhehe&password=123456
"data": null
}
```
### 6.3、获取商品详情
#### 6.3.1基本信息
- 请求路径URL`/product/{productId}`
- 请求方式:`GET`
- 接口描述:该接口用于获取某个商品的详细信息。
#### 6.3.2请求参数
- 请求参数格式:`application/json`
- 请求参数说明:
| **参数名称** | **说明** | **类型** | **是否必须** | **备注** |
|:------------|:------------------|:--------|:-----------:|:-------------|
| **productId** | 商品ID | number | 是 | 商品的唯一标识符 |
- 请求数据样例
```json
{
"productId": 12345
}
```
#### 6.3.3响应数据
- 响应数据类型:`application/json`
- 响应参数说明:
| **名称** | **类型** | **是否必须** | **备注** |
|:-------------|:---------|:-----------:|:----------------------------|
| **code** | number | 必须 | 响应码0 - 成功1 - 失败 |
| **message** | string | 非必须 | 提示信息 |
| **data** | object | 必须 | 返回商品的详细信息 |
- 响应数据样例:
```json
{
"code": 0,
"message": "操作成功",
"data": {
"productId": 12345,
"name": "二手iPhone 12",
"category": "电子产品",
"price": 3000,
"description": "几乎全新,屏幕完好,原装配件",
"imageUrl": "http://example.com/iphone12.jpg",
"sellerId": 67890,
"sellerName": "张三",
"contactInfo": "example@example.com",
"location": "北京市",
"createTime": "2024-11-01T12:00:00"
}
}
```

@ -0,0 +1,124 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Palette2">
<group name="Swing">
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
</item>
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
</item>
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.svg" removable="false" auto-create-binding="false" can-attach-label="true">
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
</item>
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
<initial-values>
<property name="text" value="Button" />
</initial-values>
</item>
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="RadioButton" />
</initial-values>
</item>
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="CheckBox" />
</initial-values>
</item>
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
<initial-values>
<property name="text" value="Label" />
</initial-values>
</item>
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
</item>
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
</item>
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
<preferred-size width="-1" height="20" />
</default-constraints>
</item>
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
</item>
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
</item>
</group>
</component>
</project>

@ -1,14 +0,0 @@
package com.trading_platform.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ExampleController {
@GetMapping("/example")
public String example() {
return "Hello, World!";
}
}

@ -0,0 +1,60 @@
package com.trading_platform.controller;
import com.trading_platform.entity.Result;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* ProductControllerHTTP
* ProductService
*/
@RestController("/product")
@Validated
public class ProductController {
// 获取商品列表
@GetMapping("/list")
public Result list() {
// 返回商品列表
return Result.success();
}
//添加商品
@PostMapping("/add")
public Result add() {
return Result.success();
}
//获取商品详情
@GetMapping("/detail/{id}")
public Result detail() {
return Result.success();
}
//删除商品
@DeleteMapping("/delete/{id}")
public Result delete() {
return Result.success();
}
//更新商品信息
@PostMapping("/update/{id}")
public Result update() {
return Result.success();
}
//搜索商品
@GetMapping("/search")
public Result search() {
return Result.success();
}
}

@ -5,12 +5,11 @@ import com.trading_platform.entity.Users;
import com.trading_platform.service.UsersService;
import com.trading_platform.utils.JwtUtil;
import com.trading_platform.utils.Sha256Util;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.constraints.Pattern;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.Map;
@ -22,10 +21,6 @@ import java.util.Map;
@RestController
@RequestMapping("/users")
@Validated
/**
* UserController
*
*/
public class UsersController {
// usersService用于执行与用户相关的业务逻辑
@ -43,25 +38,24 @@ public class UsersController {
this.usersService = usersService;
}
/**
*
*
* @param username
* @param userid id
* @param password
* @return
*/
@RequestMapping("/register")
public Result register(@Pattern(regexp = "^\\S{5,16}$") String username, @Pattern(regexp = "^\\S{5,16}$") String password) {
//查询是否已存在该用户
Users user = usersService.findByUsername(username);
public Result register(@Pattern(regexp = "^\\S{5,16}$") int userid, @Pattern(regexp = "^\\S{5,16}$") String password) {
// 查询是否已存在该用户
Users user = usersService.findById(userid);
if (user != null) {
//用户已存在,返回错误信息
// 用户已存在,返回错误信息
return Result.error("用户已存在");
} else {
//注册新用户
usersService.register(username, password);
//注册成功,返回成功信息
// 注册新用户
usersService.register(userid, password);
// 注册成功,返回成功信息
return Result.success();
}
}
@ -69,17 +63,17 @@ public class UsersController {
/**
*
*
* @param username 5-16
* @param userid id
* @param password 5-16
* @return JWT
*/
@PostMapping("/login")
public Result login(@Pattern(regexp = "^\\S{5,16}$") String username, @Pattern(regexp = "^\\S{5,16}$") String password) {
// 根据用户查询用户信息
Users loginUser = usersService.findByUsername(username);
// 如果用户信息为空,说明用户错误
public Result login(@Pattern(regexp = "^\\S{5,16}$") int userid, @Pattern(regexp = "^\\S{5,16}$") String password) {
// 根据用户ID查询用户信息
Users loginUser = usersService.findById(userid);
// 如果用户信息为空,说明用户ID错误
if (loginUser == null) {
return Result.error("用户错误");
return Result.error("用户ID错误");
}
// 比较密码使用SHA256加密后的密码与数据库中存储的密码进行比较
@ -92,6 +86,83 @@ public class UsersController {
return Result.success(token);
}
// 如果密码错误,返回错误信息
return Result.success("密码错误");
return Result.error("密码错误");
}
/**
*
* GET
*
* @param request HTTP
* @return Result
*/
@GetMapping("/info")
public Result info(HttpServletRequest request) {
// 从令牌中获取用户ID
Result userIdResult = JwtUtil.getUserIdFromToken(request);
// 如果获取用户ID失败直接返回错误结果
if (!userIdResult.isSuccess()) {
return userIdResult;
}
// 获取用户ID
Integer userId = (Integer) userIdResult.getData();
// 根据用户ID查询用户信息
Users user = usersService.findById(userId);
if (user == null) {
return Result.error("用户不存在");
}
// 返回用户信息
return Result.success(user);
}
/**
*
*
* @param request HTTP
* @param nickName
* @param phone
* @param email
* @return
*/
@PostMapping("/update")
public Result update(HttpServletRequest request,
@RequestParam(required = false) String nickName,
@RequestParam(required = false) @Pattern(regexp = "^\\d{11}$") String phone,
@RequestParam(required = false) @Pattern(regexp = "^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+$") String email) {
// 从令牌中获取用户ID
Result userIdResult = JwtUtil.getUserIdFromToken(request);
// 如果获取用户ID失败直接返回错误结果
if (!userIdResult.isSuccess()) {
return userIdResult;
}
// 获取用户ID
Integer userId = (Integer) userIdResult.getData();
// 根据用户ID查询用户信息
Users user = usersService.findById(userId);
if (user == null) {
return Result.error("用户不存在");
}
// 更新用户信息
if (nickName != null) {
user.setNickName(nickName);
}
if (phone != null) {
user.setMobile(phone);
}
if (email != null) {
user.setEmail(email);
}
// 保存更新后的用户信息
usersService.updateUser(user);
return Result.success();
}
}

@ -13,10 +13,19 @@ public class Result<T> {
private String message; //提示信息
private T data;//响应数据
/**
*
*
* @return code0truefalse
*/
public boolean isSuccess() {
return code == 0;
}
/**
*
*
* @param <E>
* @param <E>
* @param data
* @return Result
*/

@ -1,10 +1,7 @@
package com.trading_platform.mapper;
import com.trading_platform.entity.Users;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Options;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.*;
import java.util.Optional;
@ -15,14 +12,16 @@ import java.util.Optional;
@Mapper
public interface UsersMapper {
/**
*
* ID
*
* @param username
* @param id ID
* @return OptionalUsersOptional.empty()
*/
@Select("SELECT * FROM users WHERE username=#{username}")
Optional<Users> findByUsername(String username);
@Select("SELECT * FROM users WHERE id=#{id}")
Optional<Users> findById(int id);
/**
*
@ -35,5 +34,14 @@ public interface UsersMapper {
"VALUES (#{headPicUrl}, #{nickName}, #{username}, #{mobile}, #{password}, #{sex}, #{email}, #{address}, #{status}, #{createTime}, #{updateTime})")
@Options(useGeneratedKeys = true, keyProperty = "id")
void addUser(Users user);
/**
*
*
* @param user
* 使MyBatis@UpdateSQL
*/
@Update("UPDATE users SET headPicUrl=#{headPicUrl}, nickName=#{nickName}, mobile=#{mobile}, password=#{password}, sex=#{sex}, email=#{email}, address=#{address}, status=#{status}, update_time=#{updateTime} WHERE id=#{id}")
void updateUser(Users user);
}

@ -7,20 +7,17 @@ import com.trading_platform.entity.Users;
*
*/
public interface UsersService {
/**
*
*
* @param username
* @return null
*/
Users findByUsername(String username);
Users findById(int userId);
/**
*
*
* @param username
* @param userId
* @param password
*/
void register(String username, String password);
void register(int userId, String password);
void updateUser(Users user);
}

@ -23,24 +23,31 @@ public class UsersServiceImpl implements UsersService {
}
@Override
public Users findByUsername(String username) {
public Users findById(int userId) {
// 根据用户名查询用户信息
// 参数username要查询的用户名
// 返回用户对象如果找不到则返回null
return usersMapper.findByUsername(username).orElse(null);
return usersMapper.findById(userId).orElse(null);
}
@Override
public void register(String username, String password) {
public void register(int userId, String password) {
// 注册新用户
// 参数username用户的用户名
// 参数password用户的明文密码
String sha256String = Sha256Util.getSHA256String(password);
Users user = new Users();
user.setUsername(username);
user.setUserId(userId);
user.setPassword(sha256String);
// 其他字段可以根据需要设置
usersMapper.addUser(user);
}
@Override
public void updateUser(Users user) {
// 更新用户信息
// 参数user要更新的用户对象
usersMapper.updateUser(user);
}
}

@ -2,6 +2,8 @@ package com.trading_platform.utils;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.trading_platform.entity.Result;
import jakarta.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.Map;
@ -21,7 +23,7 @@ public class JwtUtil {
// 创建一个JWT并添加自定义声明以及设置过期时间
return JWT.create()
.withClaim("claims", claims)
.withExpiresAt(new Date(System.currentTimeMillis() + 1000 * 6060 * 12))
.withExpiresAt(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 12))
.sign(Algorithm.HMAC256(KEY));
}
@ -43,7 +45,28 @@ public class JwtUtil {
.getClaim("claims")
// 将声明信息转换为映射对象并返回
.asMap();
}
/**
* JWTID
*
* @param request HTTP
* @return IDResult
*/
public static Result getUserIdFromToken(HttpServletRequest request) {
// 从请求头中获取JWT令牌
String token = request.getHeader("Authorization");
if (token == null || token.isEmpty()) {
return Result.error("缺少授权令牌");
}
// 解析JWT令牌获取用户ID
Map<String, Object> claims = parseToken(token);
Integer userId = (Integer) claims.get("id");
if (userId == null) {
return Result.error("无效的令牌");
}
return Result.success(userId);
}
}

Loading…
Cancel
Save