feat(ops): add managed NE management and batch CLI collection

Introduce workbench operations for multi-vendor NE CRUD/connect-test and Netmiko batch collection with job lifecycle controls, log downloads, and paginated run filters.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
oliver 2026-05-27 23:34:29 +08:00
parent 282dbe75af
commit 042c015045
36 changed files with 3695 additions and 17 deletions

View file

@ -18,14 +18,21 @@ const en = {
openInNewTab: "Open in new tab",
openModule: "Open or switch to this module tab",
monitoring: "Monitoring",
operations: "Operations",
cards: {
umeSync: "UME Sync",
umeSyncDesc: "UME alarms, subscription & inventory",
managedNe: "NE Management",
managedNeDesc: "Multi-vendor SSH/Telnet NEs & connectivity test",
collect: "Batch Collect",
collectDesc: "Run custom CLI commands on connected NEs and save logs",
},
},
layout: {
title: "UME Integration",
titleUme: "UME Sync",
titleManagedNe: "NE Management",
titleCollect: "Batch Collect",
navUme: "UME",
netxApi: "netx api",
oclawBridge: "oclaw bridge",
@ -34,6 +41,112 @@ const en = {
langZh: "中文",
langEn: "English",
},
collect: {
eligible: {
title: "Eligible NEs (connectivity passed)",
hint: "Only NEs with connect_status=pass. Run connectivity test in NE Management first.",
empty: "No NEs with passed connectivity test.",
},
form: {
title: "Collection setup",
jobTitle: "Job title",
jobTitlePh: "Auto-generated if empty",
commands: "Commands (one per line, # for comments)",
commandsPh: "display version\ndisplay current-configuration",
commandsHint: "Commands run in order on each device; output is saved as a text log (legacy NetX format).",
meta: "{{ne}} NE(s) selected · {{cmd}} command(s)",
start: "Start collection",
starting: "Submitting…",
},
started: "Collection job started: {{id}}",
paused: "Job paused",
restarted: "Collection restarted",
deleted: "Job deleted",
nothingToRetry: "No failed devices to retry",
confirmDelete: "Delete this collection job and its log files?",
jobs: {
title: "Collection jobs",
col: {
title: "Job",
status: "Status",
progress: "Progress",
created: "Created",
lastRun: "Last run",
actions: "Actions",
},
ok: "ok",
fail: "fail",
expand: "Details",
collapse: "Hide",
pause: "Pause",
restart: "Restart",
downloadResults: "Download results",
delete: "Delete",
autoRefresh: "Auto-refresh every 2s while jobs are running",
runsInProgress: "Some devices are still being collected…",
},
runs: {
status: "Status",
message: "Message",
download: "Log",
downloadFile: "Download",
filterStatus: "Status filter",
filterDevice: "Device filter",
deviceKeywordPh: "Name / IP",
allStatus: "All statuses",
},
},
managedNe: {
title: "Network Elements",
credsNotConfigured:
"NETX_CREDENTIAL_SECRET_KEY is not set. Configure a Fernet key in .env and restart the API to store passwords.",
add: "Add NE",
importBtn: "Import",
importing: "Importing…",
edit: "Edit",
delete: "Delete",
confirmDelete: "Delete this network element?",
keywordPh: "name / IP / user / tags",
allVendors: "All vendors",
allConnectStatus: "All connect status",
col: {
name: "Name",
vendor: "Vendor",
deviceType: "Device type",
ip: "Management IP",
port: "Port",
protocol: "Protocol",
user: "Username",
password: "Password",
tags: "Tags",
remark: "Remark",
connect: "Connect",
testedAt: "Tested at",
actions: "Actions",
},
connect: {
run: "Connectivity test",
running: "Testing…",
submitted: "Submitted tests for {{n}} device(s)",
},
importResult: {
done: "Import done: {{inserted}} inserted, {{updated}} updated, {{failed}} failed row(s)",
},
form: {
requiredHint: "Fields marked with * are required",
nameConnectHint: "After a successful connectivity test, name is replaced with the device hostname",
createTitle: "Add network element",
editTitle: "Edit network element",
save: "Save",
saving: "Saving…",
cancel: "Cancel",
created: "Network element created",
updated: "Network element updated",
deleted: "Network element deleted",
passwordRequired: "Password is required",
passwordOptional: "leave blank to keep unchanged",
},
},
ume: {
token: {
title: "UME Token",

View file

@ -18,14 +18,21 @@ const zh = {
openInNewTab: "在新标签页中打开",
openModule: "打开或切换到该模块页签",
monitoring: "监控",
operations: "运维",
cards: {
umeSync: "UME同步",
umeSyncDesc: "UME 告警同步、订阅与清单",
managedNe: "网元管理",
managedNeDesc: "多厂商 SSH/Telnet 网元与连通性测试",
collect: "批量采集",
collectDesc: "对已连通网元执行定制 CLI 命令并保存日志",
},
},
layout: {
title: "UME 对接",
titleUme: "UME同步",
titleManagedNe: "网元管理",
titleCollect: "批量采集",
navUme: "UME 对接",
netxApi: "netx api",
oclawBridge: "oclaw bridge",
@ -34,6 +41,111 @@ const zh = {
langZh: "中文",
langEn: "English",
},
collect: {
eligible: {
title: "可选网元(连通性已通过)",
hint: "仅展示 connect_status=pass 的网元。请先在「网元管理」完成连通性测试。",
empty: "暂无已通过连通性测试的网元。",
},
form: {
title: "采集配置",
jobTitle: "任务名称",
jobTitlePh: "留空则自动生成",
commands: "采集命令(每行一条,# 开头为注释)",
commandsPh: "display version\ndisplay current-configuration",
commandsHint: "命令将按顺序在每台设备上执行,输出合并为一份文本日志(格式与旧版 NetX 采集一致)。",
meta: "已选 {{ne}} 台网元 · {{cmd}} 条命令",
start: "开始采集",
starting: "提交中…",
},
started: "采集任务已启动:{{id}}",
paused: "任务已暂停",
restarted: "已重新开始采集",
deleted: "任务已删除",
nothingToRetry: "没有可重试的失败网元",
confirmDelete: "确定删除该采集任务?相关日志文件将一并删除。",
jobs: {
title: "采集任务",
col: {
title: "任务",
status: "状态",
progress: "进度",
created: "创建时间",
lastRun: "最近执行",
actions: "操作",
},
ok: "成功",
fail: "失败",
expand: "详情",
collapse: "收起",
pause: "暂停",
restart: "重新开始",
downloadResults: "下载结果",
delete: "删除",
autoRefresh: "任务进行中,每 2 秒自动刷新",
runsInProgress: "部分网元仍在采集中,请稍候…",
},
runs: {
status: "状态",
message: "说明",
download: "日志",
downloadFile: "下载",
filterStatus: "状态筛选",
filterDevice: "设备筛选",
deviceKeywordPh: "名称 / IP",
allStatus: "全部状态",
},
},
managedNe: {
title: "网元管理",
credsNotConfigured: "未配置 NETX_CREDENTIAL_SECRET_KEY,无法保存密码。请在 .env 中设置 Fernet 密钥后重启 API。",
add: "新增网元",
importBtn: "批量导入",
importing: "导入中…",
edit: "编辑",
delete: "删除",
confirmDelete: "确定删除该网元?",
keywordPh: "名称 / IP / 用户名 / 标签",
allVendors: "全部厂商",
allConnectStatus: "全部连通状态",
col: {
name: "名称",
vendor: "厂商",
deviceType: "设备类型",
ip: "管理地址",
port: "端口",
protocol: "协议",
user: "用户名",
password: "密码",
tags: "标签",
remark: "备注",
connect: "连通性",
testedAt: "测试时间",
actions: "操作",
},
connect: {
run: "连通性测试",
running: "测试中…",
submitted: "已提交 {{n}} 台设备测试",
},
importResult: {
done: "导入完成:新增 {{inserted}},更新 {{updated}},失败 {{failed}} 行",
},
form: {
requiredHint: "带 * 为必填项",
nameConnectHint: "连通性测试成功后将自动更新为设备名称",
createTitle: "新增网元",
editTitle: "编辑网元",
save: "保存",
saving: "保存中…",
cancel: "取消",
created: "网元已创建",
updated: "网元已更新",
deleted: "网元已删除",
passwordRequired: "请填写密码",
passwordOptional: "留空则不修改",
},
},
ume: {
token: {
title: "UME Token 状态",