- 新增时区管理功能:时区设置、时区转换、时区显示、时区列表管理、时区切换、时区缓存管理 - 新增时区转换注解 @TimeZoneConvert 和 AOP 切面 TimeZoneConvertAspect - 新增时区转换工具类 TimeZoneUtils - 新增时区实体类、DTO、VO、Mapper、Service 和 Controller - 新增时区 API 接口:获取当前用户时区、切换用户时区、获取系统默认时区、查询时区列表、获取时区详情、新增时区、修改时区、删除时区 - 新增时区缓存常量 CacheConstants.SYS_TIMEZONE_KEY - 修改 SysUser 实体类,添加 time_zone 字段 - 修复 I18nController 导入错误,使用 RedisCache 替代 RedisUtils - 完善 API 文档、变更日志、复盘文档和会话记录 - 更新文档索引 需求编号:2026-01-21-002-04
531 lines
11 KiB
Markdown
531 lines
11 KiB
Markdown
# API 文档:时区国际化功能
|
||
|
||
## 元数据
|
||
- 需求编号:2026-01-21-002-04
|
||
- 创建时间:2026-01-25
|
||
- 创建人:SSOT 架构师
|
||
- 父需求:2026-01-21-002-项目国际化需求
|
||
|
||
## API 概述
|
||
时区国际化功能 API 提供了时区管理、时区切换、时区查询等功能,支持用户设置时区偏好、切换时区、查询当前时区和系统默认时区。API 遵循 RESTful 规范,使用标准的 HTTP 方法(GET、POST、PUT、DELETE)进行数据交互。
|
||
|
||
## 接口列表
|
||
|
||
### 接口 1:获取当前用户时区
|
||
|
||
#### 功能描述
|
||
获取当前用户的时区偏好,包括时区 ID、时区名称、时区偏移量等信息。
|
||
|
||
#### 请求方式
|
||
GET
|
||
|
||
#### 请求路径
|
||
`/system/timezone/current`
|
||
|
||
#### 权限要求
|
||
- 无(需要登录)
|
||
|
||
#### 请求参数
|
||
无
|
||
|
||
#### 响应参数
|
||
|
||
| 参数名 | 类型 | 说明 |
|
||
|--------|------|------|
|
||
| code | Integer | 状态码(200 成功,其他失败) |
|
||
| msg | String | 提示信息 |
|
||
| data | String | 时区 ID(例如:Asia/Shanghai) |
|
||
|
||
#### 成功示例
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"msg": "操作成功",
|
||
"data": "Asia/Shanghai"
|
||
}
|
||
```
|
||
|
||
#### 失败示例
|
||
```json
|
||
{
|
||
"code": 401,
|
||
"msg": "未登录或登录已过期"
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 接口 2:切换用户时区
|
||
|
||
#### 功能描述
|
||
切换当前用户的时区偏好,并清除相关缓存。切换操作会被记录到审计日志中。
|
||
|
||
#### 请求方式
|
||
POST
|
||
|
||
#### 请求路径
|
||
`/system/timezone/switch`
|
||
|
||
#### 权限要求
|
||
- 无(需要登录)
|
||
|
||
#### 请求参数
|
||
|
||
| 参数名 | 类型 | 必填 | 说明 |
|
||
|--------|------|------|------|
|
||
| timeZone | String | 是 | 时区 ID(例如:Asia/Shanghai、America/New_York) |
|
||
|
||
#### 响应参数
|
||
|
||
| 参数名 | 类型 | 说明 |
|
||
|--------|------|------|
|
||
| code | Integer | 状态码(200 成功,其他失败) |
|
||
| msg | String | 提示信息 |
|
||
|
||
#### 成功示例
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"msg": "时区切换成功"
|
||
}
|
||
```
|
||
|
||
#### 失败示例
|
||
```json
|
||
{
|
||
"code": 401,
|
||
"msg": "未登录或登录已过期"
|
||
}
|
||
```
|
||
|
||
```json
|
||
{
|
||
"code": 500,
|
||
"msg": "未找到用户信息"
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 接口 3:获取系统默认时区
|
||
|
||
#### 功能描述
|
||
获取系统默认时区配置。系统默认时区是所有用户的默认时区,当用户未设置时区偏好时使用。
|
||
|
||
#### 请求方式
|
||
GET
|
||
|
||
#### 请求路径
|
||
`/system/timezone/default`
|
||
|
||
#### 权限要求
|
||
- `system:timezone:query` - 时区查询权限
|
||
|
||
#### 请求参数
|
||
无
|
||
|
||
#### 响应参数
|
||
|
||
| 参数名 | 类型 | 说明 |
|
||
|--------|------|------|
|
||
| code | Integer | 状态码(200 成功,其他失败) |
|
||
| msg | String | 提示信息 |
|
||
| data | String | 时区 ID(例如:Asia/Shanghai) |
|
||
|
||
#### 成功示例
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"msg": "操作成功",
|
||
"data": "Asia/Shanghai"
|
||
}
|
||
```
|
||
|
||
#### 失败示例
|
||
```json
|
||
{
|
||
"code": 403,
|
||
"msg": "没有权限访问"
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 接口 4:查询时区列表
|
||
|
||
#### 功能描述
|
||
查询时区列表,支持分页查询和条件过滤。
|
||
|
||
#### 请求方式
|
||
GET
|
||
|
||
#### 请求路径
|
||
`/system/timezone/list`
|
||
|
||
#### 权限要求
|
||
- `system:timezone:list` - 时区列表查询权限
|
||
|
||
#### 请求参数
|
||
|
||
| 参数名 | 类型 | 必填 | 说明 |
|
||
|--------|------|------|------|
|
||
| pageNum | Integer | 否 | 页码(默认 1) |
|
||
| pageSize | Integer | 否 | 每页条数(默认 10) |
|
||
| timezoneId | String | 否 | 时区 ID |
|
||
| timezoneName | String | 否 | 时区名称(模糊查询) |
|
||
| isActive | String | 否 | 是否激活(0 否,1 是) |
|
||
| isDefault | String | 否 | 是否默认(0 否,1 是) |
|
||
|
||
#### 响应参数
|
||
|
||
| 参数名 | 类型 | 说明 |
|
||
|--------|------|------|
|
||
| code | Integer | 状态码(200 成功,其他失败) |
|
||
| msg | String | 提示信息 |
|
||
| rows | Array | 时区列表 |
|
||
| rows[].timezoneId | String | 时区 ID |
|
||
| rows[].timezoneName | String | 时区名称 |
|
||
| rows[].timezoneOffset | String | 时区偏移量 |
|
||
| rows[].isActive | String | 是否激活(0 否,1 是) |
|
||
| rows[].isDefault | String | 是否默认(0 否,1 是) |
|
||
| rows[].createTime | String | 创建时间 |
|
||
| rows[].updateTime | String | 更新时间 |
|
||
| rows[].remark | String | 备注 |
|
||
| total | Integer | 总记录数 |
|
||
|
||
#### 成功示例
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"msg": "查询成功",
|
||
"rows": [
|
||
{
|
||
"timezoneId": "Asia/Shanghai",
|
||
"timezoneName": "上海",
|
||
"timezoneOffset": "UTC+8",
|
||
"isActive": "1",
|
||
"isDefault": "1",
|
||
"createTime": "2026-01-25 10:00:00",
|
||
"updateTime": "2026-01-25 10:00:00",
|
||
"remark": "中国标准时间"
|
||
},
|
||
{
|
||
"timezoneId": "America/New_York",
|
||
"timezoneName": "纽约",
|
||
"timezoneOffset": "UTC-5",
|
||
"isActive": "1",
|
||
"isDefault": "0",
|
||
"createTime": "2026-01-25 10:00:00",
|
||
"updateTime": "2026-01-25 10:00:00",
|
||
"remark": "美国东部时间"
|
||
}
|
||
],
|
||
"total": 2
|
||
}
|
||
```
|
||
|
||
#### 失败示例
|
||
```json
|
||
{
|
||
"code": 403,
|
||
"msg": "没有权限访问"
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 接口 5:获取时区详情
|
||
|
||
#### 功能描述
|
||
根据时区 ID 获取时区详细信息。
|
||
|
||
#### 请求方式
|
||
GET
|
||
|
||
#### 请求路径
|
||
`/system/timezone/{timezoneId}`
|
||
|
||
#### 权限要求
|
||
- `system:timezone:query` - 时区查询权限
|
||
|
||
#### 请求参数
|
||
|
||
| 参数名 | 类型 | 必填 | 说明 |
|
||
|--------|------|------|------|
|
||
| timezoneId | String | 是 | 时区 ID(路径参数) |
|
||
|
||
#### 响应参数
|
||
|
||
| 参数名 | 类型 | 说明 |
|
||
|--------|------|------|
|
||
| code | Integer | 状态码(200 成功,其他失败) |
|
||
| msg | String | 提示信息 |
|
||
| data | Object | 时区详情 |
|
||
| data.timezoneId | String | 时区 ID |
|
||
| data.timezoneName | String | 时区名称 |
|
||
| data.timezoneOffset | String | 时区偏移量 |
|
||
| data.isActive | String | 是否激活(0 否,1 是) |
|
||
| data.isDefault | String | 是否默认(0 否,1 是) |
|
||
| data.createBy | String | 创建者 |
|
||
| data.createTime | String | 创建时间 |
|
||
| data.updateBy | String | 更新者 |
|
||
| data.updateTime | String | 更新时间 |
|
||
| data.remark | String | 备注 |
|
||
|
||
#### 成功示例
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"msg": "查询成功",
|
||
"data": {
|
||
"timezoneId": "Asia/Shanghai",
|
||
"timezoneName": "上海",
|
||
"timezoneOffset": "UTC+8",
|
||
"isActive": "1",
|
||
"isDefault": "1",
|
||
"createBy": "admin",
|
||
"createTime": "2026-01-25 10:00:00",
|
||
"updateBy": "admin",
|
||
"updateTime": "2026-01-25 10:00:00",
|
||
"remark": "中国标准时间"
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 失败示例
|
||
```json
|
||
{
|
||
"code": 403,
|
||
"msg": "没有权限访问"
|
||
}
|
||
```
|
||
|
||
```json
|
||
{
|
||
"code": 404,
|
||
"msg": "时区不存在"
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 接口 6:新增时区
|
||
|
||
#### 功能描述
|
||
新增时区配置。新增操作会被记录到审计日志中。
|
||
|
||
#### 请求方式
|
||
POST
|
||
|
||
#### 请求路径
|
||
`/system/timezone`
|
||
|
||
#### 权限要求
|
||
- `system:timezone:add` - 时区新增权限
|
||
|
||
#### 请求参数
|
||
|
||
| 参数名 | 类型 | 必填 | 说明 |
|
||
|--------|------|------|------|
|
||
| timezoneId | String | 是 | 时区 ID |
|
||
| timezoneName | String | 是 | 时区名称 |
|
||
| timezoneOffset | String | 是 | 时区偏移量 |
|
||
| isActive | String | 否 | 是否激活(默认 1) |
|
||
| isDefault | String | 否 | 是否默认(默认 0) |
|
||
| remark | String | 否 | 备注 |
|
||
|
||
#### 响应参数
|
||
|
||
| 参数名 | 类型 | 说明 |
|
||
|--------|------|------|
|
||
| code | Integer | 状态码(200 成功,其他失败) |
|
||
| msg | String | 提示信息 |
|
||
|
||
#### 成功示例
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"msg": "新增成功"
|
||
}
|
||
```
|
||
|
||
#### 失败示例
|
||
```json
|
||
{
|
||
"code": 403,
|
||
"msg": "没有权限访问"
|
||
}
|
||
```
|
||
|
||
```json
|
||
{
|
||
"code": 500,
|
||
"msg": "时区 ID 已存在"
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 接口 7:修改时区
|
||
|
||
#### 功能描述
|
||
修改时区配置。修改操作会被记录到审计日志中。
|
||
|
||
#### 请求方式
|
||
PUT
|
||
|
||
#### 请求路径
|
||
`/system/timezone`
|
||
|
||
#### 权限要求
|
||
- `system:timezone:edit` - 时区修改权限
|
||
|
||
#### 请求参数
|
||
|
||
| 参数名 | 类型 | 必填 | 说明 |
|
||
|--------|------|------|------|
|
||
| timezoneId | String | 是 | 时区 ID |
|
||
| timezoneName | String | 否 | 时区名称 |
|
||
| timezoneOffset | String | 否 | 时区偏移量 |
|
||
| isActive | String | 否 | 是否激活(0 否,1 是) |
|
||
| isDefault | String | 否 | 是否默认(0 否,1 是) |
|
||
| remark | String | 否 | 备注 |
|
||
|
||
#### 响应参数
|
||
|
||
| 参数名 | 类型 | 说明 |
|
||
|--------|------|------|
|
||
| code | Integer | 状态码(200 成功,其他失败) |
|
||
| msg | String | 提示信息 |
|
||
|
||
#### 成功示例
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"msg": "修改成功"
|
||
}
|
||
```
|
||
|
||
#### 失败示例
|
||
```json
|
||
{
|
||
"code": 403,
|
||
"msg": "没有权限访问"
|
||
}
|
||
```
|
||
|
||
```json
|
||
{
|
||
"code": 500,
|
||
"msg": "时区不存在"
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 接口 8:删除时区
|
||
|
||
#### 功能描述
|
||
删除时区配置。删除操作会被记录到审计日志中。
|
||
|
||
#### 请求方式
|
||
DELETE
|
||
|
||
#### 请求路径
|
||
`/system/timezone/{timezoneIds}`
|
||
|
||
#### 权限要求
|
||
- `system:timezone:remove` - 时区删除权限
|
||
|
||
#### 请求参数
|
||
|
||
| 参数名 | 类型 | 必填 | 说明 |
|
||
|--------|------|------|------|
|
||
| timezoneIds | String | 是 | 时区 ID 列表(多个 ID 用逗号分隔,路径参数) |
|
||
|
||
#### 响应参数
|
||
|
||
| 参数名 | 类型 | 说明 |
|
||
|--------|------|------|
|
||
| code | Integer | 状态码(200 成功,其他失败) |
|
||
| msg | String | 提示信息 |
|
||
|
||
#### 成功示例
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"msg": "删除成功"
|
||
}
|
||
```
|
||
|
||
#### 失败示例
|
||
```json
|
||
{
|
||
"code": 403,
|
||
"msg": "没有权限访问"
|
||
}
|
||
```
|
||
|
||
```json
|
||
{
|
||
"code": 500,
|
||
"msg": "时区不存在"
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 时区转换注解使用说明
|
||
|
||
### @TimeZoneConvert 注解
|
||
|
||
#### 功能描述
|
||
在 Service 方法上添加 `@TimeZoneConvert` 注解,AOP 切面会自动拦截该方法返回值,并将所有 `LocalDateTime` 字段从 UTC 转换为当前用户的时区。
|
||
|
||
#### 使用示例
|
||
|
||
```java
|
||
@Service
|
||
public class OrderServiceImpl implements IOrderService {
|
||
|
||
@TimeZoneConvert
|
||
public Order getOrderById(Long orderId) {
|
||
Order order = orderMapper.selectOrderById(orderId);
|
||
return order;
|
||
}
|
||
|
||
@TimeZoneConvert
|
||
public List<Order> getOrderList(OrderQuery query) {
|
||
List<Order> list = orderMapper.selectOrderList(query);
|
||
return list;
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 注意事项
|
||
1. 该注解仅适用于 Service 层方法
|
||
2. 该注解会递归转换对象中的所有 `LocalDateTime` 字段
|
||
3. 如果时区无效,会使用系统默认时区进行转换
|
||
4. 该注解不会修改原始对象,而是返回转换后的对象
|
||
|
||
---
|
||
|
||
## 错误码说明
|
||
|
||
| 错误码 | 说明 |
|
||
|--------|------|
|
||
| 200 | 操作成功 |
|
||
| 401 | 未登录或登录已过期 |
|
||
| 403 | 没有权限访问 |
|
||
| 404 | 资源不存在 |
|
||
| 500 | 服务器内部错误 |
|
||
|
||
---
|
||
|
||
## 相关文档
|
||
|
||
- [需求文档](../requirements/2026-01-21-002-04-时区国际化需求.md)
|
||
- [设计文档](../design/2026-01-21-002-04-时区国际化设计.md)
|
||
- [决策记录](../decisions/adr/2026-01-25-002-04-ADR-时区国际化技术选型.md)
|
||
- [变更日志](../changelog/2026-01-25-002-04-changelog.md)
|
||
- [复盘文档](../retros/2026-01-25-002-04-retro.md) |