mirror of
https://github.com/Cola-Echo/Cola.git
synced 2026-06-06 03:35:50 +00:00
Add files via upload
This commit is contained in:
15
chat.js
15
chat.js
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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' : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;">
|
||||||
|
|||||||
10
style.css
10
style.css
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user