调整网元配置模块

This commit is contained in:
lai
2024-08-02 18:55:53 +08:00
parent 8af48936e5
commit 8d8605e0cd

View File

@@ -1,6 +1,6 @@
<script setup lang="ts">
import { Modal, message } from 'ant-design-vue/lib';
import { onMounted, reactive, ref, toRaw } from 'vue';
import { nextTick, onMounted, reactive, ref, toRaw } from 'vue';
import {
addNeInfo,
delNeInfo,
@@ -15,6 +15,7 @@ import { regExpIPv4, regExpIPv6 } from '@/utils/regular-utils';
import { fnToStepName } from '../hooks/useStep';
import useI18n from '@/hooks/useI18n';
import useDictStore from '@/store/modules/dict';
const { getDict } = useDictStore();
const { t } = useI18n();
@@ -97,13 +98,6 @@ let tableState: any = reactive({
/**表格字段列 */
let tableColumns: any = [
{
title: t('common.operate'),
dataIndex: 'operation',
key: 'operation',
align: 'left',
width: 100,
},
{
title: t('views.ne.common.neType'),
dataIndex: 'neType',
@@ -132,6 +126,13 @@ let tableColumns: any = [
align: 'left',
width: 100,
},
{
title: t('common.operate'),
dataIndex: 'operation',
key: 'operation',
align: 'left',
width: 90,
},
];
/**
@@ -394,31 +395,70 @@ function fnStepPrev() {
});
}
/**下一步操作 先全部集体发过去请求新增 */
/**下一步操作 */
function fnStepNext(stepName: 'NeInfoConfigPara5G') {
if (stepName === 'NeInfoConfigPara5G') {
Modal.confirm({
title: t('common.tipTitle'),
content: t('views.system.quickStart.stepNeInfoStepNext'),
okButtonProps: {
loading: tabState.confirmLoading,
},
onOk() {
tabState.confirmLoading = true;
// 使用 Promise.allSettled 等待所有 Promise 完成
Promise.allSettled(
tabState.panes.map((item: any) =>
item.id ? updateNeInfo(item) : addNeInfo(item)
)
).finally(() => {
tabState.confirmLoading = false;
fnToStepName('NeInfoConfigPara5G');
});
fnToStepName('NeInfoConfigPara5G');
},
});
}
}
const editableData: any = reactive({});
const inputField = ref<HTMLInputElement | null>(null); // 定义输入框的 ref
//可编辑行
function edit(key: string) {
// 查找相关的项
const itemToEdit = tabState.panes.find((item: any) => key === item.key);
editableData[key] = { ...itemToEdit };
//聚焦input框
nextTick(() => {
if (inputField.value) {
inputField.value.focus();
}
});
}
//脱离input框时即保存
function save(key: string) {
const from = toRaw(tabState.panes.filter((item: any) => key === item.key)[0]);
if (editableData[key].ip !== from.ip) {
const fromData = Object.assign(from, editableData[key]);
//同步hosts下addr
for (const host of fromData.hosts) {
host.addr = fromData.ip;
}
updateNeInfo(fromData)
.then(res => {
if (res.code === RESULT_CODE_SUCCESS) {
message.success({
content: t('common.operateOk'),
duration: 3,
});
fnGetList();
} else {
message.error({
content: `${res.msg}`,
duration: 3,
});
}
})
.finally(() => {
fnModalCancel();
});
}
//退出编辑框
delete editableData[key];
}
/**获取列表 */
function fnGetList() {
listAllNeInfo({
@@ -426,13 +466,15 @@ function fnGetList() {
}).then(res => {
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) {
tabState.panes = [];
for (const item of res.data) {
if (item.neType === 'OMC' || !Array.isArray(item.hosts)) continue;
res.data.forEach((item: any, index: any) => {
if (item.neType === 'OMC' || !Array.isArray(item.hosts)) return;
item.key = index + 1;
tabState.panes.push(item);
}
});
}
});
}
//
onMounted(() => {
// 初始字典数据
@@ -471,7 +513,7 @@ onMounted(() => {
:scroll="{ y: 'calc(100vh - 480px)' }"
@resizeColumn="(w:number, col:any) => (col.width = w)"
>
<template #bodyCell="{ column, record }">
<template #bodyCell="{ column, text, record }">
<template v-if="column.key === 'operation'">
<a-space :size="8" align="center">
<a-tooltip>
@@ -495,284 +537,44 @@ onMounted(() => {
</a-tooltip>
</a-space>
</template>
<template v-if="column.dataIndex === 'ip'">
<div class="editable-cell">
<div
v-if="editableData[record.key]"
class="editable-cell-input-wrapper"
>
<a-input
ref="inputField"
v-model:value="editableData[record.key].ip"
@blur="save(record.key)"
/>
</div>
<div
v-else
class="editable-cell-text-wrapper"
@dblclick="edit(record.key)"
>
{{ text || ' ' }}
<edit-outlined
class="editable-cell-icon"
@click="edit(record.key)"
/>
</div>
</div>
</template>
</template>
</a-table>
<!-- 新增框或修改框 -->
<ProModal
:drag="true"
:width="800"
:destroyOnClose="true"
:keyboard="false"
:mask-closable="false"
:visible="modalState.visibleByEdit"
:title="modalState.title"
:confirm-loading="modalState.confirmLoading"
@ok="fnModalOk"
@cancel="fnModalCancel"
>
<a-form
name="modalStateFrom"
layout="horizontal"
:label-col="{ span: 6 }"
:labelWrap="true"
:model="modalState.from"
autocomplete="off"
>
<a-row :gutter="16">
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.ne.common.neType')"
name="neType"
:rules="{
required: true,
message: t('views.ne.common.neTypePlease'),
}"
>
<a-auto-complete
v-model:value="modalState.from.neType"
:options="
NE_TYPE_LIST.filter(s => s !== 'OMC').map(v => ({
value: v,
}))
"
@change="(v:any) => fnNeTypeChange(v, modalState.from)"
>
<a-input
allow-clear
:placeholder="t('views.ne.common.neTypePlease')"
:maxlength="32"
>
<template #prefix>
<a-tooltip placement="topLeft">
<template #title>
{{ t('views.ne.common.neTypeTip') }}
</template>
<InfoCircleOutlined style="color: rgba(0, 0, 0, 0.45)" />
</a-tooltip>
</template>
</a-input>
</a-auto-complete>
</a-form-item>
</a-col>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.ne.common.neId')"
name="neId"
:rules="{
required: true,
message: t('views.ne.common.neIdPlease'),
}"
>
<a-input
v-model:value="modalState.from.neId"
allow-clear
:placeholder="t('views.ne.common.neIdPlease')"
:maxlength="24"
>
<template #prefix>
<a-tooltip placement="topLeft">
<template #title>
{{ t('views.ne.common.neIdTip') }}
</template>
<InfoCircleOutlined style="color: rgba(0, 0, 0, 0.45)" />
</a-tooltip>
</template>
</a-input>
</a-form-item>
</a-col>
</a-row>
<a-row :gutter="16">
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.ne.common.ipAddr')"
name="ip"
:rules="[
{
required: true,
},
{
validator: modalStateFromEqualIPV4AndIPV6,
},
]"
>
<a-input
v-model:value="modalState.from.ip"
allow-clear
:placeholder="t('views.ne.common.ipAddrPlease')"
:maxlength="128"
@change="(e:any) => fnNeIPChange(e, modalState.from)"
>
<template #prefix>
<a-tooltip placement="topLeft">
<template #title>
<div>
{{ t('views.ne.common.ipAddrTip') }}
</div>
</template>
<InfoCircleOutlined style="color: rgba(0, 0, 0, 0.45)" />
</a-tooltip>
</template>
</a-input>
</a-form-item>
</a-col>
<a-col :lg="12" :md="12" :xs="24"> </a-col>
</a-row>
<template v-if="modalState.from.hosts.length > 0">
<a-divider orientation="left">
{{ t('views.ne.neInfo.hostConfig') }}
</a-divider>
<!-- 主机连接配置 -->
<a-row :gutter="16">
<a-col :lg="12" :md="12" :xs="24">
<a-form-item :label="t('views.ne.neHost.addr')">
<a-input
v-model:value="modalState.from.hosts[0].addr"
allow-clear
:maxlength="128"
:placeholder="t('common.inputPlease')"
>
</a-input>
</a-form-item>
</a-col>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item :label="t('views.ne.neHost.port')" name="port">
<a-input-number
v-model:value="modalState.from.hosts[0].port"
:min="10"
:max="65535"
:step="1"
:maxlength="5"
:placeholder="t('common.inputPlease')"
style="width: 100%"
></a-input-number>
</a-form-item>
</a-col>
</a-row>
<a-row :gutter="16">
<a-col :lg="12" :md="12" :xs="24">
<a-form-item :label="t('views.ne.neHost.user')">
<a-input
v-model:value="modalState.from.hosts[0].user"
allow-clear
:maxlength="32"
:placeholder="t('common.inputPlease')"
>
</a-input>
</a-form-item>
</a-col>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item :label="t('views.ne.neHost.authMode')">
<a-select
v-model:value="modalState.from.hosts[0].authMode"
default-value="0"
:options="dict.neHostAuthMode"
>
</a-select>
</a-form-item>
</a-col>
</a-row>
<a-form-item
v-if="modalState.from.hosts[0].authMode === '0'"
:label="t('views.ne.neHost.password')"
:label-col="{ span: 3 }"
:label-wrap="true"
>
<a-input-password
v-model:value="modalState.from.hosts[0].password"
:maxlength="128"
:placeholder="t('common.inputPlease')"
>
</a-input-password>
</a-form-item>
<template v-if="modalState.from.hosts[0].authMode === '1'">
<a-form-item
:label="t('views.ne.neHost.privateKey')"
:label-col="{ span: 3 }"
:label-wrap="true"
>
<a-textarea
v-model:value="modalState.from.hosts[0].privateKey"
:auto-size="{ minRows: 4, maxRows: 6 }"
:maxlength="3000"
:show-count="true"
:placeholder="t('views.ne.neHost.privateKeyPlease')"
/>
</a-form-item>
<a-form-item
:label="t('views.ne.neHost.passPhrase')"
:label-col="{ span: 3 }"
:label-wrap="true"
>
<a-input-password
v-model:value="modalState.from.hosts[0].passPhrase"
:maxlength="128"
:placeholder="t('common.inputPlease')"
>
</a-input-password>
</a-form-item>
</template>
<a-form-item
:label="t('views.ne.neHost.test')"
name="test"
:label-col="{ span: 3 }"
:label-wrap="true"
>
<a-button
type="dashed"
shape="round"
@click="fnHostTest(modalState.from.hosts[0])"
:disabled="tabState.confirmLoading"
>
<template #icon><LinkOutlined /></template>
</a-button>
<a-button
type="link"
@click="fnHostAuthorized(modalState.from.hosts[0])"
:disabled="tabState.confirmLoading"
v-if="
modalState.from.hosts[0].hostType === 'ssh' &&
modalState.from.hosts[0].authMode !== '2'
"
>
{{ t('views.ne.neHost.authRSA') }}
</a-button>
</a-form-item>
</template>
<!-- <a-form-item :wrapper-col="{ offset: 10, span: 4 }">
<a-button
type="primary"
ghost
html-type="submit"
:disabled="tabState.confirmLoading"
>
{{ t('views.system.quickStart.save') }}
</a-button>
</a-form-item> -->
</a-form>
</ProModal>
<div class="ne-oper">
<a-space direction="horizontal" :size="18">
<!-- 添加网元 -->
<a-button type="primary" @click.prevent="fnModalVisibleByEdit()">
<template #icon><PlusOutlined /></template>
{{ t('common.addText') }}
</a-button>
<a-button @click="fnStepPrev()" :disabled="tabState.confirmLoading">
{{ t('views.system.quickStart.exit') }}
</a-button>
<!-- 添加网元 -->
<a-button type="primary" ghost @click.prevent="fnModalVisibleByEdit()">
<template #icon><PlusOutlined /></template>
{{ t('common.addText') }}
</a-button>
<a-button
type="primary"
@@ -784,6 +586,270 @@ onMounted(() => {
</a-space>
</div>
</div>
<!-- 新增框或修改框 -->
<ProModal
:drag="true"
:width="800"
:destroyOnClose="true"
:keyboard="false"
:mask-closable="false"
:visible="modalState.visibleByEdit"
:title="modalState.title"
:confirm-loading="modalState.confirmLoading"
@ok="fnModalOk"
@cancel="fnModalCancel"
>
<a-form
name="modalStateFrom"
layout="horizontal"
:label-col="{ span: 6 }"
:labelWrap="true"
:model="modalState.from"
autocomplete="off"
>
<a-row :gutter="16">
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.ne.common.neType')"
name="neType"
:rules="{
required: true,
message: t('views.ne.common.neTypePlease'),
}"
>
<a-auto-complete
v-model:value="modalState.from.neType"
:options="
NE_TYPE_LIST.filter(s => s !== 'OMC').map(v => ({
value: v,
}))
"
@change="(v:any) => fnNeTypeChange(v, modalState.from)"
>
<a-input
allow-clear
:placeholder="t('views.ne.common.neTypePlease')"
:maxlength="32"
>
<template #prefix>
<a-tooltip placement="topLeft">
<template #title>
{{ t('views.ne.common.neTypeTip') }}
</template>
<InfoCircleOutlined style="color: rgba(0, 0, 0, 0.45)" />
</a-tooltip>
</template>
</a-input>
</a-auto-complete>
</a-form-item>
</a-col>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.ne.common.neId')"
name="neId"
:rules="{
required: true,
message: t('views.ne.common.neIdPlease'),
}"
>
<a-input
v-model:value="modalState.from.neId"
allow-clear
:placeholder="t('views.ne.common.neIdPlease')"
:maxlength="24"
>
<template #prefix>
<a-tooltip placement="topLeft">
<template #title>
{{ t('views.ne.common.neIdTip') }}
</template>
<InfoCircleOutlined style="color: rgba(0, 0, 0, 0.45)" />
</a-tooltip>
</template>
</a-input>
</a-form-item>
</a-col>
</a-row>
<a-row :gutter="16">
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
:label="t('views.ne.common.ipAddr')"
name="ip"
:rules="[
{
required: true,
},
{
validator: modalStateFromEqualIPV4AndIPV6,
},
]"
>
<a-input
v-model:value="modalState.from.ip"
allow-clear
:placeholder="t('views.ne.common.ipAddrPlease')"
:maxlength="128"
@change="(e:any) => fnNeIPChange(e, modalState.from)"
>
<template #prefix>
<a-tooltip placement="topLeft">
<template #title>
<div>
{{ t('views.ne.common.ipAddrTip') }}
</div>
</template>
<InfoCircleOutlined style="color: rgba(0, 0, 0, 0.45)" />
</a-tooltip>
</template>
</a-input>
</a-form-item>
</a-col>
<a-col :lg="12" :md="12" :xs="24"> </a-col>
</a-row>
<template v-if="modalState.from.hosts.length > 0">
<a-divider orientation="left">
{{ t('views.ne.neInfo.hostConfig') }}
</a-divider>
<!-- 主机连接配置 -->
<a-row :gutter="16">
<a-col :lg="12" :md="12" :xs="24">
<a-form-item :label="t('views.ne.neHost.addr')">
<a-input
v-model:value="modalState.from.hosts[0].addr"
allow-clear
:maxlength="128"
:placeholder="t('common.inputPlease')"
>
</a-input>
</a-form-item>
</a-col>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item :label="t('views.ne.neHost.port')" name="port">
<a-input-number
v-model:value="modalState.from.hosts[0].port"
:min="10"
:max="65535"
:step="1"
:maxlength="5"
:placeholder="t('common.inputPlease')"
style="width: 100%"
></a-input-number>
</a-form-item>
</a-col>
</a-row>
<a-row :gutter="16">
<a-col :lg="12" :md="12" :xs="24">
<a-form-item :label="t('views.ne.neHost.user')">
<a-input
v-model:value="modalState.from.hosts[0].user"
allow-clear
:maxlength="32"
:placeholder="t('common.inputPlease')"
>
</a-input>
</a-form-item>
</a-col>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item :label="t('views.ne.neHost.authMode')">
<a-select
v-model:value="modalState.from.hosts[0].authMode"
default-value="0"
:options="dict.neHostAuthMode"
>
</a-select>
</a-form-item>
</a-col>
</a-row>
<a-form-item
v-if="modalState.from.hosts[0].authMode === '0'"
:label="t('views.ne.neHost.password')"
:label-col="{ span: 3 }"
:label-wrap="true"
>
<a-input-password
v-model:value="modalState.from.hosts[0].password"
:maxlength="128"
:placeholder="t('common.inputPlease')"
>
</a-input-password>
</a-form-item>
<template v-if="modalState.from.hosts[0].authMode === '1'">
<a-form-item
:label="t('views.ne.neHost.privateKey')"
:label-col="{ span: 3 }"
:label-wrap="true"
>
<a-textarea
v-model:value="modalState.from.hosts[0].privateKey"
:auto-size="{ minRows: 4, maxRows: 6 }"
:maxlength="3000"
:show-count="true"
:placeholder="t('views.ne.neHost.privateKeyPlease')"
/>
</a-form-item>
<a-form-item
:label="t('views.ne.neHost.passPhrase')"
:label-col="{ span: 3 }"
:label-wrap="true"
>
<a-input-password
v-model:value="modalState.from.hosts[0].passPhrase"
:maxlength="128"
:placeholder="t('common.inputPlease')"
>
</a-input-password>
</a-form-item>
</template>
<a-form-item
:label="t('views.ne.neHost.test')"
name="test"
:label-col="{ span: 3 }"
:label-wrap="true"
>
<a-button
type="dashed"
shape="round"
@click="fnHostTest(modalState.from.hosts[0])"
:disabled="tabState.confirmLoading"
>
<template #icon><LinkOutlined /></template>
</a-button>
<a-button
type="link"
@click="fnHostAuthorized(modalState.from.hosts[0])"
:disabled="tabState.confirmLoading"
v-if="
modalState.from.hosts[0].hostType === 'ssh' &&
modalState.from.hosts[0].authMode !== '2'
"
>
{{ t('views.ne.neHost.authRSA') }}
</a-button>
</a-form-item>
</template>
<!-- <a-form-item :wrapper-col="{ offset: 10, span: 4 }">
<a-button
type="primary"
ghost
html-type="submit"
:disabled="tabState.confirmLoading"
>
{{ t('views.system.quickStart.save') }}
</a-button>
</a-form-item> -->
</a-form>
</ProModal>
</template>
<style lang="less" scoped>
@@ -807,4 +873,45 @@ onMounted(() => {
text-align: end;
}
}
.editable-cell {
position: relative;
.editable-cell-input-wrapper,
.editable-cell-text-wrapper {
padding-right: 24px;
}
.editable-cell-text-wrapper {
padding: 5px 24px 5px 5px;
}
.editable-cell-icon,
.editable-cell-icon-check {
position: absolute;
right: 0;
width: 20px;
cursor: pointer;
}
.editable-cell-icon {
margin-top: 4px;
display: none;
}
.editable-cell-icon-check {
line-height: 28px;
}
.editable-cell-icon:hover,
.editable-cell-icon-check:hover {
color: #108ee9;
}
.editable-add-btn {
margin-bottom: 8px;
}
}
.editable-cell:hover .editable-cell-icon {
display: inline-block;
}
</style>