# getSiteInfo 接口重新设计 - 彻底解决空值异常

## 问题描述
`/api/cms/website/getSiteInfo` 接口持续报错：
```
code: 1
error: "java.lang.IllegalArgumentException: Value must not be null!"
message: "操作失败"
```

## 解决方案
**完全重新设计接口**，采用防御性编程和现代化时间处理方式。

## 重新设计思路

### 1. 防御性编程
- **全面异常捕获**: 每个步骤都有 try-catch 保护
- **空值安全**: 所有方法都进行空值检查
- **兜底策略**: 每个功能都有默认值或降级方案

### 2. 现代化时间处理
- **使用 LocalDateTime**: 替代过时的 DateTime
- **标准化格式**: 统一使用 ISO 8601 格式
- **时区安全**: 避免时区相关的问题

### 3. 分层错误处理
- **接口层**: 捕获所有异常，返回友好错误信息
- **业务层**: 各个功能模块独立处理异常
- **数据层**: 安全的数据访问和转换

## 重新设计内容

### 1. 主接口重构 (`getSiteInfo`)
```java
@GetMapping("/getSiteInfo")
public ApiResult<CmsWebsite> getSiteInfo() {
    try {
        // 1. 安全获取租户ID
        Integer tenantId = getTenantId();
        if (ObjectUtil.isEmpty(tenantId)) {
            return fail("租户ID不能为空", null);
        }

        // 2. 安全查询数据库
        CmsWebsite website = cmsWebsiteService.getOne(
            new LambdaQueryWrapper<CmsWebsite>()
                .eq(CmsWebsite::getTenantId, tenantId)
                .eq(CmsWebsite::getDeleted, 0)
                .last("limit 1")
        );

        // 3. 安全构建网站信息
        buildSafeWebsiteInfo(website);

        return success(website);
    } catch (Exception e) {
        log.error("获取网站信息异常: {}", e.getMessage(), e);
        return fail("获取网站信息失败: " + e.getMessage(), null);
    }
}
```

### 2. 安全构建方法 (`buildSafeWebsiteInfo`)
- **模块化处理**: 每个功能独立处理，互不影响
- **异常隔离**: 单个模块失败不影响其他模块
- **默认值策略**: 每个模块都有合理的默认值

### 3. 现代化时间处理 (`buildSafeServerTime`)
```java
// 使用 LocalDateTime 替代 DateTime
java.time.LocalDateTime now = java.time.LocalDateTime.now();
java.time.LocalDate today = java.time.LocalDate.now();

serverTime.put("now", now.toString());           // ISO 8601 格式
serverTime.put("today", today.toString());       // yyyy-MM-dd 格式
serverTime.put("timestamp", System.currentTimeMillis());
```

### 4. 安全的导航处理 (`setSafeWebsiteNavigation`)
- **双重保护**: 数据获取和树构建都有异常处理
- **降级策略**: 树构建失败时使用平铺列表
- **空值安全**: 确保返回值永远不为 null

### 5. 安全的配置构建 (`buildSafeWebsiteConfig`)
- **字段安全**: 检查字段名和值的有效性
- **域名兜底**: 提供默认域名生成策略
- **配置隔离**: 单个配置项失败不影响整体

## 新增的安全方法

### 1. `buildSafeWebsiteInfo(CmsWebsite website)`
- 统一的网站信息构建入口
- 模块化处理各个功能
- 全面的异常处理和日志记录

### 2. `buildSafeWebsiteConfig(CmsWebsite website)`
- 安全的配置信息构建
- 字段有效性检查
- 域名信息兜底策略

### 3. `setSafeWebsiteNavigation(CmsWebsite website)`
- 安全的导航信息设置
- 双重异常保护
- 树构建失败时的降级策略

### 4. `buildSafeServerTime()`
- 使用现代化的 LocalDateTime
- ISO 8601 标准时间格式
- 完整的异常处理

### 5. `getSafeSysDomain(CmsWebsite website)` 和 `getSafeDomain(CmsWebsite website)`
- 安全的域名生成
- 多层空值检查
- 默认域名兜底策略

## 技术改进

### 1. 时间处理现代化
```java
// 旧方式 (可能有问题)
DateTime date = DateUtil.date();
String today = DateUtil.today();

// 新方式 (安全可靠)
LocalDateTime now = LocalDateTime.now();
LocalDate today = LocalDate.now();
```

### 2. 异常处理分层
```java
// 接口层 - 捕获所有异常
try {
    buildSafeWebsiteInfo(website);
    return success(website);
} catch (Exception e) {
    return fail("获取网站信息失败: " + e.getMessage(), null);
}

// 业务层 - 模块化异常处理
try {
    setWebsiteStatus(website);
} catch (Exception e) {
    log.warn("设置网站状态失败: {}", e.getMessage());
    website.setStatus(0); // 默认状态
}
```

### 3. 空值安全策略
```java
// 确保返回值永远不为 null
if (topNavs != null && !topNavs.isEmpty()) {
    website.setTopNavs(CommonUtil.toTreeData(topNavs, ...));
} else {
    website.setTopNavs(new ArrayList<>());
}
```

## 测试建议

1. **正常场景**: 测试有完整站点数据的租户
2. **异常场景**: 测试没有站点数据的租户
3. **边界场景**: 测试站点数据不完整的情况
4. **多租户场景**: 测试不同租户之间的数据隔离
5. **性能场景**: 测试大量导航数据的处理
6. **时间场景**: 测试不同时区的时间处理

## 影响范围

- ✅ **彻底解决** `getSiteInfo` 接口的空值异常
- ✅ **现代化** 时间处理方式，使用 LocalDateTime
- ✅ **增强** 系统整体稳定性和健壮性
- ✅ **改善** 错误日志的可读性和调试能力
- ✅ **保持** 向后兼容，不影响现有功能
- ✅ **提升** 多租户数据安全性
