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:
451
toy-control.js
451
toy-control.js
@@ -18,7 +18,13 @@ const TOY_ICONS = {
|
||||
wave: `<svg viewBox="0 0 24 24" width="28" height="28"><path d="M2 12c2-3 4-6 6-6s4 6 6 6 4-6 6-6" stroke="currentColor" stroke-width="1.5" fill="none" stroke-linecap="round" stroke-linejoin="round"/><path d="M2 18c2-3 4-6 6-6s4 6 6 6 4-6 6-6" stroke="currentColor" stroke-width="1.5" fill="none" stroke-linecap="round" stroke-linejoin="round"/></svg>`,
|
||||
pause: `<svg viewBox="0 0 24 24" width="28" height="28"><rect x="6" y="4" width="4" height="16" stroke="currentColor" stroke-width="1.5" fill="none" rx="1"/><rect x="14" y="4" width="4" height="16" stroke="currentColor" stroke-width="1.5" fill="none" rx="1"/></svg>`,
|
||||
shock: `<svg viewBox="0 0 24 24" width="28" height="28"><path d="M13 2L3 14h9l-1 8 10-12h-9l1-8z" stroke="currentColor" stroke-width="1.5" fill="currentColor" stroke-linecap="round" stroke-linejoin="round"/></svg>`,
|
||||
back: `<svg viewBox="0 0 24 24" width="24" height="24"><path d="M15 18l-6-6 6-6" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"/></svg>`
|
||||
back: `<svg viewBox="0 0 24 24" width="24" height="24"><path d="M15 18l-6-6 6-6" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"/></svg>`,
|
||||
micOn: `<svg viewBox="0 0 24 24" width="28" height="28"><path d="M12 1a3 3 0 00-3 3v8a3 3 0 006 0V4a3 3 0 00-3-3z" stroke="currentColor" stroke-width="1.5" fill="none"/><path d="M19 10v2a7 7 0 01-14 0v-2" stroke="currentColor" stroke-width="1.5" fill="none" stroke-linecap="round"/><line x1="12" y1="19" x2="12" y2="23" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/><line x1="8" y1="23" x2="16" y2="23" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>`,
|
||||
micOff: `<svg viewBox="0 0 24 24" width="28" height="28"><path d="M12 1a3 3 0 00-3 3v8a3 3 0 006 0V4a3 3 0 00-3-3z" stroke="currentColor" stroke-width="1.5" fill="none"/><path d="M19 10v2a7 7 0 01-14 0v-2" stroke="currentColor" stroke-width="1.5" fill="none" stroke-linecap="round"/><line x1="12" y1="19" x2="12" y2="23" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/><line x1="8" y1="23" x2="16" y2="23" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>`,
|
||||
cameraOn: `<svg viewBox="0 0 24 24" width="28" height="28"><path d="M23 7l-7 5 7 5V7z" stroke="currentColor" stroke-width="1.5" fill="none" stroke-linecap="round" stroke-linejoin="round"/><rect x="1" y="5" width="15" height="14" rx="2" ry="2" stroke="currentColor" stroke-width="1.5" fill="none"/></svg>`,
|
||||
cameraOff: `<svg viewBox="0 0 24 24" width="28" height="28"><path d="M23 7l-7 5 7 5V7z" stroke="currentColor" stroke-width="1.5" fill="none" stroke-linecap="round" stroke-linejoin="round"/><rect x="1" y="5" width="15" height="14" rx="2" ry="2" stroke="currentColor" stroke-width="1.5" fill="none"/></svg>`,
|
||||
// 像素爱心图标(用于多玩具切换)
|
||||
pixelHeart: `<svg viewBox="0 0 16 16" width="24" height="24"><rect x="2" y="4" width="2" height="2" fill="currentColor"/><rect x="4" y="2" width="2" height="2" fill="currentColor"/><rect x="6" y="2" width="2" height="2" fill="currentColor"/><rect x="8" y="2" width="2" height="2" fill="currentColor"/><rect x="10" y="2" width="2" height="2" fill="currentColor"/><rect x="12" y="4" width="2" height="2" fill="currentColor"/><rect x="2" y="6" width="2" height="2" fill="currentColor"/><rect x="4" y="4" width="2" height="2" fill="currentColor"/><rect x="6" y="4" width="2" height="2" fill="currentColor"/><rect x="8" y="4" width="2" height="2" fill="currentColor"/><rect x="10" y="4" width="2" height="2" fill="currentColor"/><rect x="12" y="6" width="2" height="2" fill="currentColor"/><rect x="2" y="8" width="2" height="2" fill="currentColor"/><rect x="4" y="6" width="2" height="2" fill="currentColor"/><rect x="6" y="6" width="2" height="2" fill="currentColor"/><rect x="8" y="6" width="2" height="2" fill="currentColor"/><rect x="10" y="6" width="2" height="2" fill="currentColor"/><rect x="12" y="8" width="2" height="2" fill="currentColor"/><rect x="4" y="8" width="2" height="2" fill="currentColor"/><rect x="6" y="8" width="2" height="2" fill="currentColor"/><rect x="8" y="8" width="2" height="2" fill="currentColor"/><rect x="10" y="8" width="2" height="2" fill="currentColor"/><rect x="6" y="10" width="2" height="2" fill="currentColor"/><rect x="8" y="10" width="2" height="2" fill="currentColor"/><rect x="4" y="10" width="2" height="2" fill="currentColor"/><rect x="10" y="10" width="2" height="2" fill="currentColor"/><rect x="6" y="12" width="4" height="2" fill="currentColor"/></svg>`
|
||||
};
|
||||
|
||||
// 控制模式定义
|
||||
@@ -73,11 +79,21 @@ let toyControlState = {
|
||||
currentMode: null,
|
||||
messages: [],
|
||||
activeModes: new Set(),
|
||||
sessionStartTime: null
|
||||
sessionStartTime: null,
|
||||
micEnabled: false, // 麦克风状态
|
||||
cameraEnabled: false, // 摄像头状态
|
||||
// 多玩具支持
|
||||
isMulti: false, // 是否多玩具模式
|
||||
toys: [], // 多玩具列表
|
||||
currentToyIndex: 0, // 当前控制的玩具索引
|
||||
wheelOpen: false // 轮盘是否展开
|
||||
};
|
||||
|
||||
// 显示控制界面
|
||||
export function showToyControlPage(gift, contact, contactIndex) {
|
||||
// 判断是否多玩具模式
|
||||
const isMulti = gift.isMulti === true;
|
||||
|
||||
toyControlState = {
|
||||
isActive: true,
|
||||
gift: gift,
|
||||
@@ -87,9 +103,30 @@ export function showToyControlPage(gift, contact, contactIndex) {
|
||||
currentMode: null,
|
||||
messages: [],
|
||||
activeModes: new Set(),
|
||||
sessionStartTime: Date.now()
|
||||
sessionStartTime: Date.now(),
|
||||
micEnabled: false,
|
||||
cameraEnabled: false,
|
||||
// 多玩具支持
|
||||
isMulti: isMulti,
|
||||
toys: isMulti ? gift.toys : [],
|
||||
currentToyIndex: 0,
|
||||
wheelOpen: false
|
||||
};
|
||||
|
||||
// 如果是多玩具模式,设置当前玩具为第一个
|
||||
if (isMulti && gift.toys && gift.toys.length > 0) {
|
||||
const firstToy = gift.toys[0];
|
||||
toyControlState.gift = {
|
||||
...gift,
|
||||
giftId: firstToy.giftId,
|
||||
giftName: firstToy.giftName,
|
||||
giftEmoji: firstToy.giftEmoji,
|
||||
giftDesc: firstToy.giftDesc,
|
||||
hasControl: firstToy.hasControl,
|
||||
hasShock: firstToy.hasShock
|
||||
};
|
||||
}
|
||||
|
||||
// 标记正在使用
|
||||
if (contact.pendingGifts) {
|
||||
const pendingGift = contact.pendingGifts.find(g => g.timestamp === gift.timestamp);
|
||||
@@ -159,6 +196,9 @@ function renderToyControlPage() {
|
||||
</button>
|
||||
</div>
|
||||
<div class="wechat-toy-btn-row">
|
||||
<button class="wechat-toy-btn wechat-toy-btn-media" data-media="mic" title="麦克风">
|
||||
${toyControlState.micEnabled ? TOY_ICONS.micOn : TOY_ICONS.micOff}
|
||||
</button>
|
||||
<button class="wechat-toy-btn" data-mode="wave">
|
||||
${TOY_CONTROL_MODES.wave.icon}
|
||||
<span class="wechat-toy-btn-label">${TOY_CONTROL_MODES.wave.name}</span>
|
||||
@@ -167,6 +207,9 @@ function renderToyControlPage() {
|
||||
${TOY_CONTROL_MODES.pause.icon}
|
||||
<span class="wechat-toy-btn-label">${TOY_CONTROL_MODES.pause.name}</span>
|
||||
</button>
|
||||
<button class="wechat-toy-btn wechat-toy-btn-media" data-media="camera" title="摄像头">
|
||||
${toyControlState.cameraEnabled ? TOY_ICONS.cameraOn : TOY_ICONS.cameraOff}
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
buttonsEl.innerHTML = buttonsHtml;
|
||||
@@ -187,12 +230,246 @@ function renderToyControlPage() {
|
||||
}
|
||||
}
|
||||
|
||||
// 清空消息
|
||||
if (messagesEl) {
|
||||
// 多玩具轮盘选择器
|
||||
renderToyWheelSelector();
|
||||
|
||||
// 不清空消息(保留聊天内容)
|
||||
// 只在首次进入时清空
|
||||
if (messagesEl && messagesEl.children.length === 0 && toyControlState.messages.length === 0) {
|
||||
messagesEl.innerHTML = '';
|
||||
}
|
||||
}
|
||||
|
||||
// 渲染多玩具轮盘选择器
|
||||
function renderToyWheelSelector() {
|
||||
// 移除旧的轮盘和遮罩
|
||||
const existingWheel = document.getElementById('wechat-toy-wheel-container');
|
||||
if (existingWheel) {
|
||||
existingWheel.remove();
|
||||
}
|
||||
const existingOverlay = document.getElementById('wechat-toy-wheel-overlay');
|
||||
if (existingOverlay) {
|
||||
existingOverlay.remove();
|
||||
}
|
||||
|
||||
// 只在多玩具模式下显示
|
||||
if (!toyControlState.isMulti || toyControlState.toys.length <= 1) return;
|
||||
|
||||
const controlPage = document.getElementById('wechat-toy-control-page');
|
||||
if (!controlPage) return;
|
||||
|
||||
// 创建背景遮罩(点击关闭轮盘)
|
||||
const overlay = document.createElement('div');
|
||||
overlay.id = 'wechat-toy-wheel-overlay';
|
||||
overlay.className = `wechat-toy-wheel-overlay ${toyControlState.wheelOpen ? 'active' : ''}`;
|
||||
|
||||
// 创建轮盘容器
|
||||
const wheelContainer = document.createElement('div');
|
||||
wheelContainer.id = 'wechat-toy-wheel-container';
|
||||
wheelContainer.className = 'wechat-toy-wheel-container';
|
||||
|
||||
// 创建中心爱心按钮
|
||||
const heartBtn = document.createElement('button');
|
||||
heartBtn.className = 'wechat-toy-wheel-heart';
|
||||
heartBtn.innerHTML = TOY_ICONS.pixelHeart;
|
||||
heartBtn.title = '切换玩具';
|
||||
|
||||
// 创建轮盘选项
|
||||
const wheelOptions = document.createElement('div');
|
||||
wheelOptions.className = `wechat-toy-wheel-options ${toyControlState.wheelOpen ? 'open' : ''}`;
|
||||
|
||||
const toys = toyControlState.toys;
|
||||
const angleStep = 360 / toys.length;
|
||||
// 移动端使用更小的半径
|
||||
const isMobile = window.innerWidth <= 420;
|
||||
const radius = isMobile ? 55 : 70;
|
||||
|
||||
toys.forEach((toy, index) => {
|
||||
const option = document.createElement('button');
|
||||
option.className = `wechat-toy-wheel-option ${index === toyControlState.currentToyIndex ? 'active' : ''}`;
|
||||
option.dataset.toyIndex = index;
|
||||
|
||||
// 计算位置(从顶部开始,顺时针排列)
|
||||
const angle = -90 + (angleStep * index); // -90 从顶部开始
|
||||
const x = Math.cos(angle * Math.PI / 180) * radius;
|
||||
const y = Math.sin(angle * Math.PI / 180) * radius;
|
||||
|
||||
option.style.setProperty('--x', `${x}px`);
|
||||
option.style.setProperty('--y', `${y}px`);
|
||||
option.innerHTML = `<span class="emoji">${toy.giftEmoji}</span><span class="name">${toy.giftName}</span>`;
|
||||
|
||||
wheelOptions.appendChild(option);
|
||||
});
|
||||
|
||||
wheelContainer.appendChild(wheelOptions);
|
||||
wheelContainer.appendChild(heartBtn);
|
||||
|
||||
// 插入遮罩和轮盘到控制区域上方
|
||||
const chatArea = controlPage.querySelector('.wechat-toy-control-chat');
|
||||
if (chatArea) {
|
||||
chatArea.parentNode.insertBefore(overlay, chatArea);
|
||||
chatArea.parentNode.insertBefore(wheelContainer, chatArea);
|
||||
} else {
|
||||
controlPage.appendChild(overlay);
|
||||
controlPage.appendChild(wheelContainer);
|
||||
}
|
||||
|
||||
// 绑定爱心按钮事件(支持触摸)
|
||||
heartBtn.addEventListener('click', toggleToyWheel);
|
||||
heartBtn.addEventListener('touchend', (e) => {
|
||||
e.preventDefault();
|
||||
toggleToyWheel();
|
||||
});
|
||||
|
||||
// 绑定遮罩点击事件(关闭轮盘)
|
||||
overlay.addEventListener('click', closeToyWheel);
|
||||
overlay.addEventListener('touchend', (e) => {
|
||||
e.preventDefault();
|
||||
closeToyWheel();
|
||||
});
|
||||
|
||||
// 绑定轮盘选项事件(支持触摸)
|
||||
wheelOptions.querySelectorAll('.wechat-toy-wheel-option').forEach(opt => {
|
||||
opt.addEventListener('click', (e) => {
|
||||
const index = parseInt(opt.dataset.toyIndex);
|
||||
switchToToy(index);
|
||||
});
|
||||
opt.addEventListener('touchend', (e) => {
|
||||
e.preventDefault();
|
||||
const index = parseInt(opt.dataset.toyIndex);
|
||||
switchToToy(index);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// 切换轮盘展开/收起
|
||||
function toggleToyWheel() {
|
||||
toyControlState.wheelOpen = !toyControlState.wheelOpen;
|
||||
|
||||
const options = document.querySelector('.wechat-toy-wheel-options');
|
||||
const overlay = document.getElementById('wechat-toy-wheel-overlay');
|
||||
if (options) {
|
||||
options.classList.toggle('open', toyControlState.wheelOpen);
|
||||
}
|
||||
if (overlay) {
|
||||
overlay.classList.toggle('active', toyControlState.wheelOpen);
|
||||
}
|
||||
}
|
||||
|
||||
// 关闭轮盘
|
||||
function closeToyWheel() {
|
||||
toyControlState.wheelOpen = false;
|
||||
|
||||
const options = document.querySelector('.wechat-toy-wheel-options');
|
||||
const overlay = document.getElementById('wechat-toy-wheel-overlay');
|
||||
if (options) {
|
||||
options.classList.remove('open');
|
||||
}
|
||||
if (overlay) {
|
||||
overlay.classList.remove('active');
|
||||
}
|
||||
}
|
||||
|
||||
// 切换到指定玩具
|
||||
async function switchToToy(index) {
|
||||
if (index < 0 || index >= toyControlState.toys.length) return;
|
||||
if (index === toyControlState.currentToyIndex) {
|
||||
// 同一个玩具,只关闭轮盘
|
||||
closeToyWheel();
|
||||
return;
|
||||
}
|
||||
|
||||
const previousToy = toyControlState.toys[toyControlState.currentToyIndex];
|
||||
const newToy = toyControlState.toys[index];
|
||||
|
||||
// 更新当前玩具索引
|
||||
toyControlState.currentToyIndex = index;
|
||||
|
||||
// 更新当前gift信息
|
||||
toyControlState.gift = {
|
||||
...toyControlState.gift,
|
||||
giftId: newToy.giftId,
|
||||
giftName: newToy.giftName,
|
||||
giftEmoji: newToy.giftEmoji,
|
||||
giftDesc: newToy.giftDesc,
|
||||
hasControl: newToy.hasControl,
|
||||
hasShock: newToy.hasShock
|
||||
};
|
||||
|
||||
// 重置模式状态(切换玩具后从暂停开始)
|
||||
toyControlState.currentMode = null;
|
||||
toyControlState.activeModes.clear();
|
||||
|
||||
// 关闭轮盘状态(渲染时会应用)
|
||||
toyControlState.wheelOpen = false;
|
||||
|
||||
// 重新渲染界面(保留消息)
|
||||
renderToyControlPage();
|
||||
|
||||
// 更新按钮状态
|
||||
document.querySelectorAll('.wechat-toy-btn').forEach(btn => {
|
||||
btn.classList.remove('active');
|
||||
});
|
||||
|
||||
// 添加切换提示消息
|
||||
addToyMessage('system', `已切换到 ${newToy.giftEmoji} ${newToy.giftName}`);
|
||||
|
||||
// AI对切换做出反应
|
||||
showToyTypingIndicator();
|
||||
|
||||
const isCharacterUsing = toyControlState.target === 'character';
|
||||
let prompt;
|
||||
|
||||
if (isCharacterUsing) {
|
||||
prompt = `[玩具切换]
|
||||
用户刚把玩具从"${previousToy.giftName}"切换到"${newToy.giftName}"了。
|
||||
${newToy.giftName}的特点:${newToy.giftDesc}
|
||||
|
||||
请对这个切换做出反应:
|
||||
- 可以表现出对新玩具的期待、紧张或好奇
|
||||
- 如果是更刺激的玩具可以表现出紧张
|
||||
- 如果是比较温和的可以表现出失落或放松
|
||||
|
||||
【重要规则】
|
||||
1. 只能输出纯文字,禁止使用任何特殊格式标签
|
||||
2. 禁止使用小括号描述动作如(xxx)
|
||||
3. 回复简短,1-2句话即可`;
|
||||
} else {
|
||||
prompt = `[玩具切换]
|
||||
你把用户正在用的玩具从"${previousToy.giftName}"切换到"${newToy.giftName}"了。
|
||||
${newToy.giftName}的特点:${newToy.giftDesc}
|
||||
|
||||
请对这个切换做出反应:
|
||||
- 可以调侃用户接下来要体验的感觉
|
||||
- 或者表达你为什么要给用户换这个
|
||||
|
||||
【重要规则】
|
||||
1. 只能输出纯文字,禁止使用任何特殊格式标签
|
||||
2. 禁止使用小括号描述动作如(xxx)
|
||||
3. 回复简短,1-2句话即可`;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await callToyAI(prompt);
|
||||
hideToyTypingIndicator();
|
||||
|
||||
if (response) {
|
||||
let reply = response.trim();
|
||||
reply = reply.replace(/<\s*meme\s*>[\s\S]*?<\s*\/\s*meme\s*>/gi, '').trim();
|
||||
reply = reply.replace(/\[.*?\]/g, '').trim();
|
||||
reply = reply.replace(/([^)]*)/g, '').trim();
|
||||
reply = reply.replace(/\([^)]*\)/g, '').trim();
|
||||
|
||||
if (reply) {
|
||||
addToyMessage('ai', reply);
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
hideToyTypingIndicator();
|
||||
console.error('[可乐] 玩具切换AI回复失败:', err);
|
||||
}
|
||||
}
|
||||
|
||||
// 绑定事件
|
||||
let toyEventsBound = false;
|
||||
function bindToyControlEvents() {
|
||||
@@ -216,6 +493,12 @@ function bindToyControlEvents() {
|
||||
document.getElementById('wechat-toy-control-buttons')?.addEventListener('click', (e) => {
|
||||
const btn = e.target.closest('.wechat-toy-btn');
|
||||
if (btn) {
|
||||
// 检查是否是媒体按钮(麦克风/摄像头)
|
||||
const media = btn.dataset.media;
|
||||
if (media) {
|
||||
onMediaToggle(media);
|
||||
return;
|
||||
}
|
||||
const mode = btn.dataset.mode;
|
||||
if (mode) {
|
||||
onButtonPress(mode, 'user');
|
||||
@@ -234,6 +517,99 @@ function bindToyControlEvents() {
|
||||
});
|
||||
}
|
||||
|
||||
// 麦克风/摄像头切换处理
|
||||
async function onMediaToggle(mediaType) {
|
||||
if (!toyControlState.isActive) return;
|
||||
|
||||
const isMic = mediaType === 'mic';
|
||||
const wasEnabled = isMic ? toyControlState.micEnabled : toyControlState.cameraEnabled;
|
||||
const nowEnabled = !wasEnabled;
|
||||
|
||||
// 更新状态
|
||||
if (isMic) {
|
||||
toyControlState.micEnabled = nowEnabled;
|
||||
} else {
|
||||
toyControlState.cameraEnabled = nowEnabled;
|
||||
}
|
||||
|
||||
// 更新按钮图标
|
||||
updateMediaButtonUI();
|
||||
|
||||
// 显示typing
|
||||
showToyTypingIndicator();
|
||||
|
||||
// 构建提示词
|
||||
const prompt = buildMediaTogglePrompt(mediaType, nowEnabled);
|
||||
|
||||
try {
|
||||
const response = await callToyAI(prompt);
|
||||
hideToyTypingIndicator();
|
||||
|
||||
if (response) {
|
||||
await processAIResponse(response);
|
||||
}
|
||||
} catch (err) {
|
||||
hideToyTypingIndicator();
|
||||
console.error('[可乐] 玩具控制AI回复失败:', err);
|
||||
}
|
||||
}
|
||||
|
||||
// 更新媒体按钮UI
|
||||
function updateMediaButtonUI() {
|
||||
const micBtn = document.querySelector('.wechat-toy-btn-media[data-media="mic"]');
|
||||
const cameraBtn = document.querySelector('.wechat-toy-btn-media[data-media="camera"]');
|
||||
|
||||
if (micBtn) {
|
||||
micBtn.innerHTML = toyControlState.micEnabled ? TOY_ICONS.micOn : TOY_ICONS.micOff;
|
||||
micBtn.classList.toggle('active', toyControlState.micEnabled);
|
||||
}
|
||||
if (cameraBtn) {
|
||||
cameraBtn.innerHTML = toyControlState.cameraEnabled ? TOY_ICONS.cameraOn : TOY_ICONS.cameraOff;
|
||||
cameraBtn.classList.toggle('active', toyControlState.cameraEnabled);
|
||||
}
|
||||
}
|
||||
|
||||
// 构建媒体切换提示词
|
||||
function buildMediaTogglePrompt(mediaType, isEnabled) {
|
||||
const isCharacterUsing = toyControlState.target === 'character';
|
||||
const isMic = mediaType === 'mic';
|
||||
const mediaName = isMic ? '麦克风' : '摄像头';
|
||||
const action = isEnabled ? '打开' : '关闭';
|
||||
|
||||
let prompt = `【${mediaName}${action}】\n`;
|
||||
|
||||
if (isCharacterUsing) {
|
||||
// 角色在用玩具
|
||||
if (isEnabled) {
|
||||
prompt += isMic
|
||||
? `用户打开了麦克风,现在可以听到用户的声音了。你正在使用玩具,听到用户的声音会让你更有感觉。请做出反应。`
|
||||
: `用户打开了摄像头,现在可以看到用户了。你正在使用玩具,看到用户会让你更害羞/更有感觉。请做出反应。`;
|
||||
} else {
|
||||
prompt += isMic
|
||||
? `用户关闭了麦克风,现在听不到用户的声音了。你可能会有点失落或者松一口气。请做出反应。`
|
||||
: `用户关闭了摄像头,现在看不到用户了。你可能会有点失落或者松一口气。请做出反应。`;
|
||||
}
|
||||
} else {
|
||||
// 用户在用玩具
|
||||
if (isEnabled) {
|
||||
prompt += isMic
|
||||
? `用户打开了麦克风,你现在可以听到用户的声音/喘息/呻吟了。请做出反应,可以调侃、撩拨或关心用户。`
|
||||
: `用户打开了摄像头,你现在可以看到用户使用玩具的样子了。请做出反应,可以调侃、撩拨或关心用户。`;
|
||||
} else {
|
||||
prompt += isMic
|
||||
? `用户关闭了麦克风,你现在听不到用户的声音了。请做出反应。`
|
||||
: `用户关闭了摄像头,你现在看不到用户了。请做出反应。`;
|
||||
}
|
||||
}
|
||||
|
||||
prompt += `\n\n【当前状态】
|
||||
- 麦克风:${toyControlState.micEnabled ? '已打开(可以听到声音)' : '已关闭'}
|
||||
- 摄像头:${toyControlState.cameraEnabled ? '已打开(可以看到画面)' : '已关闭'}
|
||||
- 当前模式:${toyControlState.currentMode ? (TOY_CONTROL_MODES[toyControlState.currentMode]?.name || '已暂停') : '未开始'}`;
|
||||
|
||||
return prompt;
|
||||
}
|
||||
|
||||
// 按钮点击处理
|
||||
async function onButtonPress(buttonId, pressedBy = 'user') {
|
||||
if (!toyControlState.isActive) return;
|
||||
@@ -345,6 +721,18 @@ function buildButtonPressPrompt(buttonId, buttonName, pressedBy) {
|
||||
3. 禁止使用[语音:xxx]、[照片:xxx]、[表情:xxx]等格式
|
||||
4. 直接输出角色说的话和感受`;
|
||||
|
||||
// 添加当前媒体状态信息
|
||||
const mediaStatus = [];
|
||||
if (toyControlState.micEnabled) {
|
||||
mediaStatus.push('麦克风已开启(可以听到对方的声音/喘息)');
|
||||
}
|
||||
if (toyControlState.cameraEnabled) {
|
||||
mediaStatus.push('摄像头已开启(可以看到对方)');
|
||||
}
|
||||
if (mediaStatus.length > 0) {
|
||||
prompt += `\n\n【当前连接状态】${mediaStatus.join(',')}`;
|
||||
}
|
||||
|
||||
return prompt;
|
||||
}
|
||||
|
||||
@@ -644,21 +1032,44 @@ function saveToySession() {
|
||||
const seconds = (durationSec % 60).toString().padStart(2, '0');
|
||||
const durationStr = `${minutes}:${seconds}`;
|
||||
|
||||
const session = {
|
||||
gift: {
|
||||
id: toyControlState.gift.giftId,
|
||||
name: toyControlState.gift.giftName,
|
||||
emoji: toyControlState.gift.giftEmoji
|
||||
},
|
||||
target: toyControlState.target,
|
||||
time: timeStr,
|
||||
timestamp: toyControlState.sessionStartTime || Date.now(),
|
||||
duration: durationStr,
|
||||
messages: toyControlState.messages.map(m => ({
|
||||
role: m.role,
|
||||
content: m.content
|
||||
}))
|
||||
};
|
||||
// 构建session记录
|
||||
let session;
|
||||
if (toyControlState.isMulti) {
|
||||
// 多玩具模式
|
||||
session = {
|
||||
isMulti: true,
|
||||
toys: toyControlState.toys.map(t => ({
|
||||
id: t.giftId,
|
||||
name: t.giftName,
|
||||
emoji: t.giftEmoji
|
||||
})),
|
||||
target: toyControlState.target,
|
||||
time: timeStr,
|
||||
timestamp: toyControlState.sessionStartTime || Date.now(),
|
||||
duration: durationStr,
|
||||
messages: toyControlState.messages.map(m => ({
|
||||
role: m.role,
|
||||
content: m.content
|
||||
}))
|
||||
};
|
||||
} else {
|
||||
// 单玩具模式
|
||||
session = {
|
||||
gift: {
|
||||
id: toyControlState.gift.giftId,
|
||||
name: toyControlState.gift.giftName,
|
||||
emoji: toyControlState.gift.giftEmoji
|
||||
},
|
||||
target: toyControlState.target,
|
||||
time: timeStr,
|
||||
timestamp: toyControlState.sessionStartTime || Date.now(),
|
||||
duration: durationStr,
|
||||
messages: toyControlState.messages.map(m => ({
|
||||
role: m.role,
|
||||
content: m.content
|
||||
}))
|
||||
};
|
||||
}
|
||||
|
||||
contact.toyHistory.push(session);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user