# 🏪 useShopInfo Hook 使用指南

## 📋 概述

`useShopInfo` 是一个用于管理商店信息的React Hook，提供了商店信息的获取、缓存和管理功能。它基于`getShopInfo()`接口，为全站提供统一的商店信息访问方式。

## ✨ 特性

- 🚀 **自动缓存**：30分钟本地缓存，减少网络请求
- 🔄 **智能刷新**：支持强制刷新和自动过期更新
- 📱 **离线支持**：网络失败时使用缓存数据
- 🛠️ **工具方法**：提供常用信息的便捷获取方法
- 🎯 **TypeScript**：完整的类型支持
- ⚡ **性能优化**：使用useCallback避免不必要的重渲染

## 🔧 基本用法

### 1. 导入Hook
```typescript
import { useShopInfo } from '@/hooks/useShopInfo';
```

### 2. 在组件中使用
```typescript
const MyComponent = () => {
  const { 
    shopInfo, 
    loading, 
    error,
    getWebsiteName,
    getWebsiteLogo 
  } = useShopInfo();

  if (loading) {
    return <div>加载中...</div>;
  }

  if (error) {
    return <div>加载失败: {error}</div>;
  }

  return (
    <div>
      <img src={getWebsiteLogo()} alt="Logo" />
      <h1>{getWebsiteName()}</h1>
    </div>
  );
};
```

## 📊 API 参考

### 状态属性

| 属性 | 类型 | 说明 |
|------|------|------|
| `shopInfo` | `CmsWebsite \| null` | 商店信息对象 |
| `loading` | `boolean` | 是否正在加载 |
| `error` | `string \| null` | 错误信息 |

### 方法

| 方法 | 参数 | 返回值 | 说明 |
|------|------|--------|------|
| `fetchShopInfo` | `forceRefresh?: boolean` | `Promise<CmsWebsite \| null>` | 获取商店信息 |
| `refreshShopInfo` | - | `Promise<CmsWebsite \| null>` | 强制刷新商店信息 |
| `clearCache` | - | `void` | 清除本地缓存 |

### 工具方法

| 方法 | 返回值 | 说明 |
|------|--------|------|
| `getWebsiteName()` | `string` | 获取网站名称，默认"商城" |
| `getWebsiteLogo()` | `string` | 获取网站Logo URL |
| `getDarkLogo()` | `string` | 获取深色模式Logo URL |
| `getDomain()` | `string` | 获取网站域名 |
| `getPhone()` | `string` | 获取联系电话 |
| `getEmail()` | `string` | 获取邮箱地址 |
| `getAddress()` | `string` | 获取地址 |
| `getIcpNo()` | `string` | 获取ICP备案号 |
| `getStatus()` | `object` | 获取网站状态信息 |
| `getConfig()` | `any` | 获取网站配置 |
| `getNavigation()` | `object` | 获取导航菜单 |
| `isSearchEnabled()` | `boolean` | 是否支持搜索 |
| `getVersionInfo()` | `object` | 获取版本信息 |

## 🎯 使用场景

### 1. 页面头部组件
```typescript
// src/pages/index/Header.tsx
import { useShopInfo } from '@/hooks/useShopInfo';

const Header = () => {
  const { getWebsiteName, getWebsiteLogo, loading } = useShopInfo();

  return (
    <NavBar
      left={
        <div style={{display: 'flex', alignItems: 'center'}}>
          <Avatar size="22" src={getWebsiteLogo()} />
          <span>{getWebsiteName()}</span>
        </div>
      }
    />
  );
};
```

### 2. 首页组件
```typescript
// src/pages/index/index.tsx
import { useShopInfo } from '@/hooks/useShopInfo';

const Home = () => {
  const { shopInfo, loading, error } = useShopInfo();

  useEffect(() => {
    if (shopInfo) {
      // 设置页面标题
      Taro.setNavigationBarTitle({
        title: shopInfo.websiteName || '商城'
      });
    }
  }, [shopInfo]);

  // 分享配置
  useShareAppMessage(() => ({
    title: shopInfo?.websiteName || '精选商城',
    imageUrl: shopInfo?.websiteLogo
  }));

  return (
    <div>
      {/* 页面内容 */}
    </div>
  );
};
```

### 3. 商品详情页分享
```typescript
// src/shop/goodsDetail/index.tsx
import { useShopInfo } from '@/hooks/useShopInfo';

const GoodsDetail = () => {
  const { getWebsiteName, getWebsiteLogo } = useShopInfo();

  useShareAppMessage(() => ({
    title: `${goods?.name} - ${getWebsiteName()}`,
    path: `/shop/goodsDetail/index?id=${goodsId}`,
    imageUrl: goods?.image || getWebsiteLogo()
  }));

  return (
    <div>
      {/* 商品详情 */}
    </div>
  );
};
```

### 4. 联系我们页面
```typescript
const ContactPage = () => {
  const { 
    getPhone, 
    getEmail, 
    getAddress, 
    getIcpNo 
  } = useShopInfo();

  return (
    <div>
      <div>电话: {getPhone()}</div>
      <div>邮箱: {getEmail()}</div>
      <div>地址: {getAddress()}</div>
      <div>备案号: {getIcpNo()}</div>
    </div>
  );
};
```

### 5. 网站状态检查
```typescript
const StatusChecker = () => {
  const { getStatus, getVersionInfo } = useShopInfo();
  
  const status = getStatus();
  const version = getVersionInfo();

  return (
    <div>
      <div>运行状态: {status.running ? '正常' : '维护中'}</div>
      <div>版本: {version.version === 10 ? '免费版' : version.version === 20 ? '专业版' : '永久授权'}</div>
      {version.expirationTime && (
        <div>到期时间: {version.expirationTime}</div>
      )}
    </div>
  );
};
```

## 🔄 缓存机制

### 缓存策略
- **缓存时间**：30分钟
- **存储位置**：微信小程序本地存储
- **缓存键名**：`shop_info` 和 `shop_info_cache_time`

### 缓存行为
1. **首次加载**：从服务器获取数据并缓存
2. **后续加载**：优先使用缓存，缓存过期时自动刷新
3. **网络失败**：使用缓存数据（即使过期）
4. **强制刷新**：忽略缓存，直接从服务器获取

### 手动管理缓存
```typescript
const { refreshShopInfo, clearCache } = useShopInfo();

// 强制刷新
const handleRefresh = async () => {
  await refreshShopInfo();
};

// 清除缓存
const handleClearCache = () => {
  clearCache();
};
```

## 🚀 性能优化

### 1. 避免重复请求
```typescript
// ✅ 推荐：多个组件使用同一个Hook实例
const App = () => {
  const shopInfo = useShopInfo();
  
  return (
    <ShopInfoProvider value={shopInfo}>
      <Header />
      <Content />
      <Footer />
    </ShopInfoProvider>
  );
};
```

### 2. 条件渲染优化
```typescript
const Component = () => {
  const { shopInfo, loading } = useShopInfo();

  // ✅ 使用loading状态避免闪烁
  if (loading) {
    return <Skeleton />;
  }

  return (
    <div>
      {shopInfo && (
        <img src={shopInfo.websiteLogo} alt="Logo" />
      )}
    </div>
  );
};
```

## 🛠️ 迁移指南

### 从直接调用API迁移

#### 迁移前 ❌
```typescript
// 旧代码
const [config, setConfig] = useState<CmsWebsite>();

useEffect(() => {
  getShopInfo().then((data) => {
    setConfig(data);
  });
}, []);
```

#### 迁移后 ✅
```typescript
// 新代码
const { shopInfo: config, loading } = useShopInfo();
```

### 批量替换步骤

1. **替换导入**
```typescript
// 删除
import { getShopInfo } from '@/api/layout';

// 添加
import { useShopInfo } from '@/hooks/useShopInfo';
```

2. **替换状态管理**
```typescript
// 删除
const [config, setConfig] = useState<CmsWebsite>();

// 替换为
const { shopInfo: config, loading, error } = useShopInfo();
```

3. **删除useEffect**
```typescript
// 删除这些代码
useEffect(() => {
  getShopInfo().then((data) => {
    setConfig(data);
  });
}, []);
```

## 🧪 测试示例

```typescript
// 测试组件
const TestComponent = () => {
  const { 
    shopInfo, 
    loading, 
    error,
    refreshShopInfo,
    getWebsiteName 
  } = useShopInfo();

  return (
    <div>
      <div>状态: {loading ? '加载中' : '已加载'}</div>
      <div>错误: {error || '无'}</div>
      <div>网站名: {getWebsiteName()}</div>
      <button onClick={refreshShopInfo}>刷新</button>
      <pre>{JSON.stringify(shopInfo, null, 2)}</pre>
    </div>
  );
};
```

## 🎉 总结

`useShopInfo` Hook 提供了：

- ✅ **统一的商店信息管理**
- ✅ **智能缓存机制**
- ✅ **丰富的工具方法**
- ✅ **完整的TypeScript支持**
- ✅ **简单的迁移路径**

通过使用这个Hook，你可以在整个应用中轻松访问和管理商店信息，提高代码的可维护性和用户体验。
