GameServerManager/server/data/plugins/example-plugin/index.html
2025-07-12 11:09:14 +08:00

1512 lines
No EOL
63 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>示例插件 - GSM3</title>
<script src="gsm3-api.js"></script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
min-height: 100vh;
padding: 20px;
}
.container {
max-width: 1200px;
margin: 0 auto;
}
.header {
text-align: center;
margin-bottom: 40px;
}
.header h1 {
font-size: 3rem;
margin-bottom: 10px;
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3);
background: linear-gradient(45deg, #ffd700, #ffed4e);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.header p {
font-size: 1.2rem;
opacity: 0.9;
}
.cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 30px;
margin-bottom: 40px;
}
.card {
background: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(10px);
border-radius: 20px;
padding: 30px;
border: 1px solid rgba(255, 255, 255, 0.2);
transition: all 0.3s ease;
position: relative;
overflow: hidden;
}
.card::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 4px;
background: linear-gradient(90deg, #ffd700, #ffed4e, #ffd700);
background-size: 200% 100%;
animation: shimmer 2s infinite;
}
@keyframes shimmer {
0% { background-position: -200% 0; }
100% { background-position: 200% 0; }
}
.card:hover {
transform: translateY(-10px);
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.2);
}
.card h3 {
font-size: 1.5rem;
margin-bottom: 15px;
color: #ffd700;
}
.card p {
line-height: 1.6;
opacity: 0.9;
}
.features {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 20px;
margin-bottom: 40px;
}
.feature {
background: rgba(255, 255, 255, 0.05);
padding: 20px;
border-radius: 15px;
text-align: center;
border: 1px solid rgba(255, 255, 255, 0.1);
transition: all 0.3s ease;
}
.feature:hover {
background: rgba(255, 255, 255, 0.1);
transform: scale(1.05);
}
.feature-icon {
font-size: 2.5rem;
margin-bottom: 15px;
display: block;
}
.feature h4 {
margin-bottom: 10px;
color: #ffd700;
}
.demo-section {
background: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(10px);
border-radius: 20px;
padding: 30px;
border: 1px solid rgba(255, 255, 255, 0.2);
margin-bottom: 30px;
}
.demo-section h3 {
color: #ffd700;
margin-bottom: 20px;
font-size: 1.5rem;
}
.button-group {
display: flex;
gap: 15px;
flex-wrap: wrap;
margin-bottom: 20px;
}
.btn {
padding: 12px 24px;
border: none;
border-radius: 25px;
background: linear-gradient(45deg, #667eea, #764ba2);
color: white;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
text-decoration: none;
display: inline-block;
}
.btn:hover {
transform: translateY(-2px);
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2);
background: linear-gradient(45deg, #764ba2, #667eea);
}
.btn-success {
background: linear-gradient(45deg, #56ab2f, #a8e6cf);
}
.btn-warning {
background: linear-gradient(45deg, #f093fb, #f5576c);
}
.btn-info {
background: linear-gradient(45deg, #4facfe, #00f2fe);
}
.status-display {
background: rgba(0, 0, 0, 0.2);
padding: 15px;
border-radius: 10px;
margin-top: 15px;
font-family: 'Courier New', monospace;
}
.footer {
text-align: center;
padding: 20px;
opacity: 0.7;
border-top: 1px solid rgba(255, 255, 255, 0.1);
}
.pulse {
animation: pulse 2s infinite;
}
@keyframes pulse {
0% { opacity: 1; }
50% { opacity: 0.7; }
100% { opacity: 1; }
}
.loading {
display: inline-block;
width: 20px;
height: 20px;
border: 3px solid rgba(255, 255, 255, 0.3);
border-radius: 50%;
border-top-color: #ffd700;
animation: spin 1s ease-in-out infinite;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
@media (max-width: 768px) {
.header h1 {
font-size: 2rem;
}
.cards {
grid-template-columns: 1fr;
}
.button-group {
flex-direction: column;
}
}
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>🧩 示例插件</h1>
<p>欢迎使用 GSM3 插件系统演示</p>
</div>
<!-- 开发文档说明 -->
<div class="demo-section">
<h3>📚 插件开发文档</h3>
<p>这是一个完整的插件开发示例,展示了如何使用 GSM3 插件系统创建功能丰富的 Web 界面。</p>
<div class="cards" style="margin-bottom: 20px;">
<div class="card">
<h3>📖 开发指南</h3>
<p>查看完整的插件开发文档了解插件结构、API使用方法和最佳实践。</p>
<div style="margin-top: 15px;">
<a href="../插件开发文档.md" target="_blank" class="btn btn-info">查看开发文档</a>
</div>
</div>
<div class="card">
<h3>🔧 快速开始</h3>
<p>复制这个示例插件作为模板,修改配置文件和界面即可创建您自己的插件。</p>
<div style="margin-top: 15px;">
<button class="btn btn-success" onclick="showQuickStart()">快速开始指南</button>
</div>
</div>
<div class="card">
<h3>🎯 核心功能</h3>
<p>本示例展示了系统信息、实例管理、文件操作、终端管理等核心API的使用方法。</p>
<div style="margin-top: 15px;">
<button class="btn btn-warning" onclick="showApiOverview()">API概览</button>
</div>
</div>
</div>
<!-- 快速开始指南 -->
<div id="quickStartGuide" style="display: none; margin-top: 20px; padding: 20px; background: rgba(255,255,255,0.1); border-radius: 15px;">
<h4>🚀 快速开始指南</h4>
<ol style="line-height: 1.8; padding-left: 20px;">
<li>复制 <code>example-plugin</code> 目录并重命名为您的插件名称</li>
<li>修改 <code>plugin.json</code> 文件中的插件信息</li>
<li>编辑 <code>index.html</code> 文件,创建您的界面</li>
<li>使用 <code>gsm3-api.js</code> 调用系统API</li>
<li>重新加载插件页面查看效果</li>
</ol>
<div style="margin-top: 15px;">
<button class="btn" onclick="hideQuickStart()">关闭</button>
</div>
</div>
<!-- API概览 -->
<div id="apiOverview" style="display: none; margin-top: 20px; padding: 20px; background: rgba(255,255,255,0.1); border-radius: 15px;">
<h4>🎯 主要API功能</h4>
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px; margin-top: 15px;">
<div style="background: rgba(255,255,255,0.1); padding: 15px; border-radius: 10px;">
<h5 style="color: #ffd700; margin-bottom: 10px;">系统信息</h5>
<ul style="font-size: 0.9rem; line-height: 1.6;">
<li>getSystemStatus()</li>
<li>getSystemInfo()</li>
<li>healthCheck()</li>
</ul>
</div>
<div style="background: rgba(255,255,255,0.1); padding: 15px; border-radius: 10px;">
<h5 style="color: #ffd700; margin-bottom: 10px;">实例管理</h5>
<ul style="font-size: 0.9rem; line-height: 1.6;">
<li>getInstances()</li>
<li>createInstance()</li>
<li>startInstance()</li>
<li>stopInstance()</li>
</ul>
</div>
<div style="background: rgba(255,255,255,0.1); padding: 15px; border-radius: 10px;">
<h5 style="color: #ffd700; margin-bottom: 10px;">文件操作</h5>
<ul style="font-size: 0.9rem; line-height: 1.6;">
<li>readFile()</li>
<li>writeFile()</li>
<li>listDirectory()</li>
<li>createDirectory()</li>
</ul>
</div>
<div style="background: rgba(255,255,255,0.1); padding: 15px; border-radius: 10px;">
<h5 style="color: #ffd700; margin-bottom: 10px;">终端管理</h5>
<ul style="font-size: 0.9rem; line-height: 1.6;">
<li>getTerminals()</li>
<li>getTerminalStats()</li>
<li>getTerminalSessions()</li>
<li>updateTerminalSessionName()</li>
</ul>
</div>
</div>
<div style="margin-top: 15px;">
<button class="btn" onclick="hideApiOverview()">关闭</button>
</div>
</div>
</div>
<div class="cards">
<div class="card">
<h3>🚀 插件功能</h3>
<p>这个示例插件展示了 GSM3 插件系统的强大功能。您可以创建自定义的 Web 界面,集成各种工具和服务,扩展面板的功能。</p>
</div>
<div class="card">
<h3>🎨 自定义界面</h3>
<p>使用 HTML、CSS 和 JavaScript 创建美观的用户界面。支持响应式设计,适配各种设备屏幕。</p>
</div>
<div class="card">
<h3>🔧 易于开发</h3>
<p>简单的文件结构,只需要在插件目录中放置您的文件即可。支持热重载,开发体验流畅。</p>
</div>
</div>
<div class="features">
<div class="feature">
<span class="feature-icon"></span>
<h4>高性能</h4>
<p>优化的加载速度</p>
</div>
<div class="feature">
<span class="feature-icon">🔒</span>
<h4>安全可靠</h4>
<p>沙箱环境运行</p>
</div>
<div class="feature">
<span class="feature-icon">🎯</span>
<h4>易于使用</h4>
<p>直观的操作界面</p>
</div>
<div class="feature">
<span class="feature-icon">🔄</span>
<h4>实时更新</h4>
<p>动态内容刷新</p>
</div>
</div>
<div class="demo-section">
<h3>🎮 交互演示</h3>
<p>点击下面的按钮体验插件的交互功能:</p>
<div class="button-group">
<button class="btn" onclick="showMessage('info', '这是一个信息提示!')">信息提示</button>
<button class="btn btn-success" onclick="showMessage('success', '操作成功完成!')">成功消息</button>
<button class="btn btn-warning" onclick="showMessage('warning', '这是一个警告消息!')">警告消息</button>
<button class="btn btn-info" onclick="simulateLoading()">模拟加载</button>
</div>
<div id="statusDisplay" class="status-display">
<strong>状态:</strong> 就绪 | <strong>时间:</strong> <span id="currentTime"></span>
</div>
</div>
<div class="demo-section">
<h3>🔌 API调用演示</h3>
<p>体验插件调用主面板API的功能</p>
<div class="button-group">
<button class="btn" onclick="getSystemStatus()">获取系统状态</button>
<button class="btn btn-success" onclick="getInstances()">获取实例列表</button>
<button class="btn btn-warning" onclick="getSystemInfo()">获取系统信息</button>
<button class="btn btn-info" onclick="getApiVersion()">获取API版本</button>
</div>
</div>
<div class="demo-section">
<h3>📁 文件操作演示</h3>
<p>体验插件文件操作API的功能</p>
<div class="button-group">
<button class="btn" onclick="listRootDirectory()">列出根目录</button>
<button class="btn btn-success" onclick="createTestFile()">创建测试文件</button>
<button class="btn btn-warning" onclick="readTestFile()">读取测试文件</button>
<button class="btn btn-info" onclick="deleteTestFile()">删除测试文件</button>
</div>
<div class="button-group">
<button class="btn" onclick="createTestDirectory()">创建测试目录</button>
<button class="btn btn-success" onclick="copyTestFile()">复制文件</button>
<button class="btn btn-warning" onclick="moveTestFile()">移动文件</button>
<button class="btn btn-info" onclick="searchFiles()">搜索文件</button>
</div>
<div class="button-group">
<input type="text" id="filePathInput" placeholder="输入文件路径" value="test.txt" style="padding: 12px; border-radius: 25px; border: 1px solid rgba(255,255,255,0.3); background: rgba(255,255,255,0.1); color: white; margin-right: 10px;">
<button class="btn" onclick="checkFileExists()">检查文件是否存在</button>
<button class="btn btn-info" onclick="getFileInfo()">获取文件信息</button>
</div>
<div id="apiResult" class="status-display" style="max-height: 300px; overflow-y: auto; white-space: pre-wrap; font-family: 'Courier New', monospace;">
<strong>API调用结果:</strong> 点击上方按钮查看API响应
</div>
</div>
<div class="demo-section">
<h3>🖥️ 实例管理演示</h3>
<p>体验插件实例管理API的功能</p>
<div class="button-group">
<button class="btn" onclick="getInstances()">获取实例列表</button>
<button class="btn btn-success" onclick="getMarketInstances()">获取市场实例</button>
<button class="btn btn-warning" onclick="showCreateInstanceForm()">创建实例</button>
<button class="btn btn-info" onclick="getInstanceDetails()">获取实例详情</button>
</div>
<div class="button-group">
<input type="text" id="instanceIdInput" placeholder="输入实例ID" value="" style="padding: 12px; border-radius: 25px; border: 1px solid rgba(255,255,255,0.3); background: rgba(255,255,255,0.1); color: white; margin-right: 10px;">
<button class="btn" onclick="startInstance()">启动实例</button>
<button class="btn btn-warning" onclick="stopInstance()">停止实例</button>
<button class="btn btn-info" onclick="restartInstance()">重启实例</button>
<button class="btn btn-danger" onclick="deleteInstance()">删除实例</button>
</div>
<!-- 创建实例表单 -->
<div id="createInstanceForm" style="display: none; margin-top: 20px; padding: 20px; background: rgba(255,255,255,0.1); border-radius: 15px;">
<h4>创建新实例</h4>
<div style="margin-bottom: 15px;">
<input type="text" id="instanceName" placeholder="实例名称" style="width: 100%; padding: 12px; border-radius: 8px; border: 1px solid rgba(255,255,255,0.3); background: rgba(255,255,255,0.1); color: white; margin-bottom: 10px;">
</div>
<div style="margin-bottom: 15px;">
<input type="text" id="instanceDescription" placeholder="实例描述" style="width: 100%; padding: 12px; border-radius: 8px; border: 1px solid rgba(255,255,255,0.3); background: rgba(255,255,255,0.1); color: white; margin-bottom: 10px;">
</div>
<div style="margin-bottom: 15px;">
<input type="text" id="instanceWorkingDir" placeholder="工作目录" style="width: 100%; padding: 12px; border-radius: 8px; border: 1px solid rgba(255,255,255,0.3); background: rgba(255,255,255,0.1); color: white; margin-bottom: 10px;">
</div>
<div style="margin-bottom: 15px;">
<input type="text" id="instanceStartCommand" placeholder="启动命令" style="width: 100%; padding: 12px; border-radius: 8px; border: 1px solid rgba(255,255,255,0.3); background: rgba(255,255,255,0.1); color: white; margin-bottom: 10px;">
</div>
<div style="margin-bottom: 15px;">
<select id="instanceStopCommand" style="width: 100%; padding: 12px; border-radius: 8px; border: 1px solid rgba(255,255,255,0.3); background: rgba(255,255,255,0.1); color: white; margin-bottom: 10px;">
<option value="ctrl+c">ctrl+c</option>
<option value="stop">stop</option>
<option value="exit">exit</option>
</select>
</div>
<div style="margin-bottom: 15px;">
<label style="color: white; display: flex; align-items: center;">
<input type="checkbox" id="instanceAutoStart" style="margin-right: 10px;">
自动启动
</label>
</div>
<div class="button-group">
<button class="btn btn-success" onclick="createInstance()">创建实例</button>
<button class="btn" onclick="hideCreateInstanceForm()">取消</button>
</div>
</div>
</div>
<div class="demo-section">
<h3>💻 终端管理演示</h3>
<p>体验插件终端管理API的功能</p>
<div class="button-group">
<button class="btn" onclick="getTerminalStats()">获取终端统计</button>
<button class="btn btn-success" onclick="getTerminalSessions()">获取终端会话</button>
<button class="btn btn-warning" onclick="getActiveTerminalProcesses()">获取活跃进程</button>
<button class="btn btn-info" onclick="getDefaultShell()">获取默认Shell</button>
</div>
<div class="button-group">
<button class="btn" onclick="getTerminalThemes()">获取终端主题</button>
<button class="btn btn-success" onclick="getTerminalFonts()">获取终端字体</button>
<button class="btn btn-warning" onclick="validateTerminalConfig()">验证终端配置</button>
<button class="btn btn-info" onclick="testTerminalConnection()">测试终端连接</button>
</div>
<div class="button-group">
<input type="text" id="sessionIdInput" placeholder="输入会话ID" value="session-001" style="padding: 12px; border-radius: 25px; border: 1px solid rgba(255,255,255,0.3); background: rgba(255,255,255,0.1); color: white; margin-right: 10px;">
<input type="text" id="sessionNameInput" placeholder="输入新会话名称" value="新会话名称" style="padding: 12px; border-radius: 25px; border: 1px solid rgba(255,255,255,0.3); background: rgba(255,255,255,0.1); color: white; margin-right: 10px;">
<button class="btn" onclick="updateTerminalSessionName()">更新会话名称</button>
</div>
</div>
<div class="demo-section">
<h3>📊 系统信息</h3>
<div id="systemInfo">
<p><strong>插件名称:</strong> 示例插件</p>
<p><strong>版本:</strong> 1.0.0</p>
<p><strong>作者:</strong> GSM3团队</p>
<p><strong>加载时间:</strong> <span id="loadTime"></span></p>
<p><strong>浏览器:</strong> <span id="browserInfo"></span></p>
</div>
</div>
<div class="footer">
<p>© 2024 GSM3 插件系统 | 由 GSM3 团队开发</p>
</div>
</div>
<script>
// 页面加载完成时间
const loadTime = new Date().toLocaleString()
document.getElementById('loadTime').textContent = loadTime
// 浏览器信息
const browserInfo = navigator.userAgent.split(' ').slice(-2).join(' ')
document.getElementById('browserInfo').textContent = browserInfo
// 实时时间更新
function updateTime() {
const now = new Date().toLocaleTimeString()
document.getElementById('currentTime').textContent = now
}
updateTime()
setInterval(updateTime, 1000)
// 显示消息
function showMessage(type, message) {
const statusDisplay = document.getElementById('statusDisplay')
const colors = {
info: '#4facfe',
success: '#56ab2f',
warning: '#f5576c',
error: '#ff6b6b'
}
statusDisplay.style.borderLeft = `4px solid ${colors[type]}`
statusDisplay.innerHTML = `
<strong>状态:</strong> ${message} | <strong>时间:</strong> <span id="currentTime">${new Date().toLocaleTimeString()}</span>
`
// 添加脉冲效果
statusDisplay.classList.add('pulse')
setTimeout(() => {
statusDisplay.classList.remove('pulse')
}, 2000)
}
// 模拟加载
function simulateLoading() {
const statusDisplay = document.getElementById('statusDisplay')
statusDisplay.innerHTML = `
<strong>状态:</strong> <span class="loading"></span> 正在加载... | <strong>时间:</strong> ${new Date().toLocaleTimeString()}
`
setTimeout(() => {
showMessage('success', '加载完成!')
}, 3000)
}
// 添加一些动画效果
document.addEventListener('DOMContentLoaded', function() {
const cards = document.querySelectorAll('.card')
cards.forEach((card, index) => {
card.style.animationDelay = `${index * 0.1}s`
card.style.animation = 'fadeInUp 0.6s ease forwards'
})
})
// CSS动画定义
const style = document.createElement('style')
style.textContent = `
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(30px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
`
document.head.appendChild(style)
// ==================== API调用演示函数 ====================
async function getSystemStatus() {
try {
if (!window.gsm3) {
throw new Error('GSM3 API对象未找到')
}
showApiLoading('正在初始化API...')
await window.gsm3.initialize()
showApiLoading('正在获取系统状态...')
const result = await window.gsm3.getSystemStatus()
showApiResult('系统状态', result)
if (window.gsm3.showNotification) {
window.gsm3.showNotification('success', '系统状态获取成功')
}
} catch (error) {
showApiError('获取系统状态失败', error)
if (window.gsm3 && window.gsm3.showNotification) {
window.gsm3.showNotification('error', '获取系统状态失败: ' + error.message)
}
}
}
async function getInstances() {
try {
if (!window.gsm3) {
throw new Error('GSM3 API对象未找到')
}
showApiLoading('正在初始化API...')
await window.gsm3.initialize()
showApiLoading('正在获取实例列表...')
const result = await window.gsm3.getInstances()
showApiResult('实例列表', result)
if (window.gsm3.showNotification) {
window.gsm3.showNotification('success', '实例列表获取成功')
}
} catch (error) {
showApiError('获取实例列表失败', error)
if (window.gsm3 && window.gsm3.showNotification) {
window.gsm3.showNotification('error', '获取实例列表失败: ' + error.message)
}
}
}
async function getSystemInfo() {
try {
if (!window.gsm3) {
throw new Error('GSM3 API对象未找到')
}
showApiLoading('正在初始化API...')
await window.gsm3.initialize()
showApiLoading('正在获取系统信息...')
const result = await window.gsm3.getSystemInfo()
showApiResult('系统信息', result)
if (window.gsm3.showNotification) {
window.gsm3.showNotification('success', '系统信息获取成功')
}
} catch (error) {
showApiError('获取系统信息失败', error)
if (window.gsm3 && window.gsm3.showNotification) {
window.gsm3.showNotification('error', '获取系统信息失败: ' + error.message)
}
}
}
async function getApiVersion() {
try {
if (!window.gsm3) {
throw new Error('GSM3 API对象未找到')
}
showApiLoading('正在初始化API...')
await window.gsm3.initialize()
showApiLoading('正在获取API版本...')
const result = await window.gsm3.getVersion()
showApiResult('API版本', result)
if (window.gsm3.showNotification) {
window.gsm3.showNotification('info', 'API版本信息获取成功')
}
} catch (error) {
showApiError('获取API版本失败', error)
if (window.gsm3 && window.gsm3.showNotification) {
window.gsm3.showNotification('error', '获取API版本失败: ' + error.message)
}
}
}
function showApiLoading(message) {
const apiResult = document.getElementById('apiResult')
apiResult.innerHTML = `<strong>API调用结果:</strong> <span class="loading"></span> ${message}`
}
function showApiResult(title, result) {
const apiResult = document.getElementById('apiResult')
apiResult.innerHTML = `<strong>API调用结果 - ${title}:</strong>\n${JSON.stringify(result, null, 2)}`
}
function showApiError(title, error) {
const apiResult = document.getElementById('apiResult')
apiResult.innerHTML = `<strong>API调用错误 - ${title}:</strong>\n${error.message || error}`
apiResult.style.borderLeft = '4px solid #ff6b6b'
}
// ==================== 文件操作函数 ====================
// 列出根目录
async function listRootDirectory() {
try {
if (!window.gsm3) {
throw new Error('GSM3 API对象未找到')
}
showApiLoading('正在初始化API...')
await window.gsm3.initialize()
showApiLoading('正在列出根目录...')
const result = await window.gsm3.listDirectory()
showApiResult('根目录内容', result)
if (window.gsm3.showNotification) {
window.gsm3.showNotification('success', '目录列表获取成功')
}
} catch (error) {
showApiError('列出目录失败', error)
if (window.gsm3 && window.gsm3.showNotification) {
window.gsm3.showNotification('error', '列出目录失败: ' + error.message)
}
}
}
// 创建测试文件
async function createTestFile() {
try {
if (!window.gsm3) {
throw new Error('GSM3 API对象未找到')
}
showApiLoading('正在初始化API...')
await window.gsm3.initialize()
showApiLoading('正在创建测试文件...')
const content = `这是一个测试文件\n创建时间: ${new Date().toLocaleString()}\n随机数: ${Math.random()}`
const result = await window.gsm3.writeFile('test.txt', content)
showApiResult('创建测试文件', result)
if (window.gsm3.showNotification) {
window.gsm3.showNotification('success', '测试文件创建成功')
}
} catch (error) {
showApiError('创建文件失败', error)
if (window.gsm3 && window.gsm3.showNotification) {
window.gsm3.showNotification('error', '创建文件失败: ' + error.message)
}
}
}
// 读取测试文件
async function readTestFile() {
try {
if (!window.gsm3) {
throw new Error('GSM3 API对象未找到')
}
showApiLoading('正在初始化API...')
await window.gsm3.initialize()
showApiLoading('正在读取测试文件...')
const result = await window.gsm3.readFile('test.txt')
showApiResult('读取测试文件', result)
if (window.gsm3.showNotification) {
window.gsm3.showNotification('success', '文件读取成功')
}
} catch (error) {
showApiError('读取文件失败', error)
if (window.gsm3 && window.gsm3.showNotification) {
window.gsm3.showNotification('error', '读取文件失败: ' + error.message)
}
}
}
// 删除测试文件
async function deleteTestFile() {
try {
if (!window.gsm3) {
throw new Error('GSM3 API对象未找到')
}
showApiLoading('正在初始化API...')
await window.gsm3.initialize()
showApiLoading('正在删除测试文件...')
const result = await window.gsm3.deleteFile('test.txt')
showApiResult('删除测试文件', result)
if (window.gsm3.showNotification) {
window.gsm3.showNotification('success', '文件删除成功')
}
} catch (error) {
showApiError('删除文件失败', error)
if (window.gsm3 && window.gsm3.showNotification) {
window.gsm3.showNotification('error', '删除文件失败: ' + error.message)
}
}
}
// 创建测试目录
async function createTestDirectory() {
try {
if (!window.gsm3) {
throw new Error('GSM3 API对象未找到')
}
showApiLoading('正在初始化API...')
await window.gsm3.initialize()
showApiLoading('正在创建测试目录...')
const result = await window.gsm3.createDirectory('test-dir')
showApiResult('创建测试目录', result)
if (window.gsm3.showNotification) {
window.gsm3.showNotification('success', '目录创建成功')
}
} catch (error) {
showApiError('创建目录失败', error)
if (window.gsm3 && window.gsm3.showNotification) {
window.gsm3.showNotification('error', '创建目录失败: ' + error.message)
}
}
}
// 复制文件
async function copyTestFile() {
try {
if (!window.gsm3) {
throw new Error('GSM3 API对象未找到')
}
showApiLoading('正在初始化API...')
await window.gsm3.initialize()
showApiLoading('正在检查源文件...')
const exists = await window.gsm3.exists('test.txt')
if (!exists.exists) {
showApiError('复制文件失败', new Error('源文件 test.txt 不存在,请先创建测试文件'))
return
}
showApiLoading('正在复制文件...')
const result = await window.gsm3.copy('test.txt', 'test-copy.txt')
showApiResult('复制文件', result)
if (window.gsm3.showNotification) {
window.gsm3.showNotification('success', '文件复制成功')
}
} catch (error) {
showApiError('复制文件失败', error)
if (window.gsm3 && window.gsm3.showNotification) {
window.gsm3.showNotification('error', '复制文件失败: ' + error.message)
}
}
}
// 移动文件
async function moveTestFile() {
try {
if (!window.gsm3) {
throw new Error('GSM3 API对象未找到')
}
showApiLoading('正在初始化API...')
await window.gsm3.initialize()
showApiLoading('正在检查源文件...')
const exists = await window.gsm3.exists('test-copy.txt')
if (!exists.exists) {
showApiError('移动文件失败', new Error('源文件 test-copy.txt 不存在,请先复制文件'))
return
}
showApiLoading('正在移动文件...')
const result = await window.gsm3.move('test-copy.txt', 'test-moved.txt')
showApiResult('移动文件', result)
if (window.gsm3.showNotification) {
window.gsm3.showNotification('success', '文件移动成功')
}
} catch (error) {
showApiError('移动文件失败', error)
if (window.gsm3 && window.gsm3.showNotification) {
window.gsm3.showNotification('error', '移动文件失败: ' + error.message)
}
}
}
// 搜索文件
async function searchFiles() {
try {
if (!window.gsm3) {
throw new Error('GSM3 API对象未找到')
}
showApiLoading('正在初始化API...')
await window.gsm3.initialize()
showApiLoading('正在搜索文件...')
const result = await window.gsm3.searchFiles('*.txt')
showApiResult('搜索文件 (*.txt)', result)
if (window.gsm3.showNotification) {
window.gsm3.showNotification('success', '文件搜索完成')
}
} catch (error) {
showApiError('搜索文件失败', error)
if (window.gsm3 && window.gsm3.showNotification) {
window.gsm3.showNotification('error', '搜索文件失败: ' + error.message)
}
}
}
// 检查文件是否存在
async function checkFileExists() {
try {
if (!window.gsm3) {
throw new Error('GSM3 API对象未找到')
}
const filePath = document.getElementById('filePathInput').value
if (!filePath) {
showApiError('检查文件失败', new Error('请输入文件路径'))
return
}
showApiLoading('正在初始化API...')
await window.gsm3.initialize()
showApiLoading('正在检查文件是否存在...')
const result = await window.gsm3.exists(filePath)
showApiResult(`检查文件是否存在: ${filePath}`, result)
if (window.gsm3.showNotification) {
window.gsm3.showNotification('info', '文件检查完成')
}
} catch (error) {
showApiError('检查文件失败', error)
if (window.gsm3 && window.gsm3.showNotification) {
window.gsm3.showNotification('error', '检查文件失败: ' + error.message)
}
}
}
// 获取文件信息
async function getFileInfo() {
try {
if (!window.gsm3) {
throw new Error('GSM3 API对象未找到')
}
const filePath = document.getElementById('filePathInput').value
if (!filePath) {
showApiError('获取文件信息失败', new Error('请输入文件路径'))
return
}
showApiLoading('正在初始化API...')
await window.gsm3.initialize()
showApiLoading('正在获取文件信息...')
const result = await window.gsm3.getFileInfo(filePath)
showApiResult(`获取文件信息: ${filePath}`, result)
if (window.gsm3.showNotification) {
window.gsm3.showNotification('success', '文件信息获取成功')
}
} catch (error) {
showApiError('获取文件信息失败', error)
if (window.gsm3 && window.gsm3.showNotification) {
window.gsm3.showNotification('error', '获取文件信息失败: ' + error.message)
}
}
}
// ==================== 实例管理函数 ====================
// 显示创建实例表单
function showCreateInstanceForm() {
document.getElementById('createInstanceForm').style.display = 'block'
}
// 隐藏创建实例表单
function hideCreateInstanceForm() {
document.getElementById('createInstanceForm').style.display = 'none'
// 清空表单
document.getElementById('instanceName').value = ''
document.getElementById('instanceDescription').value = ''
document.getElementById('instanceWorkingDir').value = ''
document.getElementById('instanceStartCommand').value = ''
document.getElementById('instanceStopCommand').value = 'ctrl+c'
document.getElementById('instanceAutoStart').checked = false
}
// 创建实例
async function createInstance() {
try {
if (!window.gsm3) {
throw new Error('GSM3 API对象未找到')
}
const name = document.getElementById('instanceName').value
const description = document.getElementById('instanceDescription').value
const workingDirectory = document.getElementById('instanceWorkingDir').value
const startCommand = document.getElementById('instanceStartCommand').value
const stopCommand = document.getElementById('instanceStopCommand').value
const autoStart = document.getElementById('instanceAutoStart').checked
if (!name || !workingDirectory || !startCommand) {
showApiError('创建实例失败', new Error('请填写实例名称、工作目录和启动命令'))
return
}
const instanceData = {
name: name.trim(),
description: description.trim(),
workingDirectory: workingDirectory.trim(),
startCommand: startCommand.trim(),
stopCommand: stopCommand,
autoStart: autoStart
}
showApiLoading('正在初始化API...')
await window.gsm3.initialize()
showApiLoading('正在创建实例...')
const result = await window.gsm3.createInstance(instanceData)
showApiResult('创建实例成功', result)
hideCreateInstanceForm()
if (window.gsm3.showNotification) {
window.gsm3.showNotification('success', '实例创建成功')
}
} catch (error) {
showApiError('创建实例失败', error)
if (window.gsm3 && window.gsm3.showNotification) {
window.gsm3.showNotification('error', '创建实例失败: ' + error.message)
}
}
}
// 获取市场实例
async function getMarketInstances() {
try {
if (!window.gsm3) {
throw new Error('GSM3 API对象未找到')
}
showApiLoading('正在初始化API...')
await window.gsm3.initialize()
showApiLoading('正在获取市场实例列表...')
const result = await window.gsm3.getMarketInstances()
showApiResult('市场实例列表', result)
if (window.gsm3.showNotification) {
window.gsm3.showNotification('success', '市场实例列表获取成功')
}
} catch (error) {
showApiError('获取市场实例列表失败', error)
if (window.gsm3 && window.gsm3.showNotification) {
window.gsm3.showNotification('error', '获取市场实例列表失败: ' + error.message)
}
}
}
// 获取实例详情
async function getInstanceDetails() {
try {
if (!window.gsm3) {
throw new Error('GSM3 API对象未找到')
}
const instanceId = document.getElementById('instanceIdInput').value
if (!instanceId) {
showApiError('获取实例详情失败', new Error('请输入实例ID'))
return
}
showApiLoading('正在初始化API...')
await window.gsm3.initialize()
showApiLoading('正在获取实例详情...')
const result = await window.gsm3.getInstance(instanceId)
showApiResult(`实例详情: ${instanceId}`, result)
if (window.gsm3.showNotification) {
window.gsm3.showNotification('success', '实例详情获取成功')
}
} catch (error) {
showApiError('获取实例详情失败', error)
if (window.gsm3 && window.gsm3.showNotification) {
window.gsm3.showNotification('error', '获取实例详情失败: ' + error.message)
}
}
}
// 启动实例
async function startInstance() {
try {
if (!window.gsm3) {
throw new Error('GSM3 API对象未找到')
}
const instanceId = document.getElementById('instanceIdInput').value
if (!instanceId) {
showApiError('启动实例失败', new Error('请输入实例ID'))
return
}
showApiLoading('正在初始化API...')
await window.gsm3.initialize()
showApiLoading('正在启动实例...')
const result = await window.gsm3.startInstance(instanceId)
showApiResult(`启动实例: ${instanceId}`, result)
if (window.gsm3.showNotification) {
window.gsm3.showNotification('success', '实例启动成功')
}
} catch (error) {
showApiError('启动实例失败', error)
if (window.gsm3 && window.gsm3.showNotification) {
window.gsm3.showNotification('error', '启动实例失败: ' + error.message)
}
}
}
// 停止实例
async function stopInstance() {
try {
if (!window.gsm3) {
throw new Error('GSM3 API对象未找到')
}
const instanceId = document.getElementById('instanceIdInput').value
if (!instanceId) {
showApiError('停止实例失败', new Error('请输入实例ID'))
return
}
showApiLoading('正在初始化API...')
await window.gsm3.initialize()
showApiLoading('正在停止实例...')
const result = await window.gsm3.stopInstance(instanceId)
showApiResult(`停止实例: ${instanceId}`, result)
if (window.gsm3.showNotification) {
window.gsm3.showNotification('success', '实例停止成功')
}
} catch (error) {
showApiError('停止实例失败', error)
if (window.gsm3 && window.gsm3.showNotification) {
window.gsm3.showNotification('error', '停止实例失败: ' + error.message)
}
}
}
// 重启实例
async function restartInstance() {
try {
if (!window.gsm3) {
throw new Error('GSM3 API对象未找到')
}
const instanceId = document.getElementById('instanceIdInput').value
if (!instanceId) {
showApiError('重启实例失败', new Error('请输入实例ID'))
return
}
showApiLoading('正在初始化API...')
await window.gsm3.initialize()
showApiLoading('正在重启实例...')
const result = await window.gsm3.restartInstance(instanceId)
showApiResult(`重启实例: ${instanceId}`, result)
if (window.gsm3.showNotification) {
window.gsm3.showNotification('success', '实例重启成功')
}
} catch (error) {
showApiError('重启实例失败', error)
if (window.gsm3 && window.gsm3.showNotification) {
window.gsm3.showNotification('error', '重启实例失败: ' + error.message)
}
}
}
// 删除实例
async function deleteInstance() {
try {
if (!window.gsm3) {
throw new Error('GSM3 API对象未找到')
}
const instanceId = document.getElementById('instanceIdInput').value
if (!instanceId) {
showApiError('删除实例失败', new Error('请输入实例ID'))
return
}
if (!confirm(`确定要删除实例 ${instanceId} 吗?此操作不可撤销!`)) {
return
}
showApiLoading('正在初始化API...')
await window.gsm3.initialize()
showApiLoading('正在删除实例...')
const result = await window.gsm3.deleteInstance(instanceId)
showApiResult(`删除实例: ${instanceId}`, result)
if (window.gsm3.showNotification) {
window.gsm3.showNotification('success', '实例删除成功')
}
} catch (error) {
showApiError('删除实例失败', error)
if (window.gsm3 && window.gsm3.showNotification) {
window.gsm3.showNotification('error', '删除实例失败: ' + error.message)
}
}
}
// ==================== 终端管理函数 ====================
// 获取终端统计信息
async function getTerminalStats() {
try {
if (!window.gsm3) {
throw new Error('GSM3 API对象未找到')
}
showApiLoading('正在初始化API...')
await window.gsm3.initialize()
showApiLoading('正在获取终端统计信息...')
const result = await window.gsm3.getTerminalStats()
showApiResult('终端统计信息', result)
if (window.gsm3.showNotification) {
window.gsm3.showNotification('success', '终端统计信息获取成功')
}
} catch (error) {
showApiError('获取终端统计信息失败', error)
if (window.gsm3 && window.gsm3.showNotification) {
window.gsm3.showNotification('error', '获取终端统计信息失败: ' + error.message)
}
}
}
// 获取终端会话列表
async function getTerminalSessions() {
try {
if (!window.gsm3) {
throw new Error('GSM3 API对象未找到')
}
showApiLoading('正在初始化API...')
await window.gsm3.initialize()
showApiLoading('正在获取终端会话列表...')
const result = await window.gsm3.getTerminalSessions()
showApiResult('终端会话列表', result)
if (window.gsm3.showNotification) {
window.gsm3.showNotification('success', '终端会话列表获取成功')
}
} catch (error) {
showApiError('获取终端会话列表失败', error)
if (window.gsm3 && window.gsm3.showNotification) {
window.gsm3.showNotification('error', '获取终端会话列表失败: ' + error.message)
}
}
}
// 获取活跃终端进程
async function getActiveTerminalProcesses() {
try {
if (!window.gsm3) {
throw new Error('GSM3 API对象未找到')
}
showApiLoading('正在初始化API...')
await window.gsm3.initialize()
showApiLoading('正在获取活跃终端进程...')
const result = await window.gsm3.getActiveTerminalProcesses()
showApiResult('活跃终端进程', result)
if (window.gsm3.showNotification) {
window.gsm3.showNotification('success', '活跃终端进程获取成功')
}
} catch (error) {
showApiError('获取活跃终端进程失败', error)
if (window.gsm3 && window.gsm3.showNotification) {
window.gsm3.showNotification('error', '获取活跃终端进程失败: ' + error.message)
}
}
}
// 获取默认Shell
async function getDefaultShell() {
try {
if (!window.gsm3) {
throw new Error('GSM3 API对象未找到')
}
showApiLoading('正在初始化API...')
await window.gsm3.initialize()
showApiLoading('正在获取默认Shell信息...')
const result = await window.gsm3.getDefaultShell()
showApiResult('默认Shell信息', result)
if (window.gsm3.showNotification) {
window.gsm3.showNotification('success', '默认Shell信息获取成功')
}
} catch (error) {
showApiError('获取默认Shell信息失败', error)
if (window.gsm3 && window.gsm3.showNotification) {
window.gsm3.showNotification('error', '获取默认Shell信息失败: ' + error.message)
}
}
}
// 获取终端主题
async function getTerminalThemes() {
try {
if (!window.gsm3) {
throw new Error('GSM3 API对象未找到')
}
showApiLoading('正在初始化API...')
await window.gsm3.initialize()
showApiLoading('正在获取终端主题配置...')
const result = await window.gsm3.getTerminalThemes()
showApiResult('终端主题配置', result)
if (window.gsm3.showNotification) {
window.gsm3.showNotification('success', '终端主题配置获取成功')
}
} catch (error) {
showApiError('获取终端主题配置失败', error)
if (window.gsm3 && window.gsm3.showNotification) {
window.gsm3.showNotification('error', '获取终端主题配置失败: ' + error.message)
}
}
}
// 获取终端字体
async function getTerminalFonts() {
try {
if (!window.gsm3) {
throw new Error('GSM3 API对象未找到')
}
showApiLoading('正在初始化API...')
await window.gsm3.initialize()
showApiLoading('正在获取终端字体配置...')
const result = await window.gsm3.getTerminalFonts()
showApiResult('终端字体配置', result)
if (window.gsm3.showNotification) {
window.gsm3.showNotification('success', '终端字体配置获取成功')
}
} catch (error) {
showApiError('获取终端字体配置失败', error)
if (window.gsm3 && window.gsm3.showNotification) {
window.gsm3.showNotification('error', '获取终端字体配置失败: ' + error.message)
}
}
}
// 验证终端配置
async function validateTerminalConfig() {
try {
if (!window.gsm3) {
throw new Error('GSM3 API对象未找到')
}
showApiLoading('正在初始化API...')
await window.gsm3.initialize()
showApiLoading('正在验证终端配置...')
const workingDirectory = process.cwd ? process.cwd() : '/'
const shell = process.platform === 'win32' ? 'powershell.exe' : '/bin/bash'
const result = await window.gsm3.validateTerminalConfig(workingDirectory, shell)
showApiResult('验证终端配置', result)
if (window.gsm3.showNotification) {
window.gsm3.showNotification('success', '终端配置验证成功')
}
} catch (error) {
showApiError('验证终端配置失败', error)
if (window.gsm3 && window.gsm3.showNotification) {
window.gsm3.showNotification('error', '验证终端配置失败: ' + error.message)
}
}
}
// 测试终端连接
async function testTerminalConnection() {
try {
if (!window.gsm3) {
throw new Error('GSM3 API对象未找到')
}
showApiLoading('正在初始化API...')
await window.gsm3.initialize()
showApiLoading('正在测试终端连接...')
const workingDirectory = process.cwd ? process.cwd() : '/'
const result = await window.gsm3.testTerminalConnection(workingDirectory)
showApiResult('测试终端连接', result)
if (window.gsm3.showNotification) {
window.gsm3.showNotification('success', '终端连接测试成功')
}
} catch (error) {
showApiError('测试终端连接失败', error)
if (window.gsm3 && window.gsm3.showNotification) {
window.gsm3.showNotification('error', '测试终端连接失败: ' + error.message)
}
}
}
// 更新终端会话名称
async function updateTerminalSessionName() {
try {
if (!window.gsm3) {
throw new Error('GSM3 API对象未找到')
}
const sessionId = document.getElementById('sessionIdInput').value
const sessionName = document.getElementById('sessionNameInput').value
if (!sessionId || !sessionName) {
showApiError('更新会话名称失败', new Error('请输入会话ID和新名称'))
return
}
showApiLoading('正在初始化API...')
await window.gsm3.initialize()
showApiLoading('正在更新终端会话名称...')
const result = await window.gsm3.updateTerminalSessionName(sessionId, sessionName)
showApiResult(`更新会话名称: ${sessionId} -> ${sessionName}`, result)
if (window.gsm3.showNotification) {
window.gsm3.showNotification('success', '终端会话名称更新成功')
}
} catch (error) {
showApiError('更新终端会话名称失败', error)
if (window.gsm3 && window.gsm3.showNotification) {
window.gsm3.showNotification('error', '更新终端会话名称失败: ' + error.message)
}
}
}
// 显示快速开始指南
function showQuickStart() {
const guide = document.getElementById('quickStartGuide')
const overview = document.getElementById('apiOverview')
guide.style.display = 'block'
overview.style.display = 'none'
}
// 隐藏快速开始指南
function hideQuickStart() {
const guide = document.getElementById('quickStartGuide')
guide.style.display = 'none'
}
// 显示API概览
function showApiOverview() {
const guide = document.getElementById('quickStartGuide')
const overview = document.getElementById('apiOverview')
overview.style.display = 'block'
guide.style.display = 'none'
}
// 隐藏API概览
function hideApiOverview() {
const overview = document.getElementById('apiOverview')
overview.style.display = 'none'
}
// 控制台欢迎信息
console.log('%c🧩 GSM3 插件系统', 'color: #667eea; font-size: 20px; font-weight: bold;')
console.log('%c欢迎使用示例插件', 'color: #764ba2; font-size: 14px;')
console.log('插件开发文档: 查看 ../插件开发文档.md')
console.log('API使用示例: 点击页面上的按钮体验各种功能')
console.log('快速开始: 复制此插件目录作为模板开始开发')
// 等待GSM3 API加载完成后进行健康检查
window.addEventListener('load', async () => {
// 等待一段时间确保gsm3-api.js完全加载
setTimeout(async () => {
if (window.gsm3) {
try {
console.log('GSM3 API对象已加载:', window.gsm3)
const health = await window.gsm3.healthCheck()
console.log('GSM3 API连接正常:', health)
} catch (error) {
console.warn('GSM3 API连接失败:', error)
}
} else {
console.error('GSM3 API对象未找到请检查gsm3-api.js是否正确加载')
console.log('当前window对象包含的gsm3相关属性:', Object.keys(window).filter(key => key.includes('gsm3')))
}
}, 1000)
})
</script>
</body>
</html>