feat: MCP Token 复制按钮 — 后台一键取回明文 Token 到剪贴板
This commit is contained in:
@@ -797,6 +797,16 @@ func MCPStatus(c *gin.Context) {
|
||||
})
|
||||
}
|
||||
|
||||
// MCPGetToken 返回完整明文 Token(供后台「复制」按钮使用,需已登录后台会话)
|
||||
func MCPGetToken(c *gin.Context) {
|
||||
_, token := getMCPAuthState()
|
||||
if token == "" {
|
||||
c.JSON(http.StatusOK, gin.H{"success": false, "message": "Token 未生成,请先点「重新生成」"})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"success": true, "token": token})
|
||||
}
|
||||
|
||||
// MCPRegenerateToken 生成新随机 Token 并自动启用 MCP,返回完整新 Token(仅此一次明文展示)
|
||||
func MCPRegenerateToken(c *gin.Context) {
|
||||
b := make([]byte, 24)
|
||||
|
||||
@@ -72,6 +72,7 @@ func main() {
|
||||
|
||||
// MCP 管理(后台 UI)
|
||||
admin.GET("/api/mcp/status", handlers.MCPStatus)
|
||||
admin.GET("/api/mcp/token", handlers.MCPGetToken)
|
||||
admin.POST("/api/mcp/token", handlers.MCPRegenerateToken)
|
||||
admin.POST("/api/mcp/enabled", handlers.MCPSetEnabled)
|
||||
}
|
||||
|
||||
@@ -139,6 +139,7 @@
|
||||
<label style="font-size:12px; color:#666">Token</label>
|
||||
<div style="display:flex; gap:8px; align-items:center">
|
||||
<input type="text" id="cfg_mcp_token" class="input" readonly style="flex:1; background:#fff; color:#555">
|
||||
<button class="btn btn-primary" onclick="copyMCPToken(this)" style="padding:8px 14px; white-space:nowrap">📋 复制</button>
|
||||
<button class="btn btn-primary" onclick="regenMCPToken()" style="padding:8px 14px; white-space:nowrap">🔄 重新生成</button>
|
||||
</div>
|
||||
<div style="font-size:11px; color:#999; margin-top:6px">
|
||||
@@ -200,6 +201,37 @@
|
||||
});
|
||||
}
|
||||
|
||||
async function copyMCPToken(btn) {
|
||||
try {
|
||||
const resp = await fetch('/admin/api/mcp/token');
|
||||
const res = await resp.json();
|
||||
if (!res.success) { alert('❌ ' + (res.message || 'Token 未生成')); return; }
|
||||
const token = res.token;
|
||||
let copied = false;
|
||||
try {
|
||||
await navigator.clipboard.writeText(token);
|
||||
copied = true;
|
||||
} catch (e) {
|
||||
// 非 HTTPS/localhost 环境降级方案
|
||||
const ta = document.createElement('textarea');
|
||||
ta.value = token;
|
||||
ta.style.position = 'fixed';
|
||||
ta.style.opacity = '0';
|
||||
document.body.appendChild(ta);
|
||||
ta.focus(); ta.select();
|
||||
try { copied = document.execCommand('copy'); } catch (e2) {}
|
||||
document.body.removeChild(ta);
|
||||
}
|
||||
if (copied) {
|
||||
const old = btn.textContent;
|
||||
btn.textContent = '✅ 已复制';
|
||||
setTimeout(() => { btn.textContent = old; }, 1500);
|
||||
} else {
|
||||
prompt('自动复制不可用,请手动复制 Token:', token);
|
||||
}
|
||||
} catch(e) { alert('获取 Token 失败'); }
|
||||
}
|
||||
|
||||
async function regenMCPToken() {
|
||||
if (!confirm('确定重新生成 Token?\n\n旧 Token 将立即失效,已接入的 AI 客户端需要更新为新 Token。')) return;
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user