AI实现在线聊天室--04(消息输入功能丰富的方案备选)

7 阅读3分钟

上篇:AI实现在线聊天室--03 这篇在上次基础上做个方案备选记录(丰富消息输入功能)

丰富消息输入功能的创意与实现方案

为聊天室的消息输入功能添加更多丰富的交互方式可以显著提升用户体验。以下是一些值得考虑的改进方向及具体实现方案:

1. 富文本编辑功能(不需要)

实现方案

javascript

// 在HTML中添加工具栏
<div class="toolbar">
  <button data-cmd="bold"><i class="fas fa-bold"></i></button>
  <button data-cmd="italic"><i class="fas fa-italic"></i></button>
  <button data-cmd="insertUnorderedList"><i class="fas fa-list-ul"></i></button>
  <button data-cmd="createLink"><i class="fas fa-link"></i></button>
  <button data-cmd="insertImage"><i class="fas fa-image"></i></button>
</div>

<div id="message-input" contenteditable="true"></div>

<script>
// 工具栏功能实现
document.querySelectorAll('.toolbar button').forEach(btn => {
  btn.addEventListener('click', () => {
    const cmd = btn.dataset.cmd;
    if(cmd === 'insertImage') {
      const url = prompt('输入图片URL:');
      if(url) document.execCommand(cmd, false, url);
    } else if(cmd === 'createLink') {
      const url = prompt('输入链接URL:');
      if(url) document.execCommand(cmd, false, url);
    } else {
      document.execCommand(cmd, false, null);
    }
    document.getElementById('message-input').focus();
  });
});
</script>

2. 表情符号选择器

实现方案

javascript

// 添加表情选择按钮和面板
<button id="emoji-btn"><i class="far fa-smile"></i></button>
<div id="emoji-picker" class="emoji-panel">
  <!-- 动态加载表情 -->
</div>

<script>
// 表情选择器实现
const emojiCategories = {
  people: ['😀', '😃', '😄', '😁', '😆'],
  nature: ['🐶', '🐱', '🐭', '🐹', '🐰'],
  // 更多分类...
};

document.getElementById('emoji-btn').addEventListener('click', (e) => {
  const picker = document.getElementById('emoji-picker');
  picker.innerHTML = '';
  
  Object.entries(emojiCategories).forEach(([category, emojis]) => {
    const categoryEl = document.createElement('div');
    categoryEl.className = 'emoji-category';
    categoryEl.innerHTML = `<h4>${category}</h4>`;
    
    emojis.forEach(emoji => {
      const span = document.createElement('span');
      span.textContent = emoji;
      span.addEventListener('click', () => {
        insertAtCursor(emoji);
        picker.style.display = 'none';
      });
      categoryEl.appendChild(span);
    });
    
    picker.appendChild(categoryEl);
  });
  
  picker.style.display = picker.style.display === 'block' ? 'none' : 'block';
  e.stopPropagation();
});

function insertAtCursor(text) {
  const input = document.getElementById('message-input');
  const start = input.selectionStart;
  const end = input.selectionEnd;
  input.value = input.value.substring(0, start) + text + input.value.substring(end);
  input.selectionStart = input.selectionEnd = start + text.length;
  input.focus();
}
</script>

3. 文件上传功能(没有后端支持,暂不需要)

实现方案

javascript

<input type="file" id="file-upload" style="display:none">
<button id="upload-btn"><i class="fas fa-paperclip"></i></button>

<script>
document.getElementById('upload-btn').addEventListener('click', () => {
  document.getElementById('file-upload').click();
});

document.getElementById('file-upload').addEventListener('change', (e) => {
  const file = e.target.files[0];
  if (!file) return;
  
  // 显示上传状态
  showUploadStatus(`正在上传 ${file.name}...`);
  
  // 实际项目中这里应该是上传到服务器
  setTimeout(() => {
    // 模拟上传完成
    if (file.type.startsWith('image/')) {
      sendMessage({
        type: 'image',
        url: URL.createObjectURL(file),
        name: file.name
      });
    } else {
      sendMessage({
        type: 'file',
        name: file.name,
        size: formatFileSize(file.size)
      });
    }
  }, 1500);
});

function formatFileSize(bytes) {
  if (bytes === 0) return '0 Bytes';
  const k = 1024;
  const sizes = ['Bytes', 'KB', 'MB', 'GB'];
  const i = Math.floor(Math.log(bytes) / Math.log(k));
  return parseFloat((bytes / Math.pow(k, i)).toFixed(1) + ' ' + sizes[i];
}
</script>

4. 消息模板/快捷回复

实现方案

javascript

<button id="quick-reply-btn"><i class="fas fa-comment-alt"></i></button>
<div id="quick-replies" class="quick-reply-panel">
  <div data-template="Hi there!">Hi there!</div>
  <div data-template="I'll be right back">I'll be right back</div>
  <div data-template="Can we talk later?">Can we talk later?</div>
</div>

<script>
document.getElementById('quick-reply-btn').addEventListener('click', (e) => {
  const panel = document.getElementById('quick-replies');
  panel.style.display = panel.style.display === 'block' ? 'none' : 'block';
  e.stopPropagation();
});

document.querySelectorAll('#quick-replies div').forEach(item => {
  item.addEventListener('click', () => {
    document.getElementById('message-input').value += item.dataset.template;
    document.getElementById('quick-replies').style.display = 'none';
  });
});
</script>

5. 输入状态指示器

实现方案

javascript

let typingTimeout;
let isTyping = false;

messageInput.addEventListener('input', () => {
  if (!isTyping) {
    socket.send(JSON.stringify({ type: 'typing', status: true }));
    isTyping = true;
  }
  
  clearTimeout(typingTimeout);
  typingTimeout = setTimeout(() => {
    socket.send(JSON.stringify({ type: 'typing', status: false }));
    isTyping = false;
  }, 1000);
});

// 服务端需要处理typing消息并广播给其他用户
// 客户端接收后显示"对方正在输入..."的提示

6. 消息预览功能(对应Markdown的部分,不需要)

实现方案

javascript

<div id="message-preview" class="message-preview"></div>

<script>
messageInput.addEventListener('input', () => {
  const preview = document.getElementById('message-preview');
  preview.innerHTML = formatMessagePreview(messageInput.value);
});

function formatMessagePreview(text) {
  // 简单Markdown支持
  return text
    .replace(/**(.*?)**/g, '<strong>$1</strong>')
    .replace(/*(.*?)*/g, '<em>$1</em>')
    .replace(/(https?://[^\s]+)/g, '<a href="$1" target="_blank">$1</a>');
}
</script>

7. 语音输入支持(只需移动端支持,暂不考虑)

实现方案

javascript

<button id="voice-btn"><i class="fas fa-microphone"></i></button>

<script>
document.getElementById('voice-btn').addEventListener('click', () => {
  const recognition = new (window.SpeechRecognition || window.webkitSpeechRecognition)();
  recognition.lang = 'zh-CN';
  
  recognition.onstart = () => {
    showVoiceStatus('正在聆听...');
  };
  
  recognition.onresult = (event) => {
    const transcript = event.results[0][0].transcript;
    messageInput.value += transcript;
  };
  
  recognition.onerror = (event) => {
    showVoiceStatus('识别错误: ' + event.error);
  };
  
  recognition.onend = () => {
    showVoiceStatus('');
  };
  
  recognition.start();
});
</script>

8. 代码片段支持(不需要)

实现方案

javascript

<button id="code-btn"><i class="fas fa-code"></i></button>

<script>
document.getElementById('code-btn').addEventListener('click', () => {
  const lang = prompt('输入代码语言(如javascript、python等):', 'javascript');
  if (!lang) return;
  
  const code = prompt('粘贴你的代码:');
  if (!code) return;
  
  sendMessage({
    type: 'code',
    language: lang,
    content: code
  });
});

// 渲染时代码高亮可以使用Prism.js等库
</script>

9. 消息撤回功能

实现方案

javascript

// 消息元素添加右键菜单
messageElement.addEventListener('contextmenu', (e) => {
  e.preventDefault();
  if (messageElement.dataset.sender === currentUser) {
    showContextMenu(e.pageX, e.pageY, [
      { text: '撤回消息', action: () => recallMessage(messageId) }
    ]);
  }
});

function recallMessage(messageId) {
  socket.send(JSON.stringify({
    type: 'recall',
    messageId: messageId
  }));
}

// 服务端需要处理recall消息并广播给所有用户

10. 输入自动完成

实现方案

javascript

messageInput.addEventListener('input', (e) => {
  const word = getCurrentWord(e.target.value, e.target.selectionStart);
  if (word.startsWith('@')) {
    showUserSuggestions(word.substring(1));
  } else if (word.startsWith(':')) {
    showEmojiSuggestions(word.substring(1));
  }
});

function showUserSuggestions(prefix) {
  const matchingUsers = onlineUsers.filter(u => 
    u.username.toLowerCase().startsWith(prefix.toLowerCase())
  );
  
  // 显示匹配用户列表
  // 选择后替换@前缀和用户名
}

// 类似实现emoji自动完成

整合建议

  1. 逐步添加功能:根据用户需求优先级逐步实现这些功能
  2. 保持UI简洁:使用折叠菜单或图标按钮避免界面混乱
  3. 考虑移动端:确保所有功能在移动设备上也能良好工作
  4. 性能优化:特别是文件上传和图片处理要注意性能影响
  5. 用户引导:新功能添加时提供简单的使用引导或提示

这些增强功能可以显著提升聊天室的交互体验,让用户沟通更加高效和愉快。您可以根据项目需求选择最适合的功能进行实现。