crush-level-web/src/hooks/useRedDot.md

227 lines
5.4 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.

# useRedDot Hook 使用指南
## 概述
`useRedDot` 是一个用于管理应用中红点提示的 React Hook。它提供了完整的红点状态管理功能**默认显示红点,查看后消失**。
## 特性
-**默认显示逻辑**localStorage 不存在记录时显示红点
-**自动持久化**:使用 localStorage 存储已查看状态
-**一次性显示**:查看后自动消失
-**命名空间隔离**:通过前缀避免键名冲突
-**批量操作**:支持批量标记已读和清除
-**TypeScript 支持**:完整的类型定义
## 基本用法
### 1. 导入 Hook
```typescript
import { useRedDot, RED_DOT_KEYS } from '@/hooks/useRedDot';
```
### 2. 在组件中使用
```typescript
const MyComponent = () => {
const { hasRedDot, markAsViewed, showRedDot } = useRedDot({
prefix: 'my_feature_' // 可选,默认为 'red_dot_'
});
return (
<div>
<div className="flex items-center gap-2">
<span>设置</span>
{hasRedDot('settings') && <Badge variant="dot" />}
</div>
<button onClick={() => markAsViewed('settings')}>
查看设置
</button>
</div>
);
};
```
## API 参考
### 参数
```typescript
interface UseRedDotOptions {
prefix?: string; // localStorage 键名前缀,默认 'red_dot_'
}
```
### 返回值
```typescript
interface UseRedDotReturn {
// 检查是否显示红点
hasRedDot: (key: string) => boolean;
// 标记为已查看(消除红点)
markAsViewed: (key: string) => void;
// 显示红点
showRedDot: (key: string) => void;
// 批量标记已查看
markMultipleAsViewed: (keys: string[]) => void;
// 清除所有红点
clearAllRedDots: () => void;
// 获取所有有红点的功能键
getAllRedDotKeys: () => string[];
}
```
## 预定义常量
为了避免硬编码字符串,提供了预定义的红点键:
```typescript
export const RED_DOT_KEYS = {
CHAT_BUBBLE: 'chat_bubble',
CHAT_BACKGROUND: 'chat_background',
CHAT_MODEL: 'chat_model',
PROFILE_SETTING: 'profile_setting',
} as const;
```
## 完整示例
### 聊天设置页面
```typescript
import { useRedDot, RED_DOT_KEYS } from '@/hooks/useRedDot';
import { Badge } from '@/components/ui/badge';
const ChatSettingsPage = () => {
const { hasRedDot, markAsViewed } = useRedDot({
prefix: `chat_${chatId}_`
});
const handleBubbleSettingClick = () => {
// 点击时标记为已查看
markAsViewed(RED_DOT_KEYS.CHAT_BUBBLE);
// 打开设置页面
openBubbleSettings();
};
return (
<div>
<div className="setting-item" onClick={handleBubbleSettingClick}>
<div className="flex items-center gap-2">
<span>聊天气泡</span>
{hasRedDot(RED_DOT_KEYS.CHAT_BUBBLE) && <Badge variant="dot" />}
</div>
</div>
<div className="setting-item" onClick={() => {
markAsViewed(RED_DOT_KEYS.CHAT_BACKGROUND);
openBackgroundSettings();
}}>
<div className="flex items-center gap-2">
<span>聊天背景</span>
{hasRedDot(RED_DOT_KEYS.CHAT_BACKGROUND) && <Badge variant="dot" />}
</div>
</div>
</div>
);
};
```
### 管理页面(显示红点)
```typescript
const AdminPage = () => {
const { showRedDot } = useRedDot();
const handleNewFeatureRelease = () => {
// 发布新功能时显示红点
showRedDot(RED_DOT_KEYS.CHAT_BUBBLE);
showRedDot(RED_DOT_KEYS.CHAT_BACKGROUND);
};
return (
<button onClick={handleNewFeatureRelease}>
发布聊天新功能
</button>
);
};
```
## 高级用法
### 1. 不同用户/场景的隔离
```typescript
// 为不同用户使用不同前缀
const userARedDot = useRedDot({ prefix: `user_${userA.id}_` });
const userBRedDot = useRedDot({ prefix: `user_${userB.id}_` });
// 为不同功能模块使用不同前缀
const chatRedDot = useRedDot({ prefix: 'chat_' });
const profileRedDot = useRedDot({ prefix: 'profile_' });
```
### 2. 批量操作
```typescript
const { markMultipleAsViewed, clearAllRedDots } = useRedDot();
// 用户查看了整个设置页面,标记多个功能为已读
const handleSettingsPageVisit = () => {
markMultipleAsViewed([
RED_DOT_KEYS.CHAT_BUBBLE,
RED_DOT_KEYS.CHAT_BACKGROUND,
RED_DOT_KEYS.CHAT_MODEL
]);
};
// 重置所有红点(比如用户重新登录)
const handleUserLogin = () => {
clearAllRedDots();
};
```
### 3. 状态监控
```typescript
const { getAllRedDotKeys, hasRedDot } = useRedDot();
// 获取当前所有未读功能
const unreadFeatures = getAllRedDotKeys();
console.log('用户有', unreadFeatures.length, '个未读功能');
// 检查是否有任何未读
const hasAnyUnread = unreadFeatures.length > 0;
```
## 注意事项
1. **localStorage 限制**:确保浏览器支持 localStorage
2. **前缀命名**:使用有意义的前缀避免冲突
3. **性能考虑**:避免在 render 方法中频繁调用 showRedDot
4. **错误处理**Hook 内部已处理 localStorage 异常
## 存储格式
红点状态在 localStorage 中的存储格式:
```
键名: ${prefix}${redDotKey}
值: 'viewed' | undefined (删除)
```
**重要逻辑**
- **不存在记录** = 显示红点(默认状态)
- **存在 'viewed' 记录** = 不显示红点(已查看)
例如:
- 无记录 -> 显示红点
- `chat_123_chat_bubble: 'viewed'` -> 不显示红点
- `profile_settings: 'viewed'` -> 不显示红点