# 应用启动预加载优化

## 概述

为了提升用户体验，避免"先有鸡还是先有蛋"的问题，应用在启动时会自动加载所有必要的配置数据。

## 预加载的数据

### 1. API 配置 ✅

**为什么需要预加载：**
- 聊天功能依赖 API 配置才能调用 LLM
- 用户可能直接开始聊天而不访问 API 配置页面

**加载逻辑：**
```javascript
// 1. 加载配置文件列表
await apiConfigStore.fetchProfiles();

// 2. 如果有配置但没有选中，自动加载第一个
if (profiles.length > 0 && !currentProfile) {
  await fetchProfile(profiles[0].id);
}
```

**日志输出：**
```
[App] ✅ API 配置文件列表加载完成
[App] 📝 自动加载第一个配置文件: Default
[App] ✅ API 配置详情加载完成
```

### 2. 预设列表 ✅

**为什么需要预加载：**
- 聊天时使用预设中的参数（temperature、max_tokens 等）
- 提示词组件来自预设配置

**加载逻辑：**
```javascript
// 1. 加载预设列表
await presetStore.fetchPresets();

// 2. 如果没有选中预设，自动选择第一个
if (!selectedPreset && presets.length > 0) {
  selectPreset(presets[0].name);
}
```

**日志输出：**
```
[App] ✅ 预设列表加载完成
[App] 📝 自动选择第一个预设: Default
```

### 3. 角色卡列表 ✅

**为什么需要预加载：**
- 用户打开应用后需要立即看到可用的角色
- 避免切换到角色卡标签页时才加载的延迟

**加载逻辑：**
```javascript
await characterStore.fetchCharacters();
```

**日志输出：**
```
[App] ✅ 角色卡列表加载完成
```

### 4. 世界书列表 ✅

**为什么需要预加载：**
- 角色卡可能绑定世界书
- 聊天时需要激活世界书条目

**加载逻辑：**
```javascript
await worldBookStore.fetchWorldBooks();
```

**日志输出：**
```
[App] ✅ 世界书列表加载完成
```

## 不需要预加载的数据

### Token 使用统计 ❌

**原因：**
- 这是查看型数据，不是必需的配置
- 数据量可能较大
- 用户不一定需要查看

**加载时机：**
- 用户切换到 Token 使用标签页时再加载

### 任务列表 ❌

**原因：**
- 任务是动态生成的
- 每次聊天时根据选项创建
- 不需要持久化

**加载时机：**
- 聊天时根据需要创建

### 正则规则 ❌

**原因：**
- 使用时才加载
- 可能按角色或预设分别加载

**加载时机：**
- 处理消息时按需加载

## 技术实现

### 并行加载

使用 `Promise.allSettled` 并行加载所有数据，而不是串行：

```javascript
Promise.allSettled([
  loadApiConfig(),
  loadPresets(),
  loadCharacters(),
  loadWorldBooks()
]).then((results) => {
  // 处理结果
});
```

**优势：**
- ⚡ 速度更快：4个请求同时发起，总时间 ≈ 最慢的那个请求
- 🛡️ 容错性强：单个失败不影响其他数据加载
- 📊 可统计：知道哪些成功、哪些失败

### 错误处理

每个加载任务都有独立的 try-catch：

```javascript
(async () => {
  try {
    await fetchData();
    console.log('✅ 加载成功');
  } catch (err) {
    console.error('❌ 加载失败:', err);
  }
})()
```

**优势：**
- 单个数据源失败不会中断其他加载
- 详细的错误日志便于调试
- 应用仍可正常使用（降级处理）

### 性能监控

记录加载耗时：

```javascript
const startTime = Date.now();
// ... 加载数据 ...
const duration = ((Date.now() - startTime) / 1000).toFixed(2);
console.log(`[App] 🎉 配置加载完成 (${duration}s)`);
```

**日志输出：**
```
[App] 🎉 配置加载完成 (1.23s)
[App] 📊 成功: 4, 失败: 0
```

## 用户体验提升

### Before（优化前）

```
用户操作流程：
1. 打开应用
2. 点击左侧边栏 → API 配置
3. 等待加载配置文件
4. 选择/创建配置
5. 点击左侧边栏 → 预设
6. 等待加载预设列表
7. 选择预设
8. 点击左侧边栏 → 角色卡
9. 等待加载角色列表
10. 选择角色
11. 开始聊天

总耗时：~5-10秒（多次等待）
```

### After（优化后）

```
用户操作流程：
1. 打开应用（后台自动加载所有配置）
2. 等待 ~1-2秒（并行加载）
3. 直接选择角色开始聊天

总耗时：~1-2秒（一次等待）
```

**提升：**
- ⏱️ 减少等待时间 60-80%
- 🎯 操作步骤减少 7步 → 2步
- 😊 用户体验更流畅

## 日志示例

### 成功情况

```
[App] 🚀 应用启动，开始加载默认配置...
[App] ✅ API 配置文件列表加载完成
[App] 📝 自动加载第一个配置文件: Default
[App] ✅ API 配置详情加载完成
[App] ✅ 预设列表加载完成
[App] 📝 自动选择第一个预设: Default
[App] ✅ 角色卡列表加载完成
[App] ✅ 世界书列表加载完成
[App] 🎉 配置加载完成 (1.23s)
[App] 📊 成功: 4, 失败: 0
```

### 部分失败情况

```
[App] 🚀 应用启动，开始加载默认配置...
[App] ✅ API 配置文件列表加载完成
[App] ✅ 预设列表加载完成
[App] 📝 自动选择第一个预设: Default
[App] ✅ 角色卡列表加载完成
[App] ❌ 世界书列表加载失败: Network error
[App] 🎉 配置加载完成 (2.45s)
[App] 📊 成功: 3, 失败: 1
[App] ⚠️ 部分配置加载失败，但应用仍可正常使用
```

### 没有配置的情况

```
[App] 🚀 应用启动，开始加载默认配置...
[App] ✅ API 配置文件列表加载完成
[App] ⚠️ 没有可用的 API 配置文件，请先到 API 配置页面创建
[App] ✅ 预设列表加载完成
[App] ⚠️ 没有可用的预设
[App] ✅ 角色卡列表加载完成
[App] ✅ 世界书列表加载完成
[App] 🎉 配置加载完成 (0.89s)
[App] 📊 成功: 4, 失败: 0
```

## 最佳实践

### 1. 只预加载必要的数据

**应该预加载：**
- ✅ 应用运行必需的配置
- ✅ 用户首次操作就需要看到的数据
- ✅ 数据量小、加载快的内容

**不应该预加载：**
- ❌ 查看型数据（统计、历史等）
- ❌ 大数据量的内容
- ❌ 用户可能不需要的功能

### 2. 并行而非串行

```javascript
// ❌ 错误：串行加载，总时间 = 所有请求时间之和
await loadA();
await loadB();
await loadC();

// ✅ 正确：并行加载，总时间 ≈ 最慢的请求
await Promise.allSettled([
  loadA(),
  loadB(),
  loadC()
]);
```

### 3. 容错处理

```javascript
// ❌ 错误：一个失败全部中断
await Promise.all([loadA(), loadB(), loadC()]);

// ✅ 正确：单个失败不影响其他
await Promise.allSettled([loadA(), loadB(), loadC()]);
```

### 4. 详细日志

```javascript
// ❌ 错误：没有日志，无法调试
await fetchData();

// ✅ 正确：清晰的日志输出
console.log('[App] 🚀 开始加载...');
try {
  await fetchData();
  console.log('[App] ✅ 加载成功');
} catch (err) {
  console.error('[App] ❌ 加载失败:', err);
}
```

### 5. 性能监控

```javascript
const startTime = Date.now();
await loadData();
const duration = Date.now() - startTime;
console.log(`加载耗时: ${duration}ms`);
```

## 未来优化方向

### 1. 缓存策略

```javascript
// 检查是否有缓存数据
const cached = localStorage.getItem('apiConfig');
if (cached) {
  // 使用缓存，后台静默更新
  useCache(cached);
  fetchAndUpdateInBackground();
} else {
  // 没有缓存，正常加载
  await fetchData();
}
```

### 2. 懒加载非关键数据

```javascript
// 关键数据：立即加载
await loadCriticalData();

// 非关键数据：空闲时加载
requestIdleCallback(() => {
  loadNonCriticalData();
});
```

### 3. 预取用户可能需要的数据

```javascript
// 用户选择了角色，预取该角色的聊天历史
selectCharacter(char => {
  preloadChatHistory(char.id);
});
```

## 总结

通过应用启动时预加载必要配置：

✅ **用户体验提升**
- 减少等待时间 60-80%
- 操作步骤大幅简化
- 无需手动切换页面配置

✅ **技术优势**
- 并行加载，速度更快
- 容错性强，单个失败不影响整体
- 详细日志，便于调试

✅ **代码质量**
- 清晰的加载逻辑
- 完善的错误处理
- 性能监控和统计

这种优化让应用更加"开箱即用"，用户打开即可开始使用，无需繁琐的初始配置步骤。