datai/datai-scenes/datai-scene-salesforce/docs/api-docs/2026-01-25-002-04-api.md
Kris 8b1e7d78a3 feat: 实现时区国际化功能
- 新增时区管理功能:时区设置、时区转换、时区显示、时区列表管理、时区切换、时区缓存管理
- 新增时区转换注解 @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
2026-01-25 18:54:33 +08:00

531 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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)