feat(managed-ne): add bulk import template download with device_type reference sheet

Expose GET /v1/managed-ne/import/template and a workbench button to download xlsx/csv templates listing supported Netmiko device types.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
oliver 2026-05-28 09:41:25 +08:00
parent 042c015045
commit 3024e13812
6 changed files with 69 additions and 0 deletions

View file

@ -102,6 +102,7 @@ const en = {
"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",
downloadTemplate: "Download template",
importing: "Importing…",
edit: "Edit",
delete: "Delete",

View file

@ -101,6 +101,7 @@ const zh = {
credsNotConfigured: "未配置 NETX_CREDENTIAL_SECRET_KEY,无法保存密码。请在 .env 中设置 Fernet 密钥后重启 API。",
add: "新增网元",
importBtn: "批量导入",
downloadTemplate: "下载导入模板",
importing: "导入中…",
edit: "编辑",
delete: "删除",

View file

@ -7,6 +7,7 @@ import {
fetchManagedNe,
fetchManagedNeMeta,
importManagedNe,
managedNeImportTemplateUrl,
updateManagedNe,
} from "../services/api";
import { queryKeys } from "../constants/queryKeys";
@ -233,6 +234,12 @@ export function NePage() {
<button type="button" onClick={openCreate} disabled={!credsOk}>
{t("managedNe.add")}
</button>
<button
type="button"
onClick={() => window.location.assign(managedNeImportTemplateUrl("xlsx"))}
>
{t("managedNe.downloadTemplate")}
</button>
<button
type="button"
onClick={() => importRef.current?.click()}

View file

@ -129,6 +129,9 @@ export const deleteManagedNe = (id: string) => apiDelete<{ ok: boolean }>(`/v1/m
export const connectTestManagedNe = (ids: string[]) =>
apiPost<{ ok: boolean; submitted: number }>("/v1/managed-ne/connect-test", { ids });
export const managedNeImportTemplateUrl = (format: "xlsx" | "csv" = "xlsx") =>
`/v1/managed-ne/import/template?format=${format}`;
export const importManagedNe = async (file: File): Promise<ManagedNeImportResult> => {
const form = new FormData();
form.append("file", file);