wechat-emojis 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. package/API.md +228 -0
  2. package/REACT_USAGE.md +456 -0
  3. package/README.md +251 -0
  4. package/assets/animal//345/217/221/346/212/226.png +0 -0
  5. package/assets/animal//347/214/252/345/244/264.png +0 -0
  6. package/assets/animal//350/267/263/350/267/263.png +0 -0
  7. package/assets/animal//350/275/254/345/234/210.png +0 -0
  8. package/assets/blessing//345/272/206/347/245/235.png +0 -0
  9. package/assets/blessing//347/203/237/350/212/261.png +0 -0
  10. package/assets/blessing//347/210/206/347/253/271.png +0 -0
  11. package/assets/blessing//347/231/274.png +0 -0
  12. package/assets/blessing//347/244/274/347/211/251.png +0 -0
  13. package/assets/blessing//347/246/217.png +0 -0
  14. package/assets/blessing//347/272/242/345/214/205.png +0 -0
  15. package/assets/face/666.png +0 -0
  16. package/assets/face/Emm.png +0 -0
  17. package/assets/face//344/272/262/344/272/262.png +0 -0
  18. package/assets/face//345/201/267/347/254/221.png +0 -0
  19. package/assets/face//345/202/262/346/205/242.png +0 -0
  20. package/assets/face//345/206/215/350/247/201.png +0 -0
  21. package/assets/face//345/212/240/346/262/271.png +0 -0
  22. package/assets/face//345/217/221/345/221/206.png +0 -0
  23. package/assets/face//345/217/221/346/200/222.png +0 -0
  24. package/assets/face//345/217/257/346/200/234.png +0 -0
  25. package/assets/face//345/217/263/345/223/274/345/223/274.png +0 -0
  26. package/assets/face//345/217/271/346/260/224.png +0 -0
  27. package/assets/face//345/220/203/347/223/234.png +0 -0
  28. package/assets/face//345/220/220.png +0 -0
  29. package/assets/face//345/221/262/347/211/231.png +0 -0
  30. package/assets/face//345/222/222/351/252/202.png +0 -0
  31. package/assets/face//345/223/207.png +0 -0
  32. package/assets/face//345/230/230.png +0 -0
  33. package/assets/face//345/230/277/345/223/210.png +0 -0
  34. package/assets/face//345/233/247.png +0 -0
  35. package/assets/face//345/233/260.png +0 -0
  36. package/assets/face//345/235/217/347/254/221.png +0 -0
  37. package/assets/face//345/244/247/345/223/255.png +0 -0
  38. package/assets/face//345/244/251/345/225/212.png +0 -0
  39. package/assets/face//345/244/261/346/234/233.png +0 -0
  40. package/assets/face//345/245/270/347/254/221.png +0 -0
  41. package/assets/face//345/245/275/347/232/204.png +0 -0
  42. package/assets/face//345/247/224/345/261/210.png +0 -0
  43. package/assets/face//345/256/263/347/276/236.png +0 -0
  44. package/assets/face//345/260/264/345/260/254.png +0 -0
  45. package/assets/face//345/276/227/346/204/217.png +0 -0
  46. package/assets/face//345/276/256/347/254/221.png +0 -0
  47. package/assets/face//345/277/253/345/223/255/344/272/206.png +0 -0
  48. package/assets/face//346/201/220/346/203/247.png +0 -0
  49. package/assets/face//346/202/240/351/227/262.png +0 -0
  50. package/assets/face//346/203/212/346/201/220.png +0 -0
  51. package/assets/face//346/203/212/350/256/266.png +0 -0
  52. package/assets/face//346/204/211/345/277/253.png +0 -0
  53. package/assets/face//346/206/250/347/254/221.png +0 -0
  54. package/assets/face//346/211/223/350/204/270.png +0 -0
  55. package/assets/face//346/212/223/347/213/202.png +0 -0
  56. package/assets/face//346/212/240/351/274/273.png +0 -0
  57. package/assets/face//346/215/202/350/204/270.png +0 -0
  58. package/assets/face//346/222/207/345/230/264.png +0 -0
  59. package/assets/face//346/223/246/346/261/227.png +0 -0
  60. package/assets/face//346/225/262/346/211/223.png +0 -0
  61. package/assets/face//346/227/240/350/257/255.png +0 -0
  62. package/assets/face//346/227/272/346/237/264.png +0 -0
  63. package/assets/face//346/231/225.png +0 -0
  64. package/assets/face//346/234/272/346/231/272.png +0 -0
  65. package/assets/face//346/261/227.png +0 -0
  66. package/assets/face//346/265/201/346/263/252.png +0 -0
  67. package/assets/face//347/224/237/347/227/205.png +0 -0
  68. package/assets/face//347/226/221/351/227/256.png +0 -0
  69. package/assets/face//347/231/275/347/234/274.png +0 -0
  70. package/assets/face//347/232/261/347/234/211.png +0 -0
  71. package/assets/face//347/235/241.png +0 -0
  72. package/assets/face//347/240/264/346/266/225/344/270/272/347/254/221.png +0 -0
  73. package/assets/face//347/244/276/344/274/232.png +0 -0
  74. package/assets/face//347/254/221/350/204/270.png +0 -0
  75. package/assets/face//347/277/273/347/231/275/347/234/274.png +0 -0
  76. package/assets/face//350/200/266.png +0 -0
  77. package/assets/face//350/204/270/347/272/242.png +0 -0
  78. package/assets/face//350/211/262.png +0 -0
  79. package/assets/face//350/213/246/346/266/251.png +0 -0
  80. package/assets/face//350/241/260.png +0 -0
  81. package/assets/face//350/243/202/345/274/200.png +0 -0
  82. package/assets/face//350/256/251/346/210/221/347/234/213/347/234/213.png +0 -0
  83. package/assets/face//350/260/203/347/232/256.png +0 -0
  84. package/assets/face//351/204/231/350/247/206.png +0 -0
  85. package/assets/face//351/227/255/345/230/264.png +0 -0
  86. package/assets/face//351/230/264/351/231/251.png +0 -0
  87. package/assets/face//351/232/276/350/277/207.png +0 -0
  88. package/assets/face//351/252/267/351/253/205.png +0 -0
  89. package/assets/face//351/274/223/346/216/214.png +0 -0
  90. package/assets/gesture/OK.png +0 -0
  91. package/assets/gesture//345/213/276/345/274/225.png +0 -0
  92. package/assets/gesture//345/220/210/345/215/201.png +0 -0
  93. package/assets/gesture//345/274/261.png +0 -0
  94. package/assets/gesture//345/274/272.png +0 -0
  95. package/assets/gesture//345/276/227/346/204/217.png +0 -0
  96. package/assets/gesture//346/212/261/346/213/263.png +0 -0
  97. package/assets/gesture//346/213/245/346/212/261.png +0 -0
  98. package/assets/gesture//346/213/263/345/244/264.png +0 -0
  99. package/assets/gesture//346/217/241/346/211/213.png +0 -0
  100. package/assets/gesture//350/200/266.png +0 -0
  101. package/assets/gesture//350/203/234/345/210/251.png +0 -0
  102. package/assets/other//344/276/277/344/276/277.png +0 -0
  103. package/assets/other//345/207/213/350/260/242.png +0 -0
  104. package/assets/other//345/222/226/345/225/241.png +0 -0
  105. package/assets/other//345/225/244/351/205/222.png +0 -0
  106. package/assets/other//345/230/264/345/224/207.png +0 -0
  107. package/assets/other//345/244/252/351/230/263.png +0 -0
  108. package/assets/other//345/245/213/346/226/227.png +0 -0
  109. package/assets/other//345/277/203/347/242/216.png +0 -0
  110. package/assets/other//346/231/232/345/256/211.png +0 -0
  111. package/assets/other//347/202/270/345/274/271.png +0 -0
  112. package/assets/other//347/210/206/347/217/240.png +0 -0
  113. package/assets/other//347/210/206/347/253/271.png +0 -0
  114. package/assets/other//347/210/261/345/277/203.png +0 -0
  115. package/assets/other//350/217/234/345/210/200.png +0 -0
  116. package/assets/other//350/233/213/347/263/225.png +0 -0
  117. package/assets/other//351/262/234/350/212/261.png +0 -0
  118. package/package.json +49 -0
  119. package/wechatEmoji.js +314 -0
  120. package/wechatEmoji.ts +364 -0
package/API.md ADDED
@@ -0,0 +1,228 @@
1
+ # 微信表情包 TypeScript API 文档
2
+
3
+ ## 概述
4
+
5
+ `wechatEmoji.ts` 提供了完整的 TypeScript 支持,让你可以类型安全地访问微信表情包资源。
6
+
7
+ ## 安装和使用
8
+
9
+ ### 1. 通过 NPM 安装(推荐)
10
+
11
+ ```bash
12
+ # 安装包
13
+ npm install wechat-emojis
14
+
15
+ # 复制表情资源到项目的 public 目录(重要)
16
+ mkdir -p public/assets
17
+ cp -r node_modules/wechat-emojis/assets/* public/assets/
18
+ ```
19
+
20
+ 使用 NPM 包:
21
+
22
+ ```typescript
23
+ import WeChatEmojis, {
24
+ EmojiCategory,
25
+ getEmojiPath,
26
+ getEmojisByCategory,
27
+ searchEmojis
28
+ } from 'wechat-emojis';
29
+ ```
30
+
31
+ ### 2. 直接使用 TypeScript 源文件
32
+
33
+ ```typescript
34
+ import WeChatEmojis, {
35
+ EmojiCategory,
36
+ getEmojiPath,
37
+ getEmojisByCategory,
38
+ searchEmojis
39
+ } from './wechatEmoji';
40
+ ```
41
+
42
+ ### 3. 编译后使用 JavaScript
43
+
44
+ ```bash
45
+ # 编译 TypeScript
46
+ npx tsc wechatEmoji.ts --target es2017 --module commonjs
47
+
48
+ # 在 Node.js 中使用
49
+ const { getEmojiPath, EmojiCategory } = require('./wechatEmoji.js');
50
+ ```
51
+
52
+ ## API 参考
53
+
54
+ ### 类型定义
55
+
56
+ #### `EmojiCategory` 枚举
57
+
58
+ ```typescript
59
+ enum EmojiCategory {
60
+ FACE = 'face', // 人脸表情
61
+ GESTURE = 'gesture', // 手势表情
62
+ ANIMAL = 'animal', // 动物表情
63
+ BLESSING = 'blessing', // 祝福表情
64
+ OTHER = 'other' // 其他表情
65
+ }
66
+ ```
67
+
68
+ #### `EmojiInfo` 接口
69
+
70
+ ```typescript
71
+ interface EmojiInfo {
72
+ name: string; // 表情名称
73
+ category: EmojiCategory; // 表情类别
74
+ path: string; // 图片文件路径
75
+ englishName?: string; // 英文名称(可选)
76
+ }
77
+ ```
78
+
79
+ #### `EmojiName` 类型
80
+
81
+ 包含所有有效表情名称的联合类型,提供编译时类型检查。
82
+
83
+ ### 核心函数
84
+
85
+ #### `getEmojiPath(name: EmojiName): string | null`
86
+
87
+ 获取表情图片路径。
88
+
89
+ ```typescript
90
+ const path = getEmojiPath('微笑'); // 'assets/face/微笑.png'
91
+ const invalid = getEmojiPath('不存在'); // null
92
+ ```
93
+
94
+ #### `getEmojiInfo(name: EmojiName): EmojiInfo | null`
95
+
96
+ 获取表情详细信息。
97
+
98
+ ```typescript
99
+ const emoji = getEmojiInfo('微笑');
100
+ // { name: '微笑', category: EmojiCategory.FACE, path: 'assets/face/微笑.png' }
101
+ ```
102
+
103
+ #### `getEmojisByCategory(category: EmojiCategory): EmojiInfo[]`
104
+
105
+ 按类别获取表情列表。
106
+
107
+ ```typescript
108
+ const faceEmojis = getEmojisByCategory(EmojiCategory.FACE);
109
+ console.log(`人脸表情数量: ${faceEmojis.length}`); // 75
110
+ ```
111
+
112
+ #### `getAllEmojis(): EmojiInfo[]`
113
+
114
+ 获取所有表情信息。
115
+
116
+ ```typescript
117
+ const allEmojis = getAllEmojis();
118
+ console.log(`总表情数量: ${allEmojis.length}`); // 108
119
+ ```
120
+
121
+ #### `searchEmojis(keyword: string): EmojiInfo[]`
122
+
123
+ 搜索包含关键词的表情。
124
+
125
+ ```typescript
126
+ const laughEmojis = searchEmojis('笑');
127
+ // 返回包含 '微笑', '偷笑', '坏笑' 等的表情
128
+ ```
129
+
130
+ #### `hasEmoji(name: string): name is EmojiName`
131
+
132
+ 检查表情是否存在(类型守卫)。
133
+
134
+ ```typescript
135
+ if (hasEmoji('微笑')) {
136
+ // TypeScript 知道这里 '微笑' 是有效的 EmojiName
137
+ const path = getEmojiPath('微笑');
138
+ }
139
+ ```
140
+
141
+ #### `getEmojiNames(category?: EmojiCategory): string[]`
142
+
143
+ 获取表情名称列表。
144
+
145
+ ```typescript
146
+ const allNames = getEmojiNames();
147
+ const faceNames = getEmojiNames(EmojiCategory.FACE);
148
+ ```
149
+
150
+ #### `getRandomEmoji(category?: EmojiCategory): EmojiInfo`
151
+
152
+ 随机获取表情。
153
+
154
+ ```typescript
155
+ const randomEmoji = getRandomEmoji();
156
+ const randomFaceEmoji = getRandomEmoji(EmojiCategory.FACE);
157
+ ```
158
+
159
+ ## 使用示例
160
+
161
+ ### React 组件示例
162
+
163
+ ```typescript
164
+ import React from 'react';
165
+ import { getEmojiPath, getEmojisByCategory, EmojiCategory } from 'wechat-emojis';
166
+
167
+ const EmojiPicker: React.FC = () => {
168
+ const faceEmojis = getEmojisByCategory(EmojiCategory.FACE);
169
+
170
+ return (
171
+ <div className="emoji-picker">
172
+ {faceEmojis.map(emoji => (
173
+ <img
174
+ key={emoji.name}
175
+ src={getEmojiPath(emoji.name)}
176
+ alt={emoji.name}
177
+ title={emoji.name}
178
+ className="emoji-item"
179
+ onClick={() => console.log(`选择了: ${emoji.name}`)}
180
+ />
181
+ ))}
182
+ </div>
183
+ );
184
+ };
185
+ ```
186
+
187
+ ### Vue 组件示例
188
+
189
+ ```vue
190
+ <template>
191
+ <div class="emoji-grid">
192
+ <img
193
+ v-for="emoji in emojis"
194
+ :key="emoji.name"
195
+ :src="getEmojiPath(emoji.name)"
196
+ :alt="emoji.name"
197
+ :title="emoji.name"
198
+ @click="selectEmoji(emoji)"
199
+ />
200
+ </div>
201
+ </template>
202
+
203
+ <script setup lang="ts">
204
+ import { getEmojisByCategory, getEmojiPath, EmojiCategory } from 'wechat-emojis';
205
+
206
+ const emojis = getEmojisByCategory(EmojiCategory.FACE);
207
+
208
+ const selectEmoji = (emoji: EmojiInfo) => {
209
+ console.log(`选择了表情: ${emoji.name}`);
210
+ };
211
+ </script>
212
+ ```
213
+
214
+ ## 数据统计
215
+
216
+ - **总表情数量**: 108 个
217
+ - **人脸表情**: 75 个
218
+ - **手势表情**: 7 个
219
+ - **动物表情**: 4 个
220
+ - **祝福表情**: 7 个
221
+ - **其他表情**: 15 个
222
+
223
+ ## 注意事项
224
+
225
+ 1. **类型安全**: 使用 `EmojiName` 类型可以在编译时检查表情名称的有效性
226
+ 2. **路径相对性**: 返回的路径是相对于项目根目录的
227
+ 3. **兼容性**: 编译目标为 ES2017,兼容现代浏览器和 Node.js
228
+ 4. **性能**: 所有数据在模块加载时预计算,查询性能优秀
package/REACT_USAGE.md ADDED
@@ -0,0 +1,456 @@
1
+ # React 项目中使用微信表情包
2
+
3
+ 本指南详细介绍如何在React项目中集成和使用微信表情包模块。
4
+
5
+ ## 📦 安装和配置
6
+
7
+ ### 方式一:使用npm包(推荐)
8
+
9
+ 1. **安装包**:
10
+
11
+ ```bash
12
+ npm install wechat-emojis
13
+ ```
14
+
15
+ 2. **复制资源文件**:
16
+ 由于npm包中的图片资源需要被复制到你的项目public目录,请执行以下命令:
17
+
18
+ ```bash
19
+ # 复制表情资源到你的项目
20
+ cp -r node_modules/wechat-emojis/assets/* public/assets/
21
+ ```
22
+
23
+ 你也可以在 `package.json` 中配置一个脚本,在安装后自动完成复制:
24
+
25
+ ```json
26
+ // package.json
27
+ {
28
+ "scripts": {
29
+ "postinstall": "cp -r node_modules/wechat-emojis/assets/* public/assets/"
30
+ }
31
+ }
32
+ ```
33
+
34
+ 3. **在React项目中使用**:
35
+
36
+ ```typescript
37
+ // 直接从npm包导入
38
+ import {
39
+ getEmojiPath,
40
+ getEmojisByCategory,
41
+ EmojiCategory,
42
+ type EmojiName
43
+ } from 'wechat-emojis';
44
+
45
+ // 使用示例
46
+ const WeChatEmoji: React.FC<{name: EmojiName}> = ({ name }) => {
47
+ const emojiPath = getEmojiPath(name);
48
+ // 确保你的 public 目录配置正确,可以直接访问 /assets/
49
+ return <img src={`/${emojiPath}`} alt={name} width={24} height={24} />;
50
+ };
51
+ ```
52
+
53
+ ### 方式二:直接复制文件
54
+
55
+ 1. **复制必要文件到React项目**:
56
+ ```bash
57
+ # 在你的React项目根目录下
58
+ mkdir -p src/utils/wechat-emojis
59
+ mkdir -p public/assets
60
+
61
+ # 复制TypeScript模块
62
+ cp path/to/wechatEmoji.ts src/utils/wechat-emojis/
63
+ cp path/to/wechatEmoji.js src/utils/wechat-emojis/
64
+
65
+ # 复制表情资源到public目录
66
+ cp -r path/to/assets/* public/assets/
67
+ ```
68
+
69
+ 2. **调整图片路径**(重要):
70
+ 由于React项目中public目录的资源访问方式,需要修改 `wechatEmoji.ts` 中的图片路径,将所有 `'assets/'` 替换为 `'/assets/'`。
71
+
72
+
73
+ ## 🚀 基础使用
74
+
75
+ ### 1. 导入模块
76
+
77
+ ```typescript
78
+ // 从 npm 包导入 (推荐)
79
+ import {
80
+ getEmojiPath,
81
+ getEmojisByCategory,
82
+ EmojiCategory,
83
+ type EmojiName
84
+ } from 'wechat-emojis';
85
+ ```
86
+
87
+ ### 2. 创建表情组件
88
+
89
+ ```tsx
90
+ // src/components/WeChatEmoji.tsx
91
+ import React from 'react';
92
+ import { getEmojiPath, type EmojiName } from 'wechat-emojis';
93
+
94
+ interface WeChatEmojiProps {
95
+ name: EmojiName;
96
+ size?: number;
97
+ className?: string;
98
+ alt?: string;
99
+ }
100
+
101
+ const WeChatEmoji: React.FC<WeChatEmojiProps> = ({
102
+ name,
103
+ size = 24,
104
+ className = '',
105
+ alt
106
+ }) => {
107
+ const emojiPath = getEmojiPath(name);
108
+
109
+ if (!emojiPath) {
110
+ console.warn(`表情 "${name}" 不存在`);
111
+ return null;
112
+ }
113
+
114
+ return (
115
+ <img
116
+ src={emojiPath}
117
+ alt={alt || name}
118
+ width={size}
119
+ height={size}
120
+ className={`wechat-emoji ${className}`}
121
+ style={{
122
+ display: 'inline-block',
123
+ verticalAlign: 'middle'
124
+ }}
125
+ />
126
+ );
127
+ };
128
+
129
+ export default WeChatEmoji;
130
+ ```
131
+
132
+ ### 3. 使用表情组件
133
+
134
+ ```tsx
135
+ // src/App.tsx
136
+ import React from 'react';
137
+ import WeChatEmoji from './components/WeChatEmoji';
138
+
139
+ function App() {
140
+ return (
141
+ <div className="App">
142
+ <h1>微信表情示例</h1>
143
+
144
+ {/* 基础使用 */}
145
+ <p>
146
+ 你好 <WeChatEmoji name="微笑" size={20} />
147
+ 今天天气真好 <WeChatEmoji name="太阳" size={20} />
148
+ </p>
149
+
150
+ {/* 不同尺寸 */}
151
+ <div>
152
+ <WeChatEmoji name="大哭" size={16} />
153
+ <WeChatEmoji name="大哭" size={24} />
154
+ <WeChatEmoji name="大哭" size={32} />
155
+ </div>
156
+ </div>
157
+ );
158
+ }
159
+
160
+ export default App;
161
+ ```
162
+
163
+ ## 🎨 高级使用示例
164
+
165
+ ### 1. 表情选择器组件
166
+
167
+ ```tsx
168
+ // src/components/EmojiPicker.tsx
169
+ import React, { useState } from 'react';
170
+ import {
171
+ getEmojisByCategory,
172
+ EmojiCategory,
173
+ type EmojiInfo
174
+ } from 'wechat-emojis';
175
+ import WeChatEmoji from './WeChatEmoji';
176
+
177
+ interface EmojiPickerProps {
178
+ onEmojiSelect: (emoji: EmojiInfo) => void;
179
+ categories?: EmojiCategory[];
180
+ }
181
+
182
+ const EmojiPicker: React.FC<EmojiPickerProps> = ({
183
+ onEmojiSelect,
184
+ categories = [
185
+ EmojiCategory.FACE,
186
+ EmojiCategory.GESTURE,
187
+ EmojiCategory.ANIMAL,
188
+ EmojiCategory.BLESSING,
189
+ EmojiCategory.OTHER
190
+ ]
191
+ }) => {
192
+ const [activeCategory, setActiveCategory] = useState<EmojiCategory>(EmojiCategory.FACE);
193
+
194
+ const categoryNames = {
195
+ [EmojiCategory.FACE]: '人脸',
196
+ [EmojiCategory.GESTURE]: '手势',
197
+ [EmojiCategory.ANIMAL]: '动物',
198
+ [EmojiCategory.BLESSING]: '祝福',
199
+ [EmojiCategory.OTHER]: '其他'
200
+ };
201
+
202
+ return (
203
+ <div className="emoji-picker">
204
+ {/* 分类标签 */}
205
+ <div className="emoji-categories">
206
+ {categories.map(category => (
207
+ <button
208
+ key={category}
209
+ className={`category-btn ${activeCategory === category ? 'active' : ''}`}
210
+ onClick={() => setActiveCategory(category)}
211
+ >
212
+ {categoryNames[category]}
213
+ </button>
214
+ ))}
215
+ </div>
216
+
217
+ {/* 表情网格 */}
218
+ <div className="emoji-grid">
219
+ {getEmojisByCategory(activeCategory).map(emoji => (
220
+ <button
221
+ key={emoji.name}
222
+ className="emoji-item"
223
+ onClick={() => onEmojiSelect(emoji)}
224
+ title={emoji.name}
225
+ >
226
+ <WeChatEmoji name={emoji.name} size={24} />
227
+ </button>
228
+ ))}
229
+ </div>
230
+ </div>
231
+ );
232
+ };
233
+
234
+ export default EmojiPicker;
235
+ ```
236
+
237
+ ### 2. 聊天消息组件
238
+
239
+ ```tsx
240
+ // src/components/ChatMessage.tsx
241
+ import React from 'react';
242
+ import { getEmojiPath, type EmojiName } from 'wechat-emojis';
243
+
244
+ interface ChatMessageProps {
245
+ content: string;
246
+ emojiSize?: number;
247
+ }
248
+
249
+ const ChatMessage: React.FC<ChatMessageProps> = ({ content, emojiSize = 20 }) => {
250
+ // 解析消息中的表情标记,例如 [微笑] → 表情图片
251
+ const parseEmojis = (text: string) => {
252
+ const emojiRegex = /\[([^\]]+)\]/g;
253
+ const parts = [];
254
+ let lastIndex = 0;
255
+ let match;
256
+
257
+ while ((match = emojiRegex.exec(text)) !== null) {
258
+ // 添加表情前的文本
259
+ if (match.index > lastIndex) {
260
+ parts.push(text.slice(lastIndex, match.index));
261
+ }
262
+
263
+ // 添加表情
264
+ const emojiName = match[1] as EmojiName;
265
+ const emojiPath = getEmojiPath(emojiName);
266
+
267
+ if (emojiPath) {
268
+ parts.push(
269
+ <img
270
+ key={`emoji-${match.index}`}
271
+ src={emojiPath}
272
+ alt={emojiName}
273
+ width={emojiSize}
274
+ height={emojiSize}
275
+ style={{
276
+ display: 'inline-block',
277
+ verticalAlign: 'middle',
278
+ margin: '0 2px'
279
+ }}
280
+ />
281
+ );
282
+ } else {
283
+ // 如果表情不存在,保留原文本
284
+ parts.push(match[0]);
285
+ }
286
+
287
+ lastIndex = match.index + match[0].length;
288
+ }
289
+
290
+ // 添加剩余文本
291
+ if (lastIndex < text.length) {
292
+ parts.push(text.slice(lastIndex));
293
+ }
294
+
295
+ return parts;
296
+ };
297
+
298
+ return (
299
+ <div className="chat-message">
300
+ {parseEmojis(content)}
301
+ </div>
302
+ );
303
+ };
304
+
305
+ export default ChatMessage;
306
+ ```
307
+
308
+ ## 💡 使用技巧和最佳实践
309
+
310
+ ### 1. 性能优化
311
+
312
+ ```tsx
313
+ // 使用 React.memo 优化表情组件
314
+ const WeChatEmoji = React.memo<WeChatEmojiProps>(({ name, size, className, alt }) => {
315
+ // ... 组件实现
316
+ });
317
+
318
+ // 预加载常用表情
319
+ const preloadEmojis = (emojiNames: EmojiName[]) => {
320
+ emojiNames.forEach(name => {
321
+ const path = getEmojiPath(name);
322
+ if (path) {
323
+ const img = new Image();
324
+ img.src = path;
325
+ }
326
+ });
327
+ };
328
+ ```
329
+
330
+ ### 2. 错误处理
331
+
332
+ ```tsx
333
+ const WeChatEmoji: React.FC<WeChatEmojiProps> = ({ name, size = 24, fallback }) => {
334
+ const [hasError, setHasError] = useState(false);
335
+ const emojiPath = getEmojiPath(name);
336
+
337
+ if (!emojiPath || hasError) {
338
+ return fallback || <span>[{name}]</span>;
339
+ }
340
+
341
+ return (
342
+ <img
343
+ src={emojiPath}
344
+ alt={name}
345
+ width={size}
346
+ height={size}
347
+ onError={() => setHasError(true)}
348
+ />
349
+ );
350
+ };
351
+ ```
352
+
353
+ ### 3. 样式定制
354
+
355
+ ```css
356
+ /* src/styles/emoji.css */
357
+ .wechat-emoji {
358
+ display: inline-block;
359
+ vertical-align: middle;
360
+ user-select: none;
361
+ pointer-events: none;
362
+ }
363
+
364
+ .emoji-picker {
365
+ border: 1px solid #e0e0e0;
366
+ border-radius: 8px;
367
+ padding: 12px;
368
+ background: white;
369
+ box-shadow: 0 2px 8px rgba(0,0,0,0.1);
370
+ }
371
+
372
+ .emoji-categories {
373
+ display: flex;
374
+ gap: 8px;
375
+ margin-bottom: 12px;
376
+ border-bottom: 1px solid #f0f0f0;
377
+ padding-bottom: 8px;
378
+ }
379
+
380
+ .category-btn {
381
+ padding: 6px 12px;
382
+ border: none;
383
+ background: #f5f5f5;
384
+ border-radius: 4px;
385
+ cursor: pointer;
386
+ font-size: 12px;
387
+ }
388
+
389
+ .category-btn.active {
390
+ background: #1890ff;
391
+ color: white;
392
+ }
393
+
394
+ .emoji-grid {
395
+ display: grid;
396
+ grid-template-columns: repeat(8, 1fr);
397
+ gap: 4px;
398
+ max-height: 200px;
399
+ overflow-y: auto;
400
+ }
401
+
402
+ .emoji-item {
403
+ padding: 6px;
404
+ border: none;
405
+ background: transparent;
406
+ border-radius: 4px;
407
+ cursor: pointer;
408
+ display: flex;
409
+ align-items: center;
410
+ justify-content: center;
411
+ }
412
+
413
+ .emoji-item:hover {
414
+ background: #f0f0f0;
415
+ }
416
+ ```
417
+
418
+ ## 🔧 TypeScript 支持
419
+
420
+ 项目完全支持TypeScript,提供完整的类型定义:
421
+
422
+ ```typescript
423
+ import type {
424
+ EmojiName, // 所有表情名称的联合类型
425
+ EmojiInfo, // 表情信息接口
426
+ EmojiCategory // 表情分类枚举
427
+ } from 'wechat-emojis';
428
+
429
+ // 类型安全的表情使用
430
+ const validEmoji: EmojiName = '微笑'; // ✅ 正确
431
+ const invalidEmoji: EmojiName = '不存在'; // ❌ TypeScript 错误
432
+ ```
433
+
434
+ ## 🚨 注意事项
435
+
436
+ 1. **图片路径**:确保assets目录位于public文件夹根目录,并且代码中引用的路径是正确的(例如,以 `/assets/` 开头)。
437
+ 2. **性能**:大量表情时考虑懒加载和虚拟滚动
438
+ 3. **兼容性**:确保目标浏览器支持所需的图片格式
439
+ 4. **版权**:注意表情包的使用权限和版权问题
440
+
441
+ ## 📱 移动端适配
442
+
443
+ ```css
444
+ /* 移动端优化 */
445
+ @media (max-width: 768px) {
446
+ .emoji-grid {
447
+ grid-template-columns: repeat(6, 1fr);
448
+ }
449
+
450
+ .emoji-item {
451
+ padding: 8px;
452
+ }
453
+ }
454
+ ```
455
+
456
+ 这样你就可以在React项目中完美使用微信表情包了!