# 🔄 useShopInfo Hook 字段迁移到AppInfo

## 📋 迁移概述

已成功将`useShopInfo` Hook从`CmsWebsite`字段结构迁移到`AppInfo`字段结构，以匹配后台返回的新字段格式。

## 🆚 字段对比表

### 核心字段映射

| 功能 | 原CmsWebsite字段 | 新AppInfo字段 | 状态 |
|------|------------------|---------------|------|
| **应用名称** | `websiteName` | `appName` | ✅ 已映射 |
| **Logo** | `websiteLogo` | `logo` | ✅ 已映射 |
| **图标** | `websiteIcon` | `icon` | ✅ 已映射 |
| **域名** | `domain` | `domain` | ✅ 保持不变 |
| **版本** | `version` | `version` | ✅ 保持不变 |
| **过期时间** | `expirationTime` | `expirationTime` | ✅ 保持不变 |
| **运行状态** | `running` | `running` | ✅ 保持不变 |
| **状态文本** | `statusText` | `statusText` | ✅ 保持不变 |
| **配置** | `config` | `config` | ✅ 保持不变 |
| **导航** | `topNavs/bottomNavs` | `topNavs/bottomNavs` | ✅ 保持不变 |

### 新增字段

| 字段 | 类型 | 说明 |
|------|------|------|
| `appId` | `number` | 应用ID |
| `description` | `string` | 应用描述 |
| `keywords` | `string` | 关键词 |
| `appCode` | `string` | 应用代码 |
| `mpQrCode` | `string` | 小程序二维码 |
| `title` | `string` | 应用标题 |
| `expired` | `boolean` | 是否过期 |
| `expiredDays` | `number` | 过期天数 |
| `soon` | `number` | 即将过期标识 |
| `statusIcon` | `string` | 状态图标 |
| `serverTime` | `Object` | 服务器时间 |
| `setting` | `Object` | 应用设置 |

### 移除字段

| 原字段 | 处理方式 | 说明 |
|--------|----------|------|
| `websiteDarkLogo` | 使用`logo`替代 | AppInfo中无深色Logo |
| `phone` | 从`config`中获取 | 移至配置中 |
| `email` | 从`config`中获取 | 移至配置中 |
| `address` | 从`config`中获取 | 移至配置中 |
| `icpNo` | 从`config`中获取 | 移至配置中 |
| `search` | 从`config`中获取 | 移至配置中 |
| `templateId` | 移除 | AppInfo中无此字段 |

## 🔧 新增工具方法

### 基于AppInfo的新方法

```typescript
// 应用基本信息
getAppName()          // 获取应用名称
getAppLogo()          // 获取应用Logo
getAppIcon()          // 获取应用图标
getDescription()      // 获取应用描述
getKeywords()         // 获取关键词
getTitle()            // 获取应用标题
getMpQrCode()         // 获取小程序二维码

// 应用配置
getSetting()          // 获取应用设置
getServerTime()       // 获取服务器时间

// 过期状态管理
isExpired()           // 检查是否过期
getExpiredDays()      // 获取过期天数
isSoonExpired()       // 检查是否即将过期
```

### 兼容旧方法

```typescript
// 保持向后兼容
getWebsiteName()      // 映射到getAppName()
getWebsiteLogo()      // 映射到getAppLogo()
getDarkLogo()         // 使用普通Logo
getPhone()            // 从config中获取
getEmail()            // 从config中获取
getAddress()          // 从config中获取
getIcpNo()            // 从config中获取
isSearchEnabled()     // 从config中获取
```

## 📊 使用示例

### 新方法使用

```typescript
const {
  // 新的AppInfo方法
  getAppName,
  getAppLogo,
  getDescription,
  getMpQrCode,
  isExpired,
  getExpiredDays,
  
  // 兼容旧方法
  getWebsiteName,
  getWebsiteLogo
} = useShopInfo();

// 使用新方法
const appName = getAppName();           // "时里亲子市集"
const appLogo = getAppLogo();           // Logo URL
const description = getDescription();    // 应用描述
const qrCode = getMpQrCode();           // 小程序二维码
const expired = isExpired();            // false
const expiredDays = getExpiredDays();   // 30

// 兼容旧方法（推荐逐步迁移到新方法）
const websiteName = getWebsiteName();   // 等同于getAppName()
const websiteLogo = getWebsiteLogo();   // 等同于getAppLogo()
```

### 状态检查

```typescript
const { getStatus, isExpired, isSoonExpired } = useShopInfo();

const status = getStatus();
console.log(status);
// {
//   running: 1,
//   statusText: "运行中",
//   statusIcon: "success",
//   expired: false,
//   expiredDays: 30,
//   soon: 0
// }

if (isExpired()) {
  console.log('应用已过期');
} else if (isSoonExpired()) {
  console.log(`应用将在${getExpiredDays()}天后过期`);
}
```

### 配置获取

```typescript
const { getConfig, getSetting, getServerTime } = useShopInfo();

const config = getConfig();       // 应用配置
const setting = getSetting();     // 应用设置
const serverTime = getServerTime(); // 服务器时间

// 从配置中获取联系信息
const phone = getPhone();         // 从config.phone获取
const email = getEmail();         // 从config.email获取
const address = getAddress();     // 从config.address获取
```

## 🔄 迁移建议

### 1. **逐步迁移**

```typescript
// 阶段1：使用兼容方法（当前可用）
const websiteName = getWebsiteName();
const websiteLogo = getWebsiteLogo();

// 阶段2：迁移到新方法（推荐）
const appName = getAppName();
const appLogo = getAppLogo();
```

### 2. **新功能使用新方法**

```typescript
// 新功能直接使用AppInfo方法
const { 
  getAppName, 
  getAppLogo, 
  getDescription,
  isExpired,
  getMpQrCode 
} = useShopInfo();
```

### 3. **配置字段处理**

```typescript
// 对于移至config的字段，使用对应的getter方法
const phone = getPhone();     // 自动从config中获取
const email = getEmail();     // 自动从config中获取
const icpNo = getIcpNo();     // 自动从config中获取
```

## ⚠️ 注意事项

### 1. **字段可能为空**

```typescript
// AppInfo中某些字段可能不存在，需要提供默认值
const description = getDescription() || '暂无描述';
const qrCode = getMpQrCode() || '';
```

### 2. **配置字段依赖**

```typescript
// 联系信息现在依赖config字段
const config = getConfig();
if (config && typeof config === 'object') {
  const phone = getPhone();
  const email = getEmail();
}
```

### 3. **过期状态处理**

```typescript
// 新增的过期状态需要特殊处理
const { isExpired, getExpiredDays, isSoonExpired } = useShopInfo();

if (isExpired()) {
  // 应用已过期的处理逻辑
  showExpiredDialog();
} else if (isSoonExpired()) {
  // 即将过期的提醒逻辑
  showExpirationWarning(getExpiredDays());
}
```

## 🧪 测试验证

### 1. **字段映射测试**

```typescript
const TestComponent = () => {
  const { 
    shopInfo,
    getAppName,
    getAppLogo,
    getWebsiteName,
    getWebsiteLogo 
  } = useShopInfo();

  return (
    <div>
      <h3>原始数据</h3>
      <pre>{JSON.stringify(shopInfo, null, 2)}</pre>
      
      <h3>新方法</h3>
      <div>应用名称: {getAppName()}</div>
      <div>应用Logo: {getAppLogo()}</div>
      
      <h3>兼容方法</h3>
      <div>网站名称: {getWebsiteName()}</div>
      <div>网站Logo: {getWebsiteLogo()}</div>
    </div>
  );
};
```

### 2. **过期状态测试**

```typescript
const ExpirationTest = () => {
  const { 
    isExpired, 
    getExpiredDays, 
    isSoonExpired,
    getStatus 
  } = useShopInfo();

  const status = getStatus();

  return (
    <div>
      <div>过期状态: {isExpired() ? '已过期' : '正常'}</div>
      <div>过期天数: {getExpiredDays()}</div>
      <div>即将过期: {isSoonExpired() ? '是' : '否'}</div>
      <div>详细状态: {JSON.stringify(status, null, 2)}</div>
    </div>
  );
};
```

## 🎉 迁移完成

useShopInfo Hook已成功迁移到AppInfo字段结构：

- ✅ **新增AppInfo专用方法**：基于新字段结构的工具方法
- ✅ **保持向后兼容**：旧方法名仍然可用
- ✅ **增强功能**：新增过期状态、应用设置等功能
- ✅ **智能映射**：自动处理字段差异和默认值
- ✅ **类型安全**：完整的TypeScript支持

**现在Hook完全支持AppInfo字段结构，同时保持向后兼容！** 🚀
