Compare commits

...

1 Commits

Author SHA1 Message Date
Cola-Echo
262611c736 Add files via upload 2026-01-02 16:10:57 +08:00
5 changed files with 28 additions and 15 deletions

15
chat.js
View File

@@ -1476,7 +1476,8 @@ function getRealMsgIndexForVoice(container, msgElement) {
let visualMsgCount = 1; let visualMsgCount = 1;
const content = msg.content || ''; const content = msg.content || '';
const isSpecial = msg.isVoice || msg.isSticker || msg.isPhoto || msg.isMusic; const isSpecial = msg.isVoice || msg.isSticker || msg.isPhoto || msg.isMusic;
if (!isSpecial && content.indexOf('|||') >= 0) { // 只有 assistant 消息才会被 ||| 分割显示
if (msg.role === 'assistant' && !isSpecial && content.indexOf('|||') >= 0) {
const parts = content.split('|||').map(p => p.trim()).filter(p => p); const parts = content.split('|||').map(p => p.trim()).filter(p => p);
visualMsgCount = parts.length || 1; visualMsgCount = parts.length || 1;
} }
@@ -2022,14 +2023,14 @@ export async function sendMessage(messageText, isMultipleMessages = false, isVoi
} }
} }
const voiceMatch = aiMsg.match(/^\[语音[:]\s*(.+?)\]$/); const voiceMatch = aiMsg.match(/^\s*\[语音[:]\s*(.+?)\]\s*$/);
if (voiceMatch) { if (voiceMatch) {
aiMsg = voiceMatch[1]; aiMsg = voiceMatch[1];
aiIsVoice = true; aiIsVoice = true;
} }
// 解析AI照片格式 [照片:描述] // 解析AI照片格式 [照片:描述]
const photoMatch = aiMsg.match(/^\[照片[:]\s*(.+?)\]$/); const photoMatch = aiMsg.match(/^\s*\[照片[:]\s*(.+?)\]\s*$/);
if (photoMatch) { if (photoMatch) {
aiMsg = photoMatch[1]; aiMsg = photoMatch[1];
aiIsPhoto = true; aiIsPhoto = true;
@@ -2602,14 +2603,14 @@ export async function sendStickerMessage(stickerUrl, description = '') {
if (!aiMsg.trim()) continue; if (!aiMsg.trim()) continue;
} }
const voiceMatch = aiMsg.match(/^\[语音[:]\s*(.+?)\]$/); const voiceMatch = aiMsg.match(/^\s*\[语音[:]\s*(.+?)\]\s*$/);
if (voiceMatch) { if (voiceMatch) {
aiMsg = voiceMatch[1]; aiMsg = voiceMatch[1];
aiIsVoice = true; aiIsVoice = true;
} }
// 解析AI照片格式 [照片:描述] // 解析AI照片格式 [照片:描述]
const photoMatch = aiMsg.match(/^\[照片[:]\s*(.+?)\]$/); const photoMatch = aiMsg.match(/^\s*\[照片[:]\s*(.+?)\]\s*$/);
if (photoMatch) { if (photoMatch) {
aiMsg = photoMatch[1]; aiMsg = photoMatch[1];
aiIsPhoto = true; aiIsPhoto = true;
@@ -3049,14 +3050,14 @@ export async function sendPhotoMessage(description) {
if (!aiMsg.trim()) continue; if (!aiMsg.trim()) continue;
} }
const voiceMatch = aiMsg.match(/^\[语音[:]\s*(.+?)\]$/); const voiceMatch = aiMsg.match(/^\s*\[语音[:]\s*(.+?)\]\s*$/);
if (voiceMatch) { if (voiceMatch) {
aiMsg = voiceMatch[1]; aiMsg = voiceMatch[1];
aiIsVoice = true; aiIsVoice = true;
} }
// 解析AI照片格式 [照片:描述] // 解析AI照片格式 [照片:描述]
const photoMatch = aiMsg.match(/^\[照片[:]\s*(.+?)\]$/); const photoMatch = aiMsg.match(/^\s*\[照片[:]\s*(.+?)\]\s*$/);
if (photoMatch) { if (photoMatch) {
aiMsg = photoMatch[1]; aiMsg = photoMatch[1];
aiIsPhoto = true; aiIsPhoto = true;

View File

@@ -7,7 +7,7 @@ import { requestSave } from './save-manager.js';
import { currentChatIndex, openChat, showTypingIndicator, hideTypingIndicator, appendMessage } from './chat.js'; import { currentChatIndex, openChat, showTypingIndicator, hideTypingIndicator, appendMessage } from './chat.js';
import { showToast } from './toast.js'; import { showToast } from './toast.js';
import { getContext } from '../../../extensions.js'; import { getContext } from '../../../extensions.js';
import { formatQuoteDate } from './utils.js'; import { formatQuoteDate, sleep } from './utils.js';
import { isInGroupChat, getCurrentGroupIndex, openGroupChat } from './group-chat.js'; import { isInGroupChat, getCurrentGroupIndex, openGroupChat } from './group-chat.js';
// 当前显示菜单的消息索引 // 当前显示菜单的消息索引
@@ -504,12 +504,17 @@ async function regenerateMessage(msgIndex, contact) {
if (!finalMsg) continue; if (!finalMsg) continue;
let isVoice = false; let isVoice = false;
const voiceMatch = finalMsg.match(/^\[语音[:]\s*(.+?)\]$/); const voiceMatch = finalMsg.match(/^\s*\[语音[:]\s*(.+?)\]\s*$/);
if (voiceMatch) { if (voiceMatch) {
finalMsg = voiceMatch[1]; finalMsg = voiceMatch[1];
isVoice = true; isVoice = true;
} }
// 每条消息都要有typing效果和2-2.5秒延迟(与普通回复一致)
showTypingIndicator(contact);
await sleep(2000 + Math.random() * 500);
hideTypingIndicator();
contact.chatHistory.push({ contact.chatHistory.push({
role: 'assistant', role: 'assistant',
content: finalMsg, content: finalMsg,
@@ -735,7 +740,8 @@ function getRealMsgIndex(container, msgElement) {
const content = msg.content || ''; const content = msg.content || '';
const isSpecial = msg.isVoice || msg.isSticker || msg.isPhoto || msg.isMusic; const isSpecial = msg.isVoice || msg.isSticker || msg.isPhoto || msg.isMusic;
// 检查是否包含 ||| 或 <meme> 标签(这些会导致消息被分割显示) // 检查是否包含 ||| 或 <meme> 标签(这些会导致消息被分割显示)
if (!isSpecial && (content.indexOf('|||') >= 0 || /<\s*meme\s*>/i.test(content))) { // 注意:只有 assistant 消息才会被分割,用户消息不会分割
if (msg.role === 'assistant' && !isSpecial && (content.indexOf('|||') >= 0 || /<\s*meme\s*>/i.test(content))) {
// 使用 splitAIMessages 计算实际分割数量 // 使用 splitAIMessages 计算实际分割数量
const parts = splitAIMessages(content).filter(p => p && p.trim()); const parts = splitAIMessages(content).filter(p => p && p.trim());
visualMsgCount = parts.length || 1; visualMsgCount = parts.length || 1;

View File

@@ -331,7 +331,7 @@ export function generateCharacterTablesHtml() {
data-char-idx="${charIdx}" data-char-idx="${charIdx}"
data-other="${escapeHtml(otherText)}" data-other="${escapeHtml(otherText)}"
title="${hasOther ? '点击查看/编辑' : '点击添加'}" title="${hasOther ? '点击查看/编辑' : '点击添加'}"
style="width: 100%; font-size: 11px; padding: 3px 4px; ${hasOther ? 'background: var(--wechat-primary); color: white;' : ''}"> style="width: 100%; font-size: 11px; padding: 3px 4px; ${hasOther ? 'background: var(--wechat-green); color: white;' : ''}">
${hasOther ? '详情' : '+'} ${hasOther ? '详情' : '+'}
</button> </button>
</td> </td>
@@ -525,7 +525,7 @@ function saveCharOtherEdit() {
const hasOther = newValue.length > 0; const hasOther = newValue.length > 0;
btn.textContent = hasOther ? '详情' : '+'; btn.textContent = hasOther ? '详情' : '+';
btn.title = hasOther ? '点击查看/编辑' : '点击添加'; btn.title = hasOther ? '点击查看/编辑' : '点击添加';
btn.style.background = hasOther ? 'var(--wechat-primary)' : ''; btn.style.background = hasOther ? 'var(--wechat-green)' : '';
btn.style.color = hasOther ? 'white' : ''; btn.style.color = hasOther ? 'white' : '';
} }

View File

@@ -1037,7 +1037,7 @@ function generateModalsHTML(settings) {
<div id="wechat-group-contacts-list" style="max-height: 300px; overflow-y: auto; border: 1px solid var(--wechat-border); border-radius: 8px; padding: 8px;"></div> <div id="wechat-group-contacts-list" style="max-height: 300px; overflow-y: auto; border: 1px solid var(--wechat-border); border-radius: 8px; padding: 8px;"></div>
<div style="margin-top: 12px; text-align: center; color: var(--wechat-text-secondary); font-size: 13px;"> <div style="margin-top: 12px; text-align: center; color: var(--wechat-text-secondary); font-size: 13px;">
已选择 <span id="wechat-group-selected-count" style="color: var(--wechat-primary); font-weight: 500;">0</span> 人 已选择 <span id="wechat-group-selected-count" style="color: var(--wechat-green); font-weight: 500;">0</span> 人
</div> </div>
<div class="wechat-modal-actions" style="margin-top: 16px;"> <div class="wechat-modal-actions" style="margin-top: 16px;">

View File

@@ -2379,9 +2379,15 @@
color: inherit; color: inherit;
} }
/* 用户消息的图标朝向左(水平翻转) */ /* 用户消息的图标朝向左(水平翻转)+ 黑色 */
.wechat-voice-bubble.self .wechat-voice-waves-icon { .wechat-voice-bubble.self .wechat-voice-waves-icon {
transform: scaleX(-1); transform: scaleX(-1);
color: #000;
}
/* 用户消息的时长文字也是黑色 */
.wechat-voice-bubble.self .wechat-voice-duration {
color: #000;
} }
/* 对方消息的图标朝向右(默认方向) */ /* 对方消息的图标朝向右(默认方向) */
@@ -5306,7 +5312,7 @@
position: absolute; position: absolute;
left: 0; left: 0;
right: 0; right: 0;
bottom: 120px; bottom: 165px;
max-height: 250px; max-height: 250px;
display: flex; display: flex;
flex-direction: column; flex-direction: column;