迁移AI小班长聊天脚本
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
export { escapeHtml, escapeHtmlWithLineBreaks } from "./chat-room/html.js";
|
||||
export { bindAppointmentAnnouncementControls, showAppointmentBanner } from "./chat-room/appointment-announcement.js";
|
||||
export { bindChatBanner } from "./chat-room/banner.js";
|
||||
export { bindChatBotControls, clearChatBotContext, sendToChatBot } from "./chat-room/chat-bot.js";
|
||||
export { bindGlobalDialogControls } from "./chat-room/dialog.js";
|
||||
export { bindDailySignInControls } from "./chat-room/daily-sign-in.js";
|
||||
export { applyFontSize, bindChatFontSizeControl, CHAT_FONT_SIZE_STORAGE_KEY, restoreChatFontSize } from "./chat-room/font-size.js";
|
||||
@@ -83,6 +84,7 @@ export { createMessageQueue } from "./chat-room/message-queue.js";
|
||||
import { escapeHtml, escapeHtmlWithLineBreaks } from "./chat-room/html.js";
|
||||
import { bindAppointmentAnnouncementControls, showAppointmentBanner } from "./chat-room/appointment-announcement.js";
|
||||
import { bindChatBanner } from "./chat-room/banner.js";
|
||||
import { bindChatBotControls, clearChatBotContext, sendToChatBot } from "./chat-room/chat-bot.js";
|
||||
import { bindGlobalDialogControls } from "./chat-room/dialog.js";
|
||||
import { bindDailySignInControls } from "./chat-room/daily-sign-in.js";
|
||||
import { applyFontSize, bindChatFontSizeControl, CHAT_FONT_SIZE_STORAGE_KEY, restoreChatFontSize } from "./chat-room/font-size.js";
|
||||
@@ -167,6 +169,9 @@ if (typeof window !== "undefined") {
|
||||
bindAppointmentAnnouncementControls,
|
||||
showAppointmentBanner,
|
||||
bindChatBanner,
|
||||
bindChatBotControls,
|
||||
clearChatBotContext,
|
||||
sendToChatBot,
|
||||
bindGlobalDialogControls,
|
||||
bindDailySignInControls,
|
||||
applyFontSize,
|
||||
@@ -265,6 +270,8 @@ if (typeof window !== "undefined") {
|
||||
window.scheduleRenderMobileUserList = scheduleRenderMobileUserList;
|
||||
window.switchMobileTab = switchMobileTab;
|
||||
window.switchTarget = switchTarget;
|
||||
window.clearChatBotContext = clearChatBotContext;
|
||||
window.sendToChatBot = sendToChatBot;
|
||||
window.runFeatureShortcut = runFeatureShortcut;
|
||||
window.runToolbarAction = runToolbarAction;
|
||||
window.openHolidayRunFromSystemMessage = openHolidayRunFromSystemMessage;
|
||||
@@ -284,6 +291,7 @@ if (typeof window !== "undefined") {
|
||||
|
||||
// 页面加载后立即注册事件委托,具体业务逻辑仍由各子模块负责。
|
||||
bindChatBanner();
|
||||
bindChatBotControls();
|
||||
bindAppointmentAnnouncementControls();
|
||||
bindGlobalDialogControls();
|
||||
bindDailySignInControls();
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
// 聊天室 AI 小班长交互模块,提供 sendToChatBot/clearChatBotContext 兼容入口。
|
||||
|
||||
import { escapeHtml } from "./html.js";
|
||||
|
||||
let chatBotSending = false;
|
||||
|
||||
/**
|
||||
* 读取页面 CSRF Token。
|
||||
*
|
||||
* @returns {string}
|
||||
*/
|
||||
function getCsrfToken() {
|
||||
return document.querySelector('meta[name="csrf-token"]')?.getAttribute("content") || "";
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断包厢窗口是否需要自动滚动到底部。
|
||||
*
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function shouldAutoScroll() {
|
||||
return window.isChatAutoScrollEnabled?.() ?? true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将系统提示追加到包厢窗口。
|
||||
*
|
||||
* @param {string} html
|
||||
* @returns {void}
|
||||
*/
|
||||
function appendPrivateSystemLine(html) {
|
||||
const messageBox = document.getElementById("chat-messages-container2");
|
||||
if (!messageBox) {
|
||||
return;
|
||||
}
|
||||
|
||||
const line = document.createElement("div");
|
||||
line.className = "msg-line";
|
||||
line.innerHTML = html;
|
||||
messageBox.appendChild(line);
|
||||
|
||||
if (shouldAutoScroll()) {
|
||||
messageBox.scrollTop = messageBox.scrollHeight;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将 AI 错误提示追加到包厢窗口。
|
||||
*
|
||||
* @param {string} text
|
||||
* @returns {void}
|
||||
*/
|
||||
function appendBotError(text) {
|
||||
appendPrivateSystemLine(`<span style="color: #dc2626;">🤖【AI小班长】${escapeHtml(text)}</span>`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送消息给 AI 机器人。
|
||||
*
|
||||
* @param {string} content
|
||||
* @param {boolean} [isSecret]
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
export async function sendToChatBot(content, isSecret = false) {
|
||||
if (chatBotSending) {
|
||||
window.chatDialog?.alert?.("AI 正在思考中,请稍候...", "提示", "#336699");
|
||||
return;
|
||||
}
|
||||
|
||||
chatBotSending = true;
|
||||
|
||||
try {
|
||||
const response = await fetch(window.chatContext.chatBotUrl, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"X-CSRF-TOKEN": getCsrfToken(),
|
||||
"Content-Type": "application/json",
|
||||
"Accept": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
message: content,
|
||||
room_id: window.chatContext.roomId,
|
||||
is_secret: isSecret ? 1 : 0,
|
||||
}),
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (!response.ok || data.status !== "success") {
|
||||
// AI 接口错误只写入包厢窗口,避免失败提示刷到公屏。
|
||||
appendBotError(data.message || "回复失败,请稍后重试");
|
||||
}
|
||||
} catch (error) {
|
||||
appendBotError("网络连接错误,请稍后重试");
|
||||
} finally {
|
||||
chatBotSending = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除与 AI 小助手的对话上下文。
|
||||
*
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
export async function clearChatBotContext() {
|
||||
try {
|
||||
const response = await fetch(window.chatContext.chatBotClearUrl, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"X-CSRF-TOKEN": getCsrfToken(),
|
||||
"Accept": "application/json",
|
||||
},
|
||||
});
|
||||
const data = await response.json();
|
||||
|
||||
appendPrivateSystemLine(`<span style="color: #16a34a;">🤖【系统】${escapeHtml(data.message || "对话已重置")}</span>`);
|
||||
} catch (error) {
|
||||
window.chatDialog?.alert?.(`清除失败:${error.message}`, "操作失败", "#cc4444");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 暴露 AI 小班长操作给存量发送消息逻辑。
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
export function bindChatBotControls() {
|
||||
if (typeof window === "undefined") {
|
||||
return;
|
||||
}
|
||||
|
||||
window.sendToChatBot = sendToChatBot;
|
||||
window.clearChatBotContext = clearChatBotContext;
|
||||
}
|
||||
@@ -1,87 +1,6 @@
|
||||
<script>
|
||||
// ── AI 聊天机器人 ──────────────────────────────────
|
||||
let chatBotSending = false;
|
||||
{{--
|
||||
文件功能:AI 小班长前端脚本占位
|
||||
|
||||
/**
|
||||
* 发送消息给 AI 机器人
|
||||
* 先在包厢窗口显示用户消息,再调用 API 获取回复
|
||||
*/
|
||||
async function sendToChatBot(content, isSecret = false) {
|
||||
if (chatBotSending) {
|
||||
window.chatDialog.alert('AI 正在思考中,请稍候...', '提示', '#336699');
|
||||
return;
|
||||
}
|
||||
chatBotSending = true;
|
||||
|
||||
/**
|
||||
* 将 AI 错误提示追加到包厢窗口,样式与正常 AI 回复保持一致。
|
||||
*
|
||||
* @param {string} text 错误提示文本
|
||||
*/
|
||||
function appendBotError(text) {
|
||||
const msgBox = document.getElementById('chat-messages-container2');
|
||||
if (!msgBox) return;
|
||||
const errDiv = document.createElement('div');
|
||||
errDiv.className = 'msg-line';
|
||||
errDiv.innerHTML = `<span style="color: #dc2626;">🤖【AI小班长】${text}</span>`;
|
||||
msgBox.appendChild(errDiv);
|
||||
if (typeof autoScroll !== 'undefined' && autoScroll) {
|
||||
msgBox.scrollTop = msgBox.scrollHeight;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const res = await fetch(window.chatContext.chatBotUrl, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute(
|
||||
'content'),
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
message: content,
|
||||
room_id: window.chatContext.roomId,
|
||||
is_secret: isSecret ? 1 : 0,
|
||||
})
|
||||
});
|
||||
|
||||
const data = await res.json();
|
||||
|
||||
if (!res.ok || data.status !== 'success') {
|
||||
// 接口返回的错误信息:仅显示在包厢窗口,不走公屏
|
||||
appendBotError(data.message || '回复失败,请稍后重试');
|
||||
}
|
||||
} catch (e) {
|
||||
// 网络层异常:同样只显示在包厢窗口
|
||||
appendBotError('网络连接错误,请稍后重试');
|
||||
}
|
||||
|
||||
chatBotSending = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除与 AI 小助手的对话上下文
|
||||
*/
|
||||
async function clearChatBotContext() {
|
||||
try {
|
||||
const res = await fetch(window.chatContext.chatBotClearUrl, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute(
|
||||
'content'),
|
||||
'Accept': 'application/json'
|
||||
}
|
||||
});
|
||||
const data = await res.json();
|
||||
|
||||
const sysDiv = document.createElement('div');
|
||||
sysDiv.className = 'msg-line';
|
||||
sysDiv.innerHTML = '<span style="color: #16a34a;">🤖【系统】' + (data.message || '对话已重置') + '</span>';
|
||||
container2.appendChild(sysDiv);
|
||||
if (autoScroll) container2.scrollTop = container2.scrollHeight;
|
||||
} catch (e) {
|
||||
window.chatDialog.alert('清除失败:' + e.message, '操作失败', '#cc4444');
|
||||
}
|
||||
}
|
||||
</script>
|
||||
sendToChatBot 与 clearChatBotContext 已迁移到 resources/js/chat-room/chat-bot.js,
|
||||
由 resources/js/chat-room.js 统一通过 Vite 加载并暴露兼容全局函数。
|
||||
--}}
|
||||
|
||||
@@ -47,6 +47,8 @@
|
||||
// 暂时暴露给已迁移的手机抽屉 Vite 模块读取,后续在线名单整体迁移后可移除。
|
||||
window.onlineUsers = onlineUsers;
|
||||
let autoScroll = true;
|
||||
// 给已迁移到 Vite 的模块只读判断自动滚动状态,避免直接依赖 Blade 脚本作用域。
|
||||
window.isChatAutoScrollEnabled = () => autoScroll;
|
||||
let userBadgeRotationTick = 0;
|
||||
let userListRenderTimer = null;
|
||||
let _maxMsgId = 0; // 记录当前收到的最大消息 ID
|
||||
|
||||
Reference in New Issue
Block a user