feat: 快速安装页面

This commit is contained in:
TsMask
2024-04-11 17:35:19 +08:00
parent 3970797d5b
commit dc6f4560d5
9 changed files with 1126 additions and 343 deletions

View File

@@ -1,5 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { reactive, onMounted, toRaw, ref, onUnmounted } from 'vue'; import { reactive, onMounted, toRaw, onUnmounted } from 'vue';
import { message, Modal, Upload } from 'ant-design-vue/lib'; import { message, Modal, Upload } from 'ant-design-vue/lib';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants'; import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
import { useClipboard } from '@vueuse/core'; import { useClipboard } from '@vueuse/core';
@@ -21,8 +21,6 @@ const { t } = useI18n();
type LicenseStateType = { type LicenseStateType = {
/**步骤 */ /**步骤 */
setp: 'license' | 'verify'; setp: 'license' | 'verify';
/**主机ID */
hostId: string;
/**表单数据 */ /**表单数据 */
from: { from: {
neType: string; neType: string;
@@ -40,7 +38,6 @@ type LicenseStateType = {
/**授权激活对象信息状态 */ /**授权激活对象信息状态 */
const licenseState: LicenseStateType = reactive({ const licenseState: LicenseStateType = reactive({
setp: 'license', setp: 'license',
hostId: '',
from: { from: {
neType: '', neType: '',
neId: '', neId: '',
@@ -139,11 +136,10 @@ function fnGetCode() {
function fnRunCheck() { function fnRunCheck() {
if (licenseState.confirmLoading) return; if (licenseState.confirmLoading) return;
const form = toRaw(licenseState.from); const form = toRaw(licenseState.from);
if (form.activationRequestCode === '' || form.licensePath === '') { if (form.licensePath === '') {
message.error(t('common.errorFields', { num: 1 }), 3); message.error(t('common.errorFields', { num: 1 }), 3);
return; return;
} }
Object.assign(form, { hostId: licenseState.hostId });
licenseState.confirmLoading = true; licenseState.confirmLoading = true;
const hide = message.loading(t('common.loading'), 0); const hide = message.loading(t('common.loading'), 0);
changeNeLicense(form) changeNeLicense(form)
@@ -214,7 +210,6 @@ onMounted(() => {
const { neType, neId } = stepPrevFrom; const { neType, neId } = stepPrevFrom;
licenseState.from.neType = neType; licenseState.from.neType = neType;
licenseState.from.neId = neId; licenseState.from.neId = neId;
licenseState.hostId = stepPrevFrom.hostIds.split(',')[0];
// 获取code // 获取code
fnGetCode(); fnGetCode();
}); });
@@ -243,7 +238,7 @@ onUnmounted(() => {
<a-input <a-input
v-model:value="licenseState.from.activationRequestCode" v-model:value="licenseState.from.activationRequestCode"
:disabled="true" :disabled="true"
style="width: calc(100% - 200px)" style="width: calc(100% - 64px)"
/> />
<a-tooltip title="复制"> <a-tooltip title="复制">
<a-button type="default" @click="fnCopyCode()"> <a-button type="default" @click="fnCopyCode()">

View File

@@ -211,15 +211,15 @@ onMounted(() => {
dict.neHostAuthMode = resArr[0].value; dict.neHostAuthMode = resArr[0].value;
} }
}); });
// 状态还原 // 读取步骤:环境检查
const state = stepState.states[stepState.current]; const stepPrevFrom = stepState.states[0];
if (state) { if (stepPrevFrom) {
if (state.info) { if (stepPrevFrom.info) {
const info = toRaw(state.info); const info = toRaw(stepPrevFrom.info);
Object.assign(checkState.info, info); Object.assign(checkState.info, info);
} }
if (state.from) { if (stepPrevFrom.from) {
const from = toRaw(state.from); const from = toRaw(stepPrevFrom.from);
Object.assign(checkState.from, from); Object.assign(checkState.from, from);
} }
} }
@@ -244,7 +244,7 @@ onMounted(() => {
<template #label> <template #label>
平台 平台
<a-tooltip placement="topLeft"> <a-tooltip placement="topLeft">
<template #title> 支持 UbuntuUbuntu </template> <template #title> 支持 Ubuntu </template>
<InfoCircleOutlined style="color: rgba(0, 0, 0, 0.45)" /> <InfoCircleOutlined style="color: rgba(0, 0, 0, 0.45)" />
</a-tooltip> </a-tooltip>
</template> </template>

View File

@@ -1,5 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { reactive, onMounted, onBeforeMount } from 'vue'; import { reactive, onMounted, onBeforeMount, toRaw } from 'vue';
import { message } from 'ant-design-vue/lib'; import { message } from 'ant-design-vue/lib';
import { import {
RESULT_CODE_ERROR, RESULT_CODE_ERROR,
@@ -7,97 +7,97 @@ import {
} from '@/constants/result-constants'; } from '@/constants/result-constants';
import { stepState } from '../hooks/useStep'; import { stepState } from '../hooks/useStep';
import { getConfigFile, saveConfigFile } from '@/api/ne/neInfo'; import { getConfigFile, saveConfigFile } from '@/api/ne/neInfo';
import { parseDateToStr } from '@/utils/date-utils'; import useI18n from '@/hooks/useI18n';
const { t } = useI18n();
/**配置对象信息状态类型 */ /**配置对象信息状态类型 */
type ConfigState = { type ConfigState = {
/**展开指定的树节点 */ neType: string;
expandedKeys: string[]; neId: string;
/**设置选中的树节点 */ /**文件列表 */
selectedKeys: string[]; fileList: string[];
/**表单数据 */ /**OAM网管端配置 */
treeData: any[]; oam: Record<string, any>;
/**等待 loading */ oamFilePath: string;
treeLoading: boolean; /**确定按钮 loading */
/**选中的树节点 */ confirmLoading: boolean;
selected: { title: string; key: string };
/**设置选中的数据内容 */
keyTextData: string;
/**设置选中等待 loading */
keyTextLoading: boolean;
}; };
/**配置对象信息状态 */ /**配置对象信息状态 */
let configState: ConfigState = reactive({ let configState: ConfigState = reactive({
expandedKeys: ['000'], neType: '',
selectedKeys: ['oam_manager.yaml'], neId: '',
treeData: [ fileList: [],
{ oam: {
title: 'NE', httpManageCfg: {
key: '000', ipv4: '172.16.5.100',
children: [ port: 33030,
{
title: 'oam_manager',
key: 'oam_manager.yaml',
},
],
}, },
], oamConfig: {
treeLoading: false, enable: true,
selected: { title: 'oam_manager', key: 'oam_manager.yaml' }, neConfig: {
keyTextData: '...', dn: '-',
keyTextLoading: false, neId: '001',
neName: 'xxx_001',
pvFlag: 'PNF',
province: '-',
rmUid: '4400HX1xxx001',
vendorName: '',
},
ipv4: '172.16.5.100',
port: 33030,
},
snmpConfig: {
enable: false,
},
},
oamFilePath: '',
confirmLoading: false,
}); });
/**查询可选命令列表 */ /**查询配置文件或内容 */
function fnSelectConfigNode(_: any, info: any) {
const { title, key } = info.node;
configState.selectedKeys = [key];
configState.selected = { title, key };
fnGetConfigFile(key);
}
/**查询配置列表 */
function fnGetConfigFile(filePath: string = '') { function fnGetConfigFile(filePath: string = '') {
if (filePath) { if (filePath === '' && configState.confirmLoading) return;
if (configState.keyTextLoading) return; configState.confirmLoading = true;
configState.keyTextLoading = true; getConfigFile({
} else { neType: configState.neType,
if (configState.treeLoading) return; neId: configState.neId,
configState.treeLoading = true; filePath: filePath,
} fileType: 'yaml',
})
// 读取第二步的网元信息
const stepNeInfo = stepState.states[1].from;
getConfigFile(stepNeInfo.neType, stepNeInfo.neId, filePath)
.then(res => { .then(res => {
// 目录列表 // 目录列表
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) { if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) {
const treeItem = { configState.fileList = res.data;
title: stepNeInfo.neType, // 网管配置
key: stepNeInfo.neId, if (res.data.includes('oam_manager.yaml')) {
children: [] as any, configState.oamFilePath = 'oam_manager.yaml';
}; fnGetConfigFile(configState.oamFilePath);
treeItem.children = res.data.map((fileName: string) => {
return {
title: fileName.replace(/\.[^.]+$/, ''),
key: fileName,
};
});
configState.treeData = [treeItem];
configState.expandedKeys = [stepNeInfo.neId];
// 选中加载显示内容
if (treeItem.children.length > 0) {
const fileItem = treeItem.children[0];
configState.selectedKeys = [fileItem.key];
configState.selected = fileItem;
fnGetConfigFile(fileItem.key);
} }
return;
} }
// 单文件内容 // 单文件内容 yaml
if (res.code === RESULT_CODE_SUCCESS && typeof res.data === 'string') { if (res.code === RESULT_CODE_SUCCESS && typeof res.data === 'object') {
configState.keyTextData = res.data; if (filePath.startsWith('oam_manager')) {
configState.oam = res.data;
// 读取第二步的网元信息
const stepNeInfo = stepState.states[1].from;
configState.oam.snmpConfig.enable = false;
configState.oam.oamConfig.enable = true;
configState.oam.oamConfig.neConfig = {
dn: stepNeInfo.db,
neId: stepNeInfo.neId,
neName: stepNeInfo.neName,
pvFlag: stepNeInfo.pvFlag,
province: stepNeInfo.province,
rmUid: stepNeInfo.rmUid,
vendorName: stepNeInfo.vendorName,
};
}
return;
} }
// 出错 // 出错
@@ -109,119 +109,133 @@ function fnGetConfigFile(filePath: string = '') {
} }
}) })
.finally(() => { .finally(() => {
if (filePath) { configState.confirmLoading = false;
configState.keyTextLoading = false;
} else {
configState.treeLoading = false;
}
}); });
} }
/**保存配置文件 */ /**保存配置文件 */
function fnSaveConfigFile() { function fnSaveConfigFile() {
if (configState.keyTextLoading) return; if (configState.confirmLoading) return;
// 读取第二步的网元信息 configState.confirmLoading = true;
const stepNeInfo = stepState.states[1].from; const hide = message.loading(t('common.loading'), 0);
saveConfigFile({ const data = {
neType: stepNeInfo.neType, neType: configState.neType,
neId: stepNeInfo.neId, neId: configState.neId,
filePath: configState.selected.key, fileType: 'yaml',
content: configState.keyTextData, filePath: '',
content: '',
sync: true, // 同步到网元 sync: true, // 同步到网元
}) };
// 配置信息
const oamData = toRaw(configState.oam);
saveConfigFile(
Object.assign(data, {
filePath: configState.oamFilePath,
content: oamData,
})
)
.then(res => { .then(res => {
if (res.code === RESULT_CODE_SUCCESS) { if (res.code === RESULT_CODE_SUCCESS) {
saveState.saveTime = parseDateToStr(new Date(), 'HH:mm:ss'); message.success({
content: '保存成功',
duration: 3,
});
// 记录当前步骤状态信息 // 记录当前步骤状态信息
stepState.states[stepState.current] = { stepState.states[stepState.current] = {
treeData: configState.treeData, oam: oamData,
}; };
stepState.stepNext = true; stepState.stepNext = true;
} else { } else {
message.error({ message.error({
content: res.msg, content: '保存失败',
duration: 3, duration: 3,
}); });
} }
}) })
.finally(() => { .finally(() => {
saveState.timer = null; hide();
configState.confirmLoading = false;
}); });
} }
/**保存文件数据状态 */
const saveState = reactive({
timer: null as any,
saveTime: '',
});
/**文件数据变更 */
function fnChangekeyTextData(val: string) {
console.log(val);
// 在用户停止输入3秒后执行保存请求的操作
if (saveState.timer) {
clearTimeout(saveState.timer);
}
stepState.stepNext = false;
saveState.timer = setTimeout(fnSaveConfigFile, 3_000);
}
onMounted(() => { onMounted(() => {
// 读取第二步的网元信息
const stepNeInfo = stepState.states[1].from;
configState.neType = stepNeInfo.neType;
configState.neId = stepNeInfo.neId;
// 读取文件列表
fnGetConfigFile(); fnGetConfigFile();
}); });
onBeforeMount(() => { onBeforeMount(() => {});
clearTimeout(saveState.timer);
});
</script> </script>
<template> <template>
<a-row :gutter="8"> <a-form
<a-col :lg="6" :md="6" :xs="24"> name="modalStateFrom"
<a-spin :spinning="configState.treeLoading"> layout="horizontal"
<a-directory-tree :label-col="{ span: 6 }"
v-model:expandedKeys="configState.expandedKeys" :labelWrap="true"
v-model:selectedKeys="configState.selectedKeys" >
@select="fnSelectConfigNode" <div>网管端配置</div>
:tree-data="configState.treeData" {{ configState.oam }}
></a-directory-tree> <a-row :gutter="16">
</a-spin> <a-col :lg="12" :md="12" :xs="24">
</a-col> <a-form-item label="httpManageCfg.ipv4" name="ipv4">
<a-col :lg="18" :md="18" :xs="24"> <a-input
<a-spin :spinning="configState.treeLoading || configState.keyTextLoading"> v-model:value="configState.oam.httpManageCfg.ipv4"
<CodemirrorEdite allow-clear
v-model:value="configState.keyTextData" :placeholder="t('common.inputPlease')"
:disabled="configState.keyTextLoading" :maxlength="32"
lang="yaml" ></a-input>
height="500px" </a-form-item>
@change="fnChangekeyTextData" </a-col>
></CodemirrorEdite> <a-col :lg="12" :md="12" :xs="24">
<div <a-form-item label="httpManageCfg.port" name="port">
class="edite-tip" <a-input
:class="{ 'edite-tip__ing': saveState.timer > 0 }" v-model:value="configState.oam.httpManageCfg.port"
> allow-clear
{{ configState.selected.title }} :placeholder="t('common.inputPlease')"
<template v-if="saveState.saveTime.length > 1"> :maxlength="32"
| 最近保存: {{ saveState.saveTime }} ></a-input>
</template> </a-form-item>
</div> </a-col>
</a-spin> </a-row>
</a-col> <a-row :gutter="16">
</a-row> <a-col :lg="12" :md="12" :xs="24">
<a-form-item label="oamconfig.ipv4" name="ipv4">
<a-input
v-model:value="configState.oam.oamConfig.ipv4"
allow-clear
:placeholder="t('common.inputPlease')"
:maxlength="32"
></a-input>
</a-form-item>
</a-col>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item label="oamconfig.port" name="port">
<a-input
v-model:value="configState.oam.oamConfig.port"
allow-clear
:placeholder="t('common.inputPlease')"
:maxlength="32"
></a-input>
</a-form-item>
</a-col>
</a-row>
<a-form-item :wrapper-col="{ span: 14, offset: 3 }">
<a-button
type="primary"
html-type="submit"
@click="fnSaveConfigFile()"
:loading="configState.confirmLoading"
>
保存配置
</a-button>
</a-form-item>
</a-form>
</template> </template>
<style lang="less" scoped> <style lang="less" scoped></style>
.edite-tip {
min-height: 24px;
padding: 0 4px;
color: #fff;
line-height: 24px;
background: var(--ant-primary-color);
border-radius: 2px;
cursor: pointer;
transition: all 0.3s, border 0s, line-height 0s, box-shadow 0s;
&__ing {
background: var(--ant-primary-color-disabled);
}
}
</style>

View File

@@ -0,0 +1,242 @@
<script setup lang="ts">
import { reactive, onMounted, onBeforeMount, toRaw } from 'vue';
import { message } from 'ant-design-vue/lib';
import {
RESULT_CODE_ERROR,
RESULT_CODE_SUCCESS,
} from '@/constants/result-constants';
import { stepState } from '../hooks/useStep';
import { getConfigFile, saveConfigFile } from '@/api/ne/neInfo';
import useI18n from '@/hooks/useI18n';
const { t } = useI18n();
/**配置对象信息状态类型 */
type ConfigState = {
neType: string;
neId: string;
/**文件列表 */
fileList: string[];
/**OAM网管端配置 */
oam: Record<string, any>;
oamFilePath: string;
/**确定按钮 loading */
confirmLoading: boolean;
};
/**配置对象信息状态 */
let configState: ConfigState = reactive({
neType: '',
neId: '',
fileList: [],
oam: {
httpmanagecfg: {
ipv4: '172.16.5.110',
port: 33030,
},
oamconfig: {
enable: true,
neconfig: {
dn: '-',
neId: '001',
neName: 'IMS_001',
pVFlag: 'PNF',
province: '-',
rmUID: '4400HX1IMS001',
vendorName: '',
},
ipv4: '172.16.5.100',
port: 33030,
},
snmpconfig: {
enable: false,
},
},
oamFilePath: '',
cfg: {},
cfgFilePath: '',
confirmLoading: false,
});
/**查询配置文件或内容 */
function fnGetConfigFile(filePath: string = '') {
if (filePath === '' && configState.confirmLoading) return;
configState.confirmLoading = true;
getConfigFile({
neType: configState.neType,
neId: configState.neId,
filePath: filePath,
fileType: 'yaml',
})
.then(res => {
// 目录列表
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) {
configState.fileList = res.data;
// 网管配置
if (res.data.includes('oam_manager.yaml')) {
configState.oamFilePath = 'oam_manager.yaml';
fnGetConfigFile(configState.oamFilePath);
}
return;
}
// 单文件内容 yaml
if (res.code === RESULT_CODE_SUCCESS && typeof res.data === 'object') {
if (filePath.startsWith('oam_manager')) {
configState.oam = res.data;
// 读取第二步的网元信息
const stepNeInfo = stepState.states[1].from;
configState.oam.snmpconfig.enable = false;
configState.oam.oamconfig.enable = true;
configState.oam.oamconfig.neconfig = {
dn: stepNeInfo.db,
neId: stepNeInfo.neId,
neName: stepNeInfo.neName,
pVFlag: stepNeInfo.pvFlag,
province: stepNeInfo.province,
rmUID: stepNeInfo.rmUid,
vendorName: stepNeInfo.vendorName,
};
}
return;
}
// 出错
if (res.code === RESULT_CODE_ERROR) {
message.error({
content: res.msg,
duration: 3,
});
}
})
.finally(() => {
configState.confirmLoading = false;
});
}
/**保存配置文件 */
function fnSaveConfigFile() {
if (configState.confirmLoading) return;
configState.confirmLoading = true;
const hide = message.loading(t('common.loading'), 0);
const data = {
neType: configState.neType,
neId: configState.neId,
fileType: 'yaml',
filePath: '',
content: '',
sync: true, // 同步到网元
};
// 配置信息
const oamData = toRaw(configState.oam);
saveConfigFile(
Object.assign(data, {
filePath: configState.oamFilePath,
content: oamData,
})
)
.then(res => {
if (res.code === RESULT_CODE_SUCCESS) {
message.success({
content: '保存成功',
duration: 3,
});
// 记录当前步骤状态信息
stepState.states[stepState.current] = {
oam: oamData,
};
stepState.stepNext = true;
} else {
message.error({
content: '保存失败',
duration: 3,
});
}
})
.finally(() => {
hide();
configState.confirmLoading = false;
});
}
onMounted(() => {
// 读取第二步的网元信息
const stepNeInfo = stepState.states[1].from;
configState.neType = stepNeInfo.neType;
configState.neId = stepNeInfo.neId;
// 读取文件列表
fnGetConfigFile();
});
onBeforeMount(() => {});
</script>
<template>
<a-form
name="modalStateFrom"
layout="horizontal"
:label-col="{ span: 6 }"
:labelWrap="true"
>
<div>网管端配置</div>
<a-row :gutter="16">
<a-col :lg="12" :md="12" :xs="24">
<a-form-item label="httpmanagecfg.ipv4" name="ipv4">
<a-input
v-model:value="configState.oam.httpmanagecfg.ipv4"
allow-clear
:placeholder="t('common.inputPlease')"
:maxlength="32"
></a-input>
</a-form-item>
</a-col>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item label="httpmanagecfg.port" name="port">
<a-input
v-model:value="configState.oam.httpmanagecfg.port"
allow-clear
:placeholder="t('common.inputPlease')"
:maxlength="32"
></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="oamconfig.ipv4" name="ipv4">
<a-input
v-model:value="configState.oam.oamconfig.ipv4"
allow-clear
:placeholder="t('common.inputPlease')"
:maxlength="32"
></a-input>
</a-form-item>
</a-col>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item label="oamconfig.port" name="port">
<a-input
v-model:value="configState.oam.oamconfig.port"
allow-clear
:placeholder="t('common.inputPlease')"
:maxlength="32"
></a-input>
</a-form-item>
</a-col>
</a-row>
<a-form-item :wrapper-col="{ span: 14, offset: 3 }">
<a-button
type="primary"
html-type="submit"
@click="fnSaveConfigFile()"
:loading="configState.confirmLoading"
>
保存配置
</a-button>
</a-form-item>
</a-form>
</template>
<style lang="less" scoped></style>

View File

@@ -0,0 +1,310 @@
<script setup lang="ts">
import { reactive, onMounted, onBeforeMount, toRaw } from 'vue';
import { message } from 'ant-design-vue/lib';
import {
RESULT_CODE_ERROR,
RESULT_CODE_SUCCESS,
} from '@/constants/result-constants';
import { stepState } from '../hooks/useStep';
import { getConfigFile, saveConfigFile } from '@/api/ne/neInfo';
import useI18n from '@/hooks/useI18n';
const { t } = useI18n();
/**配置对象信息状态类型 */
type ConfigState = {
neType: string;
neId: string;
/**文件列表 */
fileList: string[];
/**OAM网管端配置 */
oam: Record<string, any>;
oamFilePath: string;
/**网元主要配置 */
cfg: Record<string, any>;
cfgFilePath: string;
/**确定按钮 loading */
confirmLoading: boolean;
};
/**配置对象信息状态 */
let configState: ConfigState = reactive({
neType: '',
neId: '',
fileList: [],
oam: {
httpmanagecfg: {
ipv4: '172.16.5.150',
port: 33030,
},
oamconfig: {
enable: true,
neconfig: {
dn: '-',
neId: '001',
neName: 'SMF_001',
pVFlag: 'PNF',
province: '-',
rmUID: '4400HX1SMF001',
vendorName: '',
},
ipv4: '172.16.5.100',
port: 33030,
},
snmpconfig: {
enable: false,
},
},
oamFilePath: '',
cfg: {
localconfig: {
n4interfacecfg: {
ipv4: '172.16.5.150',
port: 8805,
},
telnetip: '172.16.5.150',
},
},
cfgFilePath: '',
confirmLoading: false,
});
/**查询配置文件或内容 */
function fnGetConfigFile(filePath: string = '') {
if (filePath === '' && configState.confirmLoading) return;
configState.confirmLoading = true;
getConfigFile({
neType: configState.neType,
neId: configState.neId,
filePath: filePath,
fileType: 'yaml',
})
.then(res => {
// 目录列表
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) {
configState.fileList = res.data;
// 网管配置
if (res.data.includes('oam_manager.yaml')) {
configState.oamFilePath = 'oam_manager.yaml';
fnGetConfigFile(configState.oamFilePath);
}
// 网元配置
if (res.data.includes('smf_conf.yaml')) {
configState.cfgFilePath = 'smf_conf.yaml';
fnGetConfigFile(configState.cfgFilePath);
}
return;
}
// 单文件内容 yaml
if (res.code === RESULT_CODE_SUCCESS && typeof res.data === 'object') {
if (filePath.startsWith('oam_manager')) {
configState.oam = res.data;
// 读取第二步的网元信息
const stepNeInfo = stepState.states[1].from;
configState.oam.snmpconfig.enable = false;
configState.oam.oamconfig.enable = true;
configState.oam.oamconfig.neconfig = {
dn: stepNeInfo.db,
neId: stepNeInfo.neId,
neName: stepNeInfo.neName,
pVFlag: stepNeInfo.pvFlag,
province: stepNeInfo.province,
rmUID: stepNeInfo.rmUid,
vendorName: stepNeInfo.vendorName,
};
}
if (filePath.startsWith('smf_conf')) {
configState.cfg = res.data;
}
return;
}
// 出错
if (res.code === RESULT_CODE_ERROR) {
message.error({
content: res.msg,
duration: 3,
});
}
})
.finally(() => {
configState.confirmLoading = false;
});
}
/**保存配置文件 */
function fnSaveConfigFile() {
if (configState.confirmLoading) return;
configState.confirmLoading = true;
const hide = message.loading(t('common.loading'), 0);
const data = {
neType: configState.neType,
neId: configState.neId,
fileType: 'yaml',
filePath: '',
content: '',
sync: true, // 同步到网元
};
// 配置信息
const oamData = toRaw(configState.oam);
const cfgData = toRaw(configState.cfg);
Promise.all([
saveConfigFile(
Object.assign(data, {
filePath: configState.oamFilePath,
content: oamData,
})
),
saveConfigFile(
Object.assign(data, {
filePath: configState.cfgFilePath,
content: cfgData,
})
),
])
.then(resArr => {
if (
resArr[0].code === RESULT_CODE_SUCCESS &&
resArr[1].code === RESULT_CODE_SUCCESS
) {
message.success({
content: '保存成功',
duration: 3,
});
// 记录当前步骤状态信息
stepState.states[stepState.current] = {
oam: oamData,
cfg: cfgData,
};
stepState.stepNext = true;
} else {
message.error({
content: '保存失败',
duration: 3,
});
}
})
.finally(() => {
hide();
configState.confirmLoading = false;
});
}
onMounted(() => {
// 读取第二步的网元信息
const stepNeInfo = stepState.states[1].from;
configState.neType = stepNeInfo.neType;
configState.neId = stepNeInfo.neId;
// 读取文件列表
fnGetConfigFile();
});
onBeforeMount(() => {});
</script>
<template>
<a-form
name="modalStateFrom"
layout="horizontal"
:label-col="{ span: 6 }"
:labelWrap="true"
>
<div>网管端配置</div>
<a-row :gutter="16">
<a-col :lg="12" :md="12" :xs="24">
<a-form-item label="httpmanagecfg.ipv4" name="ipv4">
<a-input
v-model:value="configState.oam.httpmanagecfg.ipv4"
allow-clear
:placeholder="t('common.inputPlease')"
:maxlength="32"
></a-input>
</a-form-item>
</a-col>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item label="httpmanagecfg.port" name="port">
<a-input
v-model:value="configState.oam.httpmanagecfg.port"
allow-clear
:placeholder="t('common.inputPlease')"
:maxlength="32"
></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="oamconfig.ipv4" name="ipv4">
<a-input
v-model:value="configState.oam.oamconfig.ipv4"
allow-clear
:placeholder="t('common.inputPlease')"
:maxlength="32"
></a-input>
</a-form-item>
</a-col>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item label="oamconfig.port" name="port">
<a-input
v-model:value="configState.oam.oamconfig.port"
allow-clear
:placeholder="t('common.inputPlease')"
:maxlength="32"
></a-input>
</a-form-item>
</a-col>
</a-row>
<div>网元端配置</div>
<a-row :gutter="16">
<a-col :lg="12" :md="12" :xs="24">
<a-form-item label="localconfig.n4interfacecfg.ipv4" name="ipv4">
<a-input
v-model:value="configState.cfg.localconfig.n4interfacecfg.ipv4"
allow-clear
:placeholder="t('common.inputPlease')"
:maxlength="32"
></a-input>
</a-form-item>
</a-col>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item label="localconfig.n4interfacecfg.port" name="port">
<a-input
v-model:value="configState.cfg.localconfig.n4interfacecfg.port"
allow-clear
:placeholder="t('common.inputPlease')"
:maxlength="32"
></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="localconfig.telnetip" name="telnetip">
<a-input
v-model:value="configState.cfg.localconfig.telnetip"
allow-clear
:placeholder="t('common.inputPlease')"
:maxlength="32"
></a-input>
</a-form-item>
</a-col>
<a-col :lg="12" :md="12" :xs="24"> </a-col>
</a-row>
<a-form-item :wrapper-col="{ span: 14, offset: 3 }">
<a-button
type="primary"
html-type="submit"
@click="fnSaveConfigFile()"
:loading="configState.confirmLoading"
>
保存配置
</a-button>
</a-form-item>
</a-form>
</template>
<style lang="less" scoped></style>

View File

@@ -0,0 +1,232 @@
<script setup lang="ts">
import { reactive, onMounted, onBeforeMount } from 'vue';
import { message } from 'ant-design-vue/lib';
import {
RESULT_CODE_ERROR,
RESULT_CODE_SUCCESS,
} from '@/constants/result-constants';
import { stepState } from '../hooks/useStep';
import { getConfigFile, saveConfigFile } from '@/api/ne/neInfo';
import { parseDateToStr } from '@/utils/date-utils';
/**配置对象信息状态类型 */
type ConfigState = {
/**展开指定的树节点 */
expandedKeys: string[];
/**设置选中的树节点 */
selectedKeys: string[];
/**表单数据 */
treeData: any[];
/**等待 loading */
treeLoading: boolean;
/**选中的树节点 */
selected: { title: string; key: string };
/**设置选中的数据内容 */
keyTextData: string;
/**设置选中等待 loading */
keyTextLoading: boolean;
};
/**配置对象信息状态 */
let configState: ConfigState = reactive({
expandedKeys: ['000'],
selectedKeys: ['oam_manager.yaml'],
treeData: [
{
title: 'NE',
key: '000',
children: [
{
title: 'oam_manager',
key: 'oam_manager.yaml',
},
],
},
],
treeLoading: false,
selected: { title: 'oam_manager', key: 'oam_manager.yaml' },
keyTextData: '...',
keyTextLoading: false,
});
/**查询可选命令列表 */
function fnSelectConfigNode(_: any, info: any) {
const { title, key } = info.node;
configState.selectedKeys = [key];
configState.selected = { title, key };
fnGetConfigFile(key);
}
/**查询配置列表 */
function fnGetConfigFile(filePath: string = '') {
if (filePath) {
if (configState.keyTextLoading) return;
configState.keyTextLoading = true;
} else {
if (configState.treeLoading) return;
configState.treeLoading = true;
}
// 读取第二步的网元信息
const stepNeInfo = stepState.states[1].from;
getConfigFile({
neType: stepNeInfo.neType,
neId: stepNeInfo.neId,
filePath: filePath,
fileType: 'txt',
})
.then(res => {
// 目录列表
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) {
const treeItem = {
title: stepNeInfo.neType,
key: stepNeInfo.neId,
children: [] as any,
};
treeItem.children = res.data.map((fileName: string) => {
return {
title: fileName.replace(/\.[^.]+$/, ''),
key: fileName,
};
});
configState.treeData = [treeItem];
configState.expandedKeys = [stepNeInfo.neId];
// 选中加载显示内容
if (treeItem.children.length > 0) {
const fileItem = treeItem.children[0];
configState.selectedKeys = [fileItem.key];
configState.selected = fileItem;
fnGetConfigFile(fileItem.key);
}
}
// 单文件内容
if (res.code === RESULT_CODE_SUCCESS && typeof res.data === 'string') {
configState.keyTextData = res.data;
}
// 出错
if (res.code === RESULT_CODE_ERROR) {
message.error({
content: res.msg,
duration: 3,
});
}
})
.finally(() => {
if (filePath) {
configState.keyTextLoading = false;
} else {
configState.treeLoading = false;
}
});
}
/**保存配置文件 */
function fnSaveConfigFile() {
if (configState.keyTextLoading) return;
// 读取第二步的网元信息
const stepNeInfo = stepState.states[1].from;
saveConfigFile({
neType: stepNeInfo.neType,
neId: stepNeInfo.neId,
filePath: configState.selected.key,
content: configState.keyTextData,
sync: true, // 同步到网元
})
.then(res => {
if (res.code === RESULT_CODE_SUCCESS) {
saveState.saveTime = parseDateToStr(new Date(), 'HH:mm:ss');
// 记录当前步骤状态信息
stepState.states[stepState.current] = {
treeData: configState.treeData,
};
stepState.stepNext = true;
} else {
message.error({
content: res.msg,
duration: 3,
});
}
})
.finally(() => {
saveState.timer = null;
});
}
/**保存文件数据状态 */
const saveState = reactive({
timer: null as any,
saveTime: '',
});
/**文件数据变更 */
function fnChangekeyTextData(val: string) {
console.log(val);
// 在用户停止输入3秒后执行保存请求的操作
if (saveState.timer) {
clearTimeout(saveState.timer);
}
stepState.stepNext = false;
saveState.timer = setTimeout(fnSaveConfigFile, 3_000);
}
onMounted(() => {
fnGetConfigFile();
});
onBeforeMount(() => {
clearTimeout(saveState.timer);
});
</script>
<template>
<a-row :gutter="8">
<a-col :lg="6" :md="6" :xs="24">
<a-spin :spinning="configState.treeLoading">
<a-directory-tree
v-model:expandedKeys="configState.expandedKeys"
v-model:selectedKeys="configState.selectedKeys"
@select="fnSelectConfigNode"
:tree-data="configState.treeData"
></a-directory-tree>
</a-spin>
</a-col>
<a-col :lg="18" :md="18" :xs="24">
<a-spin :spinning="configState.treeLoading || configState.keyTextLoading">
<CodemirrorEdite
v-model:value="configState.keyTextData"
:disabled="configState.keyTextLoading"
lang="yaml"
height="500px"
@change="fnChangekeyTextData"
></CodemirrorEdite>
<div
class="edite-tip"
:class="{ 'edite-tip__ing': saveState.timer > 0 }"
>
{{ configState.selected.title }}
<template v-if="saveState.saveTime.length > 1">
| 最近保存: {{ saveState.saveTime }}
</template>
</div>
</a-spin>
</a-col>
</a-row>
</template>
<style lang="less" scoped>
.edite-tip {
min-height: 24px;
padding: 0 4px;
color: #fff;
line-height: 24px;
background: var(--ant-primary-color);
border-radius: 2px;
cursor: pointer;
transition: all 0.3s, border 0s, line-height 0s, box-shadow 0s;
&__ing {
background: var(--ant-primary-color-disabled);
}
}
</style>

View File

@@ -1,22 +1,17 @@
<script setup lang="ts"> <script setup lang="ts">
import { reactive, onMounted, toRaw, ref } from 'vue'; import { reactive, onMounted, toRaw } from 'vue';
import { message, Form, Upload } from 'ant-design-vue/lib'; import { message, Form, Upload } from 'ant-design-vue/lib';
import useI18n from '@/hooks/useI18n'; import useI18n from '@/hooks/useI18n';
import { import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
RESULT_CODE_ERROR,
RESULT_CODE_SUCCESS,
} from '@/constants/result-constants';
import { NE_TYPE_LIST } from '@/constants/ne-constants'; import { NE_TYPE_LIST } from '@/constants/ne-constants';
import TerminalSSH from '@/components/TerminalSSH/index.vue';
import { ColumnsType } from 'ant-design-vue/lib/table'; import { ColumnsType } from 'ant-design-vue/lib/table';
import { checkInstallNeSoftware, listNeSoftware } from '@/api/ne/neSoftware'; import { installNeSoftware, listNeSoftware } from '@/api/ne/neSoftware';
import { parseDateToStr } from '@/utils/date-utils'; import { parseDateToStr } from '@/utils/date-utils';
import { FileType } from 'ant-design-vue/lib/upload/interface'; import { FileType } from 'ant-design-vue/lib/upload/interface';
import { UploadRequestOption } from 'ant-design-vue/lib/vc-upload/interface'; import { UploadRequestOption } from 'ant-design-vue/lib/vc-upload/interface';
import { uploadFileChunk } from '@/api/tool/file'; import { uploadFileChunk } from '@/api/tool/file';
import { stepState } from '../hooks/useStep'; import { stepState } from '../hooks/useStep';
const { t } = useI18n(); const { t } = useI18n();
const emit = defineEmits(['next']);
/**表格字段列 */ /**表格字段列 */
let tableColumns: ColumnsType = [ let tableColumns: ColumnsType = [
@@ -33,9 +28,9 @@ let tableColumns: ColumnsType = [
width: 100, width: 100,
}, },
{ {
title: 'fileName', title: 'name',
dataIndex: 'fileName', dataIndex: 'name',
key: 'fileName', key: 'name',
align: 'left', align: 'left',
width: 300, width: 300,
}, },
@@ -46,20 +41,20 @@ let tableColumns: ColumnsType = [
width: 100, width: 100,
}, },
{ {
title: 'comment', title: 'description',
dataIndex: 'comment', dataIndex: 'description',
key: 'comment', key: 'description',
align: 'left', align: 'left',
ellipsis: true, ellipsis: true,
}, },
{ {
title: 'updateTime', title: 'createTime',
dataIndex: 'updateTime', dataIndex: 'createTime',
align: 'left', align: 'left',
width: 150, width: 150,
customRender(opt) { customRender(opt) {
if (!opt.value) return ''; if (!opt.value) return '';
return parseDateToStr(opt.value); return parseDateToStr(+opt.value);
}, },
}, },
]; ];
@@ -155,9 +150,9 @@ function fnGetList(pageNum?: number) {
/**安装对象信息状态类型 */ /**安装对象信息状态类型 */
type InstallStateType = { type InstallStateType = {
/**步骤 */ /**步骤 */
setp: 'pkg' | 'preinput' | 'ssh'; setp: 'pkg' | 'preinput' | 'log';
/**安装步骤命令 */ /**步骤日志输出 */
setpSSHArr: string[]; setpLog: string;
/**主机ID */ /**主机ID */
hostId: string; hostId: string;
/**文件操作类型 上传 or 选择 */ /**文件操作类型 上传 or 选择 */
@@ -182,7 +177,7 @@ type InstallStateType = {
/**安装对象信息状态 */ /**安装对象信息状态 */
let installState: InstallStateType = reactive({ let installState: InstallStateType = reactive({
setp: 'pkg', setp: 'pkg',
setpSSHArr: [], setpLog: '',
hostId: '', hostId: '',
optionType: 'upload', optionType: 'upload',
from: { from: {
@@ -200,6 +195,7 @@ let installState: InstallStateType = reactive({
mcc: '001', mcc: '001',
mnc: '01', mnc: '01',
priIP: '172.16.16.51', priIP: '172.16.16.51',
pisCSCF: 'true',
}, },
}); });
@@ -315,25 +311,14 @@ function fnUploadFile(up: UploadRequestOption) {
}); });
} }
/**软件包运行检查 */ /**软件包检查 */
function fnRunCheck() { function fnRunCheck() {
if (installState.confirmLoading) return; if (installState.confirmLoading) return;
const hide = message.loading(t('common.loading'), 0); const hide = message.loading(t('common.loading'), 0);
installStateFrom installStateFrom
.validate() .validate()
.then(() => { .then(() => {
const form = toRaw(installState.from); installState.setp = 'preinput';
Object.assign(form, { hostId: installState.hostId });
installState.confirmLoading = true;
return checkInstallNeSoftware(form);
})
.then(res => {
if (res.code === RESULT_CODE_SUCCESS) {
installState.setpSSHArr = res.data;
installState.setp = 'preinput';
} else {
message.error(res.msg, 3);
}
}) })
.catch(e => { .catch(e => {
message.error(t('common.errorFields', { num: e.errorFields.length }), 3); message.error(t('common.errorFields', { num: e.errorFields.length }), 3);
@@ -344,107 +329,53 @@ function fnRunCheck() {
}); });
} }
/**安装检查预输入 */ /**开始安装 */
function fnInstallPreinput() { function fnInstall() {
if (installState.confirmLoading) return; if (installState.confirmLoading) return;
// IMS installState.confirmLoading = true;
if (installState.from.neType === 'IMS') { const hide = message.loading(t('common.loading'), 0);
const modipplmn = installState.setpSSHArr[1]; const from = toRaw(installState.from);
if (modipplmn.includes('modipplmn.sh')) { const preinput = toRaw(installState.preinput);
installState.setpSSHArr[1] = modipplmn Object.assign(from, { hostId: installState.hostId });
.replace('{PUBIP}', installState.preinput.pubIP) installNeSoftware({
.replace('{MCC}', installState.preinput.mcc) software: from,
.replace('{MNC}', installState.preinput.mnc); preinput: preinput,
} action: 'install',
const modintraip = installState.setpSSHArr[2]; })
if (modintraip.includes('modintraip.sh')) { .then(res => {
installState.setpSSHArr[2] = modintraip.replace( if (res.code === RESULT_CODE_SUCCESS) {
'{PRIIP}', installState.setp = 'log';
installState.preinput.priIP installState.setpLog = res.data;
); message.success('软件安装成功', 3);
} // 记录当前步骤状态信息
} stepState.states[stepState.current] = {
// 其他 from: from,
// preinput: preinput,
};
installState.setp = 'ssh'; stepState.stepNext = true;
} else {
message.error(res.msg, 3);
}
})
.finally(() => {
hide();
installState.confirmLoading = false;
});
} }
/**安装终端 */ /**重新安装 */
const installTerminal = ref(); function fnInstallReset() {
/**
* 终端连接状态
* @param data 主机连接结果
*/
function fnTerminalConnect(data: Record<string, any>) {
console.log('fnTerminalConnect', data);
}
/**
* 终端消息数据
* @param data 主机连接结果
*/
function fnTerminalMessage(res: Record<string, any>) {
const { code, requestId, data } = res;
if (code === RESULT_CODE_ERROR) {
console.warn(res.msg);
return;
}
console.log('fnTerminalMessage', data);
// 安装遇到问题
if (data.includes('Errors were encountered while processing:')) {
installTerminal.value.send('logout');
return;
}
// 安装成功后退出
if (data.includes('software install successful')) {
installTerminal.value.send('logout');
message.success('软件安装成功', 3);
// 记录当前步骤状态信息
stepState.states[stepState.current] = { from: {} };
stepState.stepNext = true;
return;
}
// IMS预输入
if (data.includes('(P/I/S-CSCF Config)? <y/n>')) {
installTerminal.value.send(installState.preinput.pisCSCF);
return;
}
// 命令结束后继续输入命令
if (data.endsWith('$ ')) {
console.log('结束');
const cmdStr = installState.setpSSHArr.shift();
if (cmdStr) {
installTerminal.value.send(cmdStr);
}
return;
}
}
/**
* 终端关闭状态
* @param data 主机连接结果
*/
function fnTerminalClose(data: Record<string, any>) {
console.log('fnTerminalClose', data);
}
/**终端重新安装 */
function fnTerminalReset() {
installState.setp = 'pkg'; installState.setp = 'pkg';
installState.optionType = 'option'; installState.optionType = 'option';
} }
onMounted(() => { onMounted(() => {
// 读取步骤:网元信息 // 读取步骤:网元信息
const stepPrevFrom = stepState.states[1].from; const stepPrevFrom = stepState.states[1];
installState.from.neType = stepPrevFrom.neType; if (stepPrevFrom && stepPrevFrom.from) {
installState.hostId = stepPrevFrom.hostIds.split(',')[0]; installState.from.neType = stepPrevFrom.from.neType;
installState.hostId = stepPrevFrom.from.hostIds.split(',')[0];
}
}); });
</script> </script>
@@ -515,8 +446,8 @@ onMounted(() => {
</a-form-item> </a-form-item>
<a-form-item <a-form-item
:label="t('views.configManage.softwareManage.updateComment')" :label="t('views.configManage.softwareManage.updateComment')"
name="comment" name="description"
v-bind="installStateFrom.validateInfos.comment" v-bind="installStateFrom.validateInfos.description"
> >
<a-textarea <a-textarea
v-model:value="installState.from.description" v-model:value="installState.from.description"
@@ -575,16 +506,16 @@ onMounted(() => {
}" }"
> >
<template #bodyCell="{ column, record }"> <template #bodyCell="{ column, record }">
<template v-if="column.key === 'fileName'"> <template v-if="column.key === 'name'">
<a-tooltip placement="topLeft"> <a-tooltip placement="topLeft">
<template #title>{{ record.path }}</template> <template #title>{{ record.path }}</template>
<div style="cursor: pointer">{{ record.fileName }}</div> <div style="cursor: pointer">{{ record.name }}</div>
</a-tooltip> </a-tooltip>
</template> </template>
<template v-if="column.key === 'comment'"> <template v-if="column.key === 'description'">
<a-tooltip placement="topLeft"> <a-tooltip placement="topLeft">
<template #title>{{ record.comment }}</template> <template #title>{{ record.description }}</template>
<div style="cursor: pointer">{{ record.comment }}</div> <div style="cursor: pointer">{{ record.description }}</div>
</a-tooltip> </a-tooltip>
</template> </template>
</template> </template>
@@ -659,7 +590,7 @@ onMounted(() => {
<a-button <a-button
type="primary" type="primary"
html-type="submit" html-type="submit"
@click="fnInstallPreinput()" @click="fnInstall()"
:loading="installState.confirmLoading" :loading="installState.confirmLoading"
> >
开始安装 开始安装
@@ -669,7 +600,7 @@ onMounted(() => {
<div>---- 安装进行信息</div> <div>---- 安装进行信息</div>
<template v-if="installState.setp === 'ssh'"> <template v-if="installState.setp === 'log'">
<a-form-item <a-form-item
name="info" name="info"
label="安装日志" label="安装日志"
@@ -677,23 +608,18 @@ onMounted(() => {
:wrapper-col="{ span: 24 }" :wrapper-col="{ span: 24 }"
:label-wrap="true" :label-wrap="true"
> >
<TerminalSSH <TerminalText
ref="installTerminal" id="installLog"
:id="installState.hostId" :rows="28"
:hostId="installState.hostId" :value="installState.setpLog"
init-cmd="clear" ></TerminalText>
@connect="fnTerminalConnect"
@message="fnTerminalMessage"
@close="fnTerminalClose"
>
</TerminalSSH>
</a-form-item> </a-form-item>
<a-form-item :wrapper-col="{ span: 14, offset: 3 }"> <a-form-item :wrapper-col="{ span: 14, offset: 3 }">
<a-button <a-button
type="primary" type="primary"
html-type="submit" html-type="submit"
@click="fnTerminalReset()" @click="fnInstallReset()"
:loading="installState.confirmLoading" :loading="installState.confirmLoading"
> >
返回重新选择安装 返回重新选择安装

View File

@@ -8,7 +8,6 @@ import { addNeInfo, updateNeInfo, getTypeAndIDNeInfo } from '@/api/ne/neInfo';
import { NE_TYPE_LIST } from '@/constants/ne-constants'; import { NE_TYPE_LIST } from '@/constants/ne-constants';
import { stepState } from '../hooks/useStep'; import { stepState } from '../hooks/useStep';
const { t } = useI18n(); const { t } = useI18n();
const emit = defineEmits(['next']);
/**对话框对象信息状态类型 */ /**对话框对象信息状态类型 */
type ModalStateType = { type ModalStateType = {
@@ -204,14 +203,22 @@ function fnNeInfo() {
onMounted(() => { onMounted(() => {
// 读取步骤:环境检查 // 读取步骤:环境检查
const stepPrevFrom = stepState.states[0].from; const stepPrevFrom = stepState.states[0];
modalState.from.ip = stepPrevFrom.addr; if (stepPrevFrom && stepPrevFrom.from) {
Object.assign(modalState.from.hosts[0], stepPrevFrom); modalState.from.ip = stepPrevFrom.from.addr;
Object.assign(modalState.from.hosts[1], { Object.assign(modalState.from.hosts[0], stepPrevFrom.from);
addr: stepPrevFrom.addr, Object.assign(modalState.from.hosts[1], {
user: 'admin', addr: modalState.from.ip,
password: 'admin', user: 'admin',
}); password: 'admin',
});
}
// 读取步骤:网元信息
const stepCurrentFrom = stepState.states[1];
if (stepCurrentFrom && stepCurrentFrom.from) {
Object.assign(modalState.from, stepCurrentFrom.from);
}
}); });
</script> </script>

View File

@@ -1,13 +1,75 @@
<script lang="ts" setup> <script lang="ts" setup>
import { PageContainer } from 'antdv-pro-layout'; import { PageContainer } from 'antdv-pro-layout';
import { message } from 'ant-design-vue/lib'; import { message } from 'ant-design-vue/lib';
import StepCheck from './components/StepCheck.vue'; import { defineAsyncComponent, watch, shallowRef } from 'vue';
import StepNeInfo from './components/StepNeInfo.vue';
import StepInstall from './components/StepInstall.vue';
import StepConfig from './components/StepConfig.vue';
import StepActivate from './components/StepActivate.vue';
import StepFinish from './components/StepFinish.vue';
import { stepState, fnStepPrev, fnStepNext } from './hooks/useStep'; import { stepState, fnStepPrev, fnStepNext } from './hooks/useStep';
// 异步加载组件
const StepCheck = defineAsyncComponent(
() => import('./components/StepCheck.vue')
);
// 当前组件
const currentComponent = shallowRef(StepCheck);
watch(
() => stepState.current,
v => {
if (v === 0) {
currentComponent.value = StepCheck;
return;
}
if (v === 1) {
const StepNeInfo = defineAsyncComponent(
() => import('./components/StepNeInfo.vue')
);
currentComponent.value = StepNeInfo;
return;
}
if (v === 2) {
const StepInstall = defineAsyncComponent(
() => import('./components/StepInstall.vue')
);
currentComponent.value = StepInstall;
return;
}
if (v === 3) {
// 读取第二步的网元信息
const stepNeInfo = stepState.states[1].from;
if (stepNeInfo.neType === 'SMF') {
const StepConfigSMF = defineAsyncComponent(
() => import('./components/StepConfigSMF.vue')
);
currentComponent.value = StepConfigSMF;
} else if (stepNeInfo.neType === 'AMF') {
const StepConfigText = defineAsyncComponent(
() => import('./components/StepConfigText.vue')
);
currentComponent.value = StepConfigText;
} else {
const StepConfig = defineAsyncComponent(
() => import('./components/StepConfig.vue')
);
currentComponent.value = StepConfig;
}
return;
}
if (v === 4) {
const StepActivate = defineAsyncComponent(
() => import('./components/StepActivate.vue')
);
currentComponent.value = StepActivate;
return;
}
if (v === 5) {
const StepFinish = defineAsyncComponent(
() => import('./components/StepFinish.vue')
);
currentComponent.value = StepFinish;
return;
}
}
);
</script> </script>
<template> <template>
@@ -66,12 +128,7 @@ import { stepState, fnStepPrev, fnStepNext } from './hooks/useStep';
</template> </template>
<!-- 步骤页面 --> <!-- 步骤页面 -->
<StepCheck v-if="stepState.current === 0"></StepCheck> <component :is="currentComponent" />
<StepNeInfo v-if="stepState.current === 1"></StepNeInfo>
<StepInstall v-if="stepState.current === 2"></StepInstall>
<StepConfig v-if="stepState.current === 3"></StepConfig>
<StepActivate v-if="stepState.current === 4"></StepActivate>
<StepFinish v-if="stepState.current === 5"></StepFinish>
</a-card> </a-card>
</PageContainer> </PageContainer>
</template> </template>