Files
jiang13-forum/.trae/documents/emoji-effect-adjustment.md
freefire 536707f812 feat: 新增贴纸系统,重构评论编辑器与内容处理
1. 新增多平台贴纸库:贴吧、微博、知乎、小红书、抖音、B站共500+贴纸,搭配颜文字贴纸
2. 实现贴纸选择器面板,支持分类浏览、键盘导航和懒加载
3. 重构评论内容渲染:替换旧的@提及高亮逻辑,新增HTML净化与双向兼容
4. 重构评论编辑器为Tiptap富文本版本,支持表情插入、格式编辑
5. 优化评论编辑体验,修复滚动位置保留问题,调整评论区UI样式
6. 移除旧版EmojiPicker工具类,新增贴纸数据管理模块
2026-08-08 02:24:04 +08:00

5.0 KiB
Raw Blame History

表情效果调整计划

问题分析

当前实现存在 5 个问题,根因如下:

1. 插入表情后有选择状态(蓝色高亮)

  • 根因: Tiptap setImage 插入图片节点后,节点处于 "node-selected" 状态,显示蓝色选中框
  • 位置: CommentEditor.tsx L155-163

2. 输入框表情太大

  • 根因: CSS 选择器 img[src^="data:image/svg"] 只匹配旧 SVG data URI不匹配新的 AVIF URL/stickers/tieba/tb_01.avif),导致表情图片无尺寸约束,以原始大尺寸渲染
  • 位置: global.css L5584-5603

3. 插入表情后光标换行

  • 根因: ArticleImage.configure({ inline: false }) 使图片为块级节点,插入后自动换行
  • 位置: CommentEditor.tsx L92

4. 表情栏目太宽松

  • 根因: Grid 仅 6 列gap 4pxpadding 10px
  • 位置: global.css L5502-5510

5. 颜文字太小

  • 根因: .sticker-picker-textfont-size: 8px,极小
  • 位置: global.css L5606-5616

改动方案

文件 1: CommentEditor.tsx

改动 A — 图片改为内联 (L92):

// 旧
ArticleImage.configure({ inline: false, allowBase64: true }),
// 新
ArticleImage.configure({ inline: true, allowBase64: true }),

改动 B — insertSticker 插入后取消选中和换行 (L155-163):

const insertSticker = useCallback((sticker: Sticker) => {
  if (!editor) return;
  if (sticker.type === 'text' && sticker.text) {
    editor.chain().focus().insertContent(sticker.text).run();
  } else if (sticker.url) {
    // 插入内联图片 + 尾随零宽空格,确保光标在图片后面而非选中图片
    editor.chain().focus().insertContent([
      { type: 'image', attrs: { src: sticker.url, alt: sticker.name } },
      { type: 'text', text: '\u200b' },
    ]).run();
  }
  setShowSticker(false);
}, [editor]);

insertContent + 零宽空格替代 setImage,避免 node-selected 状态,光标自然落在图片后。

文件 2: StickerPicker.tsx

改动 C — 键盘导航列数匹配新网格 (L44):

// 旧
const cols = 6;
// 新
const cols = 8;

文件 3: global.css

改动 D — 表情选择器密度提升 (L5502-5510):

.sticker-picker-grid {
  display: grid;
  grid-template-columns: repeat(8, 1fr);  /* 6 → 8 */
  gap: 2px;                                /* 4px → 2px */
  padding: 6px;                            /* 10px → 6px */
  overflow-y: auto;
  flex: 1;
  min-height: 0;
}

改动 E — 选择器项缩小 (L5512-5522):

.sticker-picker-item {
  padding: 2px;   /* 4px → 2px */
  /* 其余不变 */
}

改动 F — 颜文字字体放大 (L5606-5616):

.sticker-picker-text {
  font-size: 14px;   /* 8px → 14px */
  line-height: 1.4;  /* 1.2 → 1.4 */
  /* 其余不变 */
}

改动 G — 替换旧 SVG 选择器为通用贴纸选择器 (L5584-5603):

删除旧的 img[src^="data:image/svg"] 选择器,替换为基于 /stickers/ 路径的选择器:

/* 编辑器内贴纸 img 尺寸约束 */
.comment-editor .article-prosemirror img[src*="/stickers/"],
.comment-editor .article-editor-content img[src*="/stickers/"] {
  display: inline-block;
  width: 28px;
  height: 28px;
  vertical-align: middle;
  margin: 0 1px;
  border-radius: 4px;
  object-fit: contain;
}

/* 评论正文中的贴纸 img */
.floor-body img[src*="/stickers/"],
.comment-body img[src*="/stickers/"] {
  display: inline-block;
  vertical-align: middle;
  width: 28px;
  height: 28px;
  margin: 0 1px;
  background: transparent;
  border-radius: 4px;
  object-fit: contain;
}

改动 H — 移动端网格也改为 8 列 (L5619-5624):

@media (max-width: 640px) {
  .sticker-picker { max-height: 240px; }
  .sticker-picker-grid { grid-template-columns: repeat(6, 1fr); } /* 移动端 6 列 */
  .sticker-picker-tab { padding: 6px 10px; font-size: 12px; }
  .comment-editor .article-tool-btn { width: 30px; height: 30px; }
}

移动端保持 6 列(屏幕窄),桌面端 8 列。

不改动

  • ArticleImageExtension.tsx — 无需修改,inline: true 通过 configure() 传入即可
  • kaomoji.ts / emojiData.ts / hot.ts — 数据层不变
  • CommentContent.tsx — 渲染层不变CSS 覆盖即可)
  • PostEditor帖子编辑器— 不受影响,仍使用 inline: false

验证

  1. npm run build 无报错
  2. 浏览器验证:
    • 选择表情后插入无蓝色选中框
    • 表情在输入框中显示 28px内联在文字中
    • 插入表情后光标紧跟表情后方,不换行
    • 表情选择器 8 列密度更高
    • 颜文字标签内字体清晰可读