152 lines
6.6 KiB
JavaScript
152 lines
6.6 KiB
JavaScript
"use strict";
|
|
const fs = require("fs");
|
|
|
|
Editor.Panel.extend({
|
|
style: fs.readFileSync(Editor.url("packages://mcp-bridge/panel/index.html"), "utf-8"),
|
|
template: fs.readFileSync(Editor.url("packages://mcp-bridge/panel/index.html"), "utf-8"),
|
|
|
|
messages: {
|
|
"mcp-bridge:on-log"(event, log) { this.renderLog(log); },
|
|
"mcp-bridge:state-changed"(event, config) { this.updateUI(config.active); }
|
|
},
|
|
|
|
ready() {
|
|
const root = this.shadowRoot;
|
|
// 获取元素
|
|
const els = {
|
|
port: root.querySelector("#portInput"),
|
|
btnToggle: root.querySelector("#btnToggle"),
|
|
autoStart: root.querySelector("#autoStartCheck"),
|
|
logView: root.querySelector("#logConsole"),
|
|
tabMain: root.querySelector("#tabMain"),
|
|
tabTest: root.querySelector("#tabTest"),
|
|
panelMain: root.querySelector("#panelMain"),
|
|
panelTest: root.querySelector("#panelTest"),
|
|
toolName: root.querySelector("#toolName"),
|
|
toolParams: root.querySelector("#toolParams"),
|
|
toolsList: root.querySelector("#toolsList"),
|
|
testBtn: root.querySelector("#testBtn"),
|
|
listBtn: root.querySelector("#listToolsBtn"),
|
|
clearBtn: root.querySelector("#clearTestBtn"),
|
|
result: root.querySelector("#resultContent"),
|
|
left: root.querySelector("#testLeftPanel"),
|
|
resizer: root.querySelector("#testResizer")
|
|
};
|
|
|
|
// 1. 初始化状态
|
|
Editor.Ipc.sendToMain("mcp-bridge:get-server-state", (err, data) => {
|
|
if (data) {
|
|
els.port.value = data.config.port;
|
|
els.autoStart.value = data.autoStart;
|
|
this.updateUI(data.config.active);
|
|
els.logView.innerHTML = "";
|
|
data.logs.forEach(l => this.renderLog(l));
|
|
}
|
|
});
|
|
|
|
// 2. 标签切换
|
|
els.tabMain.addEventListener("confirm", () => {
|
|
els.tabMain.classList.add("active"); els.tabTest.classList.remove("active");
|
|
els.panelMain.classList.add("active"); els.panelTest.classList.remove("active");
|
|
});
|
|
els.tabTest.addEventListener("confirm", () => {
|
|
els.tabTest.classList.add("active"); els.tabMain.classList.remove("active");
|
|
els.panelTest.classList.add("active"); els.panelMain.classList.remove("active");
|
|
this.fetchTools(els);
|
|
});
|
|
|
|
// 3. 基础功能
|
|
els.btnToggle.addEventListener("confirm", () => {
|
|
Editor.Ipc.sendToMain("mcp-bridge:toggle-server", parseInt(els.port.value));
|
|
});
|
|
root.querySelector("#btnClear").addEventListener("confirm", () => {
|
|
els.logView.innerHTML = ""; Editor.Ipc.sendToMain("mcp-bridge:clear-logs");
|
|
});
|
|
root.querySelector("#btnCopy").addEventListener("confirm", () => {
|
|
require("electron").clipboard.writeText(els.logView.innerText);
|
|
Editor.success("Logs Copied");
|
|
});
|
|
els.autoStart.addEventListener("change", (e) => {
|
|
Editor.Ipc.sendToMain("mcp-bridge:set-auto-start", e.target.value);
|
|
});
|
|
|
|
// 4. 测试页功能
|
|
els.listBtn.addEventListener("confirm", () => this.fetchTools(els));
|
|
els.clearBtn.addEventListener("confirm", () => { els.result.value = ""; });
|
|
els.testBtn.addEventListener("confirm", () => this.runTest(els));
|
|
|
|
// 5. 【修复】拖拽逻辑
|
|
if (els.resizer && els.left) {
|
|
els.resizer.addEventListener('mousedown', (e) => {
|
|
e.preventDefault();
|
|
const startX = e.clientX;
|
|
const startW = els.left.offsetWidth;
|
|
const onMove = (ev) => { els.left.style.width = (startW + (ev.clientX - startX)) + "px"; };
|
|
const onUp = () => {
|
|
document.removeEventListener('mousemove', onMove);
|
|
document.removeEventListener('mouseup', onUp);
|
|
document.body.style.cursor = 'default';
|
|
};
|
|
document.addEventListener('mousemove', onMove);
|
|
document.addEventListener('mouseup', onUp);
|
|
document.body.style.cursor = 'col-resize';
|
|
});
|
|
}
|
|
},
|
|
|
|
fetchTools(els) {
|
|
const url = `http://localhost:${els.port.value}/list-tools`;
|
|
fetch(url).then(r => r.json()).then(data => {
|
|
els.toolsList.innerHTML = "";
|
|
data.tools.forEach(t => {
|
|
const item = document.createElement('div');
|
|
item.className = 'tool-item';
|
|
item.textContent = t.name;
|
|
item.onclick = () => {
|
|
els.toolName.value = t.name;
|
|
els.toolParams.value = JSON.stringify(this.getExample(t.name), null, 2);
|
|
};
|
|
els.toolsList.appendChild(item);
|
|
});
|
|
els.result.value = `Loaded ${data.tools.length} tools.`;
|
|
}).catch(e => { els.result.value = "Error: " + e.message; });
|
|
},
|
|
|
|
runTest(els) {
|
|
const url = `http://localhost:${els.port.value}/call-tool`;
|
|
const body = { name: els.toolName.value, arguments: JSON.parse(els.toolParams.value || "{}") };
|
|
els.result.value = "Testing...";
|
|
fetch(url, { method: 'POST', body: JSON.stringify(body) })
|
|
.then(r => r.json())
|
|
.then(d => { els.result.value = JSON.stringify(d, null, 2); })
|
|
.catch(e => { els.result.value = "Error: " + e.message; });
|
|
},
|
|
|
|
getExample(name) {
|
|
const examples = {
|
|
"set_node_name": { "id": "UUID", "newName": "Hello" },
|
|
"update_node_transform": { "id": "UUID", "x": 0, "y": 0, "color": "#FF0000" },
|
|
"create_node": { "name": "Node", "type": "sprite", "parentId": "" },
|
|
"open_scene": { "url": "db://assets/Scene.fire" }
|
|
};
|
|
return examples[name] || {};
|
|
},
|
|
|
|
renderLog(log) {
|
|
const view = this.shadowRoot.querySelector("#logConsole");
|
|
if (!view) return;
|
|
const atBottom = view.scrollHeight - view.scrollTop <= view.clientHeight + 50;
|
|
const el = document.createElement("div");
|
|
el.className = `log-item ${log.type}`;
|
|
el.innerHTML = `<span class="time">${log.time}</span><span class="msg">${log.content}</span>`;
|
|
view.appendChild(el);
|
|
if (atBottom) view.scrollTop = view.scrollHeight;
|
|
},
|
|
|
|
updateUI(active) {
|
|
const btn = this.shadowRoot.querySelector("#btnToggle");
|
|
if (!btn) return;
|
|
btn.innerText = active ? "Stop" : "Start";
|
|
btn.style.backgroundColor = active ? "#aa4444" : "#44aa44";
|
|
}
|
|
}); |