bugfix
This commit is contained in:
parent
7378cea02b
commit
81af72a74b
1
wwwroot/get_languages.dspy
Normal file
1
wwwroot/get_languages.dspy
Normal file
@ -0,0 +1 @@
|
|||||||
|
return get_languages()
|
||||||
156
wwwroot/tmp/dag.html
Normal file
156
wwwroot/tmp/dag.html
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>DAG Editor</title>
|
||||||
|
<style>
|
||||||
|
body { font-family: Arial; margin: 0; overflow: hidden; }
|
||||||
|
#toolbar { padding: 10px; background: #eee; border-bottom: 1px solid #ccc; }
|
||||||
|
#canvas { position: relative; width: 100%; height: calc(100vh - 40px); background: #fafafa; }
|
||||||
|
.node {
|
||||||
|
position: absolute; padding: 10px 15px;
|
||||||
|
background: #fff; border: 2px solid #333; border-radius: 6px;
|
||||||
|
cursor: move; user-select: none; text-align: center;
|
||||||
|
}
|
||||||
|
.start { background: #d1ffd1; border-color: green; }
|
||||||
|
.end { background: #ffd1d1; border-color: red; }
|
||||||
|
.selected { border-color: blue; }
|
||||||
|
svg { position: absolute; top: 0; left: 0; pointer-events: none; }
|
||||||
|
line, path { stroke: #333; stroke-width: 2; marker-end: url(#arrow); }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="toolbar">
|
||||||
|
<button onclick="addNode('normal')">添加节点</button>
|
||||||
|
<button onclick="addNode('start')">添加开始节点</button>
|
||||||
|
<button onclick="addNode('end')">添加结束节点</button>
|
||||||
|
<button onclick="deleteSelected()">删除选中</button>
|
||||||
|
<button onclick="exportData()">导出流程</button>
|
||||||
|
</div>
|
||||||
|
<div id="canvas">
|
||||||
|
<svg id="edges"></svg>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
let canvas = document.getElementById('canvas');
|
||||||
|
let edgesSVG = document.getElementById('edges');
|
||||||
|
let nodes = [];
|
||||||
|
let edges = [];
|
||||||
|
let selectedNode = null;
|
||||||
|
let linkingStart = null;
|
||||||
|
|
||||||
|
// 添加箭头标记
|
||||||
|
let defs = document.createElementNS("http://www.w3.org/2000/svg", "defs");
|
||||||
|
let marker = document.createElementNS("http://www.w3.org/2000/svg", "marker");
|
||||||
|
marker.setAttribute("id", "arrow");
|
||||||
|
marker.setAttribute("markerWidth", "10");
|
||||||
|
marker.setAttribute("markerHeight", "10");
|
||||||
|
marker.setAttribute("refX", "10");
|
||||||
|
marker.setAttribute("refY", "3");
|
||||||
|
marker.setAttribute("orient", "auto");
|
||||||
|
let arrowPath = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
||||||
|
arrowPath.setAttribute("d", "M0,0 L10,3 L0,6 Z");
|
||||||
|
arrowPath.setAttribute("fill", "#333");
|
||||||
|
marker.appendChild(arrowPath);
|
||||||
|
defs.appendChild(marker);
|
||||||
|
edgesSVG.appendChild(defs);
|
||||||
|
|
||||||
|
function addNode(type) {
|
||||||
|
let div = document.createElement('div');
|
||||||
|
div.className = 'node ' + (type === 'start' ? 'start' : type === 'end' ? 'end' : '');
|
||||||
|
div.style.left = "100px";
|
||||||
|
div.style.top = "100px";
|
||||||
|
div.contentEditable = true;
|
||||||
|
div.innerText = type === 'start' ? "开始" : type === 'end' ? "结束" : "节点";
|
||||||
|
|
||||||
|
div.onclick = (e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
if (linkingStart && linkingStart !== div) {
|
||||||
|
addEdge(linkingStart, div);
|
||||||
|
linkingStart.classList.remove("selected");
|
||||||
|
linkingStart = null;
|
||||||
|
} else {
|
||||||
|
if (selectedNode) selectedNode.classList.remove("selected");
|
||||||
|
div.classList.add("selected");
|
||||||
|
selectedNode = div;
|
||||||
|
linkingStart = div; // 准备连线
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 拖拽
|
||||||
|
div.onmousedown = (e) => {
|
||||||
|
let offsetX = e.offsetX, offsetY = e.offsetY;
|
||||||
|
function move(ev) {
|
||||||
|
div.style.left = (ev.pageX - offsetX) + "px";
|
||||||
|
div.style.top = (ev.pageY - offsetY) + "px";
|
||||||
|
updateEdges();
|
||||||
|
}
|
||||||
|
function up() {
|
||||||
|
document.removeEventListener('mousemove', move);
|
||||||
|
document.removeEventListener('mouseup', up);
|
||||||
|
}
|
||||||
|
document.addEventListener('mousemove', move);
|
||||||
|
document.addEventListener('mouseup', up);
|
||||||
|
};
|
||||||
|
|
||||||
|
canvas.appendChild(div);
|
||||||
|
nodes.push(div);
|
||||||
|
}
|
||||||
|
|
||||||
|
function addEdge(from, to) {
|
||||||
|
let edge = {from, to};
|
||||||
|
edges.push(edge);
|
||||||
|
updateEdges();
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateEdges() {
|
||||||
|
edgesSVG.innerHTML = "<defs>"+defs.innerHTML+"</defs>";
|
||||||
|
edges.forEach(e => {
|
||||||
|
let x1 = e.from.offsetLeft + e.from.offsetWidth/2;
|
||||||
|
let y1 = e.from.offsetTop + e.from.offsetHeight/2;
|
||||||
|
let x2 = e.to.offsetLeft + e.to.offsetWidth/2;
|
||||||
|
let y2 = e.to.offsetTop + e.to.offsetHeight/2;
|
||||||
|
|
||||||
|
let path = document.createElementNS("http://www.w3.org/2000/svg", "line");
|
||||||
|
path.setAttribute("x1", x1);
|
||||||
|
path.setAttribute("y1", y1);
|
||||||
|
path.setAttribute("x2", x2);
|
||||||
|
path.setAttribute("y2", y2);
|
||||||
|
path.setAttribute("stroke", "#333");
|
||||||
|
path.setAttribute("stroke-width", "2");
|
||||||
|
path.setAttribute("marker-end", "url(#arrow)");
|
||||||
|
path.onclick = (ev) => {
|
||||||
|
ev.stopPropagation();
|
||||||
|
edges = edges.filter(ed => ed !== e);
|
||||||
|
updateEdges();
|
||||||
|
}
|
||||||
|
edgesSVG.appendChild(path);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteSelected() {
|
||||||
|
if (selectedNode) {
|
||||||
|
edges = edges.filter(e => e.from !== selectedNode && e.to !== selectedNode);
|
||||||
|
canvas.removeChild(selectedNode);
|
||||||
|
nodes = nodes.filter(n => n !== selectedNode);
|
||||||
|
selectedNode = null;
|
||||||
|
updateEdges();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function exportData() {
|
||||||
|
let data = {
|
||||||
|
nodes: nodes.map(n => ({
|
||||||
|
id: n.innerText,
|
||||||
|
type: n.classList.contains('start') ? 'start' : n.classList.contains('end') ? 'end' : 'normal',
|
||||||
|
x: n.offsetLeft, y: n.offsetTop
|
||||||
|
})),
|
||||||
|
edges: edges.map(e => ({ from: e.from.innerText, to: e.to.innerText }))
|
||||||
|
};
|
||||||
|
console.log(JSON.stringify(data, null, 2));
|
||||||
|
alert("导出数据已打印到控制台");
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
165
wwwroot/tmp/dag1.html
Normal file
165
wwwroot/tmp/dag1.html
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>DAG 可视化编辑器</title>
|
||||||
|
<style>
|
||||||
|
body { font-family: Arial; }
|
||||||
|
#canvas { border: 1px solid #ccc; width: 100%; height: 600px; position: relative; }
|
||||||
|
.node {
|
||||||
|
position: absolute;
|
||||||
|
padding: 10px 20px;
|
||||||
|
border: 2px solid #333;
|
||||||
|
border-radius: 8px;
|
||||||
|
background: #f9f9f9;
|
||||||
|
cursor: move;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
svg {
|
||||||
|
position: absolute;
|
||||||
|
top: 0; left: 0; width: 100%; height: 100%;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
line, path {
|
||||||
|
stroke: #333;
|
||||||
|
stroke-width: 2;
|
||||||
|
fill: none;
|
||||||
|
marker-end: url(#arrow);
|
||||||
|
pointer-events: auto;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h3>DAG 可视化编辑器</h3>
|
||||||
|
<div id="canvas">
|
||||||
|
<svg id="edges"></svg>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
let nodes = [];
|
||||||
|
let edges = [];
|
||||||
|
let selectedNode = null;
|
||||||
|
const canvas = document.getElementById("canvas");
|
||||||
|
const svg = document.getElementById("edges");
|
||||||
|
|
||||||
|
function createNode(id, text, x, y) {
|
||||||
|
const div = document.createElement("div");
|
||||||
|
div.className = "node";
|
||||||
|
div.innerText = text;
|
||||||
|
div.contentEditable = true;
|
||||||
|
div.style.left = x + "px";
|
||||||
|
div.style.top = y + "px";
|
||||||
|
div.dataset.id = id;
|
||||||
|
div.onmousedown = (e) => startDrag(e, div);
|
||||||
|
div.onclick = (e) => selectNode(e, div);
|
||||||
|
canvas.appendChild(div);
|
||||||
|
nodes.push({id, x, y, el: div});
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawEdges() {
|
||||||
|
svg.innerHTML = `
|
||||||
|
<defs>
|
||||||
|
<marker id="arrow" markerWidth="10" markerHeight="10" refX="10" refY="3" orient="auto">
|
||||||
|
<path d="M0,0 L0,6 L9,3 z" fill="#333" />
|
||||||
|
</marker>
|
||||||
|
</defs>`;
|
||||||
|
edges.forEach(edge => {
|
||||||
|
const from = nodes.find(n => n.id === edge.from);
|
||||||
|
const to = nodes.find(n => n.id === edge.to);
|
||||||
|
if (from && to) {
|
||||||
|
const x1 = from.x + from.el.offsetWidth/2;
|
||||||
|
const y1 = from.y + from.el.offsetHeight/2;
|
||||||
|
const x2 = to.x + to.el.offsetWidth/2;
|
||||||
|
const y2 = to.y + to.el.offsetHeight/2;
|
||||||
|
const line = document.createElementNS("http://www.w3.org/2000/svg", "line");
|
||||||
|
line.setAttribute("x1", x1);
|
||||||
|
line.setAttribute("y1", y1);
|
||||||
|
line.setAttribute("x2", x2);
|
||||||
|
line.setAttribute("y2", y2);
|
||||||
|
line.setAttribute("stroke", "black");
|
||||||
|
line.setAttribute("marker-end", "url(#arrow)");
|
||||||
|
svg.appendChild(line);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function selectNode(e, div) {
|
||||||
|
if (!selectedNode) {
|
||||||
|
selectedNode = div.dataset.id;
|
||||||
|
} else {
|
||||||
|
if (selectedNode !== div.dataset.id) {
|
||||||
|
edges.push({from: selectedNode, to: div.dataset.id});
|
||||||
|
drawEdges();
|
||||||
|
}
|
||||||
|
selectedNode = null;
|
||||||
|
}
|
||||||
|
e.stopPropagation();
|
||||||
|
}
|
||||||
|
|
||||||
|
let dragNode = null, offsetX = 0, offsetY = 0;
|
||||||
|
function startDrag(e, div) {
|
||||||
|
dragNode = div;
|
||||||
|
offsetX = e.offsetX;
|
||||||
|
offsetY = e.offsetY;
|
||||||
|
document.onmousemove = drag;
|
||||||
|
document.onmouseup = stopDrag;
|
||||||
|
}
|
||||||
|
function drag(e) {
|
||||||
|
if (dragNode) {
|
||||||
|
dragNode.style.left = (e.pageX - canvas.offsetLeft - offsetX) + "px";
|
||||||
|
dragNode.style.top = (e.pageY - canvas.offsetTop - offsetY) + "px";
|
||||||
|
let n = nodes.find(n => n.id === dragNode.dataset.id);
|
||||||
|
n.x = e.pageX - canvas.offsetLeft - offsetX;
|
||||||
|
n.y = e.pageY - canvas.offsetTop - offsetY;
|
||||||
|
drawEdges();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function stopDrag() {
|
||||||
|
dragNode = null;
|
||||||
|
document.onmousemove = null;
|
||||||
|
document.onmouseup = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 简单自动布局:拓扑排序分层排布
|
||||||
|
function autoLayout() {
|
||||||
|
let layerMap = {};
|
||||||
|
let visited = new Set();
|
||||||
|
|
||||||
|
function dfs(nodeId, depth) {
|
||||||
|
if (layerMap[nodeId] === undefined || depth > layerMap[nodeId]) {
|
||||||
|
layerMap[nodeId] = depth;
|
||||||
|
}
|
||||||
|
edges.filter(e => e.from === nodeId).forEach(e => dfs(e.to, depth+1));
|
||||||
|
}
|
||||||
|
nodes.forEach(n => dfs(n.id, 0));
|
||||||
|
|
||||||
|
let maxLayer = Math.max(...Object.values(layerMap));
|
||||||
|
let layerGroups = Array.from({length: maxLayer+1}, () => []);
|
||||||
|
for (let n of nodes) {
|
||||||
|
let layer = layerMap[n.id] || 0;
|
||||||
|
layerGroups[layer].push(n);
|
||||||
|
}
|
||||||
|
layerGroups.forEach((group, depth) => {
|
||||||
|
group.forEach((n, i) => {
|
||||||
|
n.x = 150 * i + 50;
|
||||||
|
n.y = depth * 100 + 50;
|
||||||
|
n.el.style.left = n.x + "px";
|
||||||
|
n.el.style.top = n.y + "px";
|
||||||
|
});
|
||||||
|
});
|
||||||
|
drawEdges();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测试数据
|
||||||
|
createNode("1", "开始", 50, 50);
|
||||||
|
createNode("2", "处理", 250, 200);
|
||||||
|
createNode("3", "结束", 450, 350);
|
||||||
|
edges.push({from: "1", to: "2"});
|
||||||
|
edges.push({from: "2", to: "3"});
|
||||||
|
drawEdges();
|
||||||
|
autoLayout();
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
168
wwwroot/tmp/trag.html
Normal file
168
wwwroot/tmp/trag.html
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>RAG 可视化编辑器 (纯JS)</title>
|
||||||
|
<style>
|
||||||
|
body { margin: 0; font-family: sans-serif; display: flex; height: 100vh; }
|
||||||
|
#sidebar { width: 180px; background: #f5f5f5; padding: 10px; border-right: 1px solid #ccc; }
|
||||||
|
#canvas { flex: 1; position: relative; background: #fafafa; overflow: hidden; }
|
||||||
|
.node {
|
||||||
|
position: absolute;
|
||||||
|
border: 1px solid #333;
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 8px;
|
||||||
|
background: #fff;
|
||||||
|
cursor: move;
|
||||||
|
}
|
||||||
|
.connection {
|
||||||
|
stroke: #333;
|
||||||
|
stroke-width: 2;
|
||||||
|
fill: none;
|
||||||
|
}
|
||||||
|
#toolbar { position: absolute; top: 10px; right: 10px; background: #fff; border: 1px solid #ccc; padding: 5px; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="sidebar">
|
||||||
|
<h4>节点面板</h4>
|
||||||
|
<button onclick="addNode('DataSource')">DataSource</button><br>
|
||||||
|
<button onclick="addNode('Embedder')">Embedder</button><br>
|
||||||
|
<button onclick="addNode('VectorStore')">VectorStore</button><br>
|
||||||
|
<button onclick="addNode('Retriever')">Retriever</button><br>
|
||||||
|
<button onclick="addNode('LLM')">LLM</button><br>
|
||||||
|
<button onclick="addNode('Evaluator')">Evaluator</button><br>
|
||||||
|
<button onclick="addNode('Tool')">Tool</button><br>
|
||||||
|
<hr>
|
||||||
|
<button onclick="exportFlow()">导出JSON</button><br>
|
||||||
|
<input type="file" id="importFile" onchange="importFlow(event)">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="canvas">
|
||||||
|
<svg id="connections" width="100%" height="100%" style="position:absolute;top:0;left:0;z-index:0"></svg>
|
||||||
|
<div id="toolbar">
|
||||||
|
<button onclick="submitFlow()">提交</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
let nodes = [];
|
||||||
|
let connections = [];
|
||||||
|
let currentId = 0;
|
||||||
|
let selectedNode = null;
|
||||||
|
|
||||||
|
function addNode(type, x=100, y=100) {
|
||||||
|
const id = 'n'+(currentId++);
|
||||||
|
const div = document.createElement('div');
|
||||||
|
div.className = 'node';
|
||||||
|
div.innerText = type;
|
||||||
|
div.style.left = x+'px';
|
||||||
|
div.style.top = y+'px';
|
||||||
|
div.dataset.id = id;
|
||||||
|
div.dataset.type = type;
|
||||||
|
div.draggable = true;
|
||||||
|
|
||||||
|
div.addEventListener('dragstart', e=>{
|
||||||
|
selectedNode = div;
|
||||||
|
e.dataTransfer.setData("text/plain", id);
|
||||||
|
});
|
||||||
|
div.addEventListener('dblclick', ()=> {
|
||||||
|
if (selectedNode && selectedNode !== div) {
|
||||||
|
addConnection(selectedNode.dataset.id, div.dataset.id);
|
||||||
|
selectedNode = null;
|
||||||
|
} else {
|
||||||
|
selectedNode = div;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
document.getElementById('canvas').appendChild(div);
|
||||||
|
nodes.push({id, type, x, y});
|
||||||
|
makeDraggable(div);
|
||||||
|
}
|
||||||
|
|
||||||
|
function makeDraggable(el) {
|
||||||
|
let offsetX, offsetY;
|
||||||
|
el.onmousedown = (e)=>{
|
||||||
|
offsetX = e.offsetX;
|
||||||
|
offsetY = e.offsetY;
|
||||||
|
document.onmousemove = (ev)=>{
|
||||||
|
el.style.left = (ev.pageX - offsetX)+'px';
|
||||||
|
el.style.top = (ev.pageY - offsetY)+'px';
|
||||||
|
redrawConnections();
|
||||||
|
};
|
||||||
|
document.onmouseup = ()=>{ document.onmousemove=null; };
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function addConnection(from, to) {
|
||||||
|
connections.push({from, to});
|
||||||
|
redrawConnections();
|
||||||
|
}
|
||||||
|
|
||||||
|
function redrawConnections() {
|
||||||
|
const svg = document.getElementById('connections');
|
||||||
|
svg.innerHTML = '';
|
||||||
|
connections.forEach(c=>{
|
||||||
|
const fromEl = document.querySelector(`[data-id='${c.from}']`);
|
||||||
|
const toEl = document.querySelector(`[data-id='${c.to}']`);
|
||||||
|
if (fromEl && toEl) {
|
||||||
|
const x1 = fromEl.offsetLeft + fromEl.offsetWidth/2;
|
||||||
|
const y1 = fromEl.offsetTop + fromEl.offsetHeight/2;
|
||||||
|
const x2 = toEl.offsetLeft + toEl.offsetWidth/2;
|
||||||
|
const y2 = toEl.offsetTop + toEl.offsetHeight/2;
|
||||||
|
const path = document.createElementNS("http://www.w3.org/2000/svg","path");
|
||||||
|
path.setAttribute("d", `M${x1},${y1} C${x1+50},${y1} ${x2-50},${y2} ${x2},${y2}`);
|
||||||
|
path.setAttribute("class","connection");
|
||||||
|
svg.appendChild(path);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function exportFlow() {
|
||||||
|
const data = {
|
||||||
|
nodes: Array.from(document.querySelectorAll('.node')).map(el=>({
|
||||||
|
id: el.dataset.id,
|
||||||
|
type: el.dataset.type,
|
||||||
|
x: el.offsetLeft,
|
||||||
|
y: el.offsetTop
|
||||||
|
})),
|
||||||
|
connections
|
||||||
|
};
|
||||||
|
const blob = new Blob([JSON.stringify(data,null,2)], {type:"application/json"});
|
||||||
|
const a = document.createElement('a');
|
||||||
|
a.href = URL.createObjectURL(blob);
|
||||||
|
a.download = "flow.json";
|
||||||
|
a.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
function importFlow(event) {
|
||||||
|
const file = event.target.files[0];
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.onload = ()=>{
|
||||||
|
const data = JSON.parse(reader.result);
|
||||||
|
document.querySelectorAll('.node').forEach(n=>n.remove());
|
||||||
|
nodes=[]; connections=[]; currentId=0;
|
||||||
|
data.nodes.forEach(n=>addNode(n.type,n.x,n.y));
|
||||||
|
connections = data.connections;
|
||||||
|
redrawConnections();
|
||||||
|
};
|
||||||
|
reader.readAsText(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
function submitFlow() {
|
||||||
|
const data = {
|
||||||
|
nodes: Array.from(document.querySelectorAll('.node')).map(el=>({
|
||||||
|
id: el.dataset.id,
|
||||||
|
type: el.dataset.type,
|
||||||
|
x: el.offsetLeft,
|
||||||
|
y: el.offsetTop
|
||||||
|
})),
|
||||||
|
connections
|
||||||
|
};
|
||||||
|
console.log("提交流程数据:", data);
|
||||||
|
alert("流程已提交,控制台查看数据");
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
29
wwwroot/ws/sagelog.xterm
Normal file
29
wwwroot/ws/sagelog.xterm
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
debug(f'{params_kw=},')
|
||||||
|
async def gethostinfo(sor, ns):
|
||||||
|
sql="""select a.*
|
||||||
|
from hostdev a
|
||||||
|
where a.id= ${id}$
|
||||||
|
"""
|
||||||
|
recs = await sor.sqlExe(sql,ns.copy())
|
||||||
|
if len(recs) > 0:
|
||||||
|
r = recs[0]
|
||||||
|
r.username = r.user
|
||||||
|
if r.password:
|
||||||
|
r.password = password_decode(r.password)
|
||||||
|
if r.passphrase:
|
||||||
|
r.passphrase = password_decode(r.passphrase)
|
||||||
|
if r.jumperid:
|
||||||
|
r.jumperservers = await gethostinfo(sor, {'id':r.jumperid})
|
||||||
|
return DictObject(**r)
|
||||||
|
|
||||||
|
db = DBPools()
|
||||||
|
userid = await get_user()
|
||||||
|
dbname = get_module_dbname('msp')
|
||||||
|
async with db.sqlorContext(dbname) as sor:
|
||||||
|
ns = {
|
||||||
|
"id":"JFWxNcA_wsdFJ4ZO-4PKr"
|
||||||
|
}
|
||||||
|
r = await gethostinfo(sor, ns)
|
||||||
|
r.cmdargs = [ "~/bin/sagelog" ]
|
||||||
|
r.noinput = True
|
||||||
|
return None
|
||||||
Loading…
x
Reference in New Issue
Block a user